summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/amd/hsmp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/amd/hsmp')
-rw-r--r--drivers/platform/x86/amd/hsmp/acpi.c12
-rw-r--r--drivers/platform/x86/amd/hsmp/hsmp.c47
-rw-r--r--drivers/platform/x86/amd/hsmp/plat.c12
3 files changed, 53 insertions, 18 deletions
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index e981d45e1c12..444b43be35a2 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -226,7 +226,7 @@ static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)
}
static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
@@ -285,19 +285,19 @@ static int init_acpi(struct device *dev)
return ret;
}
-static struct bin_attribute hsmp_metric_tbl_attr = {
+static const struct bin_attribute hsmp_metric_tbl_attr = {
.attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444},
- .read = hsmp_metric_tbl_acpi_read,
+ .read_new = hsmp_metric_tbl_acpi_read,
.size = sizeof(struct hsmp_metric_table),
};
-static struct bin_attribute *hsmp_attr_list[] = {
+static const struct bin_attribute *hsmp_attr_list[] = {
&hsmp_metric_tbl_attr,
NULL
};
-static struct attribute_group hsmp_attr_grp = {
- .bin_attrs = hsmp_attr_list,
+static const struct attribute_group hsmp_attr_grp = {
+ .bin_attrs_new = hsmp_attr_list,
.is_bin_visible = hsmp_is_sock_attr_visible,
};
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c
index 227b4ad4a51a..03164e30b3a5 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.c
+++ b/drivers/platform/x86/amd/hsmp/hsmp.c
@@ -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:
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index a61f815c9f80..02ca85762b68 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -59,7 +59,7 @@ static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,
}
static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct hsmp_socket *sock;
@@ -97,13 +97,13 @@ static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
* is_bin_visible function is used to show / hide the necessary groups.
*/
#define HSMP_BIN_ATTR(index, _list) \
-static struct bin_attribute attr##index = { \
+static const struct bin_attribute attr##index = { \
.attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \
.private = (void *)index, \
- .read = hsmp_metric_tbl_plat_read, \
+ .read_new = hsmp_metric_tbl_plat_read, \
.size = sizeof(struct hsmp_metric_table), \
}; \
-static struct bin_attribute _list[] = { \
+static const struct bin_attribute _list[] = { \
&attr##index, \
NULL \
}
@@ -118,8 +118,8 @@ HSMP_BIN_ATTR(6, *sock6_attr_list);
HSMP_BIN_ATTR(7, *sock7_attr_list);
#define HSMP_BIN_ATTR_GRP(index, _list, _name) \
-static struct attribute_group sock##index##_attr_grp = { \
- .bin_attrs = _list, \
+static const struct attribute_group sock##index##_attr_grp = { \
+ .bin_attrs_new = _list, \
.is_bin_visible = hsmp_is_sock_attr_visible, \
.name = #_name, \
}