summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/intel/vsec_tpmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/intel/vsec_tpmi.c')
-rw-r--r--drivers/platform/x86/intel/vsec_tpmi.c82
1 files changed, 42 insertions, 40 deletions
diff --git a/drivers/platform/x86/intel/vsec_tpmi.c b/drivers/platform/x86/intel/vsec_tpmi.c
index 7fc6ff8d1040..0153dd57838e 100644
--- a/drivers/platform/x86/intel/vsec_tpmi.c
+++ b/drivers/platform/x86/intel/vsec_tpmi.c
@@ -50,12 +50,14 @@
#include <linux/auxiliary_bus.h>
#include <linux/bitfield.h>
#include <linux/debugfs.h>
+#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/intel_tpmi.h>
#include <linux/intel_vsec.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/pci.h>
#include <linux/security.h>
#include <linux/sizes.h>
@@ -188,6 +190,20 @@ struct tpmi_feature_state {
/* Used during auxbus device creation */
static DEFINE_IDA(intel_vsec_tpmi_ida);
+static BLOCKING_NOTIFIER_HEAD(tpmi_notify_list);
+
+int tpmi_register_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&tpmi_notify_list, nb);
+}
+EXPORT_SYMBOL_NS_GPL(tpmi_register_notifier, "INTEL_TPMI");
+
+int tpmi_unregister_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&tpmi_notify_list, nb);
+}
+EXPORT_SYMBOL_NS_GPL(tpmi_unregister_notifier, "INTEL_TPMI");
+
struct oobmsm_plat_info *tpmi_get_platform_data(struct auxiliary_device *auxdev)
{
struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev);
@@ -458,7 +474,7 @@ static ssize_t mem_write(struct file *file, const char __user *userbuf, size_t l
struct seq_file *m = file->private_data;
struct intel_tpmi_pm_feature *pfs = m->private;
u32 addr, value, punit, size;
- u32 num_elems, *array;
+ u32 num_elems;
void __iomem *mem;
int ret;
@@ -466,15 +482,14 @@ static ssize_t mem_write(struct file *file, const char __user *userbuf, size_t l
if (!size)
return -EIO;
+ u32 *array __free(kfree) = NULL;
ret = parse_int_array_user(userbuf, len, (int **)&array);
if (ret < 0)
return ret;
num_elems = *array;
- if (num_elems != 3) {
- ret = -EINVAL;
- goto exit_write;
- }
+ if (num_elems != 3)
+ return -EINVAL;
punit = array[1];
addr = array[2];
@@ -483,37 +498,23 @@ static ssize_t mem_write(struct file *file, const char __user *userbuf, size_t l
if (!IS_ALIGNED(addr, sizeof(u32)))
return -EINVAL;
- if (punit >= pfs->pfs_header.num_entries) {
- ret = -EINVAL;
- goto exit_write;
- }
+ if (punit >= pfs->pfs_header.num_entries)
+ return -EINVAL;
- if (addr >= size) {
- ret = -EINVAL;
- goto exit_write;
- }
+ if (addr >= size)
+ return -EINVAL;
- mutex_lock(&tpmi_dev_lock);
+ guard(mutex)(&tpmi_dev_lock);
mem = ioremap(pfs->vsec_offset + punit * size, size);
- if (!mem) {
- ret = -ENOMEM;
- goto unlock_mem_write;
- }
+ if (!mem)
+ return -ENOMEM;
writel(value, mem + addr);
iounmap(mem);
- ret = len;
-
-unlock_mem_write:
- mutex_unlock(&tpmi_dev_lock);
-
-exit_write:
- kfree(array);
-
- return ret;
+ return len;
}
static int mem_write_show(struct seq_file *s, void *unused)
@@ -626,15 +627,12 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
if (!name)
return -EOPNOTSUPP;
- res = kzalloc_objs(*res, pfs->pfs_header.num_entries);
- if (!res)
+ feature_vsec_dev = kzalloc_flex(*feature_vsec_dev, resource, pfs->pfs_header.num_entries);
+ if (!feature_vsec_dev)
return -ENOMEM;
- feature_vsec_dev = kzalloc_obj(*feature_vsec_dev);
- if (!feature_vsec_dev) {
- kfree(res);
- return -ENOMEM;
- }
+ feature_vsec_dev->num_resources = pfs->pfs_header.num_entries;
+ res = feature_vsec_dev->resource;
snprintf(feature_id_name, sizeof(feature_id_name), "tpmi-%s", name);
@@ -647,8 +645,6 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
}
feature_vsec_dev->dev = vsec_dev->dev;
- feature_vsec_dev->resource = res;
- feature_vsec_dev->num_resources = pfs->pfs_header.num_entries;
feature_vsec_dev->priv_data = &tpmi_info->plat_info;
feature_vsec_dev->priv_data_size = sizeof(tpmi_info->plat_info);
feature_vsec_dev->ida = &intel_vsec_tpmi_ida;
@@ -817,10 +813,6 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
auxiliary_set_drvdata(auxdev, tpmi_info);
- ret = tpmi_create_devices(tpmi_info);
- if (ret)
- return ret;
-
/*
* Allow debugfs when security policy allows. Everything this debugfs
* interface provides, can also be done via /dev/mem access. If
@@ -830,6 +822,14 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
if (!security_locked_down(LOCKDOWN_DEV_MEM) && capable(CAP_SYS_RAWIO))
tpmi_dbgfs_register(tpmi_info);
+ ret = tpmi_create_devices(tpmi_info);
+ if (ret) {
+ debugfs_remove_recursive(tpmi_info->dbgfs_dir);
+ return ret;
+ }
+
+ blocking_notifier_call_chain(&tpmi_notify_list, TPMI_CORE_INIT, auxdev);
+
return 0;
}
@@ -843,6 +843,8 @@ static void tpmi_remove(struct auxiliary_device *auxdev)
{
struct intel_tpmi_info *tpmi_info = auxiliary_get_drvdata(auxdev);
+ blocking_notifier_call_chain(&tpmi_notify_list, TPMI_CORE_EXIT, auxdev);
+
debugfs_remove_recursive(tpmi_info->dbgfs_dir);
}