From: Navneet Singh <navneet.si...@intel.com>

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

Signed-off-by: Navneet Singh <navneet.si...@intel.com>
Co-developed-by: Ira Weiny <ira.we...@intel.com>
Signed-off-by: Ira Weiny <ira.we...@intel.com>

---
Changes:
[iweiny: split this out]
[Jonathan: add documentation for extent sysfs]
[Jonathan/djbw: s/label/tag]
[Jonathan/djbw: treat tag as uuid]
[djbw: use __ATTRIBUTE_GROUPS]
[djbw: make tag invisible if it is empty]
[djbw/iweiny: use conventional id names for extents; extentX.Y]
---
 Documentation/ABI/testing/sysfs-bus-cxl | 13 ++++++++
 drivers/cxl/core/extent.c               | 58 +++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-cxl 
b/Documentation/ABI/testing/sysfs-bus-cxl
index 3a5ee88e551b..e97e6a73c960 100644
--- a/Documentation/ABI/testing/sysfs-bus-cxl
+++ b/Documentation/ABI/testing/sysfs-bus-cxl
@@ -599,3 +599,16 @@ Description:
                See Documentation/ABI/stable/sysfs-devices-node. access0 
provides
                the number to the closest initiator and access1 provides the
                number to the closest CPU.
+
+What:          /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
+Date:          October, 2024
+KernelVersion: v6.12
+Contact:       linux-...@vger.kernel.org
+Description:
+               (RO) [For Dynamic Capacity regions only]  Extent offset and
+               length within the region.  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.
diff --git a/drivers/cxl/core/extent.c b/drivers/cxl/core/extent.c
index 34456594cdc3..d7d526a51e2b 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(&region_extent->hpa_range);
+
+       return sysfs_emit(buf, "%#llx\n", length);
+}
+static DEVICE_ATTR_RO(length);
+
+static ssize_t tag_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", &region_extent->tag);
+}
+static DEVICE_ATTR_RO(tag);
+
+static struct attribute *region_extent_attrs[] = {
+       &dev_attr_offset.attr,
+       &dev_attr_length.attr,
+       &dev_attr_tag.attr,
+       NULL,
+};
+
+static uuid_t empty_tag = { 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_tag.attr &&
+           uuid_equal(&region_extent->tag, &empty_tag))
+               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.45.2


Reply via email to