Commit 3bf65915 authored by Dan Williams's avatar Dan Williams

cxl/core: Define a 'struct cxl_endpoint_decoder'

Previously the target routing specifics of switch decoders and platform
CXL window resource tracking of root decoders were factored out of
'struct cxl_decoder'. While switch decoders translate from SPA to
downstream ports, endpoint decoders translate from SPA to DPA.

This patch, 3 of 3, adds a 'struct cxl_endpoint_decoder' that tracks an
endpoint-specific Device Physical Address (DPA) resource. For now this
just defines ->dpa_res, a follow-on patch will handle requesting DPA
resource ranges from a device-DPA resource tree.
Co-developed-by: default avatarBen Widawsky <bwidawsk@kernel.org>
Signed-off-by: default avatarBen Widawsky <bwidawsk@kernel.org>
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/165784327088.1758207.15502834501671201192.stgit@dwillia2-xfh.jf.intel.comSigned-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 0f157c7f
...@@ -256,12 +256,15 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) ...@@ -256,12 +256,15 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
struct cxl_decoder *cxld; struct cxl_decoder *cxld;
if (is_cxl_endpoint(port)) { if (is_cxl_endpoint(port)) {
cxld = cxl_endpoint_decoder_alloc(port); struct cxl_endpoint_decoder *cxled;
if (IS_ERR(cxld)) {
cxled = cxl_endpoint_decoder_alloc(port);
if (IS_ERR(cxled)) {
dev_warn(&port->dev, dev_warn(&port->dev,
"Failed to allocate the decoder\n"); "Failed to allocate the decoder\n");
return PTR_ERR(cxld); return PTR_ERR(cxled);
} }
cxld = &cxled->cxld;
} else { } else {
struct cxl_switch_decoder *cxlsd; struct cxl_switch_decoder *cxlsd;
......
...@@ -244,12 +244,12 @@ static void __cxl_decoder_release(struct cxl_decoder *cxld) ...@@ -244,12 +244,12 @@ static void __cxl_decoder_release(struct cxl_decoder *cxld)
put_device(&port->dev); put_device(&port->dev);
} }
static void cxl_decoder_release(struct device *dev) static void cxl_endpoint_decoder_release(struct device *dev)
{ {
struct cxl_decoder *cxld = to_cxl_decoder(dev); struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
__cxl_decoder_release(cxld); __cxl_decoder_release(&cxled->cxld);
kfree(cxld); kfree(cxled);
} }
static void cxl_switch_decoder_release(struct device *dev) static void cxl_switch_decoder_release(struct device *dev)
...@@ -279,7 +279,7 @@ static void cxl_root_decoder_release(struct device *dev) ...@@ -279,7 +279,7 @@ static void cxl_root_decoder_release(struct device *dev)
static const struct device_type cxl_decoder_endpoint_type = { static const struct device_type cxl_decoder_endpoint_type = {
.name = "cxl_decoder_endpoint", .name = "cxl_decoder_endpoint",
.release = cxl_decoder_release, .release = cxl_endpoint_decoder_release,
.groups = cxl_decoder_endpoint_attribute_groups, .groups = cxl_decoder_endpoint_attribute_groups,
}; };
...@@ -321,6 +321,15 @@ struct cxl_decoder *to_cxl_decoder(struct device *dev) ...@@ -321,6 +321,15 @@ struct cxl_decoder *to_cxl_decoder(struct device *dev)
} }
EXPORT_SYMBOL_NS_GPL(to_cxl_decoder, CXL); EXPORT_SYMBOL_NS_GPL(to_cxl_decoder, CXL);
struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev)
{
if (dev_WARN_ONCE(dev, !is_endpoint_decoder(dev),
"not a cxl_endpoint_decoder device\n"))
return NULL;
return container_of(dev, struct cxl_endpoint_decoder, cxld.dev);
}
EXPORT_SYMBOL_NS_GPL(to_cxl_endpoint_decoder, CXL);
static struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev) static struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev)
{ {
if (dev_WARN_ONCE(dev, !is_switch_decoder(dev), if (dev_WARN_ONCE(dev, !is_switch_decoder(dev),
...@@ -1360,26 +1369,28 @@ EXPORT_SYMBOL_NS_GPL(cxl_switch_decoder_alloc, CXL); ...@@ -1360,26 +1369,28 @@ EXPORT_SYMBOL_NS_GPL(cxl_switch_decoder_alloc, CXL);
* *
* Return: A new cxl decoder to be registered by cxl_decoder_add() * Return: A new cxl decoder to be registered by cxl_decoder_add()
*/ */
struct cxl_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port) struct cxl_endpoint_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port)
{ {
struct cxl_endpoint_decoder *cxled;
struct cxl_decoder *cxld; struct cxl_decoder *cxld;
int rc; int rc;
if (!is_cxl_endpoint(port)) if (!is_cxl_endpoint(port))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
cxld = kzalloc(sizeof(*cxld), GFP_KERNEL); cxled = kzalloc(sizeof(*cxled), GFP_KERNEL);
if (!cxld) if (!cxled)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
cxld = &cxled->cxld;
rc = cxl_decoder_init(port, cxld); rc = cxl_decoder_init(port, cxld);
if (rc) { if (rc) {
kfree(cxld); kfree(cxled);
return ERR_PTR(rc); return ERR_PTR(rc);
} }
cxld->dev.type = &cxl_decoder_endpoint_type; cxld->dev.type = &cxl_decoder_endpoint_type;
return cxld; return cxled;
} }
EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_alloc, CXL); EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_alloc, CXL);
......
...@@ -239,6 +239,18 @@ struct cxl_decoder { ...@@ -239,6 +239,18 @@ struct cxl_decoder {
unsigned long flags; unsigned long flags;
}; };
/**
* struct cxl_endpoint_decoder - Endpoint / SPA to DPA decoder
* @cxld: base cxl_decoder_object
* @dpa_res: actively claimed DPA span of this decoder
* @skip: offset into @dpa_res where @cxld.hpa_range maps
*/
struct cxl_endpoint_decoder {
struct cxl_decoder cxld;
struct resource *dpa_res;
resource_size_t skip;
};
/** /**
* struct cxl_switch_decoder - Switch specific CXL HDM Decoder * struct cxl_switch_decoder - Switch specific CXL HDM Decoder
* @cxld: base cxl_decoder object * @cxld: base cxl_decoder object
...@@ -394,6 +406,7 @@ struct cxl_dport *cxl_find_dport_by_dev(struct cxl_port *port, ...@@ -394,6 +406,7 @@ struct cxl_dport *cxl_find_dport_by_dev(struct cxl_port *port,
struct cxl_decoder *to_cxl_decoder(struct device *dev); struct cxl_decoder *to_cxl_decoder(struct device *dev);
struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev); struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev);
bool is_root_decoder(struct device *dev); bool is_root_decoder(struct device *dev);
bool is_endpoint_decoder(struct device *dev); bool is_endpoint_decoder(struct device *dev);
struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port, struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
...@@ -401,7 +414,7 @@ struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port, ...@@ -401,7 +414,7 @@ struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port, struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port,
unsigned int nr_targets); unsigned int nr_targets);
int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map); int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map);
struct cxl_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port); struct cxl_endpoint_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port);
int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map); int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map);
int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld); int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld);
int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint); int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint);
......
...@@ -462,12 +462,16 @@ static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) ...@@ -462,12 +462,16 @@ static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
} }
cxld = &cxlsd->cxld; cxld = &cxlsd->cxld;
} else { } else {
cxld = cxl_endpoint_decoder_alloc(port); struct cxl_endpoint_decoder *cxled;
if (IS_ERR(cxld)) {
cxled = cxl_endpoint_decoder_alloc(port);
if (IS_ERR(cxled)) {
dev_warn(&port->dev, dev_warn(&port->dev,
"Failed to allocate the decoder\n"); "Failed to allocate the decoder\n");
return PTR_ERR(cxld); return PTR_ERR(cxled);
} }
cxld = &cxled->cxld;
} }
cxld->hpa_range = (struct range) { cxld->hpa_range = (struct range) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment