Message ID | 20241230214445.27602-14-alejandro.lucero-palau@amd.com |
---|---|
State | New |
Headers | show |
Series | cxl: add type2 device basic support | expand |
On Mon, 30 Dec 2024 21:44:31 +0000 <alejandro.lucero-palau@amd.com> wrote: > From: Alejandro Lucero <alucerop@amd.com> > > Current cxl core is relying on a CXL_DEVTYPE_CLASSMEM type device when > creating a memdev leading to problems when obtaining cxl_memdev_state > references from a CXL_DEVTYPE_DEVMEM type. This last device type is > managed by a specific vendor driver and does not need same sysfs files > since not userspace intervention is expected. > > Create a new cxl_mem device type with no attributes for Type2. > > Avoid debugfs files relying on existence of cxl_memdev_state. "Avoid debugfs files that rely on existence of cxl_memdev_state." Currently it means you keep the files but break their reliance on that state. So subtly different from what is implemented. > > Make devm_cxl_add_memdev accesible from a accel driver. > > Signed-off-by: Alejandro Lucero <alucerop@amd.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
On 1/2/25 15:01, Jonathan Cameron wrote: > On Mon, 30 Dec 2024 21:44:31 +0000 > <alejandro.lucero-palau@amd.com> wrote: > >> From: Alejandro Lucero <alucerop@amd.com> >> >> Current cxl core is relying on a CXL_DEVTYPE_CLASSMEM type device when >> creating a memdev leading to problems when obtaining cxl_memdev_state >> references from a CXL_DEVTYPE_DEVMEM type. This last device type is >> managed by a specific vendor driver and does not need same sysfs files >> since not userspace intervention is expected. >> >> Create a new cxl_mem device type with no attributes for Type2. >> >> Avoid debugfs files relying on existence of cxl_memdev_state. > "Avoid debugfs files that rely on existence of cxl_memdev_state." > > Currently it means you keep the files but break their reliance > on that state. So subtly different from what is implemented. It makes sense. I'll fix it in v10. Thanks! >> Make devm_cxl_add_memdev accesible from a accel driver. >> >> Signed-off-by: Alejandro Lucero <alucerop@amd.com> > Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> > >
alejandro.lucero-palau@ wrote: > From: Alejandro Lucero <alucerop@amd.com> > > Current cxl core is relying on a CXL_DEVTYPE_CLASSMEM type device when > creating a memdev leading to problems when obtaining cxl_memdev_state > references from a CXL_DEVTYPE_DEVMEM type. This last device type is > managed by a specific vendor driver and does not need same sysfs files > since not userspace intervention is expected. > > Create a new cxl_mem device type with no attributes for Type2. > > Avoid debugfs files relying on existence of cxl_memdev_state. > > Make devm_cxl_add_memdev accesible from a accel driver. > > Signed-off-by: Alejandro Lucero <alucerop@amd.com> > --- > drivers/cxl/core/cdat.c | 3 +++ > drivers/cxl/core/memdev.c | 14 ++++++++++++-- > drivers/cxl/core/region.c | 3 ++- > drivers/cxl/cxlmem.h | 2 -- > drivers/cxl/mem.c | 25 +++++++++++++++++++------ > include/cxl/cxl.h | 2 ++ > 6 files changed, 38 insertions(+), 11 deletions(-) > > diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c > index 8153f8d83a16..c57bc83e79ee 100644 > --- a/drivers/cxl/core/cdat.c > +++ b/drivers/cxl/core/cdat.c > @@ -577,6 +577,9 @@ static struct cxl_dpa_perf *cxled_get_dpa_perf(struct cxl_endpoint_decoder *cxle > struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); > struct cxl_dpa_perf *perf; > > + if (!mds) > + return ERR_PTR(-EINVAL); > + The references to @mds in cxled_get_dpa_perf() are gone after the DPA partition changes. If an accelerator has a CDAT it will get qos_class information for free. If it does not have a CDAT then I wonder how it is telling the BIOS the memory type for its CXL.mem? > switch (mode) { > case CXL_DECODER_RAM: > perf = &mds->ram_perf; > diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c > index 836db4a462b3..f91feca586dd 100644 > --- a/drivers/cxl/core/memdev.c > +++ b/drivers/cxl/core/memdev.c > @@ -547,9 +547,16 @@ static const struct device_type cxl_memdev_type = { > .groups = cxl_memdev_attribute_groups, > }; > > +static const struct device_type cxl_accel_memdev_type = { > + .name = "cxl_accel_memdev", > + .release = cxl_memdev_release, > + .devnode = cxl_memdev_devnode, > +}; > + > bool is_cxl_memdev(const struct device *dev) > { > - return dev->type == &cxl_memdev_type; > + return (dev->type == &cxl_memdev_type || > + dev->type == &cxl_accel_memdev_type); At this point the game is over in terms of future code that trips over the assumption that all "is_cxl_memdev() == true" devices are created equal. > } > EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, "CXL"); > > @@ -660,7 +667,10 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds, > dev->parent = cxlds->dev; > dev->bus = &cxl_bus_type; > dev->devt = MKDEV(cxl_mem_major, cxlmd->id); > - dev->type = &cxl_memdev_type; > + if (cxlds->type == CXL_DEVTYPE_DEVMEM) > + dev->type = &cxl_accel_memdev_type; > + else > + dev->type = &cxl_memdev_type; > device_set_pm_not_required(dev); > INIT_WORK(&cxlmd->detach_work, detach_memdev); > > diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c > index d77899650798..967132b49832 100644 > --- a/drivers/cxl/core/region.c > +++ b/drivers/cxl/core/region.c > @@ -1948,7 +1948,8 @@ static int cxl_region_attach(struct cxl_region *cxlr, > return -EINVAL; > } > > - cxl_region_perf_data_calculate(cxlr, cxled); > + if (cxlr->type == CXL_DECODER_HOSTONLYMEM) > + cxl_region_perf_data_calculate(cxlr, cxled); Per-above no need to worry about @mds reference in this path. > if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) { > int i; > diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h > index 4c1c53c29544..360d3728f492 100644 > --- a/drivers/cxl/cxlmem.h > +++ b/drivers/cxl/cxlmem.h > @@ -87,8 +87,6 @@ static inline bool is_cxl_endpoint(struct cxl_port *port) > return is_cxl_memdev(port->uport_dev); > } > > -struct cxl_memdev *devm_cxl_add_memdev(struct device *host, > - struct cxl_dev_state *cxlds); > int devm_cxl_sanitize_setup_notifier(struct device *host, > struct cxl_memdev *cxlmd); > struct cxl_memdev_state; > diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c > index 2f03a4d5606e..93106a43990b 100644 > --- a/drivers/cxl/mem.c > +++ b/drivers/cxl/mem.c > @@ -130,12 +130,18 @@ static int cxl_mem_probe(struct device *dev) > dentry = cxl_debugfs_create_dir(dev_name(dev)); > debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show); > > - if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds)) > - debugfs_create_file("inject_poison", 0200, dentry, cxlmd, > - &cxl_poison_inject_fops); > - if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds)) > - debugfs_create_file("clear_poison", 0200, dentry, cxlmd, > - &cxl_poison_clear_fops); > + /* > + * Avoid poison debugfs files for Type2 devices as they rely on > + * cxl_memdev_state. > + */ > + if (mds) { > + if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds)) > + debugfs_create_file("inject_poison", 0200, dentry, cxlmd, > + &cxl_poison_inject_fops); > + if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds)) > + debugfs_create_file("clear_poison", 0200, dentry, cxlmd, > + &cxl_poison_clear_fops); > + } > > rc = devm_add_action_or_reset(dev, remove_debugfs, dentry); > if (rc) > @@ -219,6 +225,13 @@ static umode_t cxl_mem_visible(struct kobject *kobj, struct attribute *a, int n) > struct cxl_memdev *cxlmd = to_cxl_memdev(dev); > struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); > > + /* > + * Avoid poison sysfs files for Type2 devices as they rely on > + * cxl_memdev_state. > + */ > + if (!mds) > + return 0; It turns out that nothing in the poison handling path requires 'struct cxl_memdev_state'. So rather than key this rejection off of @mds == NULL, I would prefer to find a way to make this optional relative to data read from 'struct cxl_mailbox', or 'struct cxl_dev_state'. Conceptually there is nothing stopping a CXL accelertor from supporting poison management commands on its mailbox, it's just unlikely.
On 1/18/25 02:27, Dan Williams wrote: > alejandro.lucero-palau@ wrote: >> From: Alejandro Lucero <alucerop@amd.com> >> >> Current cxl core is relying on a CXL_DEVTYPE_CLASSMEM type device when >> creating a memdev leading to problems when obtaining cxl_memdev_state >> references from a CXL_DEVTYPE_DEVMEM type. This last device type is >> managed by a specific vendor driver and does not need same sysfs files >> since not userspace intervention is expected. >> >> Create a new cxl_mem device type with no attributes for Type2. >> >> Avoid debugfs files relying on existence of cxl_memdev_state. >> >> Make devm_cxl_add_memdev accesible from a accel driver. >> >> Signed-off-by: Alejandro Lucero <alucerop@amd.com> >> --- >> drivers/cxl/core/cdat.c | 3 +++ >> drivers/cxl/core/memdev.c | 14 ++++++++++++-- >> drivers/cxl/core/region.c | 3 ++- >> drivers/cxl/cxlmem.h | 2 -- >> drivers/cxl/mem.c | 25 +++++++++++++++++++------ >> include/cxl/cxl.h | 2 ++ >> 6 files changed, 38 insertions(+), 11 deletions(-) >> >> diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c >> index 8153f8d83a16..c57bc83e79ee 100644 >> --- a/drivers/cxl/core/cdat.c >> +++ b/drivers/cxl/core/cdat.c >> @@ -577,6 +577,9 @@ static struct cxl_dpa_perf *cxled_get_dpa_perf(struct cxl_endpoint_decoder *cxle >> struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); >> struct cxl_dpa_perf *perf; >> >> + if (!mds) >> + return ERR_PTR(-EINVAL); >> + > The references to @mds in cxled_get_dpa_perf() are gone > after the DPA partition changes. OK > > If an accelerator has a CDAT it will get qos_class information for free. > If it does not have a CDAT then I wonder how it is telling the BIOS the > memory type for its CXL.mem? AFAIK, this is not mandatory, and the BIOS will look at CXL DVSEC for finding out. So no perf data is mandatory. FWIW, our device will export a CDAT via PCI option rom since we have to avoid the BIOS doing things we do not want to like testing the memory as some BIOS seem to do in some debug/test mode, and to advertise this flag we discussed in v1/RFC for the kernel doing nothing with that memory when found in the HMAT table. >> switch (mode) { >> case CXL_DECODER_RAM: >> perf = &mds->ram_perf; >> diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c >> index 836db4a462b3..f91feca586dd 100644 >> --- a/drivers/cxl/core/memdev.c >> +++ b/drivers/cxl/core/memdev.c >> @@ -547,9 +547,16 @@ static const struct device_type cxl_memdev_type = { >> .groups = cxl_memdev_attribute_groups, >> }; >> >> +static const struct device_type cxl_accel_memdev_type = { >> + .name = "cxl_accel_memdev", >> + .release = cxl_memdev_release, >> + .devnode = cxl_memdev_devnode, >> +}; >> + >> bool is_cxl_memdev(const struct device *dev) >> { >> - return dev->type == &cxl_memdev_type; >> + return (dev->type == &cxl_memdev_type || >> + dev->type == &cxl_accel_memdev_type); > At this point the game is over in terms of future code that trips over > the assumption that all "is_cxl_memdev() == true" devices are created > equal. Yep. >> } >> EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, "CXL"); >> >> @@ -660,7 +667,10 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds, >> dev->parent = cxlds->dev; >> dev->bus = &cxl_bus_type; >> dev->devt = MKDEV(cxl_mem_major, cxlmd->id); >> - dev->type = &cxl_memdev_type; >> + if (cxlds->type == CXL_DEVTYPE_DEVMEM) >> + dev->type = &cxl_accel_memdev_type; >> + else >> + dev->type = &cxl_memdev_type; >> device_set_pm_not_required(dev); >> INIT_WORK(&cxlmd->detach_work, detach_memdev); >> >> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c >> index d77899650798..967132b49832 100644 >> --- a/drivers/cxl/core/region.c >> +++ b/drivers/cxl/core/region.c >> @@ -1948,7 +1948,8 @@ static int cxl_region_attach(struct cxl_region *cxlr, >> return -EINVAL; >> } >> >> - cxl_region_perf_data_calculate(cxlr, cxled); >> + if (cxlr->type == CXL_DECODER_HOSTONLYMEM) >> + cxl_region_perf_data_calculate(cxlr, cxled); > Per-above no need to worry about @mds reference in this path. I'll adapt it. > >> if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) { >> int i; >> diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h >> index 4c1c53c29544..360d3728f492 100644 >> --- a/drivers/cxl/cxlmem.h >> +++ b/drivers/cxl/cxlmem.h >> @@ -87,8 +87,6 @@ static inline bool is_cxl_endpoint(struct cxl_port *port) >> return is_cxl_memdev(port->uport_dev); >> } >> >> -struct cxl_memdev *devm_cxl_add_memdev(struct device *host, >> - struct cxl_dev_state *cxlds); >> int devm_cxl_sanitize_setup_notifier(struct device *host, >> struct cxl_memdev *cxlmd); >> struct cxl_memdev_state; >> diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c >> index 2f03a4d5606e..93106a43990b 100644 >> --- a/drivers/cxl/mem.c >> +++ b/drivers/cxl/mem.c >> @@ -130,12 +130,18 @@ static int cxl_mem_probe(struct device *dev) >> dentry = cxl_debugfs_create_dir(dev_name(dev)); >> debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show); >> >> - if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds)) >> - debugfs_create_file("inject_poison", 0200, dentry, cxlmd, >> - &cxl_poison_inject_fops); >> - if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds)) >> - debugfs_create_file("clear_poison", 0200, dentry, cxlmd, >> - &cxl_poison_clear_fops); >> + /* >> + * Avoid poison debugfs files for Type2 devices as they rely on >> + * cxl_memdev_state. >> + */ >> + if (mds) { >> + if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds)) >> + debugfs_create_file("inject_poison", 0200, dentry, cxlmd, >> + &cxl_poison_inject_fops); >> + if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds)) >> + debugfs_create_file("clear_poison", 0200, dentry, cxlmd, >> + &cxl_poison_clear_fops); >> + } >> >> rc = devm_add_action_or_reset(dev, remove_debugfs, dentry); >> if (rc) >> @@ -219,6 +225,13 @@ static umode_t cxl_mem_visible(struct kobject *kobj, struct attribute *a, int n) >> struct cxl_memdev *cxlmd = to_cxl_memdev(dev); >> struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); >> >> + /* >> + * Avoid poison sysfs files for Type2 devices as they rely on >> + * cxl_memdev_state. >> + */ >> + if (!mds) >> + return 0; > It turns out that nothing in the poison handling path requires 'struct > cxl_memdev_state'. So rather than key this rejection off of @mds == > NULL, I would prefer to find a way to make this optional relative to > data read from 'struct cxl_mailbox', or 'struct cxl_dev_state'. > Conceptually there is nothing stopping a CXL accelertor from supporting > poison management commands on its mailbox, it's just unlikely. Right. This is the easiest path for the initial type2 support SFC requires, but I agree it should cover other options as well. I'll work on it for v10 and if not a major work, I'll do it. Thanks
Alejandro Lucero Palau wrote: [..] > > If an accelerator has a CDAT it will get qos_class information for free. > > If it does not have a CDAT then I wonder how it is telling the BIOS the > > memory type for its CXL.mem? > > AFAIK, this is not mandatory, and the BIOS will look at CXL DVSEC for > finding out. So no perf data is mandatory. Right. > FWIW, our device will export a CDAT via PCI option rom since we have to > avoid the BIOS doing things we do not want to like testing the memory as > some BIOS seem to do in some debug/test mode, and to advertise this flag > we discussed in v1/RFC for the kernel doing nothing with that memory > when found in the HMAT table. As long as devices that put standard things in standard places get standard Linux enabling, I am satisfied. As for the comment about HMAT, I am not sure what that is referring? The kernel should not need any other consideration for CXL accelerators. Either accelerator memory is properly marked Reserved in the EFI map, or it is not. It is a BIOS bug if it maps accelerator memory as EFI Conventional Memory (with or without the EFI_MEMORY_SP) and per the EFI spec the kernel has no responsibility to fix that up.
diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c index 8153f8d83a16..c57bc83e79ee 100644 --- a/drivers/cxl/core/cdat.c +++ b/drivers/cxl/core/cdat.c @@ -577,6 +577,9 @@ static struct cxl_dpa_perf *cxled_get_dpa_perf(struct cxl_endpoint_decoder *cxle struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_dpa_perf *perf; + if (!mds) + return ERR_PTR(-EINVAL); + switch (mode) { case CXL_DECODER_RAM: perf = &mds->ram_perf; diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 836db4a462b3..f91feca586dd 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -547,9 +547,16 @@ static const struct device_type cxl_memdev_type = { .groups = cxl_memdev_attribute_groups, }; +static const struct device_type cxl_accel_memdev_type = { + .name = "cxl_accel_memdev", + .release = cxl_memdev_release, + .devnode = cxl_memdev_devnode, +}; + bool is_cxl_memdev(const struct device *dev) { - return dev->type == &cxl_memdev_type; + return (dev->type == &cxl_memdev_type || + dev->type == &cxl_accel_memdev_type); } EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, "CXL"); @@ -660,7 +667,10 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds, dev->parent = cxlds->dev; dev->bus = &cxl_bus_type; dev->devt = MKDEV(cxl_mem_major, cxlmd->id); - dev->type = &cxl_memdev_type; + if (cxlds->type == CXL_DEVTYPE_DEVMEM) + dev->type = &cxl_accel_memdev_type; + else + dev->type = &cxl_memdev_type; device_set_pm_not_required(dev); INIT_WORK(&cxlmd->detach_work, detach_memdev); diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index d77899650798..967132b49832 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -1948,7 +1948,8 @@ static int cxl_region_attach(struct cxl_region *cxlr, return -EINVAL; } - cxl_region_perf_data_calculate(cxlr, cxled); + if (cxlr->type == CXL_DECODER_HOSTONLYMEM) + cxl_region_perf_data_calculate(cxlr, cxled); if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) { int i; diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 4c1c53c29544..360d3728f492 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -87,8 +87,6 @@ static inline bool is_cxl_endpoint(struct cxl_port *port) return is_cxl_memdev(port->uport_dev); } -struct cxl_memdev *devm_cxl_add_memdev(struct device *host, - struct cxl_dev_state *cxlds); int devm_cxl_sanitize_setup_notifier(struct device *host, struct cxl_memdev *cxlmd); struct cxl_memdev_state; diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 2f03a4d5606e..93106a43990b 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -130,12 +130,18 @@ static int cxl_mem_probe(struct device *dev) dentry = cxl_debugfs_create_dir(dev_name(dev)); debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show); - if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds)) - debugfs_create_file("inject_poison", 0200, dentry, cxlmd, - &cxl_poison_inject_fops); - if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds)) - debugfs_create_file("clear_poison", 0200, dentry, cxlmd, - &cxl_poison_clear_fops); + /* + * Avoid poison debugfs files for Type2 devices as they rely on + * cxl_memdev_state. + */ + if (mds) { + if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds)) + debugfs_create_file("inject_poison", 0200, dentry, cxlmd, + &cxl_poison_inject_fops); + if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds)) + debugfs_create_file("clear_poison", 0200, dentry, cxlmd, + &cxl_poison_clear_fops); + } rc = devm_add_action_or_reset(dev, remove_debugfs, dentry); if (rc) @@ -219,6 +225,13 @@ static umode_t cxl_mem_visible(struct kobject *kobj, struct attribute *a, int n) struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + /* + * Avoid poison sysfs files for Type2 devices as they rely on + * cxl_memdev_state. + */ + if (!mds) + return 0; + if (a == &dev_attr_trigger_poison_list.attr) if (!test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds)) diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h index f67ee745d942..f7ce683465f0 100644 --- a/include/cxl/cxl.h +++ b/include/cxl/cxl.h @@ -48,4 +48,6 @@ int cxl_pci_accel_setup_regs(struct pci_dev *pdev, struct cxl_dev_state *cxlds); int cxl_request_resource(struct cxl_dev_state *cxlds, enum cxl_resource type); int cxl_release_resource(struct cxl_dev_state *cxlds, enum cxl_resource type); void cxl_set_media_ready(struct cxl_dev_state *cxlds); +struct cxl_memdev *devm_cxl_add_memdev(struct device *host, + struct cxl_dev_state *cxlds); #endif