Skip to content

Commit eb4663b

Browse files
Robert Richterdjbw
authored andcommitted
cxl/acpi: Probe RCRB later during RCH downstream port creation
The RCRB is extracted already during ACPI CEDT table parsing while the data of this is needed not earlier than dport creation. This implementation comes with drawbacks: During ACPI table scan there is already MMIO access including mapping and unmapping, but only ACPI data should be collected here. The collected data must be transferred through a couple of interfaces until it is finally consumed when creating the dport. This causes complex data structures and function interfaces. Additionally, RCRB parsing will be extended to also extract AER data, it would be much easier do this at a later point during port and dport creation when the data structures are available to hold that data. To simplify all that, probe the RCRB at a later point during RCH downstream port creation. Change ACPI table parser to only extract the base address of either the component registers or the RCRB. Parse and extract the RCRB in devm_cxl_add_rch_dport(). This is in preparation to centralize all RCRB scanning. 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-2-terry.bowman@amd.com Co-developed-by: Dan Williams <dan.j.williams@intel.com> Link: https://lore.kernel.org/r/20230622205523.85375-3-terry.bowman@amd.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 858fd16 commit eb4663b

10 files changed

Lines changed: 90 additions & 71 deletions

File tree

drivers/cxl/acpi.c

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -372,21 +372,21 @@ static int add_host_bridge_uport(struct device *match, void *arg)
372372
return 0;
373373
}
374374

375+
/* Note, @dev is used by mock_acpi_table_parse_cedt() */
375376
struct cxl_chbs_context {
376377
struct device *dev;
377378
unsigned long long uid;
378-
resource_size_t rcrb;
379-
resource_size_t chbcr;
379+
resource_size_t base;
380380
u32 cxl_version;
381381
};
382382

383-
static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
383+
static int cxl_get_chbs(union acpi_subtable_headers *header, void *arg,
384384
const unsigned long end)
385385
{
386386
struct cxl_chbs_context *ctx = arg;
387387
struct acpi_cedt_chbs *chbs;
388388

389-
if (ctx->chbcr)
389+
if (ctx->base)
390390
return 0;
391391

392392
chbs = (struct acpi_cedt_chbs *) header;
@@ -395,23 +395,16 @@ static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
395395
return 0;
396396

397397
ctx->cxl_version = chbs->cxl_version;
398-
ctx->rcrb = CXL_RESOURCE_NONE;
399-
ctx->chbcr = CXL_RESOURCE_NONE;
398+
ctx->base = CXL_RESOURCE_NONE;
400399

401400
if (!chbs->base)
402401
return 0;
403402

404-
if (chbs->cxl_version != ACPI_CEDT_CHBS_VERSION_CXL11) {
405-
ctx->chbcr = chbs->base;
406-
return 0;
407-
}
408-
409-
if (chbs->length != CXL_RCRB_SIZE)
403+
if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 &&
404+
chbs->length != CXL_RCRB_SIZE)
410405
return 0;
411406

412-
ctx->rcrb = chbs->base;
413-
ctx->chbcr = cxl_rcrb_to_component(ctx->dev, chbs->base,
414-
CXL_RCRB_DOWNSTREAM);
407+
ctx->base = chbs->base;
415408

416409
return 0;
417410
}
@@ -443,33 +436,31 @@ static int add_host_bridge_dport(struct device *match, void *arg)
443436
.dev = match,
444437
.uid = uid,
445438
};
446-
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbcr, &ctx);
439+
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbs, &ctx);
447440

448-
if (!ctx.chbcr) {
441+
if (!ctx.base) {
449442
dev_warn(match, "No CHBS found for Host Bridge (UID %lld)\n",
450443
uid);
451444
return 0;
452445
}
453446

454-
if (ctx.rcrb != CXL_RESOURCE_NONE)
455-
dev_dbg(match, "RCRB found for UID %lld: %pa\n", uid, &ctx.rcrb);
456-
457-
if (ctx.chbcr == CXL_RESOURCE_NONE) {
458-
dev_warn(match, "CHBCR invalid for Host Bridge (UID %lld)\n",
447+
if (ctx.base == CXL_RESOURCE_NONE) {
448+
dev_warn(match, "CHBS invalid for Host Bridge (UID %lld)\n",
459449
uid);
460450
return 0;
461451
}
462452

463-
dev_dbg(match, "CHBCR found: %pa\n", &ctx.chbcr);
464-
465453
pci_root = acpi_pci_find_root(hb->handle);
466454
bridge = pci_root->bus->bridge;
467-
if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11)
468-
dport = devm_cxl_add_rch_dport(root_port, bridge, uid,
469-
ctx.chbcr, ctx.rcrb);
470-
else
471-
dport = devm_cxl_add_dport(root_port, bridge, uid,
472-
ctx.chbcr);
455+
456+
if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) {
457+
dev_dbg(match, "RCRB found for UID %lld: %pa\n", uid, &ctx.base);
458+
dport = devm_cxl_add_rch_dport(root_port, bridge, uid, ctx.base);
459+
} else {
460+
dev_dbg(match, "CHBCR found for UID %lld: %pa\n", uid, &ctx.base);
461+
dport = devm_cxl_add_dport(root_port, bridge, uid, ctx.base);
462+
}
463+
473464
if (IS_ERR(dport))
474465
return PTR_ERR(dport);
475466

drivers/cxl/core/core.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size);
6363
int cxl_dpa_free(struct cxl_endpoint_decoder *cxled);
6464
resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled);
6565
resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled);
66+
67+
enum cxl_rcrb {
68+
CXL_RCRB_DOWNSTREAM,
69+
CXL_RCRB_UPSTREAM,
70+
};
71+
resource_size_t __rcrb_to_component(struct device *dev, resource_size_t rcrb,
72+
enum cxl_rcrb which);
73+
6674
extern struct rw_semaphore cxl_dpa_rwsem;
6775

6876
int cxl_memdev_init(void);

drivers/cxl/core/port.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -938,12 +938,25 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
938938
if (!dport)
939939
return ERR_PTR(-ENOMEM);
940940

941+
if (rcrb != CXL_RESOURCE_NONE) {
942+
component_reg_phys = __rcrb_to_component(dport_dev, rcrb,
943+
CXL_RCRB_DOWNSTREAM);
944+
if (component_reg_phys == CXL_RESOURCE_NONE) {
945+
dev_warn(dport_dev, "Invalid Component Registers in RCRB");
946+
return ERR_PTR(-ENXIO);
947+
}
948+
949+
dport->rch = true;
950+
}
951+
952+
if (component_reg_phys != CXL_RESOURCE_NONE)
953+
dev_dbg(dport_dev, "Component Registers found for dport: %pa\n",
954+
&component_reg_phys);
955+
941956
dport->dport = dport_dev;
942957
dport->port_id = port_id;
943958
dport->component_reg_phys = component_reg_phys;
944959
dport->port = port;
945-
if (rcrb != CXL_RESOURCE_NONE)
946-
dport->rch = true;
947960
dport->rcrb = rcrb;
948961

949962
cond_cxl_root_lock(port);
@@ -1004,14 +1017,12 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL);
10041017
* @port: the cxl_port that references this dport
10051018
* @dport_dev: firmware or PCI device representing the dport
10061019
* @port_id: identifier for this dport in a decoder's target list
1007-
* @component_reg_phys: optional location of CXL component registers
10081020
* @rcrb: mandatory location of a Root Complex Register Block
10091021
*
10101022
* See CXL 3.0 9.11.8 CXL Devices Attached to an RCH
10111023
*/
10121024
struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
10131025
struct device *dport_dev, int port_id,
1014-
resource_size_t component_reg_phys,
10151026
resource_size_t rcrb)
10161027
{
10171028
struct cxl_dport *dport;
@@ -1022,7 +1033,7 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
10221033
}
10231034

