Skip to content

Commit d02034b

Browse files
Robert Richterdjbw
authored andcommitted
cxl/acpi: Directly bind the CEDT detected CHBCR to the Host Bridge's port
During a Host Bridge's downstream port enumeration the CHBS entries in the CEDT table are parsed, its Component Register base address extracted and then stored in struct cxl_dport. The CHBS may contain either the RCRB (RCH mode) or the Host Bridge's Component Registers (CHBCR, VH mode). The RCRB further contains the CXL downstream port register base address, while in VH mode the CXL Downstream Switch Ports are visible in the PCI hierarchy and the DP's component regs are disovered using the CXL DVSEC register locator capability. The Component Registers derived from the CHBS for both modes are different and thus also must be treated differently. That is, in RCH mode, the component regs base should be bound to the dport, but in VH mode to the CXL host bridge's port object. The current implementation stores the CHBCR in addition in struct cxl_dport and copies it later from there to struct cxl_port. As a result, the dport contains the wrong Component Registers base address and, e.g. the RAS capability of a CXL Root Port cannot be detected. To fix the CHBCR binding, attach it directly to the Host Bridge's @cxl_port structure. Do this during port creation of the Host Bridge in add_host_bridge_uport(). Factor out CHBS parsing code in add_host_bridge_dport() and use it in both functions. Co-developed-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Robert Richter <rrichter@amd.com> Signed-off-by: Terry Bowman <terry.bowman@amd.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Link: https://lore.kernel.org/r/20230622205523.85375-10-terry.bowman@amd.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent f44c7b7 commit d02034b

1 file changed

Lines changed: 63 additions & 28 deletions

File tree

drivers/cxl/acpi.c

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -335,13 +335,13 @@ struct cxl_chbs_context {
335335
u32 cxl_version;
336336
};
337337

338-
static int cxl_get_chbs(union acpi_subtable_headers *header, void *arg,
339-
const unsigned long end)
338+
static int cxl_get_chbs_iter(union acpi_subtable_headers *header, void *arg,
339+
const unsigned long end)
340340
{
341341
struct cxl_chbs_context *ctx = arg;
342342
struct acpi_cedt_chbs *chbs;
343343

344-
if (ctx->base)
344+
if (ctx->base != CXL_RESOURCE_NONE)
345345
return 0;
346346

347347
chbs = (struct acpi_cedt_chbs *) header;
@@ -350,8 +350,6 @@ static int cxl_get_chbs(union acpi_subtable_headers *header, void *arg,
350350
return 0;
351351

352352
ctx->cxl_version = chbs->cxl_version;
353-
ctx->base = CXL_RESOURCE_NONE;
354-
355353
if (!chbs->base)
356354
return 0;
357355

@@ -364,11 +362,35 @@ static int cxl_get_chbs(union acpi_subtable_headers *header, void *arg,
364362
return 0;
365363
}
366364

365+
static int cxl_get_chbs(struct device *dev, struct acpi_device *hb,
366+
struct cxl_chbs_context *ctx)
367+
{
368+
unsigned long long uid;
369+
int rc;
370+
371+
rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid);
372+
if (rc != AE_OK) {
373+
dev_err(dev, "unable to retrieve _UID\n");
374+
return -ENOENT;
375+
}
376+
377+
dev_dbg(dev, "UID found: %lld\n", uid);
378+
*ctx = (struct cxl_chbs_context) {
379+
.dev = dev,
380+
.uid = uid,
381+
.base = CXL_RESOURCE_NONE,
382+
.cxl_version = UINT_MAX,
383+
};
384+
385+
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbs_iter, ctx);
386+
387+
return 0;
388+
}
389+
367390
static int add_host_bridge_dport(struct device *match, void *arg)
368391
{
369392
acpi_status rc;
370393
struct device *bridge;
371-
unsigned long long uid;
372394
struct cxl_dport *dport;
373395
struct cxl_chbs_context ctx;
374396
struct acpi_pci_root *pci_root;
@@ -379,41 +401,38 @@ static int add_host_bridge_dport(struct device *match, void *arg)
379401
if (!hb)
380402
return 0;
381403

382-
rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid);
383-
if (rc != AE_OK) {
384-
dev_err(match, "unable to retrieve _UID\n");
385-
return -ENODEV;
386-
}
387-
388-
dev_dbg(match, "UID found: %lld\n", uid);
389-
390-
ctx = (struct cxl_chbs_context) {
391-
.dev = match,
392-
.uid = uid,
393-
};
394-
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbs, &ctx);
404+
rc = cxl_get_chbs(match, hb, &ctx);
405+
if (rc)
406+
return rc;
395407

