cxl/pci: Set the device timestamp
authorJonathan Cameron <Jonathan.Cameron@huawei.com>
Mon, 30 Jan 2023 15:13:27 +0000 (15:13 +0000)
committerDan Williams <dan.j.williams@intel.com>
Mon, 30 Jan 2023 19:30:51 +0000 (11:30 -0800)
CXL r3.0 section 8.2.9.4.2 "Set Timestamp" recommends that the host sets
the timestamp after every Conventional or CXL Reset to ensure accurate
timestamps. This should include on initial boot up. The time base that
is being set is used by a device for the poison list overflow timestamp
and all event timestamps.  Note that the command is optional and if
not supported and the device cannot return accurate timestamps it will
fill the fields in with an appropriate marker (see the specification
description of each timestamp).

Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/20230130151327.32415-1-Jonathan.Cameron@huawei.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/cxl/core/mbox.c
drivers/cxl/cxlmem.h
drivers/cxl/pci.c

index 14fa094..a122559 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/security.h>
 #include <linux/debugfs.h>
+#include <linux/ktime.h>
 #include <linux/mutex.h>
 #include <cxlmem.h>
 #include <cxl.h>
@@ -1055,6 +1056,32 @@ int cxl_mem_create_range_info(struct cxl_dev_state *cxlds)
 }
 EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, CXL);
 
+int cxl_set_timestamp(struct cxl_dev_state *cxlds)
+{
+       struct cxl_mbox_cmd mbox_cmd;
+       struct cxl_mbox_set_timestamp_in pi;
+       int rc;
+
+       pi.timestamp = cpu_to_le64(ktime_get_real_ns());
+       mbox_cmd = (struct cxl_mbox_cmd) {
+               .opcode = CXL_MBOX_OP_SET_TIMESTAMP,
+               .size_in = sizeof(pi),
+               .payload_in = &pi,
+       };
+
+       rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+       /*
+        * Command is optional. Devices may have another way of providing
+        * a timestamp, or may return all 0s in timestamp fields.
+        * Don't report an error if this command isn't supported
+        */
+       if (rc && (mbox_cmd.return_code != CXL_MBOX_CMD_RC_UNSUPPORTED))
+               return rc;
+
+       return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_set_timestamp, CXL);
+
 struct cxl_dev_state *cxl_dev_state_create(struct device *dev)
 {
        struct cxl_dev_state *cxlds;
index f21692c..802b5b3 100644 (file)
@@ -309,6 +309,7 @@ enum cxl_opcode {
        CXL_MBOX_OP_SET_EVT_INT_POLICY  = 0x0103,
        CXL_MBOX_OP_GET_FW_INFO         = 0x0200,
        CXL_MBOX_OP_ACTIVATE_FW         = 0x0202,
+       CXL_MBOX_OP_SET_TIMESTAMP       = 0x0301,
        CXL_MBOX_OP_GET_SUPPORTED_LOGS  = 0x0400,
        CXL_MBOX_OP_GET_LOG             = 0x0401,
        CXL_MBOX_OP_IDENTIFY            = 0x4000,
@@ -537,6 +538,12 @@ struct cxl_mbox_set_partition_info {
 
 #define  CXL_SET_PARTITION_IMMEDIATE_FLAG      BIT(0)
 
+/* Set Timestamp CXL 3.0 Spec 8.2.9.4.2 */
+struct cxl_mbox_set_timestamp_in {
+       __le64 timestamp;
+
+} __packed;
+
 /**
  * struct cxl_mem_command - Driver representation of a memory device command
  * @info: Command information as it exists for the UAPI
@@ -607,6 +614,8 @@ struct cxl_dev_state *cxl_dev_state_create(struct device *dev);
 void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds);
 void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds);
 void cxl_mem_get_event_records(struct cxl_dev_state *cxlds, u32 status);
+int cxl_set_timestamp(struct cxl_dev_state *cxlds);
+
 #ifdef CONFIG_CXL_SUSPEND
 void cxl_mem_active_inc(void);
 void cxl_mem_active_dec(void);
index d470052..ad2ebe7 100644 (file)
@@ -708,6 +708,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc)
                return rc;
 
+       rc = cxl_set_timestamp(cxlds);
+       if (rc)
+               return rc;
+
        rc = cxl_dev_state_identify(cxlds);
        if (rc)
                return rc;