lkml.org 
[lkml]   [2019]   [Dec]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 18/27] nvdimm/ocxl: Add an IOCTL to report controller statistics
    Date
    From: Alastair D'Silva <alastair@d-silva.org>

    The controller can report a number of statistics that are useful
    in evaluating the performance and reliability of the card.

    This patch exposes this information via an IOCTL.

    Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
    ---
    drivers/nvdimm/ocxl/scm.c | 185 +++++++++++++++++++++++++++++++++
    include/uapi/nvdimm/ocxl-scm.h | 17 +++
    2 files changed, 202 insertions(+)

    diff --git a/drivers/nvdimm/ocxl/scm.c b/drivers/nvdimm/ocxl/scm.c
    index a520f209d626..54a2bac1cab7 100644
    --- a/drivers/nvdimm/ocxl/scm.c
    +++ b/drivers/nvdimm/ocxl/scm.c
    @@ -806,6 +806,186 @@ static int scm_ioctl_controller_dump_complete(struct scm_data *scm_data)
    GLOBAL_MMIO_HCI_CONTROLLER_DUMP_COLLECTED);
    }

    +/**
    + * scm_controller_stats_header_parse() - Parse the first 64 bits of the controller stats admin command response
    + * @scm_data: the SCM metadata
    + * @length: out, returns the number of bytes in the response (excluding the 64 bit header)
    + */
    +static int scm_controller_stats_header_parse(struct scm_data *scm_data,
    + u32 *length)
    +{
    + int rc;
    + u64 val;
    +
    + u16 data_identifier;
    + u32 data_length;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset,
    + OCXL_LITTLE_ENDIAN, &val);
    + if (rc)
    + return rc;
    +
    + data_identifier = val >> 48;
    + data_length = val & 0xFFFFFFFF;
    +
    + if (data_identifier != 0x4353) {
    + dev_err(&scm_data->dev,
    + "Bad data identifier for controller stats, expected 'CS', got '%-.*s'\n",
    + 2, (char *)&data_identifier);
    + return -EINVAL;
    + }
    +
    + *length = data_length;
    + return 0;
    +}
    +
    +static int scm_ioctl_controller_stats(struct scm_data *scm_data,
    + struct scm_ioctl_controller_stats __user *uarg)
    +{
    + struct scm_ioctl_controller_stats args;
    + u32 length;
    + int rc;
    + u64 val;
    +
    + memset(&args, '\0', sizeof(args));
    +
    + mutex_lock(&scm_data->admin_command.lock);
    +
    + rc = scm_admin_command_request(scm_data, ADMIN_COMMAND_CONTROLLER_STATS);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_write64(scm_data->ocxl_afu,
    + scm_data->admin_command.request_offset + 0x08,
    + OCXL_LITTLE_ENDIAN, 0);
    + if (rc)
    + goto out;
    +
    + rc = scm_admin_command_execute(scm_data);
    + if (rc)
    + goto out;
    +
    +
    + rc = scm_admin_command_complete_timeout(scm_data,
    + ADMIN_COMMAND_CONTROLLER_STATS);
    + if (rc < 0) {
    + dev_warn(&scm_data->dev, "Controller stats timed out\n");
    + goto out;
    + }
    +
    + rc = scm_admin_response(scm_data);
    + if (rc < 0)
    + goto out;
    + if (rc != STATUS_SUCCESS) {
    + scm_warn_status(scm_data,
    + "Unexpected status from controller stats", rc);
    + goto out;
    + }
    +
    + rc = scm_controller_stats_header_parse(scm_data, &length);
    + if (rc)
    + goto out;
    +
    + if (length != 0x140)
    + scm_warn_status(scm_data,
    + "Unexpected length for controller stats data, expected 0x140, got 0x%x",
    + length);
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x08,
    + OCXL_LITTLE_ENDIAN, &val);
    + if (rc)
    + goto out;
    +
    + args.reset_count = val >> 32;
    + args.reset_uptime = val & 0xFFFFFFFF;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x10,
    + OCXL_LITTLE_ENDIAN, &val);
    + if (rc)
    + goto out;
    +
    + args.power_on_uptime = val >> 32;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x08,
    + OCXL_LITTLE_ENDIAN, &args.host_load_count);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x10,
    + OCXL_LITTLE_ENDIAN, &args.host_store_count);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x18,
    + OCXL_LITTLE_ENDIAN, &args.media_read_count);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x20,
    + OCXL_LITTLE_ENDIAN, &args.media_write_count);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x28,
    + OCXL_LITTLE_ENDIAN, &args.cache_hit_count);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x30,
    + OCXL_LITTLE_ENDIAN, &args.cache_miss_count);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x38,
    + OCXL_LITTLE_ENDIAN, &args.media_read_latency);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x40,
    + OCXL_LITTLE_ENDIAN, &args.media_write_latency);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x48,
    + OCXL_LITTLE_ENDIAN, &args.cache_read_latency);
    + if (rc)
    + goto out;
    +
    + rc = ocxl_global_mmio_read64(scm_data->ocxl_afu,
    + scm_data->admin_command.data_offset + 0x08 + 0x40 + 0x50,
    + OCXL_LITTLE_ENDIAN, &args.cache_write_latency);
    + if (rc)
    + goto out;
    +
    + if (copy_to_user(uarg, &args, sizeof(args))) {
    + rc = -EFAULT;
    + goto out;
    + }
    +
    + rc = scm_admin_response_handled(scm_data);
    + if (rc)
    + goto out;
    +
    + rc = 0;
    + goto out;
    +
    +out:
    + mutex_unlock(&scm_data->admin_command.lock);
    + return rc;
    +}
    +
    static long scm_file_ioctl(struct file *file, unsigned int cmd,
    unsigned long args)
    {
    @@ -830,6 +1010,11 @@ static long scm_file_ioctl(struct file *file, unsigned int cmd,
    case SCM_IOCTL_CONTROLLER_DUMP_COMPLETE:
    rc = scm_ioctl_controller_dump_complete(scm_data);
    break;
    +
    + case SCM_IOCTL_CONTROLLER_STATS:
    + rc = scm_ioctl_controller_stats(scm_data,
    + (struct scm_ioctl_controller_stats __user *)args);
    + break;
    }

    return rc;
    diff --git a/include/uapi/nvdimm/ocxl-scm.h b/include/uapi/nvdimm/ocxl-scm.h
    index abd2dc9ea112..0a5de46c5acd 100644
    --- a/include/uapi/nvdimm/ocxl-scm.h
    +++ b/include/uapi/nvdimm/ocxl-scm.h
    @@ -50,6 +50,22 @@ struct scm_ioctl_controller_dump_data {
    __u64 reserved[8];
    };

    +struct scm_ioctl_controller_stats {
    + __u32 reset_count;
    + __u32 reset_uptime; // seconds
    + __u32 power_on_uptime; // seconds
    + __u64 host_load_count;
    + __u64 host_store_count;
    + __u64 media_read_count;
    + __u64 media_write_count;
    + __u64 cache_hit_count;
    + __u64 cache_miss_count;
    + __u64 media_read_latency; // nanoseconds
    + __u64 media_write_latency; // nanoseconds
    + __u64 cache_read_latency; // nanoseconds
    + __u64 cache_write_latency; // nanoseconds
    +};
    +
    /* ioctl numbers */
    #define SCM_MAGIC 0x5C
    /* SCM devices */
    @@ -57,5 +73,6 @@ struct scm_ioctl_controller_dump_data {
    #define SCM_IOCTL_CONTROLLER_DUMP _IO(SCM_MAGIC, 0x02)
    #define SCM_IOCTL_CONTROLLER_DUMP_DATA _IOWR(SCM_MAGIC, 0x03, struct scm_ioctl_controller_dump_data)
    #define SCM_IOCTL_CONTROLLER_DUMP_COMPLETE _IO(SCM_MAGIC, 0x04)
    +#define SCM_IOCTL_CONTROLLER_STATS _IO(SCM_MAGIC, 0x05)

    #endif /* _UAPI_OCXL_SCM_H */
    --
    2.23.0
    \
     
     \ /
      Last update: 2019-12-03 04:50    [W:5.574 / U:0.732 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site