Skip to content

Commit f4ce1f7

Browse files
committed
cxl/acpi: Convert CFMWS parsing to ACPI sub-table helpers
The cxl_acpi driver originally open-coded its table parsing since the ACPI subtable helpers were marked __init and only used in early NUMA initialization. Now that those helpers have been exported for driver usage replace the open-coded solution with the common one. Cc: Alison Schofield <[email protected]> Acked-by: Rafael J. Wysocki <[email protected]> Link: https://lore.kernel.org/r/163553710810.2509508.14686373989517930921.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent 2d03e46 commit f4ce1f7

File tree

2 files changed

+88
-147
lines changed

2 files changed

+88
-147
lines changed

drivers/cxl/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ config CXL_ACPI
5151
tristate "CXL ACPI: Platform Support"
5252
depends on ACPI
5353
default CXL_BUS
54+
select ACPI_TABLE_LIB
5455
help
5556
Enable support for host managed device memory (HDM) resources
5657
published by a platform's ACPI CXL memory layout description. See

drivers/cxl/acpi.c

Lines changed: 87 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
#include <linux/pci.h>
99
#include "cxl.h"
1010

11-
static struct acpi_table_header *acpi_cedt;
12-
1311
/* Encode defined in CXL 2.0 8.2.5.12.7 HDM Decoder Control Register */
1412
#define CFMWS_INTERLEAVE_WAYS(x) (1 << (x)->interleave_ways)
1513
#define CFMWS_INTERLEAVE_GRANULARITY(x) ((x)->granularity + 8)
@@ -74,134 +72,63 @@ static int cxl_acpi_cfmws_verify(struct device *dev,
7472
return 0;
7573
}
7674

