mem_repair.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * The generic EDAC memory repair driver is designed to control the memory
  4. * devices with memory repair features, such as Post Package Repair (PPR),
  5. * memory sparing etc. The common sysfs memory repair interface abstracts
  6. * the control of various arbitrary memory repair functionalities into a
  7. * unified set of functions.
  8. *
  9. * Copyright (c) 2024-2025 HiSilicon Limited.
  10. */
  11. #include <linux/edac.h>
  12. enum edac_mem_repair_attributes {
  13. MR_TYPE,
  14. MR_PERSIST_MODE,
  15. MR_SAFE_IN_USE,
  16. MR_HPA,
  17. MR_MIN_HPA,
  18. MR_MAX_HPA,
  19. MR_DPA,
  20. MR_MIN_DPA,
  21. MR_MAX_DPA,
  22. MR_NIBBLE_MASK,
  23. MR_BANK_GROUP,
  24. MR_BANK,
  25. MR_RANK,
  26. MR_ROW,
  27. MR_COLUMN,
  28. MR_CHANNEL,
  29. MR_SUB_CHANNEL,
  30. MEM_DO_REPAIR,
  31. MR_MAX_ATTRS
  32. };
  33. struct edac_mem_repair_dev_attr {
  34. struct device_attribute dev_attr;
  35. u8 instance;
  36. };
  37. struct edac_mem_repair_context {
  38. char name[EDAC_FEAT_NAME_LEN];
  39. struct edac_mem_repair_dev_attr mem_repair_dev_attr[MR_MAX_ATTRS];
  40. struct attribute *mem_repair_attrs[MR_MAX_ATTRS + 1];
  41. struct attribute_group group;
  42. };
  43. const char * const edac_repair_type[] = {
  44. [EDAC_REPAIR_PPR] = "ppr",
  45. [EDAC_REPAIR_CACHELINE_SPARING] = "cacheline-sparing",
  46. [EDAC_REPAIR_ROW_SPARING] = "row-sparing",
  47. [EDAC_REPAIR_BANK_SPARING] = "bank-sparing",
  48. [EDAC_REPAIR_RANK_SPARING] = "rank-sparing",
  49. };
  50. EXPORT_SYMBOL_GPL(edac_repair_type);
  51. #define TO_MR_DEV_ATTR(_dev_attr) \
  52. container_of(_dev_attr, struct edac_mem_repair_dev_attr, dev_attr)
  53. #define MR_ATTR_SHOW(attrib, cb, type, format) \
  54. static ssize_t attrib##_show(struct device *ras_feat_dev, \
  55. struct device_attribute *attr, char *buf) \
  56. { \
  57. u8 inst = TO_MR_DEV_ATTR(attr)->instance; \
  58. struct edac_dev_feat_ctx *ctx = dev_get_drvdata(ras_feat_dev); \
  59. const struct edac_mem_repair_ops *ops = \
  60. ctx->mem_repair[inst].mem_repair_ops; \
  61. type data; \
  62. int ret; \
  63. \
  64. ret = ops->cb(ras_feat_dev->parent, ctx->mem_repair[inst].private, \
  65. &data); \
  66. if (ret) \
  67. return ret; \
  68. \
  69. return sysfs_emit(buf, format, data); \
  70. }
  71. MR_ATTR_SHOW(repair_type, get_repair_type, const char *, "%s\n")
  72. MR_ATTR_SHOW(persist_mode, get_persist_mode, bool, "%u\n")
  73. MR_ATTR_SHOW(repair_safe_when_in_use, get_repair_safe_when_in_use, bool, "%u\n")
  74. MR_ATTR_SHOW(hpa, get_hpa, u64, "0x%llx\n")
  75. MR_ATTR_SHOW(min_hpa, get_min_hpa, u64, "0x%llx\n")
  76. MR_ATTR_SHOW(max_hpa, get_max_hpa, u64, "0x%llx\n")
  77. MR_ATTR_SHOW(dpa, get_dpa, u64, "0x%llx\n")
  78. MR_ATTR_SHOW(min_dpa, get_min_dpa, u64, "0x%llx\n")
  79. MR_ATTR_SHOW(max_dpa, get_max_dpa, u64, "0x%llx\n")
  80. MR_ATTR_SHOW(nibble_mask, get_nibble_mask, u32, "0x%x\n")
  81. MR_ATTR_SHOW(bank_group, get_bank_group, u32, "%u\n")
  82. MR_ATTR_SHOW(bank, get_bank, u32, "%u\n")
  83. MR_ATTR_SHOW(rank, get_rank, u32, "%u\n")
  84. MR_ATTR_SHOW(row, get_row, u32, "0x%x\n")
  85. MR_ATTR_SHOW(column, get_column, u32, "%u\n")
  86. MR_ATTR_SHOW(channel, get_channel, u32, "%u\n")
  87. MR_ATTR_SHOW(sub_channel, get_sub_channel, u32, "%u\n")
  88. #define MR_ATTR_STORE(attrib, cb, type, conv_func) \
  89. static ssize_t attrib##_store(struct device *ras_feat_dev, \
  90. struct device_attribute *attr, \
  91. const char *buf, size_t len) \
  92. { \
  93. u8 inst = TO_MR_DEV_ATTR(attr)->instance; \
  94. struct edac_dev_feat_ctx *ctx = dev_get_drvdata(ras_feat_dev); \
  95. const struct edac_mem_repair_ops *ops = \
  96. ctx->mem_repair[inst].mem_repair_ops; \
  97. type data; \
  98. int ret; \
  99. \
  100. ret = conv_func(buf, 0, &data); \
  101. if (ret < 0) \
  102. return ret; \
  103. \
  104. ret = ops->cb(ras_feat_dev->parent, ctx->mem_repair[inst].private, \
  105. data); \
  106. if (ret) \
  107. return ret; \
  108. \
  109. return len; \
  110. }
  111. MR_ATTR_STORE(persist_mode, set_persist_mode, unsigned long, kstrtoul)
  112. MR_ATTR_STORE(hpa, set_hpa, u64, kstrtou64)
  113. MR_ATTR_STORE(dpa, set_dpa, u64, kstrtou64)
  114. MR_ATTR_STORE(nibble_mask, set_nibble_mask, unsigned long, kstrtoul)
  115. MR_ATTR_STORE(bank_group, set_bank_group, unsigned long, kstrtoul)
  116. MR_ATTR_STORE(bank, set_bank, unsigned long, kstrtoul)
  117. MR_ATTR_STORE(rank, set_rank, unsigned long, kstrtoul)
  118. MR_ATTR_STORE(row, set_row, unsigned long, kstrtoul)
  119. MR_ATTR_STORE(column, set_column, unsigned long, kstrtoul)
  120. MR_ATTR_STORE(channel, set_channel, unsigned long, kstrtoul)
  121. MR_ATTR_STORE(sub_channel, set_sub_channel, unsigned long, kstrtoul)
  122. #define MR_DO_OP(attrib, cb) \
  123. static ssize_t attrib##_store(struct device *ras_feat_dev, \
  124. struct device_attribute *attr, \
  125. const char *buf, size_t len) \
  126. { \
  127. u8 inst = TO_MR_DEV_ATTR(attr)->instance; \
  128. struct edac_dev_feat_ctx *ctx = dev_get_drvdata(ras_feat_dev); \
  129. const struct edac_mem_repair_ops *ops = ctx->mem_repair[inst].mem_repair_ops; \
  130. unsigned long data; \
  131. int ret; \
  132. \
  133. ret = kstrtoul(buf, 0, &data); \
  134. if (ret < 0) \
  135. return ret; \
  136. \
  137. ret = ops->cb(ras_feat_dev->parent, ctx->mem_repair[inst].private, data); \
  138. if (ret) \
  139. return ret; \
  140. \
  141. return len; \
  142. }
  143. MR_DO_OP(repair, do_repair)
  144. static umode_t mem_repair_attr_visible(struct kobject *kobj, struct attribute *a, int attr_id)
  145. {
  146. struct device *ras_feat_dev = kobj_to_dev(kobj);
  147. struct device_attribute *dev_attr = container_of(a, struct device_attribute, attr);
  148. struct edac_dev_feat_ctx *ctx = dev_get_drvdata(ras_feat_dev);
  149. u8 inst = TO_MR_DEV_ATTR(dev_attr)->instance;
  150. const struct edac_mem_repair_ops *ops = ctx->mem_repair[inst].mem_repair_ops;
  151. switch (attr_id) {
  152. case MR_TYPE:
  153. if (ops->get_repair_type)
  154. return a->mode;
  155. break;
  156. case MR_PERSIST_MODE:
  157. if (ops->get_persist_mode) {
  158. if (ops->set_persist_mode)
  159. return a->mode;
  160. else
  161. return 0444;
  162. }
  163. break;
  164. case MR_SAFE_IN_USE:
  165. if (ops->get_repair_safe_when_in_use)
  166. return a->mode;
  167. break;
  168. case MR_HPA:
  169. if (ops->get_hpa) {
  170. if (ops->set_hpa)
  171. return a->mode;
  172. else
  173. return 0444;
  174. }
  175. break;
  176. case MR_MIN_HPA:
  177. if (ops->get_min_hpa)
  178. return a->mode;
  179. break;
  180. case MR_MAX_HPA:
  181. if (ops->get_max_hpa)
  182. return a->mode;
  183. break;
  184. case MR_DPA:
  185. if (ops->get_dpa) {
  186. if (ops->set_dpa)
  187. return a->mode;
  188. else
  189. return 0444;
  190. }
  191. break;
  192. case MR_MIN_DPA:
  193. if (ops->get_min_dpa)
  194. return a->mode;
  195. break;
  196. case MR_MAX_DPA:
  197. if (ops->get_max_dpa)
  198. return a->mode;
  199. break;
  200. case MR_NIBBLE_MASK:
  201. if (ops->get_nibble_mask) {
  202. if (ops->set_nibble_mask)
  203. return a->mode;
  204. else
  205. return 0444;
  206. }
  207. break;
  208. case MR_BANK_GROUP:
  209. if (ops->get_bank_group) {
  210. if (ops->set_bank_group)
  211. return a->mode;
  212. else
  213. return 0444;
  214. }
  215. break;
  216. case MR_BANK:
  217. if (ops->get_bank) {
  218. if (ops->set_bank)
  219. return a->mode;
  220. else
  221. return 0444;
  222. }
  223. break;
  224. case MR_RANK:
  225. if (ops->get_rank) {
  226. if (ops->set_rank)
  227. return a->mode;
  228. else
  229. return 0444;
  230. }
  231. break;
  232. case MR_ROW:
  233. if (ops->get_row) {
  234. if (ops->set_row)
  235. return a->mode;
  236. else
  237. return 0444;
  238. }
  239. break;
  240. case MR_COLUMN:
  241. if (ops->get_column) {
  242. if (ops->set_column)
  243. return a->mode;
  244. else
  245. return 0444;
  246. }
  247. break;
  248. case MR_CHANNEL:
  249. if (ops->get_channel) {
  250. if (ops->set_channel)
  251. return a->mode;
  252. else
  253. return 0444;
  254. }
  255. break;
  256. case MR_SUB_CHANNEL:
  257. if (ops->get_sub_channel) {
  258. if (ops->set_sub_channel)
  259. return a->mode;
  260. else
  261. return 0444;
  262. }
  263. break;
  264. case MEM_DO_REPAIR:
  265. if (ops->do_repair)
  266. return a->mode;
  267. break;
  268. default:
  269. break;
  270. }
  271. return 0;
  272. }
  273. static const struct device_attribute mem_repair_dev_attr[] = {
  274. [MR_TYPE] = __ATTR_RO(repair_type),
  275. [MR_PERSIST_MODE] = __ATTR_RW(persist_mode),
  276. [MR_SAFE_IN_USE] = __ATTR_RO(repair_safe_when_in_use),
  277. [MR_HPA] = __ATTR_RW(hpa),
  278. [MR_MIN_HPA] = __ATTR_RO(min_hpa),
  279. [MR_MAX_HPA] = __ATTR_RO(max_hpa),
  280. [MR_DPA] = __ATTR_RW(dpa),
  281. [MR_MIN_DPA] = __ATTR_RO(min_dpa),
  282. [MR_MAX_DPA] = __ATTR_RO(max_dpa),
  283. [MR_NIBBLE_MASK] = __ATTR_RW(nibble_mask),
  284. [MR_BANK_GROUP] = __ATTR_RW(bank_group),
  285. [MR_BANK] = __ATTR_RW(bank),
  286. [MR_RANK] = __ATTR_RW(rank),
  287. [MR_ROW] = __ATTR_RW(row),
  288. [MR_COLUMN] = __ATTR_RW(column),
  289. [MR_CHANNEL] = __ATTR_RW(channel),
  290. [MR_SUB_CHANNEL] = __ATTR_RW(sub_channel),
  291. [MEM_DO_REPAIR] = __ATTR_WO(repair)
  292. };
  293. static int mem_repair_create_desc(struct device *dev,
  294. const struct attribute_group **attr_groups,
  295. u8 instance)
  296. {
  297. struct edac_mem_repair_context *ctx;
  298. struct attribute_group *group;
  299. int i;
  300. ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
  301. if (!ctx)
  302. return -ENOMEM;
  303. for (i = 0; i < MR_MAX_ATTRS; i++) {
  304. ctx->mem_repair_dev_attr[i].dev_attr = mem_repair_dev_attr[i];
  305. ctx->mem_repair_dev_attr[i].instance = instance;
  306. sysfs_attr_init(&ctx->mem_repair_dev_attr[i].dev_attr.attr);
  307. ctx->mem_repair_attrs[i] =
  308. &ctx->mem_repair_dev_attr[i].dev_attr.attr;
  309. }
  310. sprintf(ctx->name, "%s%d", "mem_repair", instance);
  311. group = &ctx->group;
  312. group->name = ctx->name;
  313. group->attrs = ctx->mem_repair_attrs;
  314. group->is_visible = mem_repair_attr_visible;
  315. attr_groups[0] = group;
  316. return 0;
  317. }
  318. /**
  319. * edac_mem_repair_get_desc - get EDAC memory repair descriptors
  320. * @dev: client device with memory repair feature
  321. * @attr_groups: pointer to attribute group container
  322. * @instance: device's memory repair instance number.
  323. *
  324. * Return:
  325. * * %0 - Success.
  326. * * %-EINVAL - Invalid parameters passed.
  327. * * %-ENOMEM - Dynamic memory allocation failed.
  328. */
  329. int edac_mem_repair_get_desc(struct device *dev,
  330. const struct attribute_group **attr_groups, u8 instance)
  331. {
  332. if (!dev || !attr_groups)
  333. return -EINVAL;
  334. return mem_repair_create_desc(dev, attr_groups, instance);
  335. }