acpi.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright(c) 2021 Intel Corporation. All rights reserved. */
  3. #include <linux/platform_device.h>
  4. #include <linux/module.h>
  5. #include <linux/device.h>
  6. #include <linux/kernel.h>
  7. #include <linux/acpi.h>
  8. #include <linux/pci.h>
  9. #include <linux/node.h>
  10. #include <asm/div64.h>
  11. #include "cxlpci.h"
  12. #include "cxl.h"
  13. static const guid_t acpi_cxl_qtg_id_guid =
  14. GUID_INIT(0xF365F9A6, 0xA7DE, 0x4071,
  15. 0xA6, 0x6A, 0xB4, 0x0C, 0x0B, 0x4F, 0x8E, 0x52);
  16. #define HBIW_TO_NR_MAPS_SIZE (CXL_DECODER_MAX_INTERLEAVE + 1)
  17. static const int hbiw_to_nr_maps[HBIW_TO_NR_MAPS_SIZE] = {
  18. [1] = 0, [2] = 1, [3] = 0, [4] = 2, [6] = 1, [8] = 3, [12] = 2, [16] = 4
  19. };
  20. static const int valid_hbiw[] = { 1, 2, 3, 4, 6, 8, 12, 16 };
  21. u64 cxl_do_xormap_calc(struct cxl_cxims_data *cximsd, u64 addr, int hbiw)
  22. {
  23. int nr_maps_to_apply = -1;
  24. u64 val;
  25. int pos;
  26. /*
  27. * Strictly validate hbiw since this function is used for testing and
  28. * that nullifies any expectation of trusted parameters from the CXL
  29. * Region Driver.
  30. */
  31. for (int i = 0; i < ARRAY_SIZE(valid_hbiw); i++) {
  32. if (valid_hbiw[i] == hbiw) {
  33. nr_maps_to_apply = hbiw_to_nr_maps[hbiw];
  34. break;
  35. }
  36. }
  37. if (nr_maps_to_apply == -1 || nr_maps_to_apply > cximsd->nr_maps)
  38. return ULLONG_MAX;
  39. /*
  40. * In regions using XOR interleave arithmetic the CXL HPA may not
  41. * be the same as the SPA. This helper performs the SPA->CXL HPA
  42. * or the CXL HPA->SPA translation. Since XOR is self-inverting,
  43. * so is this function.
  44. *
  45. * For root decoders using xormaps (hbiw: 2,4,6,8,12,16) applying the
  46. * xormaps will toggle a position bit.
  47. *
  48. * pos is the lowest set bit in an XORMAP
  49. * val is the XORALLBITS(addr & XORMAP)
  50. *
  51. * XORALLBITS: The CXL spec (3.1 Table 9-22) defines XORALLBITS
  52. * as an operation that outputs a single bit by XORing all the
  53. * bits in the input (addr & xormap). Implement XORALLBITS using
  54. * hweight64(). If the hamming weight is even the XOR of those
  55. * bits results in val==0, if odd the XOR result is val==1.
  56. */
  57. for (int i = 0; i < cximsd->nr_maps; i++) {
  58. if (!cximsd->xormaps[i])
  59. continue;
  60. pos = __ffs(cximsd->xormaps[i]);
  61. val = (hweight64(addr & cximsd->xormaps[i]) & 1);
  62. addr = (addr & ~(1ULL << pos)) | (val << pos);
  63. }
  64. return addr;
  65. }
  66. EXPORT_SYMBOL_FOR_MODULES(cxl_do_xormap_calc, "cxl_translate");
  67. static u64 cxl_apply_xor_maps(struct cxl_root_decoder *cxlrd, u64 addr)
  68. {
  69. int hbiw = cxlrd->cxlsd.nr_targets;
  70. struct cxl_cxims_data *cximsd;
  71. /* No xormaps for host bridge interleave ways of 1 or 3 */
  72. if (hbiw == 1 || hbiw == 3)
  73. return addr;
  74. cximsd = cxlrd->platform_data;
  75. return cxl_do_xormap_calc(cximsd, addr, hbiw);
  76. }
  77. struct cxl_cxims_context {
  78. struct device *dev;
  79. struct cxl_root_decoder *cxlrd;
  80. };
  81. static int cxl_parse_cxims(union acpi_subtable_headers *header, void *arg,
  82. const unsigned long end)
  83. {
  84. struct acpi_cedt_cxims *cxims = (struct acpi_cedt_cxims *)header;
  85. struct cxl_cxims_context *ctx = arg;
  86. struct cxl_root_decoder *cxlrd = ctx->cxlrd;
  87. struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
  88. struct device *dev = ctx->dev;
  89. struct cxl_cxims_data *cximsd;
  90. unsigned int hbig, nr_maps;
  91. int rc;
  92. rc = eig_to_granularity(cxims->hbig, &hbig);
  93. if (rc)
  94. return rc;
  95. /* Does this CXIMS entry apply to the given CXL Window? */
  96. if (hbig != cxld->interleave_granularity)
  97. return 0;
  98. /* IW 1,3 do not use xormaps and skip this parsing entirely */
  99. if (is_power_of_2(cxld->interleave_ways))
  100. /* 2, 4, 8, 16 way */
  101. nr_maps = ilog2(cxld->interleave_ways);
  102. else
  103. /* 6, 12 way */
  104. nr_maps = ilog2(cxld->interleave_ways / 3);
  105. if (cxims->nr_xormaps < nr_maps) {
  106. dev_dbg(dev, "CXIMS nr_xormaps[%d] expected[%d]\n",
  107. cxims->nr_xormaps, nr_maps);
  108. return -ENXIO;
  109. }
  110. cximsd = devm_kzalloc(dev, struct_size(cximsd, xormaps, nr_maps),
  111. GFP_KERNEL);
  112. if (!cximsd)
  113. return -ENOMEM;
  114. cximsd->nr_maps = nr_maps;
  115. memcpy(cximsd->xormaps, cxims->xormap_list,
  116. nr_maps * sizeof(*cximsd->xormaps));
  117. cxlrd->platform_data = cximsd;
  118. return 0;
  119. }
  120. static unsigned long cfmws_to_decoder_flags(int restrictions)
  121. {
  122. unsigned long flags = CXL_DECODER_F_ENABLE;
  123. if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_DEVMEM)
  124. flags |= CXL_DECODER_F_TYPE2;
  125. if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM)
  126. flags |= CXL_DECODER_F_TYPE3;
  127. if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_VOLATILE)
  128. flags |= CXL_DECODER_F_RAM;
  129. if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_PMEM)
  130. flags |= CXL_DECODER_F_PMEM;
  131. if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_FIXED)
  132. flags |= CXL_DECODER_F_LOCK;
  133. return flags;
  134. }
  135. static int cxl_acpi_cfmws_verify(struct device *dev,
  136. struct acpi_cedt_cfmws *cfmws)
  137. {
  138. int rc, expected_len;
  139. unsigned int ways;
  140. if (cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_MODULO &&
  141. cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_XOR) {
  142. dev_err(dev, "CFMWS Unknown Interleave Arithmetic: %d\n",
  143. cfmws->interleave_arithmetic);
  144. return -EINVAL;
  145. }
  146. if (!IS_ALIGNED(cfmws->base_hpa, SZ_256M)) {
  147. dev_err(dev, "CFMWS Base HPA not 256MB aligned\n");
  148. return -EINVAL;
  149. }
  150. if (!IS_ALIGNED(cfmws->window_size, SZ_256M)) {
  151. dev_err(dev, "CFMWS Window Size not 256MB aligned\n");
  152. return -EINVAL;
  153. }
  154. rc = eiw_to_ways(cfmws->interleave_ways, &ways);
  155. if (rc) {
  156. dev_err(dev, "CFMWS Interleave Ways (%d) invalid\n",
  157. cfmws->interleave_ways);
  158. return -EINVAL;
  159. }
  160. expected_len = struct_size(cfmws, interleave_targets, ways);
  161. if (cfmws->header.length < expected_len) {
  162. dev_err(dev, "CFMWS length %d less than expected %d\n",
  163. cfmws->header.length, expected_len);
  164. return -EINVAL;
  165. }
  166. if (cfmws->header.length > expected_len)
  167. dev_dbg(dev, "CFMWS length %d greater than expected %d\n",
  168. cfmws->header.length, expected_len);
  169. return 0;
  170. }
  171. /*
  172. * Note, @dev must be the first member, see 'struct cxl_chbs_context'
  173. * and mock_acpi_table_parse_cedt()
  174. */
  175. struct cxl_cfmws_context {
  176. struct device *dev;
  177. struct cxl_port *root_port;
  178. struct resource *cxl_res;
  179. int id;
  180. };
  181. /**
  182. * cxl_acpi_evaluate_qtg_dsm - Retrieve QTG ids via ACPI _DSM
  183. * @handle: ACPI handle
  184. * @coord: performance access coordinates
  185. * @entries: number of QTG IDs to return
  186. * @qos_class: int array provided by caller to return QTG IDs
  187. *
  188. * Return: number of QTG IDs returned, or -errno for errors
  189. *
  190. * Issue QTG _DSM with accompanied bandwidth and latency data in order to get
  191. * the QTG IDs that are suitable for the performance point in order of most
  192. * suitable to least suitable. Write back array of QTG IDs and return the
  193. * actual number of QTG IDs written back.
  194. */
  195. static int
  196. cxl_acpi_evaluate_qtg_dsm(acpi_handle handle, struct access_coordinate *coord,
  197. int entries, int *qos_class)
  198. {
  199. union acpi_object *out_obj, *out_buf, *obj;
  200. union acpi_object in_array[4] = {
  201. [0].integer = { ACPI_TYPE_INTEGER, coord->read_latency },
  202. [1].integer = { ACPI_TYPE_INTEGER, coord->write_latency },
  203. [2].integer = { ACPI_TYPE_INTEGER, coord->read_bandwidth },
  204. [3].integer = { ACPI_TYPE_INTEGER, coord->write_bandwidth },
  205. };
  206. union acpi_object in_obj = {
  207. .package = {
  208. .type = ACPI_TYPE_PACKAGE,
  209. .count = 4,
  210. .elements = in_array,
  211. },
  212. };
  213. int count, pkg_entries, i;
  214. u16 max_qtg;
  215. int rc;
  216. if (!entries)
  217. return -EINVAL;
  218. out_obj = acpi_evaluate_dsm(handle, &acpi_cxl_qtg_id_guid, 1, 1, &in_obj);
  219. if (!out_obj)
  220. return -ENXIO;
  221. if (out_obj->type != ACPI_TYPE_PACKAGE) {
  222. rc = -ENXIO;
  223. goto out;
  224. }
  225. /* Check Max QTG ID */
  226. obj = &out_obj->package.elements[0];
  227. if (obj->type != ACPI_TYPE_INTEGER) {
  228. rc = -ENXIO;
  229. goto out;
  230. }
  231. max_qtg = obj->integer.value;
  232. /* It's legal to have 0 QTG entries */
  233. pkg_entries = out_obj->package.count;
  234. if (pkg_entries <= 1) {
  235. rc = 0;
  236. goto out;
  237. }
  238. /* Retrieve QTG IDs package */
  239. obj = &out_obj->package.elements[1];
  240. if (obj->type != ACPI_TYPE_PACKAGE) {
  241. rc = -ENXIO;
  242. goto out;
  243. }
  244. pkg_entries = obj->package.count;
  245. count = min(entries, pkg_entries);
  246. for (i = 0; i < count; i++) {
  247. u16 qtg_id;
  248. out_buf = &obj->package.elements[i];
  249. if (out_buf->type != ACPI_TYPE_INTEGER) {
  250. rc = -ENXIO;
  251. goto out;
  252. }
  253. qtg_id = out_buf->integer.value;
  254. if (qtg_id > max_qtg)
  255. pr_warn("QTG ID %u greater than MAX %u\n",
  256. qtg_id, max_qtg);
  257. qos_class[i] = qtg_id;
  258. }
  259. rc = count;
  260. out:
  261. ACPI_FREE(out_obj);
  262. return rc;
  263. }
  264. static int cxl_acpi_qos_class(struct cxl_root *cxl_root,
  265. struct access_coordinate *coord, int entries,
  266. int *qos_class)
  267. {
  268. struct device *dev = cxl_root->port.uport_dev;
  269. acpi_handle handle;
  270. if (!dev_is_platform(dev))
  271. return -ENODEV;
  272. handle = ACPI_HANDLE(dev);
  273. if (!handle)
  274. return -ENODEV;
  275. return cxl_acpi_evaluate_qtg_dsm(handle, coord, entries, qos_class);
  276. }
  277. static void del_cxl_resource(struct resource *res)
  278. {
  279. if (!res)
  280. return;
  281. kfree(res->name);
  282. kfree(res);
  283. }
  284. static struct resource *alloc_cxl_resource(resource_size_t base,
  285. resource_size_t n, int id)
  286. {
  287. struct resource *res __free(kfree) = kzalloc_obj(*res);
  288. if (!res)
  289. return NULL;
  290. res->start = base;
  291. res->end = base + n - 1;
  292. res->flags = IORESOURCE_MEM;
  293. res->name = kasprintf(GFP_KERNEL, "CXL Window %d", id);
  294. if (!res->name)
  295. return NULL;
  296. return no_free_ptr(res);
  297. }
  298. static int add_or_reset_cxl_resource(struct resource *parent, struct resource *res)
  299. {
  300. int rc = insert_resource(parent, res);
  301. if (rc)
  302. del_cxl_resource(res);
  303. return rc;
  304. }
  305. static void cxl_setup_extended_linear_cache(struct cxl_root_decoder *cxlrd)
  306. {
  307. struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
  308. struct range *hpa = &cxld->hpa_range;
  309. resource_size_t size = range_len(hpa);
  310. resource_size_t start = hpa->start;
  311. resource_size_t cache_size;
  312. struct resource res;
  313. int nid, rc;
  314. /* Explicitly initialize cache size to 0 at the beginning */
  315. cxlrd->cache_size = 0;
  316. res = DEFINE_RES_MEM(start, size);
  317. nid = phys_to_target_node(start);
  318. rc = hmat_get_extended_linear_cache_size(&res, nid, &cache_size);
  319. if (rc)
  320. return;
  321. /*
  322. * The cache range is expected to be within the CFMWS.
  323. * Currently there is only support cache_size == cxl_size. CXL
  324. * size is then half of the total CFMWS window size.
  325. */
  326. size = size >> 1;
  327. if (cache_size && size != cache_size) {
  328. dev_warn(&cxld->dev,
  329. "Extended Linear Cache size %pa != CXL size %pa. No Support!",
  330. &cache_size, &size);
  331. return;
  332. }
  333. cxlrd->cache_size = cache_size;
  334. }
  335. DEFINE_FREE(put_cxlrd, struct cxl_root_decoder *,
  336. if (!IS_ERR_OR_NULL(_T)) put_device(&_T->cxlsd.cxld.dev))
  337. DEFINE_FREE(del_cxl_resource, struct resource *, if (_T) del_cxl_resource(_T))
  338. static int __cxl_parse_cfmws(struct acpi_cedt_cfmws *cfmws,
  339. struct cxl_cfmws_context *ctx)
  340. {
  341. struct cxl_port *root_port = ctx->root_port;
  342. struct cxl_cxims_context cxims_ctx;
  343. struct device *dev = ctx->dev;
  344. struct cxl_decoder *cxld;
  345. unsigned int ways, i, ig;
  346. int rc;
  347. rc = cxl_acpi_cfmws_verify(dev, cfmws);
  348. if (rc)
  349. return rc;
  350. rc = eiw_to_ways(cfmws->interleave_ways, &ways);
  351. if (rc)
  352. return rc;
  353. rc = eig_to_granularity(cfmws->granularity, &ig);
  354. if (rc)
  355. return rc;
  356. struct resource *res __free(del_cxl_resource) = alloc_cxl_resource(
  357. cfmws->base_hpa, cfmws->window_size, ctx->id++);
  358. if (!res)
  359. return -ENOMEM;
  360. /* add to the local resource tracking to establish a sort order */
  361. rc = add_or_reset_cxl_resource(ctx->cxl_res, no_free_ptr(res));
  362. if (rc)
  363. return rc;
  364. struct cxl_root_decoder *cxlrd __free(put_cxlrd) =
  365. cxl_root_decoder_alloc(root_port, ways);
  366. if (IS_ERR(cxlrd))
  367. return PTR_ERR(cxlrd);
  368. cxld = &cxlrd->cxlsd.cxld;
  369. cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions);
  370. cxld->target_type = CXL_DECODER_HOSTONLYMEM;
  371. cxld->hpa_range = (struct range) {
  372. .start = cfmws->base_hpa,
  373. .end = cfmws->base_hpa + cfmws->window_size - 1,
  374. };
  375. cxld->interleave_ways = ways;
  376. for (i = 0; i < ways; i++)
  377. cxld->target_map[i] = cfmws->interleave_targets[i];
  378. /*
  379. * Minimize the x1 granularity to advertise support for any
  380. * valid region granularity
  381. */
  382. if (ways == 1)
  383. ig = CXL_DECODER_MIN_GRANULARITY;
  384. cxld->interleave_granularity = ig;
  385. if (cfmws->interleave_arithmetic == ACPI_CEDT_CFMWS_ARITHMETIC_XOR) {
  386. if (ways != 1 && ways != 3) {
  387. cxims_ctx = (struct cxl_cxims_context) {
  388. .dev = dev,
  389. .cxlrd = cxlrd,
  390. };
  391. rc = acpi_table_parse_cedt(ACPI_CEDT_TYPE_CXIMS,
  392. cxl_parse_cxims, &cxims_ctx);
  393. if (rc < 0)
  394. return rc;
  395. if (!cxlrd->platform_data) {
  396. dev_err(dev, "No CXIMS for HBIG %u\n", ig);
  397. return -EINVAL;
  398. }
  399. }
  400. cxlrd->ops.hpa_to_spa = cxl_apply_xor_maps;
  401. cxlrd->ops.spa_to_hpa = cxl_apply_xor_maps;
  402. }
  403. cxl_setup_extended_linear_cache(cxlrd);
  404. cxlrd->qos_class = cfmws->qtg_id;
  405. rc = cxl_decoder_add(cxld);
  406. if (rc)
  407. return rc;
  408. rc = cxl_root_decoder_autoremove(dev, no_free_ptr(cxlrd));
  409. if (rc)
  410. return rc;
  411. dev_dbg(root_port->dev.parent, "%s added to %s\n",
  412. dev_name(&cxld->dev), dev_name(&root_port->dev));
  413. return 0;
  414. }
  415. static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
  416. const unsigned long end)
  417. {
  418. struct acpi_cedt_cfmws *cfmws = (struct acpi_cedt_cfmws *)header;
  419. struct cxl_cfmws_context *ctx = arg;
  420. struct device *dev = ctx->dev;
  421. int rc;
  422. rc = __cxl_parse_cfmws(cfmws, ctx);
  423. if (rc)
  424. dev_err(dev,
  425. "Failed to add decode range: [%#llx - %#llx] (%d)\n",
  426. cfmws->base_hpa,
  427. cfmws->base_hpa + cfmws->window_size - 1, rc);
  428. else
  429. dev_dbg(dev, "decode range: node: %d range [%#llx - %#llx]\n",
  430. phys_to_target_node(cfmws->base_hpa), cfmws->base_hpa,
  431. cfmws->base_hpa + cfmws->window_size - 1);
  432. /* never fail cxl_acpi load for a single window failure */
  433. return 0;
  434. }
  435. __mock struct acpi_device *to_cxl_host_bridge(struct device *host,
  436. struct device *dev)
  437. {
  438. struct acpi_device *adev = to_acpi_device(dev);
  439. if (!acpi_pci_find_root(adev->handle))
  440. return NULL;
  441. if (strcmp(acpi_device_hid(adev), "ACPI0016") == 0)
  442. return adev;
  443. return NULL;
  444. }
  445. /* Note, @dev is used by mock_acpi_table_parse_cedt() */
  446. struct cxl_chbs_context {
  447. struct device *dev;
  448. unsigned long long uid;
  449. resource_size_t base;
  450. u32 cxl_version;
  451. int nr_versions;
  452. u32 saved_version;
  453. };
  454. static int cxl_get_chbs_iter(union acpi_subtable_headers *header, void *arg,
  455. const unsigned long end)
  456. {
  457. struct cxl_chbs_context *ctx = arg;
  458. struct acpi_cedt_chbs *chbs;
  459. chbs = (struct acpi_cedt_chbs *) header;
  460. if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 &&
  461. chbs->length != ACPI_CEDT_CHBS_LENGTH_CXL11)
  462. return 0;
  463. if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL20 &&
  464. chbs->length != ACPI_CEDT_CHBS_LENGTH_CXL20)
  465. return 0;
  466. if (!chbs->base)
  467. return 0;
  468. if (ctx->saved_version != chbs->cxl_version) {
  469. /*
  470. * cxl_version cannot be overwritten before the next two
  471. * checks, then use saved_version
  472. */
  473. ctx->saved_version = chbs->cxl_version;
  474. ctx->nr_versions++;
  475. }
  476. if (ctx->base != CXL_RESOURCE_NONE)
  477. return 0;
  478. if (ctx->uid != chbs->uid)
  479. return 0;
  480. ctx->cxl_version = chbs->cxl_version;
  481. ctx->base = chbs->base;
  482. return 0;
  483. }
  484. static int cxl_get_chbs(struct device *dev, struct acpi_device *hb,
  485. struct cxl_chbs_context *ctx)
  486. {
  487. unsigned long long uid;
  488. int rc;
  489. rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid);
  490. if (rc != AE_OK) {
  491. dev_err(dev, "unable to retrieve _UID\n");
  492. return -ENOENT;
  493. }
  494. dev_dbg(dev, "UID found: %lld\n", uid);
  495. *ctx = (struct cxl_chbs_context) {
  496. .dev = dev,
  497. .uid = uid,
  498. .base = CXL_RESOURCE_NONE,
  499. .cxl_version = UINT_MAX,
  500. .saved_version = UINT_MAX,
  501. };
  502. acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbs_iter, ctx);
  503. if (ctx->nr_versions > 1) {
  504. /*
  505. * Disclaim eRCD support given some component register may
  506. * only be found via CHBCR
  507. */
  508. dev_info(dev, "Unsupported platform config, mixed Virtual Host and Restricted CXL Host hierarchy.");
  509. }
  510. return 0;
  511. }
  512. static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport)
  513. {
  514. struct acpi_device *hb = to_cxl_host_bridge(NULL, dev);
  515. u32 uid;
  516. if (kstrtou32(acpi_device_uid(hb), 0, &uid))
  517. return -EINVAL;
  518. return acpi_get_genport_coordinates(uid, dport->coord);
  519. }
  520. static int add_host_bridge_dport(struct device *match, void *arg)
  521. {
  522. int ret;
  523. acpi_status rc;
  524. struct device *bridge;
  525. struct cxl_dport *dport;
  526. struct cxl_chbs_context ctx;
  527. struct acpi_pci_root *pci_root;
  528. struct cxl_port *root_port = arg;
  529. struct device *host = root_port->dev.parent;
  530. struct acpi_device *hb = to_cxl_host_bridge(host, match);
  531. if (!hb)
  532. return 0;
  533. rc = cxl_get_chbs(match, hb, &ctx);
  534. if (rc)
  535. return rc;
  536. if (ctx.cxl_version == UINT_MAX) {
  537. dev_warn(match, "No CHBS found for Host Bridge (UID %lld)\n",
  538. ctx.uid);
  539. return 0;
  540. }
  541. if (ctx.base == CXL_RESOURCE_NONE) {
  542. dev_warn(match, "CHBS invalid for Host Bridge (UID %lld)\n",
  543. ctx.uid);
  544. return 0;
  545. }
  546. pci_root = acpi_pci_find_root(hb->handle);
  547. bridge = pci_root->bus->bridge;
  548. /*
  549. * In RCH mode, bind the component regs base to the dport. In
  550. * VH mode it will be bound to the CXL host bridge's port
  551. * object later in add_host_bridge_uport().
  552. */
  553. if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) {
  554. dev_dbg(match, "RCRB found for UID %lld: %pa\n", ctx.uid,
  555. &ctx.base);
  556. dport = devm_cxl_add_rch_dport(root_port, bridge, ctx.uid,
  557. ctx.base);
  558. } else {
  559. dport = devm_cxl_add_dport(root_port, bridge, ctx.uid,
  560. CXL_RESOURCE_NONE);
  561. }
  562. if (IS_ERR(dport))
  563. return PTR_ERR(dport);
  564. ret = get_genport_coordinates(match, dport);
  565. if (ret)
  566. dev_dbg(match, "Failed to get generic port perf coordinates.\n");
  567. return 0;
  568. }
  569. /*
  570. * A host bridge is a dport to a CFMWS decode and it is a uport to the
  571. * dport (PCIe Root Ports) in the host bridge.
  572. */
  573. static int add_host_bridge_uport(struct device *match, void *arg)
  574. {
  575. struct cxl_port *root_port = arg;
  576. struct device *host = root_port->dev.parent;
  577. struct acpi_device *hb = to_cxl_host_bridge(host, match);
  578. struct acpi_pci_root *pci_root;
  579. struct cxl_dport *dport;
  580. struct cxl_port *port;
  581. struct device *bridge;
  582. struct cxl_chbs_context ctx;
  583. resource_size_t component_reg_phys;
  584. int rc;
  585. if (!hb)
  586. return 0;
  587. pci_root = acpi_pci_find_root(hb->handle);
  588. bridge = pci_root->bus->bridge;
  589. dport = cxl_find_dport_by_dev(root_port, bridge);
  590. if (!dport) {
  591. dev_dbg(host, "host bridge expected and not found\n");
  592. return 0;
  593. }
  594. if (dport->rch) {
  595. dev_info(bridge, "host supports CXL (restricted)\n");
  596. return 0;
  597. }
  598. rc = cxl_get_chbs(match, hb, &ctx);
  599. if (rc)
  600. return rc;
  601. if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) {
  602. dev_warn(bridge,
  603. "CXL CHBS version mismatch, skip port registration\n");
  604. return 0;
  605. }
  606. component_reg_phys = ctx.base;
  607. if (component_reg_phys != CXL_RESOURCE_NONE)
  608. dev_dbg(match, "CHBCR found for UID %lld: %pa\n",
  609. ctx.uid, &component_reg_phys);
  610. rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus);
  611. if (rc)
  612. return rc;
  613. port = devm_cxl_add_port(host, bridge, component_reg_phys, dport);
  614. if (IS_ERR(port))
  615. return PTR_ERR(port);
  616. dev_info(bridge, "host supports CXL\n");
  617. return 0;
  618. }
  619. static int add_root_nvdimm_bridge(struct device *match, void *data)
  620. {
  621. struct cxl_decoder *cxld;
  622. struct cxl_port *root_port = data;
  623. struct cxl_nvdimm_bridge *cxl_nvb;
  624. struct device *host = root_port->dev.parent;
  625. if (!is_root_decoder(match))
  626. return 0;
  627. cxld = to_cxl_decoder(match);
  628. if (!(cxld->flags & CXL_DECODER_F_PMEM))
  629. return 0;
  630. cxl_nvb = devm_cxl_add_nvdimm_bridge(host, root_port);
  631. if (IS_ERR(cxl_nvb)) {
  632. dev_dbg(host, "failed to register pmem\n");
  633. return PTR_ERR(cxl_nvb);
  634. }
  635. dev_dbg(host, "%s: add: %s\n", dev_name(&root_port->dev),
  636. dev_name(&cxl_nvb->dev));
  637. return 1;
  638. }
  639. static struct lock_class_key cxl_root_key;
  640. static void cxl_acpi_lock_reset_class(void *dev)
  641. {
  642. device_lock_reset_class(dev);
  643. }
  644. static void cxl_set_public_resource(struct resource *priv, struct resource *pub)
  645. {
  646. priv->desc = (unsigned long) pub;
  647. }
  648. static struct resource *cxl_get_public_resource(struct resource *priv)
  649. {
  650. return (struct resource *) priv->desc;
  651. }
  652. static void remove_cxl_resources(void *data)
  653. {
  654. struct resource *res, *next, *cxl = data;
  655. for (res = cxl->child; res; res = next) {
  656. struct resource *victim = cxl_get_public_resource(res);
  657. next = res->sibling;
  658. remove_resource(res);
  659. if (victim) {
  660. remove_resource(victim);
  661. kfree(victim);
  662. }
  663. del_cxl_resource(res);
  664. }
  665. }
  666. /**
  667. * add_cxl_resources() - reflect CXL fixed memory windows in iomem_resource
  668. * @cxl_res: A standalone resource tree where each CXL window is a sibling
  669. *
  670. * Walk each CXL window in @cxl_res and add it to iomem_resource potentially
  671. * expanding its boundaries to ensure that any conflicting resources become
  672. * children. If a window is expanded it may then conflict with a another window
  673. * entry and require the window to be truncated or trimmed. Consider this
  674. * situation::
  675. *
  676. * |-- "CXL Window 0" --||----- "CXL Window 1" -----|
  677. * |--------------- "System RAM" -------------|
  678. *
  679. * ...where platform firmware has established as System RAM resource across 2
  680. * windows, but has left some portion of window 1 for dynamic CXL region
  681. * provisioning. In this case "Window 0" will span the entirety of the "System
  682. * RAM" span, and "CXL Window 1" is truncated to the remaining tail past the end
  683. * of that "System RAM" resource.
  684. */
  685. static int add_cxl_resources(struct resource *cxl_res)
  686. {
  687. struct resource *res, *new, *next;
  688. for (res = cxl_res->child; res; res = next) {
  689. new = kzalloc_obj(*new);
  690. if (!new)
  691. return -ENOMEM;
  692. new->name = res->name;
  693. new->start = res->start;
  694. new->end = res->end;
  695. new->flags = IORESOURCE_MEM;
  696. new->desc = IORES_DESC_CXL;
  697. /*
  698. * Record the public resource in the private cxl_res tree for
  699. * later removal.
  700. */
  701. cxl_set_public_resource(res, new);
  702. insert_resource_expand_to_fit(&iomem_resource, new);
  703. next = res->sibling;
  704. while (next && resource_overlaps(new, next)) {
  705. if (resource_contains(new, next)) {
  706. struct resource *_next = next->sibling;
  707. remove_resource(next);
  708. del_cxl_resource(next);
  709. next = _next;
  710. } else
  711. next->start = new->end + 1;
  712. }
  713. }
  714. return 0;
  715. }
  716. static int pair_cxl_resource(struct device *dev, void *data)
  717. {
  718. struct resource *cxl_res = data;
  719. struct resource *p;
  720. if (!is_root_decoder(dev))
  721. return 0;
  722. for (p = cxl_res->child; p; p = p->sibling) {
  723. struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
  724. struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
  725. struct resource res = {
  726. .start = cxld->hpa_range.start,
  727. .end = cxld->hpa_range.end,
  728. .flags = IORESOURCE_MEM,
  729. };
  730. if (resource_contains(p, &res)) {
  731. cxlrd->res = cxl_get_public_resource(p);
  732. break;
  733. }
  734. }
  735. return 0;
  736. }
  737. static int cxl_acpi_probe(struct platform_device *pdev)
  738. {
  739. int rc;
  740. struct resource *cxl_res;
  741. struct cxl_root *cxl_root;
  742. struct cxl_port *root_port;
  743. struct device *host = &pdev->dev;
  744. struct acpi_device *adev = ACPI_COMPANION(host);
  745. struct cxl_cfmws_context ctx;
  746. device_lock_set_class(&pdev->dev, &cxl_root_key);
  747. rc = devm_add_action_or_reset(&pdev->dev, cxl_acpi_lock_reset_class,
  748. &pdev->dev);
  749. if (rc)
  750. return rc;
  751. cxl_res = devm_kzalloc(host, sizeof(*cxl_res), GFP_KERNEL);
  752. if (!cxl_res)
  753. return -ENOMEM;
  754. cxl_res->name = "CXL mem";
  755. cxl_res->start = 0;
  756. cxl_res->end = -1;
  757. cxl_res->flags = IORESOURCE_MEM;
  758. cxl_root = devm_cxl_add_root(host);
  759. if (IS_ERR(cxl_root))
  760. return PTR_ERR(cxl_root);
  761. cxl_root->ops.qos_class = cxl_acpi_qos_class;
  762. root_port = &cxl_root->port;
  763. cxl_setup_prm_address_translation(cxl_root);
  764. rc = bus_for_each_dev(adev->dev.bus, NULL, root_port,
  765. add_host_bridge_dport);
  766. if (rc < 0)
  767. return rc;
  768. rc = devm_add_action_or_reset(host, remove_cxl_resources, cxl_res);
  769. if (rc)
  770. return rc;
  771. ctx = (struct cxl_cfmws_context) {
  772. .dev = host,
  773. .root_port = root_port,
  774. .cxl_res = cxl_res,
  775. };
  776. rc = acpi_table_parse_cedt(ACPI_CEDT_TYPE_CFMWS, cxl_parse_cfmws, &ctx);
  777. if (rc < 0)
  778. return -ENXIO;
  779. rc = add_cxl_resources(cxl_res);
  780. if (rc)
  781. return rc;
  782. /*
  783. * Populate the root decoders with their related iomem resource,
  784. * if present
  785. */
  786. device_for_each_child(&root_port->dev, cxl_res, pair_cxl_resource);
  787. /*
  788. * Root level scanned with host-bridge as dports, now scan host-bridges
  789. * for their role as CXL uports to their CXL-capable PCIe Root Ports.
  790. */
  791. rc = bus_for_each_dev(adev->dev.bus, NULL, root_port,
  792. add_host_bridge_uport);
  793. if (rc < 0)
  794. return rc;
  795. if (IS_ENABLED(CONFIG_CXL_PMEM))
  796. rc = device_for_each_child(&root_port->dev, root_port,
  797. add_root_nvdimm_bridge);
  798. if (rc < 0)
  799. return rc;
  800. /* In case PCI is scanned before ACPI re-trigger memdev attach */
  801. cxl_bus_rescan();
  802. return 0;
  803. }
  804. static const struct acpi_device_id cxl_acpi_ids[] = {
  805. { "ACPI0017" },
  806. { },
  807. };
  808. MODULE_DEVICE_TABLE(acpi, cxl_acpi_ids);
  809. static const struct platform_device_id cxl_test_ids[] = {
  810. { "cxl_acpi" },
  811. { },
  812. };
  813. MODULE_DEVICE_TABLE(platform, cxl_test_ids);
  814. static struct platform_driver cxl_acpi_driver = {
  815. .probe = cxl_acpi_probe,
  816. .driver = {
  817. .name = KBUILD_MODNAME,
  818. .acpi_match_table = cxl_acpi_ids,
  819. },
  820. .id_table = cxl_test_ids,
  821. };
  822. static int __init cxl_acpi_init(void)
  823. {
  824. return platform_driver_register(&cxl_acpi_driver);
  825. }
  826. static void __exit cxl_acpi_exit(void)
  827. {
  828. platform_driver_unregister(&cxl_acpi_driver);
  829. cxl_bus_drain();
  830. }
  831. /*
  832. * Load before dax_hmem sees 'Soft Reserved' CXL ranges. Use
  833. * subsys_initcall_sync() since there is an order dependency with
  834. * subsys_initcall(efisubsys_init), which must run first.
  835. */
  836. subsys_initcall_sync(cxl_acpi_init);
  837. /*
  838. * Arrange for host-bridge ports to be active synchronous with
  839. * cxl_acpi_probe() exit.
  840. */
  841. MODULE_SOFTDEP("pre: cxl_port");
  842. module_exit(cxl_acpi_exit);
  843. MODULE_DESCRIPTION("CXL ACPI: Platform Support");
  844. MODULE_LICENSE("GPL v2");
  845. MODULE_IMPORT_NS("CXL");
  846. MODULE_IMPORT_NS("ACPI");