77-
static void cxl_add_cfmws_decoders(struct device *dev,
78-
struct cxl_port *root_port)
75+
struct cxl_cfmws_context {
76+
struct device *dev;
77+
struct cxl_port *root_port;
78+
};
79+
80+
static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
81+
const unsigned long end)
7982
{
8083
int target_map[CXL_DECODER_MAX_INTERLEAVE];
84+
struct cxl_cfmws_context *ctx = arg;
85+
struct cxl_port *root_port = ctx->root_port;
86+
struct device *dev = ctx->dev;
8187
struct acpi_cedt_cfmws *cfmws;
8288
struct cxl_decoder *cxld;
83-
acpi_size len, cur = 0;
84-
void *cedt_subtable;
85-
int rc;
86-
87-
len = acpi_cedt->length - sizeof(*acpi_cedt);
88-
cedt_subtable = acpi_cedt + 1;
89-
90-
while (cur < len) {
91-
struct acpi_cedt_header *c = cedt_subtable + cur;
92-
int i;
93-
94-
if (c->type != ACPI_CEDT_TYPE_CFMWS) {
95-
cur += c->length;
96-
continue;
97-
}
89+
int rc, i;
9890

99-
cfmws = cedt_subtable + cur;
91+
cfmws = (struct acpi_cedt_cfmws *) header;
10092

101-
if (cfmws->header.length < sizeof(*cfmws)) {
102-
dev_warn_once(dev,
103-
"CFMWS entry skipped:invalid length:%u\n",
104-
cfmws->header.length);
105-
cur += c->length;
106-
continue;
107-
}
108-
109-
rc = cxl_acpi_cfmws_verify(dev, cfmws);
110-
if (rc) {
111-
dev_err(dev, "CFMWS range %#llx-%#llx not registered\n",
112-
cfmws->base_hpa, cfmws->base_hpa +
113-
cfmws->window_size - 1);
114-
cur += c->length;
115-
continue;
116-
}
117-
118-
for (i = 0; i < CFMWS_INTERLEAVE_WAYS(cfmws); i++)
119-
target_map[i] = cfmws->interleave_targets[i];
120-
121-
cxld = cxl_decoder_alloc(root_port,
122-
CFMWS_INTERLEAVE_WAYS(cfmws));
123-
if (IS_ERR(cxld))
124-
goto next;
125-
126-
cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions);
127-
cxld->target_type = CXL_DECODER_EXPANDER;
128-
cxld->range = (struct range) {
129-
.start = cfmws->base_hpa,
130-
.end = cfmws->base_hpa + cfmws->window_size - 1,
131-
};
132-
cxld->interleave_ways = CFMWS_INTERLEAVE_WAYS(cfmws);
133-
cxld->interleave_granularity =
134-
CFMWS_INTERLEAVE_GRANULARITY(cfmws);
135-
136-
rc = cxl_decoder_add(cxld, target_map);
137-
if (rc)
138-
put_device(&cxld->dev);
139-
else
140-
rc = cxl_decoder_autoremove(dev, cxld);
141-
if (rc) {
142-
dev_err(dev, "Failed to add decoder for %#llx-%#llx\n",
143-
cfmws->base_hpa, cfmws->base_hpa +
144-
cfmws->window_size - 1);
145-
goto next;
146-
}
147-
dev_dbg(dev, "add: %s range %#llx-%#llx\n",
148-
dev_name(&cxld->dev), cfmws->base_hpa,
93+
rc = cxl_acpi_cfmws_verify(dev, cfmws);
94+
if (rc) {
95+
dev_err(dev, "CFMWS range %#llx-%#llx not registered\n",
96+
cfmws->base_hpa,
14997
cfmws->base_hpa + cfmws->window_size - 1);
150-
next:
151-
cur += c->length;
98+
return 0;
15299
}
153-
}
154-
155-
static struct acpi_cedt_chbs *cxl_acpi_match_chbs(struct device *dev, u32 uid)
156-
{
157-
struct acpi_cedt_chbs *chbs, *chbs_match = NULL;
158-
acpi_size len, cur = 0;
159-
void *cedt_subtable;
160100

161-
len = acpi_cedt->length - sizeof(*acpi_cedt);
162-
cedt_subtable = acpi_cedt + 1;
101+
for (i = 0; i < CFMWS_INTERLEAVE_WAYS(cfmws); i++)
102+
target_map[i] = cfmws->interleave_targets[i];
163103

164-
while (cur < len) {
165-
struct acpi_cedt_header *c = cedt_subtable + cur;
166-
167-
if (c->type != ACPI_CEDT_TYPE_CHBS) {
168-
cur += c->length;
169-
continue;
170-
}
171-
172-
chbs = cedt_subtable + cur;
173-
174-
if (chbs->header.length < sizeof(*chbs)) {
175-
dev_warn_once(dev,
176-
"CHBS entry skipped: invalid length:%u\n",
177-
chbs->header.length);
178-
cur += c->length;
179-
continue;
180-
}
181-
182-
if (chbs->uid != uid) {
183-
cur += c->length;
184-
continue;
185-
}
104+
cxld = cxl_decoder_alloc(root_port, CFMWS_INTERLEAVE_WAYS(cfmws));
105+
if (IS_ERR(cxld))
106+
return 0;
186107

187-
if (chbs_match) {
188-
dev_warn_once(dev,
189-
"CHBS entry skipped: duplicate UID:%u\n",
190-
uid);
191-
cur += c->length;
192-
continue;
193-
}
108+
cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions);
109+
cxld->target_type = CXL_DECODER_EXPANDER;
110+
cxld->range = (struct range){
111+
.start = cfmws->base_hpa,
112+
.end = cfmws->base_hpa + cfmws->window_size - 1,
113+
};
114+
cxld->interleave_ways = CFMWS_INTERLEAVE_WAYS(cfmws);
115+
cxld->interleave_granularity = CFMWS_INTERLEAVE_GRANULARITY(cfmws);
194116

195-
chbs_match = chbs;
196-
cur += c->length;
117+
rc = cxl_decoder_add(cxld, target_map);
118+
if (rc)
119+
put_device(&cxld->dev);
120+
else
121+
rc = cxl_decoder_autoremove(dev, cxld);
122+
if (rc) {
123+
dev_err(dev, "Failed to add decoder for %#llx-%#llx\n",
124+
cfmws->base_hpa,
125+
cfmws->base_hpa + cfmws->window_size - 1);
126+
return 0;
197127
}
128+
dev_dbg(dev, "add: %s range %#llx-%#llx\n", dev_name(&cxld->dev),
129+
cfmws->base_hpa, cfmws->base_hpa + cfmws->window_size - 1);
198130

199-
return chbs_match ? chbs_match : ERR_PTR(-ENODEV);
200-
}
201-
202-
static resource_size_t get_chbcr(struct acpi_cedt_chbs *chbs)
203-
{
204-
return IS_ERR(chbs) ? CXL_RESOURCE_NONE : chbs->base;
131+
return 0;
205132
}
206133

207134
__mock int match_add_root_ports(struct pci_dev *pdev, void *data)
@@ -355,12 +282,35 @@ static int add_host_bridge_uport(struct device *match, void *arg)
355282
return rc;
356283
}
357284

