diff mbox series

[3/5] cxl/mem : Expose dynamic capacity configuration to userspace

Message ID 20230604-dcd-type2-upstream-v1-3-71b6341bae54@intel.com
State New, archived
Headers show
Series cxl/dcd: Add support for Dynamic Capacity Devices (DCD) | expand

Commit Message

Ira Weiny June 14, 2023, 7:16 p.m. UTC
From: Navneet Singh <navneet.singh@intel.com>

Exposing driver cached dynamic capacity configuration through sysfs
attributes.User will create one or more dynamic capacity
cxl regions based on this information and map the dynamic capacity of
the device into HDM ranges using one or more HDM decoders.

Signed-off-by: Navneet Singh <navneet.singh@intel.com>

---
[iweiny: fixups]
[djbw: fixups, no sign-off: preview only]
---
 drivers/cxl/core/memdev.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

Comments

Alison Schofield June 15, 2023, 12:40 a.m. UTC | #1
On Wed, Jun 14, 2023 at 12:16:30PM -0700, Ira Weiny wrote:
> From: Navneet Singh <navneet.singh@intel.com>
> 
> Exposing driver cached dynamic capacity configuration through sysfs
> attributes.User will create one or more dynamic capacity
> cxl regions based on this information and map the dynamic capacity of
> the device into HDM ranges using one or more HDM decoders.
> 
> Signed-off-by: Navneet Singh <navneet.singh@intel.com>
> 
> ---
> [iweiny: fixups]
> [djbw: fixups, no sign-off: preview only]
> ---
>  drivers/cxl/core/memdev.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 72 insertions(+)

Add the documentation of these new attributes in this patch.
Documentation/ABI/testing/sysfs-bus-cxl

A bit of my ignorance here, but when I keep seeing the word
'regions' below, it makes me wonder whether these attributes
are in the right place?

