ufs-sec-sysfs.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Samsung Specific feature : sysfs-nodes
  4. *
  5. * Copyright (C) 2023 Samsung Electronics Co., Ltd.
  6. *
  7. * Authors:
  8. * Storage Driver <[email protected]>
  9. */
  10. #include "ufs-sec-sysfs.h"
  11. #include <linux/sysfs.h>
  12. #include <linux/blk-pm.h>
  13. #include <linux/blkdev.h>
  14. #include <scsi/scsi_cmnd.h>
  15. #include <scsi/scsi_dbg.h>
  16. #include <scsi/scsi_device.h>
  17. #include <linux/bitfield.h>
  18. #include "ufs-qcom.h"
  19. /* sec specific vendor sysfs nodes */
  20. struct device *sec_ufs_node_dev;
  21. /* SEC next WB : begin */
  22. static void ufs_sec_wb_info_backup(struct ufs_sec_wb_info *backup)
  23. {
  24. SEC_UFS_WB_INFO_BACKUP(enable_cnt);
  25. SEC_UFS_WB_INFO_BACKUP(disable_cnt);
  26. SEC_UFS_WB_INFO_BACKUP(amount_kb);
  27. SEC_UFS_WB_INFO_BACKUP(err_cnt);
  28. backup->state_ts = jiffies;
  29. }
  30. static ssize_t ufs_sec_wb_info_show(struct device *dev, struct device_attribute *attr, char *buf)
  31. {
  32. struct ufs_sec_wb_info *wb_info_backup = ufs_sec_features.ufs_wb_backup;
  33. struct ufs_sec_wb_info *wb_info = ufs_sec_features.ufs_wb;
  34. long hours = 0;
  35. int len = 0;
  36. wb_info->state_ts = jiffies;
  37. hours = jiffies_to_msecs(wb_info->state_ts - wb_info_backup->state_ts) / 1000; /* sec */
  38. hours = (hours + 60) / (60 * 60); /* round up to hours */
  39. len = sprintf(buf, "\"TWCTRLCNT\":\"%llu\","
  40. "\"TWCTRLERRCNT\":\"%llu\","
  41. "\"TWDAILYMB\":\"%llu\","
  42. "\"TWTOTALMB\":\"%llu\","
  43. "\"TWhours\":\"%ld\"\n",
  44. (wb_info->enable_cnt + wb_info->disable_cnt),
  45. wb_info->err_cnt, /* total error count */
  46. (wb_info->amount_kb >> 10), /* WB write daily : MB */
  47. (wb_info_backup->amount_kb >> 10), /* WB write total : MB */
  48. hours);
  49. ufs_sec_wb_info_backup(wb_info_backup);
  50. return len;
  51. }
  52. static DEVICE_ATTR(SEC_UFS_TW_info, 0444, ufs_sec_wb_info_show, NULL);
  53. /* SEC next WB : end */
  54. /* UFS info nodes : begin */
  55. static ssize_t ufs_sec_unique_number_show(struct device *dev,
  56. struct device_attribute *attr, char *buf)
  57. {
  58. return snprintf(buf, PAGE_SIZE, "%s\n", get_vdi_member(unique_number));
  59. }
  60. static DEVICE_ATTR(un, 0440, ufs_sec_unique_number_show, NULL);
  61. static ssize_t ufs_sec_lt_show(struct device *dev,
  62. struct device_attribute *attr, char *buf)
  63. {
  64. struct ufs_hba *hba = get_vdi_member(hba);
  65. if (!hba) {
  66. dev_err(dev, "skipping ufs lt read\n");
  67. get_vdi_member(lt) = 0;
  68. } else if (hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) {
  69. ufshcd_rpm_get_sync(hba);
  70. ufs_sec_get_health_desc(hba);
  71. ufshcd_rpm_put(hba);
  72. } else {
  73. /* return previous LT value if not operational */
  74. dev_info(hba->dev, "ufshcd_state: %d, old LT: %01x\n",
  75. hba->ufshcd_state, get_vdi_member(lt));
  76. }
  77. return snprintf(buf, PAGE_SIZE, "%01x\n", get_vdi_member(lt));
  78. }
  79. static DEVICE_ATTR(lt, 0444, ufs_sec_lt_show, NULL);
  80. static ssize_t ufs_sec_flt_show(struct device *dev,
  81. struct device_attribute *attr, char *buf)
  82. {
  83. struct ufs_hba *hba = get_vdi_member(hba);
  84. if (!hba) {
  85. dev_err(dev, "skipping ufs flt read\n");
  86. get_vdi_member(flt) = 0;
  87. } else if (hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) {
  88. ufshcd_rpm_get_sync(hba);
  89. ufs_sec_get_health_desc(hba);
  90. ufshcd_rpm_put(hba);
  91. } else {
  92. /* return previous FLT value if not operational */
  93. dev_info(hba->dev, "ufshcd_state : %d, old FLT: %u\n",
  94. hba->ufshcd_state, get_vdi_member(flt));
  95. }
  96. return snprintf(buf, PAGE_SIZE, "%u\n", get_vdi_member(flt));
  97. }
  98. static DEVICE_ATTR(flt, 0444, ufs_sec_flt_show, NULL);
  99. static ssize_t ufs_sec_eli_show(struct device *dev,
  100. struct device_attribute *attr, char *buf)
  101. {
  102. struct ufs_hba *hba = get_vdi_member(hba);
  103. if (!hba) {
  104. dev_err(dev, "skipping ufs eli read\n");
  105. get_vdi_member(eli) = 0;
  106. } else if (hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) {
  107. ufshcd_rpm_get_sync(hba);
  108. ufs_sec_get_health_desc(hba);
  109. ufshcd_rpm_put(hba);
  110. } else {
  111. /* return previous ELI value if not operational */
  112. dev_info(hba->dev, "ufshcd_state: %d, old eli: %01x\n",
  113. hba->ufshcd_state, get_vdi_member(eli));
  114. }
  115. return sprintf(buf, "%u\n", get_vdi_member(eli));
  116. }
  117. static DEVICE_ATTR(eli, 0444, ufs_sec_eli_show, NULL);
  118. static ssize_t ufs_sec_ic_show(struct device *dev,
  119. struct device_attribute *attr, char *buf)
  120. {
  121. return sprintf(buf, "%u\n", get_vdi_member(ic));
  122. }
  123. static ssize_t ufs_sec_ic_store(struct device *dev,
  124. struct device_attribute *attr, const char *buf, size_t count)
  125. {
  126. unsigned int value;
  127. if (kstrtou32(buf, 0, &value))
  128. return -EINVAL;
  129. get_vdi_member(ic) = value;
  130. return count;
  131. }
  132. static DEVICE_ATTR(ic, 0664, ufs_sec_ic_show, ufs_sec_ic_store);
  133. static ssize_t ufs_sec_shi_show(struct device *dev,
  134. struct device_attribute *attr, char *buf)
  135. {
  136. return sprintf(buf, "%s\n", get_vdi_member(shi));
  137. }
  138. static ssize_t ufs_sec_shi_store(struct device *dev,
  139. struct device_attribute *attr, const char *buf, size_t count)
  140. {
  141. int ret;
  142. char shi_buf[256] = {0, };
  143. ret = sscanf(buf, "%255[^\n]%*c", shi_buf);
  144. if (ret != 1)
  145. return -EINVAL;
  146. snprintf(get_vdi_member(shi), 256, "%s", shi_buf);
  147. return count;
  148. }
  149. static DEVICE_ATTR(shi, 0664, ufs_sec_shi_show, ufs_sec_shi_store);
  150. static ssize_t ufs_sec_hist_info_show(struct device *dev,
  151. struct device_attribute *attr, char *buf)
  152. {
  153. return SEC_UFS_ERR_HIST_SUM(buf);
  154. }
  155. static bool is_valid_hist_info(const char *buf, size_t count)
  156. {
  157. int i;
  158. if (count != ERR_SUM_SIZE)
  159. return false;
  160. if (buf[0] != 'U' || buf[2] != 'I' || buf[4] != 'H' ||
  161. buf[6] != 'L' || buf[8] != 'X' || buf[10] != 'Q' ||
  162. buf[12] != 'R' || buf[14] != 'W' || buf[16] != 'F' ||
  163. buf[18] != 'S' || buf[19] != 'M' || buf[21] != 'S' ||
  164. buf[22] != 'H')
  165. return false;
  166. for (i = 1; i < ERR_SUM_SIZE; i += 2) {
  167. if (buf[i] - '0' < 0 || buf[i] - '0' >= 10)
  168. return false;
  169. /* increase index for "SM", "SH" */
  170. if (i == 17 || i == 20)
  171. i++;
  172. }
  173. return true;
  174. }
  175. static ssize_t ufs_sec_hist_info_store(struct device *dev,
  176. struct device_attribute *attr, const char *buf, size_t count)
  177. {
  178. if (!is_valid_hist_info(buf, count)) {
  179. pr_err("%s: %s, len(%lu)\n", __func__, buf, count);
  180. return -EINVAL;
  181. }
  182. SEC_UFS_ERR_INFO_HIST_SET_VALUE(UTP_cnt, UTP_err, buf[1]);
  183. SEC_UFS_ERR_INFO_HIST_SET_VALUE(UIC_err_cnt, UIC_err, buf[3]);
  184. SEC_UFS_ERR_INFO_HIST_SET_VALUE(op_cnt, HW_RESET_cnt, buf[5]);
  185. SEC_UFS_ERR_INFO_HIST_SET_VALUE(op_cnt, link_startup_cnt, buf[7]);
  186. SEC_UFS_ERR_INFO_HIST_SET_VALUE(Fatal_err_cnt, LLE, buf[9]);
  187. SEC_UFS_ERR_INFO_HIST_SET_VALUE(UTP_cnt, UTMR_query_task_cnt, buf[11]);
  188. SEC_UFS_ERR_INFO_HIST_SET_VALUE(UTP_cnt, UTR_read_err, buf[13]);
  189. SEC_UFS_ERR_INFO_HIST_SET_VALUE(UTP_cnt, UTR_write_err, buf[15]);
  190. SEC_UFS_ERR_INFO_HIST_SET_VALUE(Fatal_err_cnt, DFE, buf[17]);
  191. SEC_UFS_ERR_INFO_HIST_SET_VALUE(sense_cnt, scsi_medium_err, buf[20]);
  192. SEC_UFS_ERR_INFO_HIST_SET_VALUE(sense_cnt, scsi_hw_err, buf[23]);
  193. return count;
  194. }
  195. static DEVICE_ATTR(hist, 0664, ufs_sec_hist_info_show, ufs_sec_hist_info_store);
  196. static ssize_t ufs_sec_man_id_show(struct device *dev,
  197. struct device_attribute *attr, char *buf)
  198. {
  199. struct ufs_hba *hba = get_vdi_member(hba);
  200. if (!hba) {
  201. dev_err(dev, "skipping ufs manid read\n");
  202. return -EINVAL;
  203. }
  204. return snprintf(buf, PAGE_SIZE, "%04x\n", hba->dev_info.wmanufacturerid);
  205. }
  206. static DEVICE_ATTR(man_id, 0444, ufs_sec_man_id_show, NULL);
  207. static bool ufs_sec_wait_for_clear_pending(struct ufs_hba *hba, u64 timeout_us)
  208. {
  209. struct scsi_device *sdp;
  210. unsigned long flags;
  211. unsigned int tm_pending = 0;
  212. unsigned int tr_pending = 0;
  213. bool timeout = true;
  214. ktime_t start;
  215. ufshcd_hold(hba, false);
  216. start = ktime_get();
  217. do {
  218. spin_lock_irqsave(hba->host->host_lock, flags);
  219. tr_pending = 0;
  220. tm_pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
  221. __shost_for_each_device(sdp, hba->host)
  222. tr_pending += sbitmap_weight(&sdp->budget_map);
  223. spin_unlock_irqrestore(hba->host->host_lock, flags);
  224. if (!tm_pending && !tr_pending) {
  225. dev_info(hba->dev, "doorbell clr complete.\n");
  226. timeout = false;
  227. break;
  228. }
  229. usleep_range(5000, 5100);
  230. } while (ktime_to_us(ktime_sub(ktime_get(), start)) < timeout_us);
  231. ufshcd_release(hba);
  232. return timeout;
  233. }
  234. static int ufs_sec_send_pon(struct ufs_hba *hba)
  235. {
  236. struct scsi_device *sdp = hba->ufs_device_wlun;
  237. const unsigned char cdb[6] = { START_STOP, 0, 0, 0, UFS_POWERDOWN_PWR_MODE << 4, 0 };
  238. struct scsi_sense_hdr sshdr;
  239. const struct scsi_exec_args args = {
  240. .sshdr = &sshdr,
  241. .req_flags = BLK_MQ_REQ_PM,
  242. .scmd_flags = SCMD_FAIL_IF_RECOVERING,
  243. };
  244. int retries;
  245. int ret;
  246. for (retries = 3; retries > 0; --retries) {
  247. ret = scsi_execute_cmd(sdp, cdb, REQ_OP_DRV_IN, NULL,
  248. 0, 10 * HZ, 0, &args);
  249. if (ret <= 0)
  250. break;
  251. }
  252. if (ret) {
  253. if (ret > 0) {
  254. if (scsi_sense_valid(&sshdr))
  255. scsi_print_sense_hdr(sdp, NULL, &sshdr);
  256. }
  257. } else {
  258. dev_info(hba->dev, "pon done.\n");
  259. hba->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE;
  260. }
  261. return ret;
  262. }
  263. static void ufs_sec_reset_device(struct ufs_hba *hba)
  264. {
  265. struct ufs_qcom_host *host = ufshcd_get_variant(hba);
  266. unsigned long flags;
  267. spin_lock_irqsave(hba->host->host_lock, flags);
  268. hba->force_reset = true;
  269. host->skip_flush = true;
  270. hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED_FATAL;
  271. queue_work(hba->eh_wq, &hba->eh_work);
  272. spin_unlock_irqrestore(hba->host->host_lock, flags);
  273. flush_work(&hba->eh_work);
  274. dev_info(hba->dev, "reset done.\n");
  275. if (host->skip_flush)
  276. host->skip_flush = false;
  277. }
  278. static ssize_t ufs_sec_post_ffu_store(struct device *dev,
  279. struct device_attribute *attr, const char *buf, size_t count)
  280. {
  281. struct ufs_hba *hba = get_vdi_member(hba);
  282. struct scsi_device *sdp_wlu = hba->ufs_device_wlun;
  283. struct scsi_device *sdp;
  284. u32 ahit_backup = hba->ahit;
  285. unsigned long flags;
  286. int ret;
  287. /* check product name string */
  288. if (strncmp(buf, (char *)hba->dev_info.model, strlen(hba->dev_info.model)))
  289. return -EINVAL;
  290. dev_info(hba->dev, "post_ffu start\n");
  291. ufshcd_rpm_get_sync(hba);
  292. spin_lock_irqsave(hba->host->host_lock, flags);
  293. if (sdp_wlu && scsi_device_online(sdp_wlu))
  294. ret = scsi_device_get(sdp_wlu);
  295. else
  296. ret = -ENODEV;
  297. spin_unlock_irqrestore(hba->host->host_lock, flags);
  298. if (ret) {
  299. ufshcd_rpm_put(hba);
  300. return ret;
  301. }
  302. /* set SDEV_QUIESCE */
  303. shost_for_each_device(sdp, hba->host)
  304. scsi_device_quiesce(sdp);
  305. /* wait for clear outstanding requests after queue quiesce */
  306. if (ufs_sec_wait_for_clear_pending(hba, USEC_PER_SEC))
  307. dev_err(dev, "post_ffu: doorbell clr timedout 1s.\n");
  308. /* disable AH8 */
  309. ufshcd_auto_hibern8_update(hba, 0);
  310. /* reset and recovery UFS, even if the PON fails */
  311. if (ufs_sec_send_pon(hba))
  312. dev_err(dev, "post_ffu: pon failed.\n");
  313. /* reset UFS by eh_work */
  314. ufs_sec_reset_device(hba);
  315. /* enable AH8 after UFS reset */
  316. ufshcd_auto_hibern8_update(hba, ahit_backup);
  317. /* set SDEV_RUNNING */
  318. shost_for_each_device(sdp, hba->host)
  319. scsi_device_resume(sdp);
  320. scsi_device_put(sdp_wlu);
  321. ufshcd_rpm_put(hba);
  322. dev_info(hba->dev, "post_ffu finish\n");
  323. return count;
  324. }
  325. static DEVICE_ATTR(post_ffu, 0220, NULL, ufs_sec_post_ffu_store);
  326. static struct attribute *sec_ufs_info_attributes[] = {
  327. &dev_attr_un.attr,
  328. &dev_attr_lt.attr,
  329. &dev_attr_flt.attr,
  330. &dev_attr_eli.attr,
  331. &dev_attr_ic.attr,
  332. &dev_attr_shi.attr,
  333. &dev_attr_hist.attr,
  334. &dev_attr_man_id.attr,
  335. &dev_attr_post_ffu.attr,
  336. NULL
  337. };
  338. static struct attribute_group sec_ufs_info_attribute_group = {
  339. .attrs = sec_ufs_info_attributes,
  340. };
  341. /* UFS info nodes : end */
  342. /* SEC s_info : begin */
  343. static ssize_t SEC_UFS_s_info_store(struct device *dev,
  344. struct device_attribute *attr, const char *buf, size_t count)
  345. {
  346. int ret;
  347. char s_buf[512] = {0, };
  348. ret = sscanf(buf, "%511s", s_buf);
  349. if (ret != 1)
  350. return -EINVAL;
  351. snprintf(get_vdi_member(s_info), 512, "%s", s_buf);
  352. return count;
  353. }
  354. SEC_UFS_DATA_ATTR_RW(SEC_UFS_s_info, "%s\n", get_vdi_member(s_info));
  355. /* SEC s_info : end */
  356. /* SEC error info : begin */
  357. static ssize_t SEC_UFS_op_cnt_store(struct device *dev,
  358. struct device_attribute *attr, const char *buf, size_t count)
  359. {
  360. if ((buf[0] != 'C' && buf[0] != 'c') || (count != 1))
  361. return -EINVAL;
  362. SEC_UFS_ERR_INFO_BACKUP(op_cnt, HW_RESET_cnt);
  363. SEC_UFS_ERR_INFO_BACKUP(op_cnt, link_startup_cnt);
  364. SEC_UFS_ERR_INFO_BACKUP(op_cnt, Hibern8_enter_cnt);
  365. SEC_UFS_ERR_INFO_BACKUP(op_cnt, Hibern8_exit_cnt);
  366. SEC_UFS_ERR_INFO_BACKUP(op_cnt, AH8_err_cnt);
  367. return count;
  368. }
  369. static ssize_t SEC_UFS_uic_cmd_cnt_store(struct device *dev,
  370. struct device_attribute *attr, const char *buf, size_t count)
  371. {
  372. if ((buf[0] != 'C' && buf[0] != 'c') || (count != 1))
  373. return -EINVAL;
  374. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_TEST_MODE_err);
  375. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_GET_err);
  376. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_SET_err);
  377. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_PEER_GET_err);
  378. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_PEER_SET_err);
  379. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_POWERON_err);
  380. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_POWEROFF_err);
  381. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_ENABLE_err);
  382. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_RESET_err);
  383. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_END_PT_RST_err);
  384. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_LINK_STARTUP_err);
  385. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_HIBER_ENTER_err);
  386. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, DME_HIBER_EXIT_err);
  387. return count;
  388. }
  389. static ssize_t SEC_UFS_uic_err_cnt_store(struct device *dev,
  390. struct device_attribute *attr, const char *buf, size_t count)
  391. {
  392. if ((buf[0] != 'C' && buf[0] != 'c') || (count != 1))
  393. return -EINVAL;
  394. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, PAERR_cnt);
  395. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, DLERR_cnt);
  396. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, DL_PA_INIT_ERR_cnt);
  397. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, DL_NAC_RCVD_ERR_cnt);
  398. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, DL_TC_REPLAY_ERR_cnt);
  399. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, DL_FC_PROTECT_ERR_cnt);
  400. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, NLERR_cnt);
  401. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, TLERR_cnt);
  402. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, DMEERR_cnt);
  403. return count;
  404. }
  405. static ssize_t SEC_UFS_fatal_cnt_store(struct device *dev,
  406. struct device_attribute *attr, const char *buf, size_t count)
  407. {
  408. if ((buf[0] != 'C' && buf[0] != 'c') || (count != 1))
  409. return -EINVAL;
  410. SEC_UFS_ERR_INFO_BACKUP(Fatal_err_cnt, DFE);
  411. SEC_UFS_ERR_INFO_BACKUP(Fatal_err_cnt, CFE);
  412. SEC_UFS_ERR_INFO_BACKUP(Fatal_err_cnt, SBFE);
  413. SEC_UFS_ERR_INFO_BACKUP(Fatal_err_cnt, CEFE);
  414. SEC_UFS_ERR_INFO_BACKUP(Fatal_err_cnt, LLE);
  415. return count;
  416. }
  417. static ssize_t SEC_UFS_utp_cnt_store(struct device *dev,
  418. struct device_attribute *attr, const char *buf, size_t count)
  419. {
  420. if ((buf[0] != 'C' && buf[0] != 'c') || (count != 1))
  421. return -EINVAL;
  422. SEC_UFS_ERR_INFO_BACKUP(UTP_cnt, UTMR_query_task_cnt);
  423. SEC_UFS_ERR_INFO_BACKUP(UTP_cnt, UTMR_abort_task_cnt);
  424. SEC_UFS_ERR_INFO_BACKUP(UTP_cnt, UTR_read_err);
  425. SEC_UFS_ERR_INFO_BACKUP(UTP_cnt, UTR_write_err);
  426. SEC_UFS_ERR_INFO_BACKUP(UTP_cnt, UTR_sync_cache_err);
  427. SEC_UFS_ERR_INFO_BACKUP(UTP_cnt, UTR_unmap_err);
  428. SEC_UFS_ERR_INFO_BACKUP(UTP_cnt, UTR_etc_err);
  429. return count;
  430. }
  431. static ssize_t SEC_UFS_query_cnt_store(struct device *dev,
  432. struct device_attribute *attr, const char *buf, size_t count)
  433. {
  434. if ((buf[0] != 'C' && buf[0] != 'c') || (count != 1))
  435. return -EINVAL;
  436. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, NOP_err);
  437. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, R_Desc_err);
  438. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, W_Desc_err);
  439. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, R_Attr_err);
  440. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, W_Attr_err);
  441. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, R_Flag_err);
  442. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, Set_Flag_err);
  443. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, Clear_Flag_err);
  444. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, Toggle_Flag_err);
  445. return count;
  446. }
  447. static ssize_t SEC_UFS_err_sum_store(struct device *dev,
  448. struct device_attribute *attr, const char *buf, size_t count)
  449. {
  450. if ((buf[0] != 'C' && buf[0] != 'c') || (count != 1))
  451. return -EINVAL;
  452. SEC_UFS_ERR_INFO_BACKUP(op_cnt, op_err);
  453. SEC_UFS_ERR_INFO_BACKUP(UIC_cmd_cnt, UIC_cmd_err);
  454. SEC_UFS_ERR_INFO_BACKUP(UIC_err_cnt, UIC_err);
  455. SEC_UFS_ERR_INFO_BACKUP(Fatal_err_cnt, Fatal_err);
  456. SEC_UFS_ERR_INFO_BACKUP(UTP_cnt, UTP_err);
  457. SEC_UFS_ERR_INFO_BACKUP(Query_cnt, Query_err);
  458. return count;
  459. }
  460. static ssize_t sense_err_count_store(struct device *dev,
  461. struct device_attribute *attr, const char *buf, size_t count)
  462. {
  463. if ((buf[0] != 'C' && buf[0] != 'c') || (count != 1))
  464. return -EINVAL;
  465. SEC_UFS_ERR_INFO_BACKUP(sense_cnt, scsi_medium_err);
  466. SEC_UFS_ERR_INFO_BACKUP(sense_cnt, scsi_hw_err);
  467. return count;
  468. }
  469. SEC_UFS_DATA_ATTR_RW(SEC_UFS_op_cnt, "\"HWRESET\":\"%u\",\"LINKFAIL\":\"%u\""
  470. ",\"H8ENTERFAIL\":\"%u\",\"H8EXITFAIL\":\"%u\""
  471. ",\"AH8ERR\":\"%u\"\n",
  472. get_err_member(op_cnt).HW_RESET_cnt,
  473. get_err_member(op_cnt).link_startup_cnt,
  474. get_err_member(op_cnt).Hibern8_enter_cnt,
  475. get_err_member(op_cnt).Hibern8_exit_cnt,
  476. get_err_member(op_cnt).AH8_err_cnt);
  477. SEC_UFS_DATA_ATTR_RW(SEC_UFS_uic_cmd_cnt, "\"TESTMODE\":\"%u\""
  478. ",\"DME_GET\":\"%u\",\"DME_SET\":\"%u\",\"DME_PGET\":\"%u\""
  479. ",\"DME_PSET\":\"%u\",\"PWRON\":\"%u\",\"PWROFF\":\"%u\""
  480. ",\"DME_EN\":\"%u\",\"DME_RST\":\"%u\",\"EPRST\":\"%u\""
  481. ",\"LINKSTARTUP\":\"%u\",\"H8ENTER\":\"%u\""
  482. ",\"H8EXIT\":\"%u\"\n",
  483. get_err_member(UIC_cmd_cnt).DME_TEST_MODE_err,
  484. get_err_member(UIC_cmd_cnt).DME_GET_err,
  485. get_err_member(UIC_cmd_cnt).DME_SET_err,
  486. get_err_member(UIC_cmd_cnt).DME_PEER_GET_err,
  487. get_err_member(UIC_cmd_cnt).DME_PEER_SET_err,
  488. get_err_member(UIC_cmd_cnt).DME_POWERON_err,
  489. get_err_member(UIC_cmd_cnt).DME_POWEROFF_err,
  490. get_err_member(UIC_cmd_cnt).DME_ENABLE_err,
  491. get_err_member(UIC_cmd_cnt).DME_RESET_err,
  492. get_err_member(UIC_cmd_cnt).DME_END_PT_RST_err,
  493. get_err_member(UIC_cmd_cnt).DME_LINK_STARTUP_err,
  494. get_err_member(UIC_cmd_cnt).DME_HIBER_ENTER_err,
  495. get_err_member(UIC_cmd_cnt).DME_HIBER_EXIT_err);
  496. SEC_UFS_DATA_ATTR_RW(SEC_UFS_uic_err_cnt, "\"PAERR\":\"%u\""
  497. ",\"DLERR\":\"%u\""
  498. ",\"DLPAINITERROR\":\"%u\",\"DLNAC\":\"%u\""
  499. ",\"DLTCREPLAY\":\"%u\",\"DLFCX\":\"%u\""
  500. ",\"NLERR\":\"%u\",\"TLERR\":\"%u\""
  501. ",\"DMEERR\":\"%u\"\n",
  502. get_err_member(UIC_err_cnt).PAERR_cnt,
  503. get_err_member(UIC_err_cnt).DLERR_cnt,
  504. get_err_member(UIC_err_cnt).DL_PA_INIT_ERR_cnt,
  505. get_err_member(UIC_err_cnt).DL_NAC_RCVD_ERR_cnt,
  506. get_err_member(UIC_err_cnt).DL_TC_REPLAY_ERR_cnt,
  507. get_err_member(UIC_err_cnt).DL_FC_PROTECT_ERR_cnt,
  508. get_err_member(UIC_err_cnt).NLERR_cnt,
  509. get_err_member(UIC_err_cnt).TLERR_cnt,
  510. get_err_member(UIC_err_cnt).DMEERR_cnt);
  511. SEC_UFS_DATA_ATTR_RW(SEC_UFS_fatal_cnt, "\"DFE\":\"%u\",\"CFE\":\"%u\""
  512. ",\"SBFE\":\"%u\",\"CEFE\":\"%u\",\"LLE\":\"%u\"\n",
  513. get_err_member(Fatal_err_cnt).DFE,
  514. get_err_member(Fatal_err_cnt).CFE,
  515. get_err_member(Fatal_err_cnt).SBFE,
  516. get_err_member(Fatal_err_cnt).CEFE,
  517. get_err_member(Fatal_err_cnt).LLE);
  518. SEC_UFS_DATA_ATTR_RW(SEC_UFS_utp_cnt, "\"UTMRQTASK\":\"%u\""
  519. ",\"UTMRATASK\":\"%u\",\"UTRR\":\"%u\",\"UTRW\":\"%u\""
  520. ",\"UTRSYNCCACHE\":\"%u\",\"UTRUNMAP\":\"%u\""
  521. ",\"UTRETC\":\"%u\"\n",
  522. get_err_member(UTP_cnt).UTMR_query_task_cnt,
  523. get_err_member(UTP_cnt).UTMR_abort_task_cnt,
  524. get_err_member(UTP_cnt).UTR_read_err,
  525. get_err_member(UTP_cnt).UTR_write_err,
  526. get_err_member(UTP_cnt).UTR_sync_cache_err,
  527. get_err_member(UTP_cnt).UTR_unmap_err,
  528. get_err_member(UTP_cnt).UTR_etc_err);
  529. SEC_UFS_DATA_ATTR_RW(SEC_UFS_query_cnt, "\"NOPERR\":\"%u\",\"R_DESC\":\"%u\""
  530. ",\"W_DESC\":\"%u\",\"R_ATTR\":\"%u\",\"W_ATTR\":\"%u\""
  531. ",\"R_FLAG\":\"%u\",\"S_FLAG\":\"%u\",\"C_FLAG\":\"%u\""
  532. ",\"T_FLAG\":\"%u\"\n",
  533. get_err_member(Query_cnt).NOP_err,
  534. get_err_member(Query_cnt).R_Desc_err,
  535. get_err_member(Query_cnt).W_Desc_err,
  536. get_err_member(Query_cnt).R_Attr_err,
  537. get_err_member(Query_cnt).W_Attr_err,
  538. get_err_member(Query_cnt).R_Flag_err,
  539. get_err_member(Query_cnt).Set_Flag_err,
  540. get_err_member(Query_cnt).Clear_Flag_err,
  541. get_err_member(Query_cnt).Toggle_Flag_err);
  542. /* daily err sum */
  543. SEC_UFS_DATA_ATTR_RW(SEC_UFS_err_sum, "\"OPERR\":\"%u\",\"UICCMD\":\"%u\""
  544. ",\"UICERR\":\"%u\",\"FATALERR\":\"%u\",\"UTPERR\":\"%u\""
  545. ",\"QUERYERR\":\"%u\"\n",
  546. get_err_member(op_cnt).op_err,
  547. get_err_member(UIC_cmd_cnt).UIC_cmd_err,
  548. get_err_member(UIC_err_cnt).UIC_err,
  549. get_err_member(Fatal_err_cnt).Fatal_err,
  550. get_err_member(UTP_cnt).UTP_err,
  551. get_err_member(Query_cnt).Query_err);
  552. SEC_UFS_DATA_ATTR_RW(sense_err_count, "\"MEDIUM\":\"%u\",\"HWERR\":\"%u\"\n",
  553. get_err_member(sense_cnt).scsi_medium_err,
  554. get_err_member(sense_cnt).scsi_hw_err);
  555. /* accumulated err sum */
  556. SEC_UFS_DATA_ATTR_RO(SEC_UFS_err_summary,
  557. "OPERR : %u, UICCMD : %u, UICERR : %u, FATALERR : %u"
  558. ", UTPERR : %u, QUERYERR : %u\n"
  559. "MEDIUM : %u, HWERR : %u\n",
  560. SEC_UFS_ERR_INFO_GET_VALUE(op_cnt, op_err),
  561. SEC_UFS_ERR_INFO_GET_VALUE(UIC_cmd_cnt, UIC_cmd_err),
  562. SEC_UFS_ERR_INFO_GET_VALUE(UIC_err_cnt, UIC_err),
  563. SEC_UFS_ERR_INFO_GET_VALUE(Fatal_err_cnt, Fatal_err),
  564. SEC_UFS_ERR_INFO_GET_VALUE(UTP_cnt, UTP_err),
  565. SEC_UFS_ERR_INFO_GET_VALUE(Query_cnt, Query_err),
  566. SEC_UFS_ERR_INFO_GET_VALUE(sense_cnt, scsi_medium_err),
  567. SEC_UFS_ERR_INFO_GET_VALUE(sense_cnt, scsi_hw_err));
  568. static struct attribute *sec_ufs_error_attributes[] = {
  569. &dev_attr_SEC_UFS_op_cnt.attr,
  570. &dev_attr_SEC_UFS_uic_cmd_cnt.attr,
  571. &dev_attr_SEC_UFS_uic_err_cnt.attr,
  572. &dev_attr_SEC_UFS_fatal_cnt.attr,
  573. &dev_attr_SEC_UFS_utp_cnt.attr,
  574. &dev_attr_SEC_UFS_query_cnt.attr,
  575. &dev_attr_SEC_UFS_err_sum.attr,
  576. &dev_attr_sense_err_count.attr,
  577. &dev_attr_SEC_UFS_err_summary.attr,
  578. &dev_attr_SEC_UFS_TW_info.attr,
  579. &dev_attr_SEC_UFS_s_info.attr,
  580. NULL
  581. };
  582. static struct attribute_group sec_ufs_error_attribute_group = {
  583. .attrs = sec_ufs_error_attributes,
  584. };
  585. /* SEC error info : end */
  586. /* SEC cmd log : begin */
  587. static ssize_t ufs_sec_cmd_log_show(struct device *dev,
  588. struct device_attribute *attr, char *buf)
  589. {
  590. struct ufs_sec_cmd_log_info *ufs_cmd_log =
  591. ufs_sec_features.ufs_cmd_log;
  592. struct ufs_sec_cmd_log_entry *entry = NULL;
  593. int i = (ufs_cmd_log->pos + UFS_SEC_CMD_LOGGING_MAX
  594. - UFS_SEC_CMD_LOGNODE_MAX);
  595. int idx = 0;
  596. int len = 0;
  597. len += snprintf(buf + len, PAGE_SIZE - len,
  598. "%2s: %10s: %2s %3s %4s %9s %6s %16s\n",
  599. "No", "log string", "lu", "tag",
  600. "c_id", "lba", "length", "time");
  601. for (idx = 0; idx < UFS_SEC_CMD_LOGNODE_MAX; idx++, i++) {
  602. i %= UFS_SEC_CMD_LOGGING_MAX;
  603. entry = &ufs_cmd_log->entries[i];
  604. len += snprintf(buf + len, PAGE_SIZE - len,
  605. "%2d: %10s: %2d %3d 0x%02x %9u %6d %16llu\n",
  606. idx,
  607. entry->str, entry->lun, entry->tag,
  608. entry->cmd_id, entry->lba,
  609. entry->transfer_len, entry->tstamp);
  610. }
  611. return len;
  612. }
  613. static DEVICE_ATTR(cmd_log, 0440, ufs_sec_cmd_log_show, NULL);
  614. static struct attribute *sec_ufs_cmd_log_attributes[] = {
  615. &dev_attr_cmd_log.attr,
  616. NULL
  617. };
  618. static struct attribute_group sec_ufs_cmd_log_attribute_group = {
  619. .attrs = sec_ufs_cmd_log_attributes,
  620. };
  621. /* SEC cmd log : end */
  622. static int ufs_sec_create_sysfs_dev(struct ufs_hba *hba)
  623. {
  624. /* sec specific vendor sysfs nodes */
  625. if (!sec_ufs_node_dev) {
  626. #if IS_ENABLED(CONFIG_DRV_SAMSUNG)
  627. sec_ufs_node_dev = sec_device_create(hba, "ufs");
  628. #else
  629. pr_err("Fail to create dev node\n");
  630. #endif
  631. }
  632. if (IS_ERR(sec_ufs_node_dev)) {
  633. pr_err("Fail to create sysfs dev\n");
  634. return -ENODEV;
  635. }
  636. return 0;
  637. }
  638. static void ufs_sec_create_sysfs_group(struct ufs_hba *hba, struct device **dev,
  639. const struct attribute_group *dev_attr_group, const char *group_name)
  640. {
  641. int ret = 0;
  642. ret = sysfs_create_group(&(*dev)->kobj, dev_attr_group);
  643. if (ret)
  644. dev_err(hba->dev, "%s: Failed to create %s sysfs group (err = %d)\n",
  645. __func__, group_name, ret);
  646. }
  647. void ufs_sec_add_sysfs_nodes(struct ufs_hba *hba)
  648. {
  649. struct device *shost_dev = &(hba->host->shost_dev);
  650. if (ufs_sec_is_err_cnt_allowed())
  651. ufs_sec_create_sysfs_group(hba, &shost_dev,
  652. &sec_ufs_error_attribute_group, "sec_ufs_err");
  653. if (!ufs_sec_create_sysfs_dev(hba)) {
  654. ufs_sec_create_sysfs_group(hba, &sec_ufs_node_dev,
  655. &sec_ufs_info_attribute_group, "sec_ufs_info");
  656. if (ufs_sec_features.ufs_cmd_log)
  657. ufs_sec_create_sysfs_group(hba, &sec_ufs_node_dev,
  658. &sec_ufs_cmd_log_attribute_group,
  659. "sec_ufs_cmd_log");
  660. }
  661. }
  662. void ufs_sec_remove_sysfs_nodes(struct ufs_hba *hba)
  663. {
  664. struct device *shost_dev = &(hba->host->shost_dev);
  665. if (sec_ufs_node_dev) {
  666. sysfs_remove_group(&sec_ufs_node_dev->kobj,
  667. &sec_ufs_info_attribute_group);
  668. sysfs_remove_group(&sec_ufs_node_dev->kobj,
  669. &sec_ufs_cmd_log_attribute_group);
  670. }
  671. if (shost_dev)
  672. sysfs_remove_group(&shost_dev->kobj,
  673. &sec_ufs_error_attribute_group);
  674. }