285+
struct cxl_chbs_context {
286+
unsigned long long uid;
287+
resource_size_t chbcr;
288+
};
289+
290+
static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
291+
const unsigned long end)
292+
{
293+
struct cxl_chbs_context *ctx = arg;
294+
struct acpi_cedt_chbs *chbs;
295+
296+
if (ctx->chbcr)
297+
return 0;
298+
299+
chbs = (struct acpi_cedt_chbs *) header;
300+
301+
if (ctx->uid != chbs->uid)
302+
return 0;
303+
ctx->chbcr = chbs->base;
304+
305+
return 0;
306+
}
307+
358308
static int add_host_bridge_dport(struct device *match, void *arg)
359309
{
360310
int rc;
361311
acpi_status status;
362312
unsigned long long uid;
363-
struct acpi_cedt_chbs *chbs;
313+
struct cxl_chbs_context ctx;
364314
struct cxl_port *root_port = arg;
365315
struct device *host = root_port->dev.parent;
366316
struct acpi_device *bridge = to_cxl_host_bridge(host, match);
@@ -376,14 +326,18 @@ static int add_host_bridge_dport(struct device *match, void *arg)
376326
return -ENODEV;
377327
}
378328

379-
chbs = cxl_acpi_match_chbs(host, uid);
380-
if (IS_ERR(chbs)) {
329+
ctx = (struct cxl_chbs_context) {
330+
.uid = uid,
331+
};
332+
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbcr, &ctx);
333+
334+
if (ctx.chbcr == 0) {
381335
dev_warn(host, "No CHBS found for Host Bridge: %s\n",
382336
dev_name(match));
383337
return 0;
384338
}
385339

386-
rc = cxl_add_dport(root_port, match, uid, get_chbcr(chbs));
340+
rc = cxl_add_dport(root_port, match, uid, ctx.chbcr);
387341
if (rc) {
388342
dev_err(host, "failed to add downstream port: %s\n",
389343
dev_name(match));
@@ -417,65 +371,50 @@ static int add_root_nvdimm_bridge(struct device *match, void *data)
417371
return 1;
418372
}
419373

420-
static u32 cedt_instance(struct platform_device *pdev)
421-
{
422-
const bool *native_acpi0017 = acpi_device_get_match_data(&pdev->dev);
423-
424-
if (native_acpi0017 && *native_acpi0017)
425-
return 0;
426-
427-
/* for cxl_test request a non-canonical instance */
428-
return U32_MAX;
429-
}
430-
431374
static int cxl_acpi_probe(struct platform_device *pdev)
432375
{
433376
int rc;
434-
acpi_status status;
435377
struct cxl_port *root_port;
436378
struct device *host = &pdev->dev;
437379
struct acpi_device *adev = ACPI_COMPANION(host);
380+
struct cxl_cfmws_context ctx;
438381

439382
root_port = devm_cxl_add_port(host, host, CXL_RESOURCE_NONE, NULL);
440383
if (IS_ERR(root_port))
441384
return PTR_ERR(root_port);
442385
dev_dbg(host, "add: %s\n", dev_name(&root_port->dev));
443386

444-
status = acpi_get_table(ACPI_SIG_CEDT, cedt_instance(pdev), &acpi_cedt);
445-
if (ACPI_FAILURE(status))
446-
return -ENXIO;
447-
448387
rc = bus_for_each_dev(adev->dev.bus, NULL, root_port,
449388
add_host_bridge_dport);
450-
if (rc)
451-
goto out;
389+
if (rc < 0)
390+
return rc;
452391

453-
cxl_add_cfmws_decoders(host, root_port);
392+
ctx = (struct cxl_cfmws_context) {
393+
.dev = host,
394+
.root_port = root_port,
395+
};
396+
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CFMWS, cxl_parse_cfmws, &ctx);
454397

455398
/*
456399
* Root level scanned with host-bridge as dports, now scan host-bridges
457400
* for their role as CXL uports to their CXL-capable PCIe Root Ports.
458401
*/
459402
rc = bus_for_each_dev(adev->dev.bus, NULL, root_port,
460403
add_host_bridge_uport);
461-
if (rc)
462-
goto out;
404+
if (rc < 0)
405+
return rc;
463406

464407
if (IS_ENABLED(CONFIG_CXL_PMEM))
465408
rc = device_for_each_child(&root_port->dev, root_port,
466409
add_root_nvdimm_bridge);
467-
468-
out:
469-
acpi_put_table(acpi_cedt);
470410
if (rc < 0)
471411
return rc;
412+
472413
return 0;
473414
}
474415

475-
static bool native_acpi0017 = true;
476-
477416
static const struct acpi_device_id cxl_acpi_ids[] = {
478-
{ "ACPI0017", (unsigned long) &native_acpi0017 },
417+
{ "ACPI0017" },
479418
{ },
480419
};
481420
MODULE_DEVICE_TABLE(acpi, cxl_acpi_ids);
@@ -491,3 +430,4 @@ static struct platform_driver cxl_acpi_driver = {
491430
module_platform_driver(cxl_acpi_driver);
492431
MODULE_LICENSE("GPL v2");
493432
MODULE_IMPORT_NS(CXL);
433+
MODULE_IMPORT_NS(ACPI);

0 commit comments

Comments
 (0)