10241035
dport = __devm_cxl_add_dport(port, dport_dev, port_id,
1025-
component_reg_phys, rcrb);
1036+
CXL_RESOURCE_NONE, rcrb);
10261037
if (IS_ERR(dport)) {
10271038
dev_dbg(dport_dev, "failed to add RCH dport to %s: %ld\n",
10281039
dev_name(&port->dev), PTR_ERR(dport));

drivers/cxl/core/regs.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,9 +332,8 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
332332
}
333333
EXPORT_SYMBOL_NS_GPL(cxl_find_regblock, CXL);
334334

335-
resource_size_t cxl_rcrb_to_component(struct device *dev,
336-
resource_size_t rcrb,
337-
enum cxl_rcrb which)
335+
resource_size_t __rcrb_to_component(struct device *dev, resource_size_t rcrb,
336+
enum cxl_rcrb which)
338337
{
339338
resource_size_t component_reg_phys;
340339
void __iomem *addr;
@@ -395,4 +394,12 @@ resource_size_t cxl_rcrb_to_component(struct device *dev,
395394

396395
return component_reg_phys;
397396
}
398-
EXPORT_SYMBOL_NS_GPL(cxl_rcrb_to_component, CXL);
397+
398+
resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
399+
struct cxl_dport *dport)
400+
{
401+
if (!dport->rch)
402+
return CXL_RESOURCE_NONE;
403+
return __rcrb_to_component(dev, dport->rcrb, CXL_RCRB_UPSTREAM);
404+
}
405+
EXPORT_SYMBOL_NS_GPL(cxl_rcd_component_reg_phys, CXL);

drivers/cxl/cxl.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -262,14 +262,9 @@ int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs,
262262
enum cxl_regloc_type;
263263
int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
264264
struct cxl_register_map *map);
265-
266-
enum cxl_rcrb {
267-
CXL_RCRB_DOWNSTREAM,
268-
CXL_RCRB_UPSTREAM,
269-
};
270-
resource_size_t cxl_rcrb_to_component(struct device *dev,
271-
resource_size_t rcrb,
272-
enum cxl_rcrb which);
265+
struct cxl_dport;
266+
resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
267+
struct cxl_dport *dport);
273268

274269
#define CXL_RESOURCE_NONE ((resource_size_t) -1)
275270
#define CXL_TARGET_STRLEN 20
@@ -671,7 +666,6 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
671666
resource_size_t component_reg_phys);
672667
struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
673668
struct device *dport_dev, int port_id,
674-
resource_size_t component_reg_phys,
675669
resource_size_t rcrb);
676670

677671
struct cxl_decoder *to_cxl_decoder(struct device *dev);

drivers/cxl/mem.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
7272
* typical register locator mechanism.
7373
*/
7474
if (parent_dport->rch && cxlds->component_reg_phys == CXL_RESOURCE_NONE)
75-
component_reg_phys = cxl_rcrb_to_component(
76-
&cxlmd->dev, parent_dport->rcrb, CXL_RCRB_UPSTREAM);
75+
component_reg_phys =
76+
cxl_rcd_component_reg_phys(&cxlmd->dev, parent_dport);
7777
else
7878
component_reg_phys = cxlds->component_reg_phys;
7979
endpoint = devm_cxl_add_port(host, &cxlmd->dev, component_reg_phys,

tools/testing/cxl/Kbuild

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ ldflags-y += --wrap=devm_cxl_enumerate_decoders
1212
ldflags-y += --wrap=cxl_await_media_ready
1313
ldflags-y += --wrap=cxl_hdm_decode_init
1414
ldflags-y += --wrap=cxl_dvsec_rr_decode
15-
ldflags-y += --wrap=cxl_rcrb_to_component
15+
ldflags-y += --wrap=devm_cxl_add_rch_dport
16+
ldflags-y += --wrap=cxl_rcd_component_reg_phys
1617

1718
DRIVERS := ../../../drivers
1819
CXL_SRC := $(DRIVERS)/cxl

tools/testing/cxl/test/cxl.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -971,15 +971,6 @@ static int mock_cxl_port_enumerate_dports(struct cxl_port *port)
971971
return 0;
972972
}
973973

