]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
platform/x86/amd/hsmp: Add support for HSMP protocol version 7 messages
authorSuma Hegde <suma.hegde@amd.com>
Mon, 18 Nov 2024 10:27:52 +0000 (10:27 +0000)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 2 Dec 2024 17:20:14 +0000 (19:20 +0200)
Following new HSMP messages are available on family 0x1A, model 0x00-0x1F
platforms with protocol version 7. Add support for them in the driver.
- SetXgmiPstateRange(26h)
- CpuRailIsoFreqPolicy(27h)
- DfcEnable(28h)
- GetRaplUnit(30h)
- GetRaplCoreCounter(31h)
- GetRaplPackageCounter(32h)

Also update HSMP message PwrEfficiencyModeSelection-21h. This message is
updated to include GET option in recent firmware.

Signed-off-by: Suma Hegde <suma.hegde@amd.com>
Reviewed-by: Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
Link: https://lore.kernel.org/r/20241118102752.11703-1-suma.hegde@amd.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
arch/x86/include/uapi/asm/amd_hsmp.h
drivers/platform/x86/amd/hsmp/hsmp.c

index 4a7cace06204299022e3f9dc830a0cfb4c7405c6..92d8f256d096c710c96ab5fa4175d7a965f18c79 100644 (file)
@@ -50,6 +50,12 @@ enum hsmp_message_ids {
        HSMP_GET_METRIC_TABLE_VER,      /* 23h Get metrics table version */
        HSMP_GET_METRIC_TABLE,          /* 24h Get metrics table */
        HSMP_GET_METRIC_TABLE_DRAM_ADDR,/* 25h Get metrics table dram address */
+       HSMP_SET_XGMI_PSTATE_RANGE,     /* 26h Set xGMI P-state range */
+       HSMP_CPU_RAIL_ISO_FREQ_POLICY,  /* 27h Get/Set Cpu Iso frequency policy */
+       HSMP_DFC_ENABLE_CTRL,           /* 28h Enable/Disable DF C-state */
+       HSMP_GET_RAPL_UNITS = 0x30,     /* 30h Get scaling factor for energy */
+       HSMP_GET_RAPL_CORE_COUNTER,     /* 31h Get core energy counter value */
+       HSMP_GET_RAPL_PACKAGE_COUNTER,  /* 32h Get package energy counter value */
        HSMP_MSG_ID_MAX,
 };
 
