mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 04:21:09 -04:00
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: 811f67c516 ("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>
This commit is contained in:
committed by
Ilpo Järvinen
parent
57c347a2e2
commit
14473e8c4e
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user