974-
resource_size_t mock_cxl_rcrb_to_component(struct device *dev,
975-
resource_size_t rcrb,
976-
enum cxl_rcrb which)
977-
{
978-
dev_dbg(dev, "rcrb: %pa which: %d\n", &rcrb, which);
979-
980-
return (resource_size_t) which + 1;
981-
}
982-
983974
static struct cxl_mock_ops cxl_mock_ops = {
984975
.is_mock_adev = is_mock_adev,
985976
.is_mock_bridge = is_mock_bridge,
@@ -988,7 +979,6 @@ static struct cxl_mock_ops cxl_mock_ops = {
988979
.is_mock_dev = is_mock_dev,
989980
.acpi_table_parse_cedt = mock_acpi_table_parse_cedt,
990981
.acpi_evaluate_integer = mock_acpi_evaluate_integer,
991-
.cxl_rcrb_to_component = mock_cxl_rcrb_to_component,
992982
.acpi_pci_find_root = mock_acpi_pci_find_root,
993983
.devm_cxl_port_enumerate_dports = mock_cxl_port_enumerate_dports,
994984
.devm_cxl_setup_hdm = mock_cxl_setup_hdm,

tools/testing/cxl/test/mock.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,24 +259,44 @@ int __wrap_cxl_dvsec_rr_decode(struct device *dev, int dvsec,
259259
}
260260
EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, CXL);
261261

262-
resource_size_t __wrap_cxl_rcrb_to_component(struct device *dev,
263-
resource_size_t rcrb,
264-
enum cxl_rcrb which)
262+
struct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port,
263+
struct device *dport_dev,
264+
int port_id,
265+
resource_size_t rcrb)
266+
{
267+
int index;
268+
struct cxl_dport *dport;
269+
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
270+
271+
if (ops && ops->is_mock_port(dport_dev)) {
272+
dport = devm_cxl_add_dport(port, dport_dev, port_id,
273+
CXL_RESOURCE_NONE);
274+
if (!IS_ERR(dport))
275+
dport->rch = true;
276+
} else
277+
dport = devm_cxl_add_rch_dport(port, dport_dev, port_id, rcrb);
278+
put_cxl_mock_ops(index);
279+
280+
return dport;
281+
}
282+
EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, CXL);
283+
284+
resource_size_t __wrap_cxl_rcd_component_reg_phys(struct device *dev,
285+
struct cxl_dport *dport)
265286
{
266287
int index;
267288
resource_size_t component_reg_phys;
268289
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
269290

270291
if (ops && ops->is_mock_port(dev))
271-
component_reg_phys =
272-
ops->cxl_rcrb_to_component(dev, rcrb, which);
292+
component_reg_phys = CXL_RESOURCE_NONE;
273293
else
274-
component_reg_phys = cxl_rcrb_to_component(dev, rcrb, which);
294+
component_reg_phys = cxl_rcd_component_reg_phys(dev, dport);
275295
put_cxl_mock_ops(index);
276296

277297
return component_reg_phys;
278298
}
279-
EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcrb_to_component, CXL);
299+
EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, CXL);
280300

281301
MODULE_LICENSE("GPL v2");
282302
MODULE_IMPORT_NS(ACPI);

tools/testing/cxl/test/mock.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ struct cxl_mock_ops {
1515
acpi_string pathname,
1616
struct acpi_object_list *arguments,
1717
unsigned long long *data);
18-
resource_size_t (*cxl_rcrb_to_component)(struct device *dev,
19-
resource_size_t rcrb,
20-
enum cxl_rcrb which);
2118
struct acpi_pci_root *(*acpi_pci_find_root)(acpi_handle handle);
2219
bool (*is_mock_bus)(struct pci_bus *bus);
2320
bool (*is_mock_port)(struct device *dev);

0 commit comments

Comments
 (0)