platform/x86/amd/hsmp: Add support for HSMP protocol version 7 messages
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>
This commit is contained in:
@@ -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) */
|
||||
|
||||
@@ -33,7 +33,13 @@
|
||||
#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:
|
||||
|
||||
Reference in New Issue
Block a user