cxld->interleave_granularity =
CFMWS_INTERLEAVE_GRANULARITY(cfmws);
- rc = devm_cxl_add_decoder(dev, cxld, target_map);
+ rc = cxl_decoder_add(dev, cxld, target_map);
+ if (rc)
+ put_device(&cxld->dev);
+ else
+ rc = cxl_decoder_autoremove(dev, cxld);
if (rc) {
dev_err(dev, "Failed to add decoder for %#llx-%#llx\n",
cfmws->base_hpa, cfmws->base_hpa +
single_port_map[0] = dport->port_id;
- rc = devm_cxl_add_decoder(host, cxld, single_port_map);
+ rc = cxl_decoder_add(host, cxld, single_port_map);
+ if (rc)
+ put_device(&cxld->dev);
+ else
+ rc = cxl_decoder_autoremove(host, cxld);
+
if (rc == 0)
dev_dbg(host, "add: %s\n", dev_name(&cxld->dev));
-
return rc;
}
}
EXPORT_SYMBOL_GPL(cxl_decoder_alloc);
-int devm_cxl_add_decoder(struct device *host, struct cxl_decoder *cxld,
- int *target_map)
+int cxl_decoder_add(struct device *host, struct cxl_decoder *cxld,
+ int *target_map)
{
- struct cxl_port *port = to_cxl_port(cxld->dev.parent);
+ struct cxl_port *port;
struct device *dev;
int rc = 0, i;
if (IS_ERR(cxld))
return PTR_ERR(cxld);
- if (cxld->interleave_ways < 1) {
- rc = -EINVAL;
- goto err;
- }
+ if (cxld->interleave_ways < 1)
+ return -EINVAL;
+ port = to_cxl_port(cxld->dev.parent);
device_lock(&port->dev);
- if (list_empty(&port->dports))
+ if (list_empty(&port->dports)) {
rc = -EINVAL;
+ goto out_unlock;
+ }
for (i = 0; rc == 0 && target_map && i < cxld->nr_targets; i++) {
struct cxl_dport *dport = find_dport(port, target_map[i]);
if (!dport) {
rc = -ENXIO;
- break;
+ goto out_unlock;
}
dev_dbg(host, "%s: target: %d\n", dev_name(dport->dport), i);
cxld->target[i] = dport;
}
device_unlock(&port->dev);
- if (rc)
- goto err;
dev = &cxld->dev;
rc = dev_set_name(dev, "decoder%d.%d", port->id, cxld->id);
if (rc)
- goto err;
+ return rc;
- rc = device_add(dev);
- if (rc)
- goto err;
+ return device_add(dev);
- return devm_add_action_or_reset(host, unregister_cxl_dev, dev);
-err:
- put_device(dev);
+out_unlock:
+ device_unlock(&port->dev);
return rc;
}
-EXPORT_SYMBOL_GPL(devm_cxl_add_decoder);
+EXPORT_SYMBOL_GPL(cxl_decoder_add);
+
+static void cxld_unregister(void *dev)
+{
+ device_unregister(dev);
+}
+
+int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld)
+{
+ return devm_add_action_or_reset(host, cxld_unregister, &cxld->dev);
+}
+EXPORT_SYMBOL_GPL(cxl_decoder_autoremove);
/**
* __cxl_driver_register - register a driver for the cxl bus
extern struct attribute_group cxl_base_attribute_group;
-static inline void unregister_cxl_dev(void *dev)
-{
- device_unregister(dev);
-}
-
struct cxl_send_command;
struct cxl_mem_query_commands;
int cxl_query_cmd(struct cxl_memdev *cxlmd,
return cxl_nvd;
}
+static void cxl_nvd_unregister(void *dev)
+{
+ device_unregister(dev);
+}
+
int devm_cxl_add_nvdimm(struct device *host, struct cxl_memdev *cxlmd)
{
struct cxl_nvdimm *cxl_nvd;
dev_dbg(host, "%s: register %s\n", dev_name(dev->parent),
dev_name(dev));
- return devm_add_action_or_reset(host, unregister_cxl_dev, dev);
+ return devm_add_action_or_reset(host, cxl_nvd_unregister, dev);
err:
put_device(dev);
struct cxl_decoder *to_cxl_decoder(struct device *dev);
bool is_root_decoder(struct device *dev);
struct cxl_decoder *cxl_decoder_alloc(struct cxl_port *port, int nr_targets);
-int devm_cxl_add_decoder(struct device *host, struct cxl_decoder *cxld,
- int *target_map);
+int cxl_decoder_add(struct device *host, struct cxl_decoder *cxld,
+ int *target_map);
+int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld);
extern struct bus_type cxl_bus_type;