> 
> diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
> index 5d1ba7a72567..beeb5fa3a0aa 100644
> --- a/drivers/cxl/core/memdev.c
> +++ b/drivers/cxl/core/memdev.c
> @@ -99,6 +99,20 @@ static ssize_t pmem_size_show(struct device *dev, struct device_attribute *attr,
>  static struct device_attribute dev_attr_pmem_size =
>  	__ATTR(size, 0444, pmem_size_show, NULL);
>  
> +static ssize_t dc_regions_count_show(struct device *dev, struct device_attribute *attr,
> +		char *buf)
> +{
> +	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
> +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> +	int len = 0;
> +
> +	len = sysfs_emit(buf, "0x%x\n", mds->nr_dc_region);

Prefer using this notation: %#llx
grep for the sysfs_emit's to see customary usage.

> +	return len;
> +}
> +
> +struct device_attribute dev_attr_dc_regions_count =
> +	__ATTR(dc_regions_count, 0444, dc_regions_count_show, NULL);
> +
>  static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
>  			   char *buf)
>  {
> @@ -362,6 +376,57 @@ static struct attribute *cxl_memdev_ram_attributes[] = {
>  	NULL,
>  };
>  
> +static ssize_t show_size_regionN(struct cxl_memdev *cxlmd, char *buf, int pos)
> +{
> +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> +
> +	return sysfs_emit(buf, "0x%llx\n", mds->dc_region[pos].decode_len);
> +}
> +
> +#define SIZE_ATTR_RO(n)                                              \
> +static ssize_t dc##n##_size_show(                                       \
> +	struct device *dev, struct device_attribute *attr, char *buf)  \
> +{                                                                      \
> +	return show_size_regionN(to_cxl_memdev(dev), buf, (n));             \
> +}                                                                      \
> +static DEVICE_ATTR_RO(dc##n##_size)
> +SIZE_ATTR_RO(0);
> +SIZE_ATTR_RO(1);
> +SIZE_ATTR_RO(2);
> +SIZE_ATTR_RO(3);
> +SIZE_ATTR_RO(4);
> +SIZE_ATTR_RO(5);
> +SIZE_ATTR_RO(6);
> +SIZE_ATTR_RO(7);
> +
> +static struct attribute *cxl_memdev_dc_attributes[] = {
> +	&dev_attr_dc0_size.attr,
> +	&dev_attr_dc1_size.attr,
> +	&dev_attr_dc2_size.attr,
> +	&dev_attr_dc3_size.attr,
> +	&dev_attr_dc4_size.attr,
> +	&dev_attr_dc5_size.attr,
> +	&dev_attr_dc6_size.attr,
> +	&dev_attr_dc7_size.attr,
> +	&dev_attr_dc_regions_count.attr,
> +	NULL,
> +};
> +
> +static umode_t cxl_dc_visible(struct kobject *kobj, struct attribute *a, int n)
> +{
> +	struct device *dev = kobj_to_dev(kobj);
> +	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
> +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> +
> +	if (a == &dev_attr_dc_regions_count.attr)
> +		return a->mode;
> +
> +	if (n < mds->nr_dc_region)
> +		return a->mode;
> +
> +	return 0;
> +}
> +
>  static umode_t cxl_memdev_visible(struct kobject *kobj, struct attribute *a,
>  				  int n)
>  {
> @@ -385,10 +450,17 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = {
>  	.attrs = cxl_memdev_pmem_attributes,
>  };
>  
> +static struct attribute_group cxl_memdev_dc_attribute_group = {
> +	.name = "dc",
> +	.attrs = cxl_memdev_dc_attributes,
> +	.is_visible = cxl_dc_visible,
> +};
> +
>  static const struct attribute_group *cxl_memdev_attribute_groups[] = {
>  	&cxl_memdev_attribute_group,
>  	&cxl_memdev_ram_attribute_group,
>  	&cxl_memdev_pmem_attribute_group,
> +	&cxl_memdev_dc_attribute_group,
>  	NULL,
>  };
>  
> 
> -- 
> 2.40.0
>
Dave Jiang June 15, 2023, 3:41 p.m. UTC | #2
On 6/14/23 12:16, ira.weiny@intel.com wrote:
> From: Navneet Singh <navneet.singh@intel.com>
> 
> Exposing driver cached dynamic capacity configuration through sysfs
> attributes.User will create one or more dynamic capacity

Space after '.'

> cxl regions based on this information and map the dynamic capacity of
> the device into HDM ranges using one or more HDM decoders.
> 
> Signed-off-by: Navneet Singh <navneet.singh@intel.com>
> 
> ---
> [iweiny: fixups]
> [djbw: fixups, no sign-off: preview only]
> ---
>   drivers/cxl/core/memdev.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 72 insertions(+)

Missing sysfs documentation?

> 
> diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
> index 5d1ba7a72567..beeb5fa3a0aa 100644
> --- a/drivers/cxl/core/memdev.c
> +++ b/drivers/cxl/core/memdev.c
> @@ -99,6 +99,20 @@ static ssize_t pmem_size_show(struct device *dev, struct device_attribute *attr,
>   static struct device_attribute dev_attr_pmem_size =
>   	__ATTR(size, 0444, pmem_size_show, NULL);
>   
> +static ssize_t dc_regions_count_show(struct device *dev, struct device_attribute *attr,
> +		char *buf)
> +{
> +	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
> +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> +	int len = 0;
> +
> +	len = sysfs_emit(buf, "0x%x\n", mds->nr_dc_region);
> +	return len;
> +}

Just directly return sysfs_emit(). Also, emit region count as decimal 
instead of hex?

> +
> +struct device_attribute dev_attr_dc_regions_count =
> +	__ATTR(dc_regions_count, 0444, dc_regions_count_show, NULL);
> +
>   static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
>   			   char *buf)
>   {
> @@ -362,6 +376,57 @@ static struct attribute *cxl_memdev_ram_attributes[] = {
>   	NULL,
>   };
>   
> +static ssize_t show_size_regionN(struct cxl_memdev *cxlmd, char *buf, int pos)
> +{
> +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> +
> +	return sysfs_emit(buf, "0x%llx\n", mds->dc_region[pos].decode_len);
> +}

Should size be in decimal format?

DJ

> +
> +#define SIZE_ATTR_RO(n)                                              \
> +static ssize_t dc##n##_size_show(                                       \
> +	struct device *dev, struct device_attribute *attr, char *buf)  \
> +{                                                                      \
> +	return show_size_regionN(to_cxl_memdev(dev), buf, (n));             \
> +}                                                                      \
> +static DEVICE_ATTR_RO(dc##n##_size)
> +SIZE_ATTR_RO(0);
> +SIZE_ATTR_RO(1);
> +SIZE_ATTR_RO(2);
> +SIZE_ATTR_RO(3);
> +SIZE_ATTR_RO(4);
> +SIZE_ATTR_RO(5);
> +SIZE_ATTR_RO(6);
> +SIZE_ATTR_RO(7);
> +
> +static struct attribute *cxl_memdev_dc_attributes[] = {
> +	&dev_attr_dc0_size.attr,
> +	&dev_attr_dc1_size.attr,
> +	&dev_attr_dc2_size.attr,
> +	&dev_attr_dc3_size.attr,
> +	&dev_attr_dc4_size.attr,
> +	&dev_attr_dc5_size.attr,
> +	&dev_attr_dc6_size.attr,
> +	&dev_attr_dc7_size.attr,
> +	&dev_attr_dc_regions_count.attr,
> +	NULL,
> +};
> +
> +static umode_t cxl_dc_visible(struct kobject *kobj, struct attribute *a, int n)
> +{
> +	struct device *dev = kobj_to_dev(kobj);
> +	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
> +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> +
> +	if (a == &dev_attr_dc_regions_count.attr)
> +		return a->mode;
> +
> +	if (n < mds->nr_dc_region)
> +		return a->mode;
> +
> +	return 0;
> +}
> +
>   static umode_t cxl_memdev_visible(struct kobject *kobj, struct attribute *a,
>   				  int n)
>   {
> @@ -385,10 +450,17 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = {
>   	.attrs = cxl_memdev_pmem_attributes,
>   };
>   
> +static struct attribute_group cxl_memdev_dc_attribute_group = {
> +	.name = "dc",
> +	.attrs = cxl_memdev_dc_attributes,
> +	.is_visible = cxl_dc_visible,
> +};
> +
>   static const struct attribute_group *cxl_memdev_attribute_groups[] = {
>   	&cxl_memdev_attribute_group,
>   	&cxl_memdev_ram_attribute_group,
>   	&cxl_memdev_pmem_attribute_group,
> +	&cxl_memdev_dc_attribute_group,
>   	NULL,
>   };
>   
>
Ira Weiny June 16, 2023, 2:47 a.m. UTC | #3
Alison Schofield wrote:
> On Wed, Jun 14, 2023 at 12:16:30PM -0700, Ira Weiny wrote:
> > From: Navneet Singh <navneet.singh@intel.com>
> > 
> > Exposing driver cached dynamic capacity configuration through sysfs
> > attributes.User will create one or more dynamic capacity
> > cxl regions based on this information and map the dynamic capacity of
> > the device into HDM ranges using one or more HDM decoders.
> > 
> > Signed-off-by: Navneet Singh <navneet.singh@intel.com>
> > 
> > ---
> > [iweiny: fixups]
> > [djbw: fixups, no sign-off: preview only]
> > ---
> >  drivers/cxl/core/memdev.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 72 insertions(+)
> 
> Add the documentation of these new attributes in this patch.
> Documentation/ABI/testing/sysfs-bus-cxl

Good point.  And the region creation patch needs some updating for the
sysfs documentation as well...

Thanks!  I'll work on those.

Writing the documentation it seems like 'dc_region_count' should just be
'region_count'.  Because the 'dc' is redundant with the directory.
However, dcY_size has a redundant 'dc' but Y_size (ie 0_size) seems
odd.[*]

Thoughts on the 'dc' prefix for these?

[*] example listing with 2 DC regions supported.

$ ll mem1/dc/
total 0
-r--r--r-- 1 root root 4096 Jun 15 19:26 dc0_size
-r--r--r-- 1 root root 4096 Jun 15 19:26 dc1_size
-r--r--r-- 1 root root 4096 Jun 15 19:26 dc_regions_count

> 
> A bit of my ignorance here, but when I keep seeing the word
> 'regions' below, it makes me wonder whether these attributes
> are in the right place?

There is a difference between 'DC region' and CXL 'Linux' region.  It has
taken me some time to get used to the terminology.  So I think this is
correct.

> 
> > 
> > diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
> > index 5d1ba7a72567..beeb5fa3a0aa 100644
> > --- a/drivers/cxl/core/memdev.c
> > +++ b/drivers/cxl/core/memdev.c
> > @@ -99,6 +99,20 @@ static ssize_t pmem_size_show(struct device *dev, struct device_attribute *attr,
> >  static struct device_attribute dev_attr_pmem_size =
> >  	__ATTR(size, 0444, pmem_size_show, NULL);
> >  
> > +static ssize_t dc_regions_count_show(struct device *dev, struct device_attribute *attr,
> > +		char *buf)
> > +{
> > +	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
> > +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> > +	int len = 0;
> > +
> > +	len = sysfs_emit(buf, "0x%x\n", mds->nr_dc_region);
> 
> Prefer using this notation: %#llx
> grep for the sysfs_emit's to see customary usage.

oh.  I did see this oddity when I was testing and forgot to change this.

However, I think %#llx needs to be used in show_size_regionN() and this
needs to be %d.  This is just a count of the number of DC regions
supported by the device.  I don't think that needs to be in hex.  Changed
to %d.

> 
> > +	return len;
> > +}
> > +
> > +struct device_attribute dev_attr_dc_regions_count =
> > +	__ATTR(dc_regions_count, 0444, dc_regions_count_show, NULL);
> > +
> >  static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
> >  			   char *buf)
> >  {
> > @@ -362,6 +376,57 @@ static struct attribute *cxl_memdev_ram_attributes[] = {
> >  	NULL,
> >  };
> >  
> > +static ssize_t show_size_regionN(struct cxl_memdev *cxlmd, char *buf, int pos)
> > +{
> > +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> > +
> > +	return sysfs_emit(buf, "0x%llx\n", mds->dc_region[pos].decode_len);

... changed this one to %#llx.

Ira
Dave Jiang June 16, 2023, 3:58 p.m. UTC | #4
On 6/15/23 19:47, Ira Weiny wrote:
> Alison Schofield wrote:
>> On Wed, Jun 14, 2023 at 12:16:30PM -0700, Ira Weiny wrote:
>>> From: Navneet Singh <navneet.singh@intel.com>
>>>
>>> Exposing driver cached dynamic capacity configuration through sysfs
>>> attributes.User will create one or more dynamic capacity
>>> cxl regions based on this information and map the dynamic capacity of
>>> the device into HDM ranges using one or more HDM decoders.
>>>
>>> Signed-off-by: Navneet Singh <navneet.singh@intel.com>
>>>
>>> ---
>>> [iweiny: fixups]
>>> [djbw: fixups, no sign-off: preview only]
>>> ---
>>>   drivers/cxl/core/memdev.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++
>>>   1 file changed, 72 insertions(+)
>>
>> Add the documentation of these new attributes in this patch.
>> Documentation/ABI/testing/sysfs-bus-cxl
> 
> Good point.  And the region creation patch needs some updating for the
> sysfs documentation as well...
> 
> Thanks!  I'll work on those.
> 
> Writing the documentation it seems like 'dc_region_count' should just be
> 'region_count'.  Because the 'dc' is redundant with the directory.
> However, dcY_size has a redundant 'dc' but Y_size (ie 0_size) seems
> odd.[*]
> 
> Thoughts on the 'dc' prefix for these?
> 
> [*] example listing with 2 DC regions supported.
> 
> $ ll mem1/dc/
> total 0
> -r--r--r-- 1 root root 4096 Jun 15 19:26 dc0_size
> -r--r--r-- 1 root root 4096 Jun 15 19:26 dc1_size
> -r--r--r-- 1 root root 4096 Jun 15 19:26 dc_regions_count
> 
>>
>> A bit of my ignorance here, but when I keep seeing the word
>> 'regions' below, it makes me wonder whether these attributes
>> are in the right place?
> 
> There is a difference between 'DC region' and CXL 'Linux' region.  It has
> taken me some time to get used to the terminology.  So I think this is
> correct.

I think you answered your own question above here. If dc_region is 
different than CXL regions, then you'll have to keep the dc_ prefix to 
distinguish between the two. Unless you call it something different.

DJ

> 
>>
>>>
>>> diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
>>> index 5d1ba7a72567..beeb5fa3a0aa 100644
>>> --- a/drivers/cxl/core/memdev.c
>>> +++ b/drivers/cxl/core/memdev.c
>>> @@ -99,6 +99,20 @@ static ssize_t pmem_size_show(struct device *dev, struct device_attribute *attr,
>>>   static struct device_attribute dev_attr_pmem_size =
>>>   	__ATTR(size, 0444, pmem_size_show, NULL);
>>>   
>>> +static ssize_t dc_regions_count_show(struct device *dev, struct device_attribute *attr,
>>> +		char *buf)
>>> +{
>>> +	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
>>> +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
>>> +	int len = 0;
>>> +
>>> +	len = sysfs_emit(buf, "0x%x\n", mds->nr_dc_region);
>>
>> Prefer using this notation: %#llx
>> grep for the sysfs_emit's to see customary usage.
> 
> oh.  I did see this oddity when I was testing and forgot to change this.
> 
> However, I think %#llx needs to be used in show_size_regionN() and this
> needs to be %d.  This is just a count of the number of DC regions
> supported by the device.  I don't think that needs to be in hex.  Changed
> to %d.
> 
>>
>>> +	return len;
>>> +}
>>> +
>>> +struct device_attribute dev_attr_dc_regions_count =
>>> +	__ATTR(dc_regions_count, 0444, dc_regions_count_show, NULL);
>>> +
>>>   static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
>>>   			   char *buf)
>>>   {
>>> @@ -362,6 +376,57 @@ static struct attribute *cxl_memdev_ram_attributes[] = {
>>>   	NULL,
>>>   };
>>>   
>>> +static ssize_t show_size_regionN(struct cxl_memdev *cxlmd, char *buf, int pos)
>>> +{
>>> +	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
>>> +
>>> +	return sysfs_emit(buf, "0x%llx\n", mds->dc_region[pos].decode_len);
> 
> ... changed this one to %#llx.
> 
> Ira
Ira Weiny June 20, 2023, 4:23 p.m. UTC | #5
Dave Jiang wrote:
> 
> 
> On 6/15/23 19:47, Ira Weiny wrote:
> > Alison Schofield wrote:
> >> On Wed, Jun 14, 2023 at 12:16:30PM -0700, Ira Weiny wrote:
> >>> From: Navneet Singh <navneet.singh@intel.com>
> >>>

[snip]

> > 
> > Writing the documentation it seems like 'dc_region_count' should just be
> > 'region_count'.  Because the 'dc' is redundant with the directory.
> > However, dcY_size has a redundant 'dc' but Y_size (ie 0_size) seems
> > odd.[*]
> > 
> > Thoughts on the 'dc' prefix for these?
> > 
> > [*] example listing with 2 DC regions supported.
> > 
> > $ ll mem1/dc/
> > total 0
> > -r--r--r-- 1 root root 4096 Jun 15 19:26 dc0_size
> > -r--r--r-- 1 root root 4096 Jun 15 19:26 dc1_size
> > -r--r--r-- 1 root root 4096 Jun 15 19:26 dc_regions_count
> > 
> >>
> >> A bit of my ignorance here, but when I keep seeing the word
> >> 'regions' below, it makes me wonder whether these attributes
> >> are in the right place?
> > 
> > There is a difference between 'DC region' and CXL 'Linux' region.  It has
> > taken me some time to get used to the terminology.  So I think this is
> > correct.
> 
> I think you answered your own question above here. If dc_region is 
> different than CXL regions, then you'll have to keep the dc_ prefix to 
> distinguish between the two. Unless you call it something different.

But it sits in the 'dc' directory.

memX/dc/dc_regions_count
memX/dc/dc0_size
...

So it feels like the dc is redundant.  But it is probably ok as it is.

Ira
Dave Jiang June 20, 2023, 4:48 p.m. UTC | #6
On 6/20/23 09:23, Ira Weiny wrote:
> Dave Jiang wrote:
>>
>>
>> On 6/15/23 19:47, Ira Weiny wrote:
>>> Alison Schofield wrote:
>>>> On Wed, Jun 14, 2023 at 12:16:30PM -0700, Ira Weiny wrote:
>>>>> From: Navneet Singh <navneet.singh@intel.com>
>>>>>
> 
> [snip]
> 
>>>
>>> Writing the documentation it seems like 'dc_region_count' should just be
>>> 'region_count'.  Because the 'dc' is redundant with the directory.
>>> However, dcY_size has a redundant 'dc' but Y_size (ie 0_size) seems
>>> odd.[*]
>>>
>>> Thoughts on the 'dc' prefix for these?
>>>
>>> [*] example listing with 2 DC regions supported.
>>>
>>> $ ll mem1/dc/
>>> total 0
>>> -r--r--r-- 1 root root 4096 Jun 15 19:26 dc0_size
>>> -r--r--r-- 1 root root 4096 Jun 15 19:26 dc1_size
>>> -r--r--r-- 1 root root 4096 Jun 15 19:26 dc_regions_count
>>>
>>>>
>>>> A bit of my ignorance here, but when I keep seeing the word
>>>> 'regions' below, it makes me wonder whether these attributes
>>>> are in the right place?
>>>
>>> There is a difference between 'DC region' and CXL 'Linux' region.  It has
>>> taken me some time to get used to the terminology.  So I think this is
>>> correct.
>>
>> I think you answered your own question above here. If dc_region is
>> different than CXL regions, then you'll have to keep the dc_ prefix to
>> distinguish between the two. Unless you call it something different.
> 
> But it sits in the 'dc' directory.
> 
> memX/dc/dc_regions_count
> memX/dc/dc0_size
> ...
> 
> So it feels like the dc is redundant.  But it is probably ok as it is.

Ah I see what you mean. Yeah maybe dropping the dc would make it look nicer.

> 
> Ira
diff mbox series

Patch

diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 5d1ba7a72567..beeb5fa3a0aa 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -99,6 +99,20 @@  static ssize_t pmem_size_show(struct device *dev, struct device_attribute *attr,
 static struct device_attribute dev_attr_pmem_size =
 	__ATTR(size, 0444, pmem_size_show, NULL);
 
+static ssize_t dc_regions_count_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+	int len = 0;
+
+	len = sysfs_emit(buf, "0x%x\n", mds->nr_dc_region);
+	return len;
+}
+
+struct device_attribute dev_attr_dc_regions_count =
+	__ATTR(dc_regions_count, 0444, dc_regions_count_show, NULL);
+
 static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
@@ -362,6 +376,57 @@  static struct attribute *cxl_memdev_ram_attributes[] = {
 	NULL,
 };
 
+static ssize_t show_size_regionN(struct cxl_memdev *cxlmd, char *buf, int pos)
+{
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+
+	return sysfs_emit(buf, "0x%llx\n", mds->dc_region[pos].decode_len);
+}
+
+#define SIZE_ATTR_RO(n)                                              \
+static ssize_t dc##n##_size_show(                                       \
+	struct device *dev, struct device_attribute *attr, char *buf)  \
+{                                                                      \
+	return show_size_regionN(to_cxl_memdev(dev), buf, (n));             \
+}                                                                      \
+static DEVICE_ATTR_RO(dc##n##_size)
+SIZE_ATTR_RO(0);
+SIZE_ATTR_RO(1);
+SIZE_ATTR_RO(2);
+SIZE_ATTR_RO(3);
+SIZE_ATTR_RO(4);
+SIZE_ATTR_RO(5);
+SIZE_ATTR_RO(6);
+SIZE_ATTR_RO(7);
+
+static struct attribute *cxl_memdev_dc_attributes[] = {
+	&dev_attr_dc0_size.attr,
+	&dev_attr_dc1_size.attr,
+	&dev_attr_dc2_size.attr,
+	&dev_attr_dc3_size.attr,
+	&dev_attr_dc4_size.attr,
+	&dev_attr_dc5_size.attr,
+	&dev_attr_dc6_size.attr,
+	&dev_attr_dc7_size.attr,
+	&dev_attr_dc_regions_count.attr,
+	NULL,
+};
+
+static umode_t cxl_dc_visible(struct kobject *kobj, struct attribute *a, int n)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+
+	if (a == &dev_attr_dc_regions_count.attr)
+		return a->mode;
+
+	if (n < mds->nr_dc_region)
+		return a->mode;
+
+	return 0;
+}
+
 static umode_t cxl_memdev_visible(struct kobject *kobj, struct attribute *a,
 				  int n)
 {
@@ -385,10 +450,17 @@  static struct attribute_group cxl_memdev_pmem_attribute_group = {
 	.attrs = cxl_memdev_pmem_attributes,
 };
 
+static struct attribute_group cxl_memdev_dc_attribute_group = {
+	.name = "dc",
+	.attrs = cxl_memdev_dc_attributes,
+	.is_visible = cxl_dc_visible,
+};
+
 static const struct attribute_group *cxl_memdev_attribute_groups[] = {
 	&cxl_memdev_attribute_group,
 	&cxl_memdev_ram_attribute_group,
 	&cxl_memdev_pmem_attribute_group,
+	&cxl_memdev_dc_attribute_group,
 	NULL,
 };