@@ -65,6 +71,7 @@ enum hsmp_msg_type {
        HSMP_RSVD = -1,
        HSMP_SET  = 0,
        HSMP_GET  = 1,
+       HSMP_SET_GET    = 2,
 };
 
 enum hsmp_proto_versions {
@@ -72,7 +79,8 @@ enum hsmp_proto_versions {
        HSMP_PROTO_VER3,
        HSMP_PROTO_VER4,
        HSMP_PROTO_VER5,
-       HSMP_PROTO_VER6
+       HSMP_PROTO_VER6,
+       HSMP_PROTO_VER7
 };
 
 struct hsmp_msg_desc {
@@ -300,7 +308,7 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[]
         * HSMP_SET_POWER_MODE, num_args = 1, response_sz = 0
         * input: args[0] = power efficiency mode[2:0]
         */
-       {1, 0, HSMP_SET},
+       {1, 1, HSMP_SET_GET},
 
        /*
         * HSMP_SET_PSTATE_MAX_MIN, num_args = 1, response_sz = 0
@@ -325,6 +333,58 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[]
         * output: args[1] = upper 32 bits of the address
         */
        {0, 2, HSMP_GET},
+
+       /*
+        * HSMP_SET_XGMI_PSTATE_RANGE, num_args = 1, response_sz = 0
+        * input: args[0] = min xGMI p-state[15:8] + max xGMI p-state[7:0]
+        */
+       {1, 0, HSMP_SET},
+
+       /*
+        * HSMP_CPU_RAIL_ISO_FREQ_POLICY, num_args = 1, response_sz = 1
+        * input: args[0] = set/get policy[31] +
+        * disable/enable independent control[0]
+        * output: args[0] = current policy[0]
+        */
+       {1, 1, HSMP_SET_GET},
+
+       /*
+        * HSMP_DFC_ENABLE_CTRL, num_args = 1, response_sz = 1
+        * input: args[0] = set/get policy[31] + enable/disable DFC[0]
+        * output: args[0] = current policy[0]
+        */
+       {1, 1, HSMP_SET_GET},
+
+       /* RESERVED(0x29-0x2f) */
+       {0, 0, HSMP_RSVD},
+       {0, 0, HSMP_RSVD},
+       {0, 0, HSMP_RSVD},
+       {0, 0, HSMP_RSVD},
+       {0, 0, HSMP_RSVD},
+       {0, 0, HSMP_RSVD},
+       {0, 0, HSMP_RSVD},
+
+       /*
+        * HSMP_GET_RAPL_UNITS, response_sz = 1
+        * output: args[0] = tu value[19:16] + esu value[12:8]
+        */
+       {0, 1, HSMP_GET},
+
+       /*
+        * HSMP_GET_RAPL_CORE_COUNTER, num_args = 1, response_sz = 1
+        * input: args[0] = apic id[15:0]
+        * output: args[0] = lower 32 bits of energy
+        * output: args[1] = upper 32 bits of energy
+        */
+       {1, 2, HSMP_GET},
+
+       /*
+        * HSMP_GET_RAPL_PACKAGE_COUNTER, num_args = 0, response_sz = 1
+        * output: args[0] = lower 32 bits of energy
+        * output: args[1] = upper 32 bits of energy
+        */
+       {0, 2, HSMP_GET},
+
 };
 
 /* Metrics table (supported only with proto version 6) */
index f29dd93fbf0b495421f0891b81553edd856a336c..a8f3e751967857757b5cc464dfc9d1965de5c4cd 100644 (file)
 #define HSMP_WR                        true
 #define HSMP_RD                        false
 
-#define DRIVER_VERSION         "2.3"
+#define DRIVER_VERSION         "2.4"
+
+/*
+ * When same message numbers are used for both GET and SET operation,
+ * bit:31 indicates whether its SET or GET operation.
+ */
+#define CHECK_GET_BIT          BIT(31)
 
 static struct hsmp_plat_device hsmp_pdev;
 
@@ -167,11 +173,28 @@ static int validate_message(struct hsmp_message *msg)
        if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_RSVD)
                return -ENOMSG;
 
-       /* num_args and response_sz against the HSMP spec */
-       if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args ||
-           msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz)
+       /*
+        * num_args passed by user should match the num_args specified in
+        * message description table.
+        */
+       if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args)
                return -EINVAL;
 
+       /*
+        * Some older HSMP SET messages are updated to add GET in the same message.
+        * In these messages, GET returns the current value and SET also returns
+        * the successfully set value. To support this GET and SET in same message
+        * while maintaining backward compatibility for the HSMP users,
+        * hsmp_msg_desc_table[] indicates only maximum allowed response_sz.
+        */
+       if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_SET_GET) {
+               if (msg->response_sz > hsmp_msg_desc_table[msg->msg_id].response_sz)
+                       return -EINVAL;
+       } else {
+               /* only HSMP_SET or HSMP_GET messages go through this strict check */
+               if (msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz)
+                       return -EINVAL;
+       }
        return 0;
 }
 
@@ -239,6 +262,18 @@ int hsmp_test(u16 sock_ind, u32 value)
 }
 EXPORT_SYMBOL_NS_GPL(hsmp_test, AMD_HSMP);
 
+static bool is_get_msg(struct hsmp_message *msg)
+{
+       if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_GET)
+               return true;
+
+       if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_SET_GET &&
+           (msg->args[0] & CHECK_GET_BIT))
+               return true;
+
+       return false;
+}
+
 long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 {
        int __user *arguser = (int  __user *)arg;
@@ -261,7 +296,7 @@ long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
                 * Device is opened in O_WRONLY mode
                 * Execute only set/configure commands
                 */
-               if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_SET)
+               if (is_get_msg(&msg))
                        return -EPERM;
                break;
        case FMODE_READ:
@@ -269,7 +304,7 @@ long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
                 * Device is opened in O_RDONLY mode
                 * Execute only get/monitor commands
                 */
-               if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_GET)
+               if (!is_get_msg(&msg))
                        return -EPERM;
                break;
        case FMODE_READ | FMODE_WRITE: