The host will not be able to access the CXL memory on devices enabled/added below an isolated CXL downstream port. Add a check during cxl_mem probe to prevent adding devices below an isolated port. Also add a check to prevent CXL region creation below an isolated port for previously disabled devices below the port. Signed-off-by: Ben Cheatham <Benjamin.Cheatham@xxxxxxx> --- drivers/cxl/core/port.c | 28 ++++++++++++++++++++++++++++ drivers/cxl/core/region.c | 3 +++ drivers/cxl/cxl.h | 2 ++ 3 files changed, 33 insertions(+) diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index 90588bf927e0..c9e7bfc082d5 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -869,6 +869,13 @@ static int cxl_port_add(struct cxl_port *port, */ port->reg_map = cxlds->reg_map; port->reg_map.host = &port->dev; + + if (cxl_endpoint_port_isolated(port)) { + dev_err(&port->dev, + "port is under isolated CXL dport\n"); + return -EBUSY; + } + cxlmd->endpoint = port; } else if (parent_dport) { rc = dev_set_name(dev, "port%d", port->id); @@ -1174,6 +1181,27 @@ static void cxl_dport_unlink(void *data) sysfs_remove_link(&port->dev.kobj, link_name); } +bool cxl_endpoint_port_isolated(struct cxl_port *ep) +{ + struct cxl_dport *iter; + u32 status; + + for (iter = ep->parent_dport; + iter && iter->port && !is_cxl_root(iter->port); + iter = iter->port->parent_dport) { + if (!iter->regs.isolation) + continue; + + status = readl(iter->regs.isolation + + CXL_ISOLATION_STATUS_OFFSET); + if (!(status & CXL_ISOLATION_STATUS_OFFSET)) + return true; + } + + return false; +} +EXPORT_SYMBOL_NS_GPL(cxl_endpoint_port_isolated, "CXL"); + struct isolation_intr_data { struct cxl_dport *dport; struct cxl_port *port; diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index b94fda6f2e4c..db9ff3b683aa 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -3407,6 +3407,9 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd, int rc, part = READ_ONCE(cxled->part); struct cxl_region *cxlr; + if (cxl_endpoint_port_isolated(cxlmd->endpoint)) + return ERR_PTR(-EBUSY); + do { cxlr = __create_region(cxlrd, cxlds->part[part].mode, atomic_read(&cxlrd->region_id)); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 62b3ed188949..8da1e40ab4e7 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -838,6 +838,8 @@ pci_ers_result_t cxl_error_detected(struct device *dev); void cxl_port_cor_error_detected(struct device *dev); pci_ers_result_t cxl_port_error_detected(struct device *dev); +bool cxl_endpoint_port_isolated(struct cxl_port *port); + /** * struct cxl_endpoint_dvsec_info - Cached DVSEC info * @mem_enabled: cached value of mem_enabled in the DVSEC at init time -- 2.34.1