mem.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright(c) 2022 Intel Corporation. All rights reserved. */
  3. #include <linux/debugfs.h>
  4. #include <linux/device.h>
  5. #include <linux/module.h>
  6. #include <linux/pci.h>
  7. #include "cxlmem.h"
  8. #include "cxlpci.h"
  9. /**
  10. * DOC: cxl mem
  11. *
  12. * CXL memory endpoint devices and switches are CXL capable devices that are
  13. * participating in CXL.mem protocol. Their functionality builds on top of the
  14. * CXL.io protocol that allows enumerating and configuring components via
  15. * standard PCI mechanisms.
  16. *
  17. * The cxl_mem driver owns kicking off the enumeration of this CXL.mem
  18. * capability. With the detection of a CXL capable endpoint, the driver will
  19. * walk up to find the platform specific port it is connected to, and determine
  20. * if there are intervening switches in the path. If there are switches, a
  21. * secondary action is to enumerate those (implemented in cxl_core). Finally the
  22. * cxl_mem driver adds the device it is bound to as a CXL endpoint-port for use
  23. * in higher level operations.
  24. */
  25. static void enable_suspend(void *data)
  26. {
  27. cxl_mem_active_dec();
  28. }
  29. static void remove_debugfs(void *dentry)
  30. {
  31. debugfs_remove_recursive(dentry);
  32. }
  33. static int cxl_mem_dpa_show(struct seq_file *file, void *data)
  34. {
  35. struct device *dev = file->private;
  36. struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
  37. cxl_dpa_debug(file, cxlmd->cxlds);
  38. return 0;
  39. }
  40. static int cxl_debugfs_poison_inject(void *data, u64 dpa)
  41. {
  42. struct cxl_memdev *cxlmd = data;
  43. return cxl_inject_poison(cxlmd, dpa);
  44. }
  45. DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_inject_fops, NULL,
  46. cxl_debugfs_poison_inject, "%llx\n");
  47. static int cxl_debugfs_poison_clear(void *data, u64 dpa)
  48. {
  49. struct cxl_memdev *cxlmd = data;
  50. return cxl_clear_poison(cxlmd, dpa);
  51. }
  52. DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_clear_fops, NULL,
  53. cxl_debugfs_poison_clear, "%llx\n");
  54. static int cxl_mem_probe(struct device *dev)
  55. {
  56. struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
  57. struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
  58. struct cxl_dev_state *cxlds = cxlmd->cxlds;
  59. struct device *endpoint_parent;
  60. struct cxl_dport *dport;
  61. struct dentry *dentry;
  62. int rc;
  63. if (!cxlds->media_ready)
  64. return -EBUSY;
  65. /*
  66. * Someone is trying to reattach this device after it lost its port
  67. * connection (an endpoint port previously registered by this memdev was
  68. * disabled). This racy check is ok because if the port is still gone,
  69. * no harm done, and if the port hierarchy comes back it will re-trigger
  70. * this probe. Port rescan and memdev detach work share the same
  71. * single-threaded workqueue.
  72. */
  73. if (work_pending(&cxlmd->detach_work))
  74. return -EBUSY;
  75. dentry = cxl_debugfs_create_dir(dev_name(dev));
  76. debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show);
  77. if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds))
  78. debugfs_create_file("inject_poison", 0200, dentry, cxlmd,
  79. &cxl_poison_inject_fops);
  80. if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds))
  81. debugfs_create_file("clear_poison", 0200, dentry, cxlmd,
  82. &cxl_poison_clear_fops);
  83. rc = devm_add_action_or_reset(dev, remove_debugfs, dentry);
  84. if (rc)
  85. return rc;
  86. rc = devm_cxl_enumerate_ports(cxlmd);
  87. if (rc)
  88. return rc;
  89. struct cxl_port *parent_port __free(put_cxl_port) =
  90. cxl_mem_find_port(cxlmd, &dport);
  91. if (!parent_port) {
  92. dev_err(dev, "CXL port topology not found\n");
  93. return -ENXIO;
  94. }
  95. if (cxl_pmem_size(cxlds) && IS_ENABLED(CONFIG_CXL_PMEM)) {
  96. rc = devm_cxl_add_nvdimm(dev, parent_port, cxlmd);
  97. if (rc) {
  98. if (rc == -ENODEV)
  99. dev_info(dev, "PMEM disabled by platform\n");
  100. return rc;
  101. }
  102. }
  103. if (dport->rch)
  104. endpoint_parent = parent_port->uport_dev;
  105. else
  106. endpoint_parent = &parent_port->dev;
  107. scoped_guard(device, endpoint_parent) {
  108. if (!endpoint_parent->driver) {
  109. dev_err(dev, "CXL port topology %s not enabled\n",
  110. dev_name(endpoint_parent));
  111. return -ENXIO;
  112. }
  113. rc = devm_cxl_add_endpoint(endpoint_parent, cxlmd, dport);
  114. if (rc)
  115. return rc;
  116. }
  117. if (cxlmd->attach) {
  118. rc = cxlmd->attach->probe(cxlmd);
  119. if (rc)
  120. return rc;
  121. }
  122. rc = devm_cxl_memdev_edac_register(cxlmd);
  123. if (rc)
  124. dev_dbg(dev, "CXL memdev EDAC registration failed rc=%d\n", rc);
  125. /*
  126. * The kernel may be operating out of CXL memory on this device,
  127. * there is no spec defined way to determine whether this device
  128. * preserves contents over suspend, and there is no simple way
  129. * to arrange for the suspend image to avoid CXL memory which
  130. * would setup a circular dependency between PCI resume and save
  131. * state restoration.
  132. *
  133. * TODO: support suspend when all the regions this device is
  134. * hosting are locked and covered by the system address map,
  135. * i.e. platform firmware owns restoring the HDM configuration
  136. * that it locked.
  137. */
  138. cxl_mem_active_inc();
  139. return devm_add_action_or_reset(dev, enable_suspend, NULL);
  140. }
  141. /**
  142. * devm_cxl_add_memdev - Add a CXL memory device
  143. * @cxlds: CXL device state to associate with the memdev
  144. * @attach: Caller depends on CXL topology attachment
  145. *
  146. * Upon return the device will have had a chance to attach to the
  147. * cxl_mem driver, but may fail to attach if the CXL topology is not ready
  148. * (hardware CXL link down, or software platform CXL root not attached).
  149. *
  150. * When @attach is NULL it indicates the caller wants the memdev to remain
  151. * registered even if it does not immediately attach to the CXL hierarchy. When
  152. * @attach is provided a cxl_mem_probe() failure leads to failure of this routine.
  153. *
  154. * The parent of the resulting device and the devm context for allocations is
  155. * @cxlds->dev.
  156. */
  157. struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds,
  158. const struct cxl_memdev_attach *attach)
  159. {
  160. return __devm_cxl_add_memdev(cxlds, attach);
  161. }
  162. EXPORT_SYMBOL_NS_GPL(devm_cxl_add_memdev, "CXL");
  163. static ssize_t trigger_poison_list_store(struct device *dev,
  164. struct device_attribute *attr,
  165. const char *buf, size_t len)
  166. {
  167. bool trigger;
  168. int rc;
  169. if (kstrtobool(buf, &trigger) || !trigger)
  170. return -EINVAL;
  171. rc = cxl_trigger_poison_list(to_cxl_memdev(dev));
  172. return rc ? rc : len;
  173. }
  174. static DEVICE_ATTR_WO(trigger_poison_list);
  175. static umode_t cxl_mem_visible(struct kobject *kobj, struct attribute *a, int n)
  176. {
  177. struct device *dev = kobj_to_dev(kobj);
  178. struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
  179. struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
  180. if (a == &dev_attr_trigger_poison_list.attr)
  181. if (!test_bit(CXL_POISON_ENABLED_LIST,
  182. mds->poison.enabled_cmds))
  183. return 0;
  184. return a->mode;
  185. }
  186. static struct attribute *cxl_mem_attrs[] = {
  187. &dev_attr_trigger_poison_list.attr,
  188. NULL
  189. };
  190. static struct attribute_group cxl_mem_group = {
  191. .attrs = cxl_mem_attrs,
  192. .is_visible = cxl_mem_visible,
  193. };
  194. __ATTRIBUTE_GROUPS(cxl_mem);
  195. static struct cxl_driver cxl_mem_driver = {
  196. .name = "cxl_mem",
  197. .probe = cxl_mem_probe,
  198. .id = CXL_DEVICE_MEMORY_EXPANDER,
  199. .drv = {
  200. .probe_type = PROBE_FORCE_SYNCHRONOUS,
  201. .dev_groups = cxl_mem_groups,
  202. },
  203. };
  204. module_cxl_driver(cxl_mem_driver);
  205. MODULE_DESCRIPTION("CXL: Memory Expansion");
  206. MODULE_LICENSE("GPL v2");
  207. MODULE_IMPORT_NS("CXL");
  208. MODULE_ALIAS_CXL(CXL_DEVICE_MEMORY_EXPANDER);