396-
if (!ctx.base) {
408+
if (ctx.cxl_version == UINT_MAX) {
397409
dev_warn(match, "No CHBS found for Host Bridge (UID %lld)\n",
398-
uid);
410+
ctx.uid);
399411
return 0;
400412
}
401413

402414
if (ctx.base == CXL_RESOURCE_NONE) {
403415
dev_warn(match, "CHBS invalid for Host Bridge (UID %lld)\n",
404-
uid);
416+
ctx.uid);
405417
return 0;
406418
}
407419

408420
pci_root = acpi_pci_find_root(hb->handle);
409421
bridge = pci_root->bus->bridge;
410422

423+
/*
424+
* In RCH mode, bind the component regs base to the dport. In
425+
* VH mode it will be bound to the CXL host bridge's port
426+
* object later in add_host_bridge_uport().
427+
*/
411428
if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) {
412-
dev_dbg(match, "RCRB found for UID %lld: %pa\n", uid, &ctx.base);
413-
dport = devm_cxl_add_rch_dport(root_port, bridge, uid, ctx.base);
429+
dev_dbg(match, "RCRB found for UID %lld: %pa\n", ctx.uid,
430+
&ctx.base);
431+
dport = devm_cxl_add_rch_dport(root_port, bridge, ctx.uid,
432+
ctx.base);
414433
} else {
415-
dev_dbg(match, "CHBCR found for UID %lld: %pa\n", uid, &ctx.base);
416-
dport = devm_cxl_add_dport(root_port, bridge, uid, ctx.base);
434+
dport = devm_cxl_add_dport(root_port, bridge, ctx.uid,
435+
CXL_RESOURCE_NONE);
417436
}
418437

419438
if (IS_ERR(dport))
@@ -435,6 +454,8 @@ static int add_host_bridge_uport(struct device *match, void *arg)
435454
struct cxl_dport *dport;
436455
struct cxl_port *port;
437456
struct device *bridge;
457+
struct cxl_chbs_context ctx;
458+
resource_size_t component_reg_phys;
438459
int rc;
439460

440461
if (!hb)
@@ -453,12 +474,26 @@ static int add_host_bridge_uport(struct device *match, void *arg)
453474
return 0;
454475
}
455476

477+
rc = cxl_get_chbs(match, hb, &ctx);
478+
if (rc)
479+
return rc;
480+
481+
if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) {
482+
dev_warn(bridge,
483+
"CXL CHBS version mismatch, skip port registration\n");
484+
return 0;
485+
}
486+
487+
component_reg_phys = ctx.base;
488+
if (component_reg_phys != CXL_RESOURCE_NONE)
489+
dev_dbg(match, "CHBCR found for UID %lld: %pa\n",
490+
ctx.uid, &component_reg_phys);
491+
456492
rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus);
457493
if (rc)
458494
return rc;
459495

460-
port = devm_cxl_add_port(host, bridge, dport->component_reg_phys,
461-
dport);
496+
port = devm_cxl_add_port(host, bridge, component_reg_phys, dport);
462497
if (IS_ERR(port))
463498
return PTR_ERR(port);
464499

0 commit comments

Comments
 (0)