diff options
Diffstat (limited to 'drivers/cxl/core/port.c')
-rw-r--r-- | drivers/cxl/core/port.c | 163 |
1 files changed, 113 insertions, 50 deletions
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index e7c284c890bc..724be8448eb4 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -56,6 +56,8 @@ static int cxl_device_id(const struct device *dev) return CXL_DEVICE_MEMORY_EXPANDER; if (dev->type == CXL_REGION_TYPE()) return CXL_DEVICE_REGION; + if (dev->type == &cxl_pmu_type) + return CXL_DEVICE_PMU; return 0; } @@ -117,9 +119,9 @@ static ssize_t target_type_show(struct device *dev, struct cxl_decoder *cxld = to_cxl_decoder(dev); switch (cxld->target_type) { - case CXL_DECODER_ACCELERATOR: + case CXL_DECODER_DEVMEM: return sysfs_emit(buf, "accelerator\n"); - case CXL_DECODER_EXPANDER: + case CXL_DECODER_HOSTONLYMEM: return sysfs_emit(buf, "expander\n"); } return -ENXIO; @@ -561,9 +563,9 @@ static void unregister_port(void *_port) * unregistered while holding their parent port lock. */ if (!parent) - lock_dev = port->uport; + lock_dev = port->uport_dev; else if (is_cxl_root(parent)) - lock_dev = parent->uport; + lock_dev = parent->uport_dev; else lock_dev = &parent->dev; @@ -583,7 +585,8 @@ static int devm_cxl_link_uport(struct device *host, struct cxl_port *port) { int rc; - rc = sysfs_create_link(&port->dev.kobj, &port->uport->kobj, "uport"); + rc = sysfs_create_link(&port->dev.kobj, &port->uport_dev->kobj, + "uport"); if (rc) return rc; return devm_add_action_or_reset(host, cxl_unlink_uport, port); @@ -605,7 +608,7 @@ static int devm_cxl_link_parent_dport(struct device *host, if (!parent_dport) return 0; - rc = sysfs_create_link(&port->dev.kobj, &parent_dport->dport->kobj, + rc = sysfs_create_link(&port->dev.kobj, &parent_dport->dport_dev->kobj, "parent_dport"); if (rc) return rc; @@ -614,7 +617,7 @@ static int devm_cxl_link_parent_dport(struct device *host, static struct lock_class_key cxl_port_key; -static struct cxl_port *cxl_port_alloc(struct device *uport, +static struct cxl_port *cxl_port_alloc(struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport) { @@ -630,7 +633,7 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, if (rc < 0) goto err; port->id = rc; - port->uport = uport; + port->uport_dev = uport_dev; /* * The top-level cxl_port "cxl_root" does not have a cxl_port as @@ -658,12 +661,13 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, if (iter->host_bridge) port->host_bridge = iter->host_bridge; else if (parent_dport->rch) - port->host_bridge = parent_dport->dport; + port->host_bridge = parent_dport->dport_dev; else - port->host_bridge = iter->uport; - dev_dbg(uport, "host-bridge: %s\n", dev_name(port->host_bridge)); + port->host_bridge = iter->uport_dev; + dev_dbg(uport_dev, "host-bridge: %s\n", + dev_name(port->host_bridge)); } else - dev->parent = uport; + dev->parent = uport_dev; port->component_reg_phys = component_reg_phys; ida_init(&port->decoder_ida); @@ -686,8 +690,38 @@ err: return ERR_PTR(rc); } +static int cxl_setup_comp_regs(struct device *dev, struct cxl_register_map *map, + resource_size_t component_reg_phys) +{ + if (component_reg_phys == CXL_RESOURCE_NONE) + return 0; + + *map = (struct cxl_register_map) { + .dev = dev, + .reg_type = CXL_REGLOC_RBI_COMPONENT, + .resource = component_reg_phys, + .max_size = CXL_COMPONENT_REG_BLOCK_SIZE, + }; + + return cxl_setup_regs(map); +} + +static inline int cxl_port_setup_regs(struct cxl_port *port, + resource_size_t component_reg_phys) +{ + return cxl_setup_comp_regs(&port->dev, &port->comp_map, + component_reg_phys); +} + +static inline int cxl_dport_setup_regs(struct cxl_dport *dport, + resource_size_t component_reg_phys) +{ + return cxl_setup_comp_regs(dport->dport_dev, &dport->comp_map, + component_reg_phys); +} + static struct cxl_port *__devm_cxl_add_port(struct device *host, - struct device *uport, + struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport) { @@ -695,12 +729,12 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host, struct device *dev; int rc; - port = cxl_port_alloc(uport, component_reg_phys, parent_dport); + port = cxl_port_alloc(uport_dev, component_reg_phys, parent_dport); if (IS_ERR(port)) return port; dev = &port->dev; - if (is_cxl_memdev(uport)) + if (is_cxl_memdev(uport_dev)) rc = dev_set_name(dev, "endpoint%d", port->id); else if (parent_dport) rc = dev_set_name(dev, "port%d", port->id); @@ -709,6 +743,10 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host, if (rc) goto err; + rc = cxl_port_setup_regs(port, component_reg_phys); + if (rc) + goto err; + rc = device_add(dev); if (rc) goto err; @@ -735,28 +773,29 @@ err: /** * devm_cxl_add_port - register a cxl_port in CXL memory decode hierarchy * @host: host device for devm operations - * @uport: "physical" device implementing this upstream port + * @uport_dev: "physical" device implementing this upstream port * @component_reg_phys: (optional) for configurable cxl_port instances * @parent_dport: next hop up in the CXL memory decode hierarchy */ -struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, +struct cxl_port *devm_cxl_add_port(struct device *host, + struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport) { struct cxl_port *port, *parent_port; - port = __devm_cxl_add_port(host, uport, component_reg_phys, + port = __devm_cxl_add_port(host, uport_dev, component_reg_phys, parent_dport); parent_port = parent_dport ? parent_dport->port : NULL; if (IS_ERR(port)) { - dev_dbg(uport, "Failed to add%s%s%s: %ld\n", + dev_dbg(uport_dev, "Failed to add%s%s%s: %ld\n", parent_port ? " port to " : "", parent_port ? dev_name(&parent_port->dev) : "", parent_port ? "" : " root port", PTR_ERR(port)); } else { - dev_dbg(uport, "%s added%s%s%s\n", + dev_dbg(uport_dev, "%s added%s%s%s\n", dev_name(&port->dev), parent_port ? " to " : "", parent_port ? dev_name(&parent_port->dev) : "", @@ -773,33 +812,34 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port) if (is_cxl_root(port)) return NULL; - if (dev_is_pci(port->uport)) { - struct pci_dev *pdev = to_pci_dev(port->uport); + if (dev_is_pci(port->uport_dev)) { + struct pci_dev *pdev = to_pci_dev(port->uport_dev); return pdev->subordinate; } - return xa_load(&cxl_root_buses, (unsigned long)port->uport); + return xa_load(&cxl_root_buses, (unsigned long)port->uport_dev); } EXPORT_SYMBOL_NS_GPL(cxl_port_to_pci_bus, CXL); -static void unregister_pci_bus(void *uport) +static void unregister_pci_bus(void *uport_dev) { - xa_erase(&cxl_root_buses, (unsigned long)uport); + xa_erase(&cxl_root_buses, (unsigned long)uport_dev); } -int devm_cxl_register_pci_bus(struct device *host, struct device *uport, +int devm_cxl_register_pci_bus(struct device *host, struct device *uport_dev, struct pci_bus *bus) { int rc; - if (dev_is_pci(uport)) + if (dev_is_pci(uport_dev)) return -EINVAL; - rc = xa_insert(&cxl_root_buses, (unsigned long)uport, bus, GFP_KERNEL); + rc = xa_insert(&cxl_root_buses, (unsigned long)uport_dev, bus, + GFP_KERNEL); if (rc) return rc; - return devm_add_action_or_reset(host, unregister_pci_bus, uport); + return devm_add_action_or_reset(host, unregister_pci_bus, uport_dev); } EXPORT_SYMBOL_NS_GPL(devm_cxl_register_pci_bus, CXL); @@ -847,22 +887,22 @@ static struct cxl_dport *find_dport(struct cxl_port *port, int id) return NULL; } -static int add_dport(struct cxl_port *port, struct cxl_dport *new) +static int add_dport(struct cxl_port *port, struct cxl_dport *dport) { struct cxl_dport *dup; int rc; device_lock_assert(&port->dev); - dup = find_dport(port, new->port_id); + dup = find_dport(port, dport->port_id); if (dup) { dev_err(&port->dev, "unable to add dport%d-%s non-unique port id (%s)\n", - new->port_id, dev_name(new->dport), - dev_name(dup->dport)); + dport->port_id, dev_name(dport->dport_dev), + dev_name(dup->dport_dev)); return -EBUSY; } - rc = xa_insert(&port->dports, (unsigned long)new->dport, new, + rc = xa_insert(&port->dports, (unsigned long)dport->dport_dev, dport, GFP_KERNEL); if (rc) return rc; @@ -895,8 +935,8 @@ static void cxl_dport_remove(void *data) struct cxl_dport *dport = data; struct cxl_port *port = dport->port; - xa_erase(&port->dports, (unsigned long) dport->dport); - put_device(dport->dport); + xa_erase(&port->dports, (unsigned long) dport->dport_dev); + put_device(dport->dport_dev); } static void cxl_dport_unlink(void *data) @@ -920,7 +960,7 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev, int rc; if (is_cxl_root(port)) - host = port->uport; + host = port->uport_dev; else host = &port->dev; @@ -938,13 +978,29 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev, if (!dport) return ERR_PTR(-ENOMEM); - dport->dport = dport_dev; + if (rcrb != CXL_RESOURCE_NONE) { + dport->rcrb.base = rcrb; + component_reg_phys = __rcrb_to_component(dport_dev, &dport->rcrb, + CXL_RCRB_DOWNSTREAM); + if (component_reg_phys == CXL_RESOURCE_NONE) { + dev_warn(dport_dev, "Invalid Component Registers in RCRB"); + return ERR_PTR(-ENXIO); + } + + dport->rch = true; + } + + if (component_reg_phys != CXL_RESOURCE_NONE) + dev_dbg(dport_dev, "Component Registers found for dport: %pa\n", + &component_reg_phys); + + dport->dport_dev = dport_dev; dport->port_id = port_id; - dport->component_reg_phys = component_reg_phys; dport->port = port; - if (rcrb != CXL_RESOURCE_NONE) - dport->rch = true; - dport->rcrb = rcrb; + + rc = cxl_dport_setup_regs(dport, component_reg_phys); + if (rc) + return ERR_PTR(rc); cond_cxl_root_lock(port); rc = add_dport(port, dport); @@ -1004,14 +1060,12 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL); * @port: the cxl_port that references this dport * @dport_dev: firmware or PCI device representing the dport * @port_id: identifier for this dport in a decoder's target list - * @component_reg_phys: optional location of CXL component registers * @rcrb: mandatory location of a Root Complex Register Block * * See CXL 3.0 9.11.8 CXL Devices Attached to an RCH */ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, struct device *dport_dev, int port_id, - resource_size_t component_reg_phys, resource_size_t rcrb) { struct cxl_dport *dport; @@ -1022,7 +1076,7 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, } dport = __devm_cxl_add_dport(port, dport_dev, port_id, - component_reg_phys, rcrb); + CXL_RESOURCE_NONE, rcrb); if (IS_ERR(dport)) { dev_dbg(dport_dev, "failed to add RCH dport to %s: %ld\n", dev_name(&port->dev), PTR_ERR(dport)); @@ -1161,7 +1215,7 @@ static struct device *grandparent(struct device *dev) static void delete_endpoint(void *data) { struct cxl_memdev *cxlmd = data; - struct cxl_port *endpoint = dev_get_drvdata(&cxlmd->dev); + struct cxl_port *endpoint = cxlmd->endpoint; struct cxl_port *parent_port; struct device *parent; @@ -1176,6 +1230,7 @@ static void delete_endpoint(void *data) devm_release_action(parent, cxl_unlink_uport, endpoint); devm_release_action(parent, unregister_port, endpoint); } + cxlmd->endpoint = NULL; device_unlock(parent); put_device(parent); out: @@ -1187,7 +1242,7 @@ int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint) struct device *dev = &cxlmd->dev; get_device(&endpoint->dev); - dev_set_drvdata(dev, endpoint); + cxlmd->endpoint = endpoint; cxlmd->depth = endpoint->depth; return devm_add_action_or_reset(dev, delete_endpoint, cxlmd); } @@ -1363,7 +1418,7 @@ out: rc = PTR_ERR(port); else { dev_dbg(&cxlmd->dev, "add to new port %s:%s\n", - dev_name(&port->dev), dev_name(port->uport)); + dev_name(&port->dev), dev_name(port->uport_dev)); rc = cxl_add_ep(dport, &cxlmd->dev); if (rc == -EBUSY) { /* @@ -1425,7 +1480,8 @@ retry: if (port) { dev_dbg(&cxlmd->dev, "found already registered port %s:%s\n", - dev_name(&port->dev), dev_name(port->uport)); + dev_name(&port->dev), + dev_name(port->uport_dev)); rc = cxl_add_ep(dport, &cxlmd->dev); /* @@ -1465,6 +1521,13 @@ retry: } EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, CXL); +struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev, + struct cxl_dport **dport) +{ + return find_cxl_port(pdev->dev.parent, dport); +} +EXPORT_SYMBOL_NS_GPL(cxl_pci_find_port, CXL); + struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd, struct cxl_dport **dport) { @@ -1550,7 +1613,7 @@ static int cxl_decoder_init(struct cxl_port *port, struct cxl_decoder *cxld) /* Pre initialize an "empty" decoder */ cxld->interleave_ways = 1; cxld->interleave_granularity = PAGE_SIZE; - cxld->target_type = CXL_DECODER_EXPANDER; + cxld->target_type = CXL_DECODER_HOSTONLYMEM; cxld->hpa_range = (struct range) { .start = 0, .end = -1, |