platform/x86: ISST: Add Intel Speed Select PUNIT MSR interface
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Wed, 26 Jun 2019 22:38:49 +0000 (15:38 -0700)
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Tue, 2 Jul 2019 15:41:16 +0000 (18:41 +0300)
While using new non arhitectural features using PUNIT Mailbox and MMIO
read/write interface, still there is need to operate using MSRs to
control PUNIT. User space could have used user user-space MSR interface for
this, but when user space MSR access is disabled, then it can't. Here only
limited number of MSRs are allowed using this new interface.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
drivers/platform/x86/intel_speed_select_if/isst_if_common.c
include/uapi/linux/isst_if.h

index 391fc3f..de2fb52 100644 (file)
 
 static struct isst_if_cmd_cb punit_callbacks[ISST_IF_DEV_MAX];
 
+static int punit_msr_white_list[] = {
+       MSR_TURBO_RATIO_LIMIT,
+       MSR_CONFIG_TDP_CONTROL,
+};
+
 struct isst_valid_cmd_ranges {
        u16 cmd;
        u16 sub_cmd_beg;
@@ -229,6 +234,54 @@ static long isst_if_proc_phyid_req(u8 *cmd_ptr, int *write_only, int resume)
        return 0;
 }
 
+static bool match_punit_msr_white_list(int msr)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(punit_msr_white_list); ++i) {
+               if (punit_msr_white_list[i] == msr)
+                       return true;
+       }
+
+       return false;
+}
+
+static long isst_if_msr_cmd_req(u8 *cmd_ptr, int *write_only, int resume)
+{
+       struct isst_if_msr_cmd *msr_cmd;
+       int ret;
+
+       msr_cmd = (struct isst_if_msr_cmd *)cmd_ptr;
+
+       if (!match_punit_msr_white_list(msr_cmd->msr))
+               return -EINVAL;
+
+       if (msr_cmd->logical_cpu >= nr_cpu_ids)
+               return -EINVAL;
+
+       if (msr_cmd->read_write) {
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               ret = wrmsrl_safe_on_cpu(msr_cmd->logical_cpu,
+                                        msr_cmd->msr,
+                                        msr_cmd->data);
+               *write_only = 1;
+       } else {
+               u64 data;
+
+               ret = rdmsrl_safe_on_cpu(msr_cmd->logical_cpu,
+                                        msr_cmd->msr, &data);
+               if (!ret) {
+                       msr_cmd->data = data;
+                       *write_only = 0;
+               }
+       }
+
+
+       return ret;
+}
+
 static long isst_if_exec_multi_cmd(void __user *argp, struct isst_if_cmd_cb *cb)
 {
        unsigned char __user *ptr;
@@ -309,6 +362,12 @@ static long isst_if_def_ioctl(struct file *file, unsigned int cmd,
                if (cb->registered)
                        ret = isst_if_exec_multi_cmd(argp, cb);
                break;
+       case ISST_IF_MSR_COMMAND:
+               cmd_cb.cmd_size = sizeof(struct isst_if_msr_cmd);
+               cmd_cb.offset = offsetof(struct isst_if_msr_cmds, msr_cmd);
+               cmd_cb.cmd_callback = isst_if_msr_cmd_req;
+               ret = isst_if_exec_multi_cmd(argp, &cmd_cb);
+               break;
        default:
                break;
        }
index e4b1c2e..d10b832 100644 (file)
@@ -132,9 +132,41 @@ struct isst_if_mbox_cmds {
        struct isst_if_mbox_cmd mbox_cmd[1];
 };
 
+/**
+ * struct isst_if_msr_cmd - Structure to define msr command
+ * @read_write:                Value 0: Read, 1: Write
+ * @logical_cpu:       Logical CPU number
+ * @msr:               MSR number
+ * @data:              For write operation, data to write, for read
+ *                     place holder
+ *
+ * Structure to specify MSR command related to PUNIT.
+ */
+struct isst_if_msr_cmd {
+       __u32 read_write; /* Read:0, Write:1 */
+       __u32 logical_cpu;
+       __u64 msr;
+       __u64 data;
+};
+
+/**
+ * struct isst_if_msr_cmds - structure for msr commands
+ * @cmd_count: Number of mailbox commands in msr_cmd[]
+ * @msr_cmd[]: Holds one or more msr commands
+ *
+ * This structure used with ioctl ISST_IF_MSR_COMMAND to send
+ * one or more MSR commands. IOCTL return value indicates number of
+ * commands sent or error number if no commands have been sent.
+ */
+struct isst_if_msr_cmds {
+       __u32 cmd_count;
+       struct isst_if_msr_cmd msr_cmd[1];
+};
+
 #define ISST_IF_MAGIC                  0xFE
 #define ISST_IF_GET_PLATFORM_INFO      _IOR(ISST_IF_MAGIC, 0, struct isst_if_platform_info *)
 #define ISST_IF_GET_PHY_ID             _IOWR(ISST_IF_MAGIC, 1, struct isst_if_cpu_map *)
 #define ISST_IF_IO_CMD         _IOW(ISST_IF_MAGIC, 2, struct isst_if_io_regs *)
 #define ISST_IF_MBOX_COMMAND   _IOWR(ISST_IF_MAGIC, 3, struct isst_if_mbox_cmds *)
+#define ISST_IF_MSR_COMMAND    _IOWR(ISST_IF_MAGIC, 4, struct isst_if_msr_cmds *)
 #endif