]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
cxl/edac: Add support for PERFORM_MAINTENANCE command
authorShiju Jose <shiju.jose@huawei.com>
Wed, 21 May 2025 12:47:43 +0000 (13:47 +0100)
committerDave Jiang <dave.jiang@intel.com>
Fri, 23 May 2025 20:24:28 +0000 (13:24 -0700)
Add support for PERFORM_MAINTENANCE command.

CXL spec 3.2 section 8.2.10.7.1 describes the Perform Maintenance command.
This command requests the device to execute the maintenance operation
specified by the maintenance operation class and the maintenance operation
subclass.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Acked-by: Dan Williams <dan.j.williams@intel.com>
Link: https://patch.msgid.link/20250521124749.817-6-shiju.jose@huawei.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
drivers/cxl/core/edac.c
drivers/cxl/cxlmem.h

index da2e7e32150a5f8b8b25023ad23ecfb6935c998d..a0b045fe3c45116ced8244edd0ee3cc9aa4624f6 100644 (file)
@@ -813,6 +813,55 @@ static int cxl_memdev_ecs_init(struct cxl_memdev *cxlmd,
        return 0;
 }
 
+/*
+ * Perform Maintenance CXL 3.2 Spec 8.2.10.7.1
+ */
+
+/*
+ * Perform Maintenance input payload
+ * CXL rev 3.2 section 8.2.10.7.1 Table 8-117
+ */
+struct cxl_mbox_maintenance_hdr {
+       u8 op_class;
+       u8 op_subclass;
+} __packed;
+
+static int cxl_perform_maintenance(struct cxl_mailbox *cxl_mbox, u8 class,
+                                  u8 subclass, void *data_in,
+                                  size_t data_in_size)
+{
+       struct cxl_memdev_maintenance_pi {
+               struct cxl_mbox_maintenance_hdr hdr;
+               u8 data[];
+       } __packed;
+       struct cxl_mbox_cmd mbox_cmd;
+       size_t hdr_size;
+
+       struct cxl_memdev_maintenance_pi *pi __free(kvfree) =
+               kvzalloc(cxl_mbox->payload_size, GFP_KERNEL);
+       if (!pi)
+               return -ENOMEM;
+
+       pi->hdr.op_class = class;
+       pi->hdr.op_subclass = subclass;
+       hdr_size = sizeof(pi->hdr);
+       /*
+        * Check minimum mbox payload size is available for
+        * the maintenance data transfer.
+        */
+       if (hdr_size + data_in_size > cxl_mbox->payload_size)
+               return -ENOMEM;
+
+       memcpy(pi->data, data_in, data_in_size);
+       mbox_cmd = (struct cxl_mbox_cmd){
+               .opcode = CXL_MBOX_OP_DO_MAINTENANCE,
+               .size_in = hdr_size + data_in_size,
+               .payload_in = pi,
+       };
+
+       return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
+}
+
 int devm_cxl_memdev_edac_register(struct cxl_memdev *cxlmd)
 {
        struct edac_dev_feature ras_features[CXL_NR_EDAC_DEV_FEATURES];
index 872131009e4ccdd58544b6a0287e2ae3ae4d0b84..1d4fe19c554d9e29ba87fbd640b302e64332a80a 100644 (file)
@@ -531,6 +531,7 @@ enum cxl_opcode {
        CXL_MBOX_OP_GET_SUPPORTED_FEATURES      = 0x0500,
        CXL_MBOX_OP_GET_FEATURE         = 0x0501,
        CXL_MBOX_OP_SET_FEATURE         = 0x0502,
+       CXL_MBOX_OP_DO_MAINTENANCE      = 0x0600,
        CXL_MBOX_OP_IDENTIFY            = 0x4000,
        CXL_MBOX_OP_GET_PARTITION_INFO  = 0x4100,
        CXL_MBOX_OP_SET_PARTITION_INFO  = 0x4101,