Skip to content

Commit 0c0df63

Browse files
committed
Merge branch 'for-6.5/cxl-rch-eh' into for-6.5/cxl
Pick up the first half of the RCH error handling series. The back half needs some fixups for test regressions. Small conflicts with the PMU work around register enumeration and setup helpers.
2 parents d2f9fe6 + 5d2ffbe commit 0c0df63

16 files changed

Lines changed: 488 additions & 326 deletions

File tree

drivers/cxl/acpi.c

Lines changed: 116 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -327,66 +327,21 @@ __mock struct acpi_device *to_cxl_host_bridge(struct device *host,
327327
return NULL;
328328
}
329329

330-
/*
331-
* A host bridge is a dport to a CFMWS decode and it is a uport to the
332-
* dport (PCIe Root Ports) in the host bridge.
333-
*/
334-
static int add_host_bridge_uport(struct device *match, void *arg)
335-
{
336-
struct cxl_port *root_port = arg;
337-
struct device *host = root_port->dev.parent;
338-
struct acpi_device *hb = to_cxl_host_bridge(host, match);
339-
struct acpi_pci_root *pci_root;
340-
struct cxl_dport *dport;
341-
struct cxl_port *port;
342-
struct device *bridge;
343-
int rc;
344-
345-
if (!hb)
346-
return 0;
347-
348-
pci_root = acpi_pci_find_root(hb->handle);
349-
bridge = pci_root->bus->bridge;
350-
dport = cxl_find_dport_by_dev(root_port, bridge);
351-
if (!dport) {
352-
dev_dbg(host, "host bridge expected and not found\n");
353-
return 0;
354-
}
355-
356-
if (dport->rch) {
357-
dev_info(bridge, "host supports CXL (restricted)\n");
358-
return 0;
359-
}
360-
361-
rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus);
362-
if (rc)
363-
return rc;
364-
365-
port = devm_cxl_add_port(host, bridge, dport->component_reg_phys,
366-
dport);
367-
if (IS_ERR(port))
368-
return PTR_ERR(port);
369-
370-
dev_info(bridge, "host supports CXL\n");
371-
372-
return 0;
373-
}
374-
330+
/* Note, @dev is used by mock_acpi_table_parse_cedt() */
375331
struct cxl_chbs_context {
376332
struct device *dev;
377333
unsigned long long uid;
378-
resource_size_t rcrb;
379-
resource_size_t chbcr;
334+
resource_size_t base;
380335
u32 cxl_version;
381336
};
382337

383-
static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
384-
const unsigned long end)
338+
static int cxl_get_chbs_iter(union acpi_subtable_headers *header, void *arg,
339+
const unsigned long end)
385340
{
386341
struct cxl_chbs_context *ctx = arg;
387342
struct acpi_cedt_chbs *chbs;
388343

389-
if (ctx->chbcr)
344+
if (ctx->base != CXL_RESOURCE_NONE)
390345
return 0;
391346

392347
chbs = (struct acpi_cedt_chbs *) header;
@@ -395,23 +350,39 @@ static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
395350
return 0;
396351

397352
ctx->cxl_version = chbs->cxl_version;
398-
ctx->rcrb = CXL_RESOURCE_NONE;
399-
ctx->chbcr = CXL_RESOURCE_NONE;
400-
401353
if (!chbs->base)
402354
return 0;
403355

404-
if (chbs->cxl_version != ACPI_CEDT_CHBS_VERSION_CXL11) {
405-
ctx->chbcr = chbs->base;
356+
if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 &&
357+
chbs->length != CXL_RCRB_SIZE)
406358
return 0;
359+
360+
ctx->base = chbs->base;
361+
362+
return 0;
363+
}
364+
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;
407375
}
408376

409-
if (chbs->length != CXL_RCRB_SIZE)
410-
return 0;
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+
};
411384

412-
ctx->rcrb = chbs->base;
413-
ctx->chbcr = cxl_rcrb_to_component(ctx->dev, chbs->base,
414-
CXL_RCRB_DOWNSTREAM);
385+
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbs_iter, ctx);
415386

416387
return 0;
417388
}
@@ -420,7 +391,6 @@ static int add_host_bridge_dport(struct device *match, void *arg)
420391
{
421392
acpi_status rc;
422393
struct device *bridge;
423-
unsigned long long uid;
424394
struct cxl_dport *dport;
425395
struct cxl_chbs_context ctx;
426396
struct acpi_pci_root *pci_root;
@@ -431,51 +401,107 @@ static int add_host_bridge_dport(struct device *match, void *arg)
431401
if (!hb)
432402
return 0;
433403

434-
rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid);
435-
if (rc != AE_OK) {
436-
dev_err(match, "unable to retrieve _UID\n");
437-
return -ENODEV;
438-
}
439-
440-
dev_dbg(match, "UID found: %lld\n", uid);
441-
442-
ctx = (struct cxl_chbs_context) {
443-
.dev = match,
444-
.uid = uid,
445-
};
446-
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbcr, &ctx);
404+
rc = cxl_get_chbs(match, hb, &ctx);
405+
if (rc)
406+
return rc;
447407

448-
if (!ctx.chbcr) {
408+
if (ctx.cxl_version == UINT_MAX) {
449409
dev_warn(match, "No CHBS found for Host Bridge (UID %lld)\n",
450-
uid);
410+
ctx.uid);
451411
return 0;
452412
}
453413

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",
459-
uid);
414+
if (ctx.base == CXL_RESOURCE_NONE) {
415+
dev_warn(match, "CHBS invalid for Host Bridge (UID %lld)\n",
416+
ctx.uid);
460417
return 0;
461418
}
462419

463-
dev_dbg(match, "CHBCR found: %pa\n", &ctx.chbcr);
464-
465420
pci_root = acpi_pci_find_root(hb->handle);
466421
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);
422+
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+
*/
428+
if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) {
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);
433+
} else {
434+
dport = devm_cxl_add_dport(root_port, bridge, ctx.uid,
435+
CXL_RESOURCE_NONE);
436+
}
437+
473438
if (IS_ERR(dport))
474439
return PTR_ERR(dport);
475440

476441
return 0;
477442
}
478443

444+
/*
445+
* A host bridge is a dport to a CFMWS decode and it is a uport to the
446+
* dport (PCIe Root Ports) in the host bridge.
447+
*/
448+
static int add_host_bridge_uport(struct device *match, void *arg)
449+
{
450+
struct cxl_port *root_port = arg;
451+
struct device *host = root_port->dev.parent;
452+
struct acpi_device *hb = to_cxl_host_bridge(host, match);
453+
struct acpi_pci_root *pci_root;
454+
struct cxl_dport *dport;
455+
struct cxl_port *port;
456+
struct device *bridge;
457+
struct cxl_chbs_context ctx;
458+
resource_size_t component_reg_phys;
459+
int rc;
460+
461+
if (!hb)
462+
return 0;
463+
464+
pci_root = acpi_pci_find_root(hb->handle);
465+
bridge = pci_root->bus->bridge;
466+
dport = cxl_find_dport_by_dev(root_port, bridge);
467+
if (!dport) {
468+
dev_dbg(host, "host bridge expected and not found\n");
469+
return 0;
470+
}
471+
472+
if (dport->rch) {
473+
dev_info(bridge, "host supports CXL (restricted)\n");
474+
return 0;
475+
}
476+
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+
492+
rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus);
493+
if (rc)
494+
return rc;
495+
496+
port = devm_cxl_add_port(host, bridge, component_reg_phys, dport);
497+
if (IS_ERR(port))
498+
return PTR_ERR(port);
499+
500+
dev_info(bridge, "host supports CXL\n");
501+
502+
return 0;
503+
}
504+
479505
static int add_root_nvdimm_bridge(struct device *match, void *data)
480506
{
481507
struct cxl_decoder *cxld;

drivers/cxl/core/core.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size);
6464
int cxl_dpa_free(struct cxl_endpoint_decoder *cxled);
6565
resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled);
6666
resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled);
67+
68+
enum cxl_rcrb {
69+
CXL_RCRB_DOWNSTREAM,
70+
CXL_RCRB_UPSTREAM,
71+
};
72+
struct cxl_rcrb_info;
73+
resource_size_t __rcrb_to_component(struct device *dev,
74+
struct cxl_rcrb_info *ri,
75+
enum cxl_rcrb which);
76+
6777
extern struct rw_semaphore cxl_dpa_rwsem;
6878

6979
int cxl_memdev_init(void);

drivers/cxl/core/hdm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
8585
struct cxl_component_regs *regs)
8686
{
8787
struct cxl_register_map map = {
88+
.dev = &port->dev,
8889
.resource = port->component_reg_phys,
8990
.base = crb,
9091
.max_size = CXL_COMPONENT_REG_BLOCK_SIZE,
@@ -97,8 +98,7 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
9798
return -ENODEV;
9899
}
99100

100-
return cxl_map_component_regs(&port->dev, regs, &map,
101-
BIT(CXL_CM_CAP_CAP_ID_HDM));
101+
return cxl_map_component_regs(&map, regs, BIT(CXL_CM_CAP_CAP_ID_HDM));
102102
}
103103

104104
static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)

drivers/cxl/core/pci.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static int match_add_dports(struct pci_dev *pdev, void *data)
6767

6868
/**
6969
* devm_cxl_port_enumerate_dports - enumerate downstream ports of the upstream port
70-
* @port: cxl_port whose ->uport is the upstream of dports to be enumerated
70+
* @port: cxl_port whose ->uport_dev is the upstream of dports to be enumerated
7171
*
7272
* Returns a positive number of dports enumerated or a negative error
7373
* code.
@@ -603,7 +603,7 @@ static int cxl_cdat_read_table(struct device *dev,
603603
*/
604604
void read_cdat_data(struct cxl_port *port)
605605
{
606-
struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport);
606+
struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
607607
struct device *host = cxlmd->dev.parent;
608608
struct device *dev = &port->dev;
609609
struct pci_doe_mb *cdat_doe;

0 commit comments

Comments
 (0)