Extent information can be helpful to the user to coordinate memory usage with the external orchestrator and FM.
Expose the details of region extents by creating the following sysfs entries. /sys/bus/cxl/devices/dax_regionX/extentX.Y /sys/bus/cxl/devices/dax_regionX/extentX.Y/offset /sys/bus/cxl/devices/dax_regionX/extentX.Y/length /sys/bus/cxl/devices/dax_regionX/extentX.Y/tag Based on an original patch by Navneet Singh. Reviewed-by: Jonathan Cameron <jonathan.came...@huawei.com> Reviewed-by: Fan Ni <fan...@samsung.com> Tested-by: Fan Ni <fan...@samsung.com> Signed-off-by: Ira Weiny <ira.we...@intel.com> --- Changes: [iweiny: rebase] [iweiny: s/tag/uuid/ throughout the code] [iweiny: update sysfs docs to 2025] --- Documentation/ABI/testing/sysfs-bus-cxl | 36 ++++++++++++++++++++ drivers/cxl/core/extent.c | 58 +++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl index 2e26d95ac66f..6e9d60baf546 100644 --- a/Documentation/ABI/testing/sysfs-bus-cxl +++ b/Documentation/ABI/testing/sysfs-bus-cxl @@ -639,3 +639,39 @@ Description: The count is persistent across power loss and wraps back to 0 upon overflow. If this file is not present, the device does not have the necessary support for dirty tracking. + + +What: /sys/bus/cxl/devices/dax_regionX/extentX.Y/offset +Date: May, 2025 +KernelVersion: v6.16 +Contact: linux-...@vger.kernel.org +Description: + (RO) [For Dynamic Capacity regions only] Users can use the + extent information to create DAX devices on specific extents. + This is done by creating and destroying DAX devices in specific + sequences and looking at the mappings created. Extent offset + within the region. + + +What: /sys/bus/cxl/devices/dax_regionX/extentX.Y/length +Date: May, 2025 +KernelVersion: v6.16 +Contact: linux-...@vger.kernel.org +Description: + (RO) [For Dynamic Capacity regions only] Users can use the + extent information to create DAX devices on specific extents. + This is done by creating and destroying DAX devices in specific + sequences and looking at the mappings created. Extent length + within the region. + + +What: /sys/bus/cxl/devices/dax_regionX/extentX.Y/uuid +Date: May, 2025 +KernelVersion: v6.16 +Contact: linux-...@vger.kernel.org +Description: + (RO) [For Dynamic Capacity regions only] Users can use the + extent information to create DAX devices on specific extents. + This is done by creating and destroying DAX devices in specific + sequences and looking at the mappings created. UUID of this + extent. diff --git a/drivers/cxl/core/extent.c b/drivers/cxl/core/extent.c index 6df277caf974..3fb20cd7afc8 100644 --- a/drivers/cxl/core/extent.c +++ b/drivers/cxl/core/extent.c @@ -6,6 +6,63 @@ #include "core.h" +static ssize_t offset_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct region_extent *region_extent = to_region_extent(dev); + + return sysfs_emit(buf, "%#llx\n", region_extent->hpa_range.start); +} +static DEVICE_ATTR_RO(offset); + +static ssize_t length_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct region_extent *region_extent = to_region_extent(dev); + u64 length = range_len(®ion_extent->hpa_range); + + return sysfs_emit(buf, "%#llx\n", length); +} +static DEVICE_ATTR_RO(length); + +static ssize_t uuid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct region_extent *region_extent = to_region_extent(dev); + + return sysfs_emit(buf, "%pUb\n", ®ion_extent->uuid); +} +static DEVICE_ATTR_RO(uuid); + +static struct attribute *region_extent_attrs[] = { + &dev_attr_offset.attr, + &dev_attr_length.attr, + &dev_attr_uuid.attr, + NULL +}; + +static uuid_t empty_uuid = { 0 }; + +static umode_t region_extent_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct region_extent *region_extent = to_region_extent(dev); + + if (a == &dev_attr_uuid.attr && + uuid_equal(®ion_extent->uuid, &empty_uuid)) + return 0; + + return a->mode; +} + +static const struct attribute_group region_extent_attribute_group = { + .attrs = region_extent_attrs, + .is_visible = region_extent_visible, +}; + +__ATTRIBUTE_GROUPS(region_extent_attribute); + static void cxled_release_extent(struct cxl_endpoint_decoder *cxled, struct cxled_extent *ed_extent) { @@ -44,6 +101,7 @@ static void region_extent_release(struct device *dev) static const struct device_type region_extent_type = { .name = "extent", .release = region_extent_release, + .groups = region_extent_attribute_groups, }; bool is_region_extent(struct device *dev) -- 2.49.0