cxl: Export sysfs attributes for memory device QoS class
authorDave Jiang <dave.jiang@intel.com>
Thu, 21 Dec 2023 22:04:16 +0000 (15:04 -0700)
committerDan Williams <dan.j.williams@intel.com>
Fri, 22 Dec 2023 23:46:02 +0000 (15:46 -0800)
Export qos_class sysfs attributes for the CXL memory device. The QoS clas
should show up as /sys/bus/cxl/devices/memX/ram/qos_class for the volatile
partition and /sys/bus/cxl/devices/memX/pmem/qos_class for the persistent
partition. The QTG ID is retrieved via _DSM after supplying the
calculated bandwidth and latency for the entire CXL path from device to
the CPU. This ID is used to match up to the root decoder QoS class to
determine which CFMWS the memory range of a hotplugged CXL mem device
should be assigned under.

While there may be multiple DSMAS exported by the device CDAT, the driver
will only expose the first QTG ID per partition in sysfs for now. In the
future when multiple QTG IDs are necessary, they can be exposed. [1]

[1]: https://lore.kernel.org/linux-cxl/167571650007.587790.10040913293130712882.stgit@djiang5-mobl3.local/T/#md2a47b1ead3e1ba08f50eab29a4af1aed1d215ab

Suggested-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/170319625698.2212653.17544381274847420961.stgit@djiang5-mobl3
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Documentation/ABI/testing/sysfs-bus-cxl
drivers/cxl/mem.c

index e76c3600607f8cc697e0ec2eb6753fffa6eb1647..fff2581b80335891247c5fe1a86cb410ea8a559b 100644 (file)
@@ -28,6 +28,23 @@ Description:
                Payload in the CXL-2.0 specification.
 
 
+What:          /sys/bus/cxl/devices/memX/ram/qos_class
+Date:          May, 2023
+KernelVersion: v6.8
+Contact:       linux-cxl@vger.kernel.org
+Description:
+               (RO) For CXL host platforms that support "QoS Telemmetry"
+               this attribute conveys a comma delimited list of platform
+               specific cookies that identifies a QoS performance class
+               for the volatile partition of the CXL mem device. These
+               class-ids can be compared against a similar "qos_class"
+               published for a root decoder. While it is not required
+               that the endpoints map their local memory-class to a
+               matching platform class, mismatches are not recommended
+               and there are platform specific performance related
+               side-effects that may result. First class-id is displayed.
+
+
 What:          /sys/bus/cxl/devices/memX/pmem/size
 Date:          December, 2020
 KernelVersion: v5.12
@@ -38,6 +55,23 @@ Description:
                Payload in the CXL-2.0 specification.
 
 
+What:          /sys/bus/cxl/devices/memX/pmem/qos_class
+Date:          May, 2023
+KernelVersion: v6.8
+Contact:       linux-cxl@vger.kernel.org
+Description:
+               (RO) For CXL host platforms that support "QoS Telemmetry"
+               this attribute conveys a comma delimited list of platform
+               specific cookies that identifies a QoS performance class
+               for the persistent partition of the CXL mem device. These
+               class-ids can be compared against a similar "qos_class"
+               published for a root decoder. While it is not required
+               that the endpoints map their local memory-class to a
+               matching platform class, mismatches are not recommended
+               and there are platform specific performance related
+               side-effects that may result. First class-id is displayed.
+
+
 What:          /sys/bus/cxl/devices/memX/serial
 Date:          January, 2022
 KernelVersion: v5.18
index e087febf9af047c81dfb11b06d91d92d442d586c..c5c9d8e0d88d69fcc9f031e1bd46ba7c44de4fd4 100644 (file)
@@ -215,23 +215,78 @@ static ssize_t trigger_poison_list_store(struct device *dev,
 }
 static DEVICE_ATTR_WO(trigger_poison_list);
 
+static ssize_t ram_qos_class_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+       struct cxl_dev_state *cxlds = cxlmd->cxlds;
+       struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
+       struct cxl_dpa_perf *dpa_perf;
+
+       if (!dev->driver)
+               return -ENOENT;
+
+       if (list_empty(&mds->ram_perf_list))
+               return -ENOENT;
+
+       dpa_perf = list_first_entry(&mds->ram_perf_list, struct cxl_dpa_perf,
+                                   list);
+
+       return sysfs_emit(buf, "%d\n", dpa_perf->qos_class);
+}
+
+static struct device_attribute dev_attr_ram_qos_class =
+       __ATTR(qos_class, 0444, ram_qos_class_show, NULL);
+
+static ssize_t pmem_qos_class_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+       struct cxl_dev_state *cxlds = cxlmd->cxlds;
+       struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
+       struct cxl_dpa_perf *dpa_perf;
+
+       if (!dev->driver)
+               return -ENOENT;
+
+       if (list_empty(&mds->pmem_perf_list))
+               return -ENOENT;
+
+       dpa_perf = list_first_entry(&mds->pmem_perf_list, struct cxl_dpa_perf,
+                                   list);
+
+       return sysfs_emit(buf, "%d\n", dpa_perf->qos_class);
+}
+
+static struct device_attribute dev_attr_pmem_qos_class =
+       __ATTR(qos_class, 0444, pmem_qos_class_show, NULL);
+
 static umode_t cxl_mem_visible(struct kobject *kobj, struct attribute *a, int n)
 {
-       if (a == &dev_attr_trigger_poison_list.attr) {
-               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);
+       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_trigger_poison_list.attr)
                if (!test_bit(CXL_POISON_ENABLED_LIST,
                              mds->poison.enabled_cmds))
                        return 0;
-       }
+
+       if (a == &dev_attr_pmem_qos_class.attr)
+               if (list_empty(&mds->pmem_perf_list))
+                       return 0;
+
+       if (a == &dev_attr_ram_qos_class.attr)
+               if (list_empty(&mds->ram_perf_list))
+                       return 0;
+
        return a->mode;
 }
 
 static struct attribute *cxl_mem_attrs[] = {
        &dev_attr_trigger_poison_list.attr,
+       &dev_attr_ram_qos_class.attr,
+       &dev_attr_pmem_qos_class.attr,
        NULL
 };