summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2026-04-30 08:11:03 -0700
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>2026-05-07 16:06:29 +0300
commit14473e8c4e97d51eff9b2f384ae696f7a32f182b (patch)
tree5ada87b47f50f743fb5ae3b089a42dfbd5fe5e4b
parent57c347a2e2473bfb5c1f1132a3209c55efbe640b (diff)
downloadlinux-14473e8c4e97d51eff9b2f384ae696f7a32f182b.tar.gz
linux-14473e8c4e97d51eff9b2f384ae696f7a32f182b.zip
platform/x86/intel/tpmi/plr: Prevent fault during unbind
This driver faults when intel vsec driver is unbound from PCI driver interface. For example: echo 0000:00:03.1 > /sys/bus/pci/drivers/intel_vsec/unbind This is caused by accessing plr->dbgfs_dir after vsec_tpmi driver is removed. Here vsec_tpmi driver is the parent. On unbind, the parent device remove callback is called first which here will remove debugfs interface. Hence plr->dbgfs_dir is no longer valid. Register notifier for TPMI_CORE_EXIT and make this pointer to NULL, so that debugfs_remove_recursive() is not called with bad plr->dbgfs_dir pointer. After notifier is returned the vsec_tpmi driver will call remove debugfs by calling debugfs_remove_recursive(). Fixes: 811f67c51636 ("platform/x86/intel/tpmi: Add new auxiliary driver for performance limits") Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Cc: Stable@vger.kernel.org Link: https://patch.msgid.link/20260430151103.1549733-4-srinivas.pandruvada@linux.intel.com Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-rw-r--r--drivers/platform/x86/intel/plr_tpmi.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/drivers/platform/x86/intel/plr_tpmi.c b/drivers/platform/x86/intel/plr_tpmi.c
index 05727169f49c..8faecc311038 100644
--- a/drivers/platform/x86/intel/plr_tpmi.c
+++ b/drivers/platform/x86/intel/plr_tpmi.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
+#include <linux/notifier.h>
#include <linux/seq_file.h>
#include <linux/sprintf.h>
#include <linux/types.h>
@@ -60,6 +61,8 @@ struct tpmi_plr {
struct tpmi_plr_die *die_info;
int num_dies;
struct auxiliary_device *auxdev;
+ struct notifier_block nb;
+ struct mutex lock; /* Protect access to dbgfs_dir */
};
static const char * const plr_coarse_reasons[] = {
@@ -255,6 +258,30 @@ static ssize_t plr_status_write(struct file *filp, const char __user *ubuf,
}
DEFINE_SHOW_STORE_ATTRIBUTE(plr_status);
+static int intel_plr_notify(struct notifier_block *self, unsigned long action, void *data)
+{
+ struct tpmi_plr *plr = container_of(self, struct tpmi_plr, nb);
+
+ if (action == TPMI_CORE_EXIT) {
+ guard(mutex)(&plr->lock);
+ plr->dbgfs_dir = NULL;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static int intel_plr_register_notifier(struct notifier_block *nb)
+{
+ nb->notifier_call = intel_plr_notify;
+ nb->priority = 0;
+ return tpmi_register_notifier(nb);
+}
+
+static void intel_plr_unregister_notifier(struct notifier_block *nb)
+{
+ tpmi_unregister_notifier(nb);
+}
+
static int intel_plr_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
{
struct oobmsm_plat_info *plat_info;
@@ -282,10 +309,18 @@ static int intel_plr_probe(struct auxiliary_device *auxdev, const struct auxilia
if (!plr)
return -ENOMEM;
+ err = devm_mutex_init(&auxdev->dev, &plr->lock);
+ if (err)
+ return err;
+
+ intel_plr_register_notifier(&plr->nb);
+
plr->die_info = devm_kcalloc(&auxdev->dev, num_resources, sizeof(*plr->die_info),
GFP_KERNEL);
- if (!plr->die_info)
- return -ENOMEM;
+ if (!plr->die_info) {
+ err = -ENOMEM;
+ goto err_notify;
+ }
plr->num_dies = num_resources;
plr->dbgfs_dir = debugfs_create_dir("plr", dentry);
@@ -326,6 +361,9 @@ static int intel_plr_probe(struct auxiliary_device *auxdev, const struct auxilia
err:
debugfs_remove_recursive(plr->dbgfs_dir);
+err_notify:
+ intel_plr_unregister_notifier(&plr->nb);
+
return err;
}
@@ -333,6 +371,9 @@ static void intel_plr_remove(struct auxiliary_device *auxdev)
{
struct tpmi_plr *plr = auxiliary_get_drvdata(auxdev);
+ intel_plr_unregister_notifier(&plr->nb);
+
+ guard(mutex)(&plr->lock);
debugfs_remove_recursive(plr->dbgfs_dir);
}