* [PATCH 6.12.y 2/5] ACPI: bus: Introduce devm_acpi_install_notify_handler()
2026-07-10 16:14 ` [PATCH 6.12.y 1/5] ACPI: driver: Check ACPI_COMPANION() against NULL during probe Sasha Levin
@ 2026-07-10 16:14 ` Sasha Levin
2026-07-10 16:14 ` [PATCH 6.12.y 3/5] ACPI: NFIT: core: Use devm_acpi_install_notify_handler() Sasha Levin
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-07-10 16:14 UTC (permalink / raw)
To: stable; +Cc: Rafael J. Wysocki, Sasha Levin
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
[ Upstream commit ca70ce555a1eb8edf5fb1d5575f1fe19c9ae17f4 ]
Introduce devm_acpi_install_notify_handler() for installing an ACPI
notify handler managed by devres that will be removed automatically on
driver detach.
It installs the notify handler on the device object in the ACPI
namespace that corresponds to the owner device's ACPI companion, if
present (an error is returned if the owner device doesn't have an ACPI
companion).
Currently, there is no way to manually remove the notify handler
installed by it because none of its users brought on subsequently
will need to do that.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
[ rjw: Kerneldoc comment refinement ]
Link: https://patch.msgid.link/2268031.irdbgypaU6@rafael.j.wysocki
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Stable-dep-of: 18a00ed0e718 ("ACPI: NFIT: core: Fix possible deadlock and missing notifications")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/acpi/bus.c | 66 +++++++++++++++++++++++++++++++++++++++++
include/acpi/acpi_bus.h | 2 ++
2 files changed, 68 insertions(+)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 6234055d259846..8730d46a6b273c 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -622,6 +622,72 @@ void acpi_dev_remove_notify_handler(struct acpi_device *adev,
}
EXPORT_SYMBOL_GPL(acpi_dev_remove_notify_handler);
+struct acpi_notify_handler_devres {
+ acpi_notify_handler handler;
+ u32 handler_type;
+};
+
+static void devm_acpi_notify_handler_release(struct device *dev, void *res)
+{
+ struct acpi_notify_handler_devres *dr = res;
+
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(dev), dr->handler_type,
+ dr->handler);
+}
+
+/**
+ * devm_acpi_install_notify_handler - Install an ACPI notify handler for a
+ * managed device
+ * @dev: Device to install a notify handler for
+ * @handler_type: Type of the notify handler
+ * @handler: Handler function to install
+ * @context: Data passed back to the handler function
+ *
+ * This function performs the same function as acpi_dev_install_notify_handler()
+ * called for the ACPI companion of @dev with the same @handler_type, @handler,
+ * and @context arguments, but the ACPI notify handler installed by it will be
+ * automatically removed on driver detach.
+ *
+ * Callers should ensure that all resources used by @handler have been allocated
+ * prior to invoking this function, in which case those resources should be
+ * devres-managed so that they won't be released before the notify handler
+ * removal. Otherwise, special synchronization between @handler and the
+ * management of those resources is required.
+ *
+ * When the request fails, an error message is printed. Don't add extra error
+ * messages at the call sites.
+ *
+ * Return: 0 on success or a negative error number.
+ */
+int devm_acpi_install_notify_handler(struct device *dev, u32 handler_type,
+ acpi_notify_handler handler, void *context)
+{
+ struct acpi_notify_handler_devres *dr;
+ struct acpi_device *adev;
+ int ret;
+
+ adev = ACPI_COMPANION(dev);
+ if (!adev)
+ return dev_err_probe(dev, -ENODEV, "No ACPI companion in %s()\n", __func__);
+
+ dr = devres_alloc(devm_acpi_notify_handler_release, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return -ENOMEM;
+
+ ret = acpi_dev_install_notify_handler(adev, handler_type, handler, context);
+ if (ret) {
+ devres_free(dr);
+ return dev_err_probe(dev, ret, "Failed to install an ACPI notify handler\n");
+ }
+
+ dr->handler = handler;
+ dr->handler_type = handler_type;
+ devres_add(dev, dr);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devm_acpi_install_notify_handler);
+
/* Handle events targeting \_SB device (at present only graceful shutdown) */
#define ACPI_SB_NOTIFY_SHUTDOWN_REQUEST 0x81
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index b2e377b7f3373d..2aa34fcc10a157 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -625,6 +625,8 @@ int acpi_dev_install_notify_handler(struct acpi_device *adev,
void acpi_dev_remove_notify_handler(struct acpi_device *adev,
u32 handler_type,
acpi_notify_handler handler);
+int devm_acpi_install_notify_handler(struct device *dev, u32 handler_type,
+ acpi_notify_handler handler, void *context);
extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
extern int register_acpi_notifier(struct notifier_block *);
extern int unregister_acpi_notifier(struct notifier_block *);
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 6.12.y 3/5] ACPI: NFIT: core: Use devm_acpi_install_notify_handler()
2026-07-10 16:14 ` [PATCH 6.12.y 1/5] ACPI: driver: Check ACPI_COMPANION() against NULL during probe Sasha Levin
2026-07-10 16:14 ` [PATCH 6.12.y 2/5] ACPI: bus: Introduce devm_acpi_install_notify_handler() Sasha Levin
@ 2026-07-10 16:14 ` Sasha Levin
2026-07-10 16:14 ` [PATCH 6.12.y 4/5] ACPI: NFIT: core: Fix acpi_nfit_init() error cleanup Sasha Levin
2026-07-10 16:14 ` [PATCH 6.12.y 5/5] ACPI: NFIT: core: Fix possible deadlock and missing notifications Sasha Levin
3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-07-10 16:14 UTC (permalink / raw)
To: stable; +Cc: Rafael J. Wysocki, Sasha Levin
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
[ Upstream commit 198541ad53c0d0d891fedea4098f9953a0f566c0 ]
Now that devm_acpi_install_notify_handler() is available, use it in
acpi_nfit_probe() instead of a custom devm action removing an ACPI
notify handler installed via acpi_dev_install_notify_handler().
Also drop the explicit ACPI_COMPANION() check against NULL that is
not necessary any more becuase devm_acpi_install_notify_handler()
carries out an equivalent check internally and use ACPI_HANDLE() to
retrieve the platform device's ACPI handle.
No intentional functional impact.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/3048737.e9J7NaK4W3@rafael.j.wysocki
Stable-dep-of: 18a00ed0e718 ("ACPI: NFIT: core: Fix possible deadlock and missing notifications")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/acpi/nfit/core.c | 27 +++++++--------------------
1 file changed, 7 insertions(+), 20 deletions(-)
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 3eb56b77cb6d93..c00cb8661b0b52 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -3283,19 +3283,11 @@ static void acpi_nfit_put_table(void *table)
static void acpi_nfit_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_device *adev = data;
-
- device_lock(&adev->dev);
- __acpi_nfit_notify(&adev->dev, handle, event);
- device_unlock(&adev->dev);
-}
-
-static void acpi_nfit_remove_notify_handler(void *data)
-{
- struct acpi_device *adev = data;
+ struct device *dev = data;
- acpi_dev_remove_notify_handler(adev, ACPI_DEVICE_NOTIFY,
- acpi_nfit_notify);
+ device_lock(dev);
+ __acpi_nfit_notify(dev, handle, event);
+ device_unlock(dev);
}
void acpi_nfit_shutdown(void *data)
@@ -3338,13 +3330,8 @@ static int acpi_nfit_add(struct acpi_device *adev)
acpi_size sz;
int rc = 0;
- rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY,
- acpi_nfit_notify, adev);
- if (rc)
- return rc;
-
- rc = devm_add_action_or_reset(dev, acpi_nfit_remove_notify_handler,
- adev);
+ rc = devm_acpi_install_notify_handler(dev, ACPI_DEVICE_NOTIFY,
+ acpi_nfit_notify, dev);
if (rc)
return rc;
@@ -3375,7 +3362,7 @@ static int acpi_nfit_add(struct acpi_device *adev)
acpi_desc->acpi_header = *tbl;
/* Evaluate _FIT and override with that if present */
- status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf);
+ status = acpi_evaluate_object(ACPI_HANDLE(dev), "_FIT", NULL, &buf);
if (ACPI_SUCCESS(status) && buf.length > 0) {
union acpi_object *obj = buf.pointer;
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 6.12.y 4/5] ACPI: NFIT: core: Fix acpi_nfit_init() error cleanup
2026-07-10 16:14 ` [PATCH 6.12.y 1/5] ACPI: driver: Check ACPI_COMPANION() against NULL during probe Sasha Levin
2026-07-10 16:14 ` [PATCH 6.12.y 2/5] ACPI: bus: Introduce devm_acpi_install_notify_handler() Sasha Levin
2026-07-10 16:14 ` [PATCH 6.12.y 3/5] ACPI: NFIT: core: Use devm_acpi_install_notify_handler() Sasha Levin
@ 2026-07-10 16:14 ` Sasha Levin
2026-07-10 16:14 ` [PATCH 6.12.y 5/5] ACPI: NFIT: core: Fix possible deadlock and missing notifications Sasha Levin
3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-07-10 16:14 UTC (permalink / raw)
To: stable; +Cc: Rafael J. Wysocki, Dave Jiang, Sasha Levin
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
[ Upstream commit 38bf27511ef41bffebd157ec3eba41fc89ba59cd ]
If acpi_nfit_init() fails after adding the acpi_desc object to the
acpi_descs list, that object is never removed from that list because
the acpi_nfit_shutdown() devm action is not added for the NFIT device
in that case. Next, the acpi_nfit_init() failure causes
acpi_nfit_probe() to fail, the acpi_desc object is freed, and a
dangling pointer is left behind in the acpi_descs. Any subsequent
ACPI Machine Check Exception will trigger nfit_handle_mce() which
iterates over acpi_descs and so a use-after-free will occur.
Moreover, if acpi_nfit_probe() returns 0 after installing a notify
handler for the NFIT device and without allocating the acpi_desc
object and setting the NFIT device's driver data pointer, the
acpi_desc object will be allocated by acpi_nfit_update_notify()
and acpi_nfit_init() will be called to initialize it. Regardless
of whether or not acpi_nfit_init() fails in that case, the
acpi_nfit_shutdown() devm action is not added for the NFIT device
and acpi_desc is never removed from the acpi_descs list. If the
acpi_desc object is freed subsequently on driver removal, any
subsequent ACPI MCE will lead to a use-after-free like in the
previous case.
To address the first issue mentioned above, make acpi_nfit_probe()
call acpi_nfit_shutdown() directly on acpi_nfit_init() failures and
to address the other one, add a remove callback to the driver and
make it call acpi_nfit_shutdown(). Also, since it is now possible to
pass NULL to acpi_nfit_shutdown() or the acpi_desc object passed to it
may not have been initialized, add checks against NULL for acpi_desc and
its nvdimm_bus field to that function and make acpi_nfit_unregister()
clear the latter after unregistering the NVDIMM bus.
Fixes: a61fe6f7902e ("nfit, tools/testing/nvdimm: unify common init for acpi_nfit_desc")
Fixes: fbabd829fe76 ("acpi, nfit: fix module unload vs workqueue shutdown race")
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: All applicable <stable@vger.kernel.org>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://patch.msgid.link/1963615.tdWV9SEqCh@rafael.j.wysocki
Stable-dep-of: 18a00ed0e718 ("ACPI: NFIT: core: Fix possible deadlock and missing notifications")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/acpi/nfit/core.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index c00cb8661b0b52..dd7cd4b2152a57 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -3061,6 +3061,8 @@ static void acpi_nfit_unregister(void *data)
struct acpi_nfit_desc *acpi_desc = data;
nvdimm_bus_unregister(acpi_desc->nvdimm_bus);
+ /* The nvdimm_bus object may have been freed, so clear the pointer. */
+ acpi_desc->nvdimm_bus = NULL;
}
int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *data, acpi_size sz)
@@ -3293,7 +3295,10 @@ static void acpi_nfit_notify(acpi_handle handle, u32 event, void *data)
void acpi_nfit_shutdown(void *data)
{
struct acpi_nfit_desc *acpi_desc = data;
- struct device *bus_dev = to_nvdimm_bus_dev(acpi_desc->nvdimm_bus);
+ struct device *bus_dev;
+
+ if (!acpi_desc || !acpi_desc->nvdimm_bus)
+ return;
/*
* Destruct under acpi_desc_lock so that nfit_handle_mce does not
@@ -3308,6 +3313,7 @@ void acpi_nfit_shutdown(void *data)
mutex_unlock(&acpi_desc->init_mutex);
cancel_delayed_work_sync(&acpi_desc->dwork);
+ bus_dev = to_nvdimm_bus_dev(acpi_desc->nvdimm_bus);
/*
* Bounce the nvdimm bus lock to make sure any in-flight
* acpi_nfit_ars_rescan() submissions have had a chance to
@@ -3380,9 +3386,14 @@ static int acpi_nfit_add(struct acpi_device *adev)
sz - sizeof(struct acpi_table_nfit));
if (rc)
- return rc;
+ acpi_nfit_shutdown(acpi_desc);
- return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc);
+ return rc;
+}
+
+static void acpi_nfit_remove(struct acpi_device *adev)
+{
+ acpi_nfit_shutdown(dev_get_drvdata(&adev->dev));
}
static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle)
@@ -3466,6 +3477,7 @@ static struct acpi_driver acpi_nfit_driver = {
.ids = acpi_nfit_ids,
.ops = {
.add = acpi_nfit_add,
+ .remove = acpi_nfit_remove,
},
};
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 6.12.y 5/5] ACPI: NFIT: core: Fix possible deadlock and missing notifications
2026-07-10 16:14 ` [PATCH 6.12.y 1/5] ACPI: driver: Check ACPI_COMPANION() against NULL during probe Sasha Levin
` (2 preceding siblings ...)
2026-07-10 16:14 ` [PATCH 6.12.y 4/5] ACPI: NFIT: core: Fix acpi_nfit_init() error cleanup Sasha Levin
@ 2026-07-10 16:14 ` Sasha Levin
3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-07-10 16:14 UTC (permalink / raw)
To: stable; +Cc: Rafael J. Wysocki, Dave Jiang, Sasha Levin
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
[ Upstream commit 18a00ed0e718473f5c3fcfa49df46c944575e60c ]
After commit 9b311b7313d6 ("ACPI: NFIT: Install Notify() handler before
getting NFIT table"), ACPI NFIT driver removal may deadlock if an ACPI
notify on the NFIT device is triggered concurrently. A similar deadlock
may occur if an ACPI notify on the NFIT device is triggered during a
failing driver probe.
The deadlock is possible because acpi_dev_remove_notify_handler() calls
acpi_os_wait_events_complete() after removing the notify handler and the
driver core invokes it under the NFIT platform device lock which is also
acquired by acpi_nfit_notify(). Thus acpi_os_wait_events_complete() may
be waiting for acpi_nfit_notify() to complete, but the latter may not be
able to acquire the device lock which is being held by the driver core
while the former is being executed.
Moreover, after commit 03667e146f81 ("ACPI: NFIT: core: Convert the
driver to a platform one"), there are no sysfs notifications regarding
NVDIMM devices because __acpi_nvdimm_notify() always bails out after
checking the driver data pointer of the device's parent. That parent
is the ACPI companion of the platform device used for driver binding,
so its driver data pointer is always NULL after the commit in question
which was overlooked by it.
A remedy for the deadlock is to use a special separate lock for ACPI
notify synchronization with driver probe and removal instead of the
device lock of the NFIT device, while a remedy for the second issue
is to populate the driver data pointer of the NFIT device's ACPI
companion when the driver is ready to operate, so do both these things.
However, since the new lock is not held across the entire teardown and
acpi_nfit_notify() should do nothing when teardown is in progress, make
it check the driver data pointer of the NFIT device's ACPI companion, in
analogy with the existing check in __acpi_nvdimm_notify(), and bail out
if that pointer is NULL.
Fixes: 9b311b7313d6 ("ACPI: NFIT: Install Notify() handler before getting NFIT table")
Fixes: 03667e146f81 ("ACPI: NFIT: core: Convert the driver to a platform one")
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: All applicable <stable@vger.kernel.org> # 9995e4404ea4: ACPI: NFIT: core: Eliminate redundant local variable
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://patch.msgid.link/3420096.aeNJFYEL58@rafael.j.wysocki
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/acpi/bus.c | 6 +++-
drivers/acpi/nfit/core.c | 62 +++++++++++++++++++++++++++++++---------
2 files changed, 54 insertions(+), 14 deletions(-)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 8730d46a6b273c..9deb98c0a6fee7 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -623,6 +623,7 @@ void acpi_dev_remove_notify_handler(struct acpi_device *adev,
EXPORT_SYMBOL_GPL(acpi_dev_remove_notify_handler);
struct acpi_notify_handler_devres {
+ struct acpi_device *adev;
acpi_notify_handler handler;
u32 handler_type;
};
@@ -631,7 +632,7 @@ static void devm_acpi_notify_handler_release(struct device *dev, void *res)
{
struct acpi_notify_handler_devres *dr = res;
- acpi_dev_remove_notify_handler(ACPI_COMPANION(dev), dr->handler_type,
+ acpi_dev_remove_notify_handler(dr->adev, dr->handler_type,
dr->handler);
}
@@ -667,6 +668,8 @@ int devm_acpi_install_notify_handler(struct device *dev, u32 handler_type,
int ret;
adev = ACPI_COMPANION(dev);
+ if (!adev && dev->bus == &acpi_bus_type)
+ adev = to_acpi_device(dev);
if (!adev)
return dev_err_probe(dev, -ENODEV, "No ACPI companion in %s()\n", __func__);
@@ -680,6 +683,7 @@ int devm_acpi_install_notify_handler(struct device *dev, u32 handler_type,
return dev_err_probe(dev, ret, "Failed to install an ACPI notify handler\n");
}
+ dr->adev = adev;
dr->handler = handler;
dr->handler_type = handler_type;
devres_add(dev, dr);
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index dd7cd4b2152a57..c1727c5a8aaf61 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -55,6 +55,8 @@ MODULE_PARM_DESC(force_labels, "Opt-in to labels despite missing methods");
LIST_HEAD(acpi_descs);
DEFINE_MUTEX(acpi_desc_lock);
+DEFINE_MUTEX(acpi_notify_lock);
+
static struct workqueue_struct *nfit_wq;
struct nfit_table_prev {
@@ -1702,9 +1704,15 @@ static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data)
struct acpi_device *adev = data;
struct device *dev = &adev->dev;
- device_lock(dev->parent);
- __acpi_nvdimm_notify(dev, event);
- device_unlock(dev->parent);
+ /*
+ * Locking is needed here for synchronization with driver probe and
+ * removal and the parent NFIT device's ACPI driver data pointer is
+ * NULL when teardown is in progress.
+ */
+ guard(mutex)(&acpi_notify_lock);
+
+ if (acpi_driver_data(to_acpi_device(dev->parent)))
+ __acpi_nvdimm_notify(dev, event);
}
static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
@@ -3150,11 +3158,10 @@ EXPORT_SYMBOL_GPL(acpi_nfit_init);
static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
{
struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
- struct device *dev = acpi_desc->dev;
- /* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
- device_lock(dev);
- device_unlock(dev);
+ /* Bounce the notify lock to flush acpi_nfit_add / acpi_nfit_notify */
+ mutex_lock(&acpi_notify_lock);
+ mutex_unlock(&acpi_notify_lock);
/* Bounce the init_mutex to complete initial registration */
mutex_lock(&acpi_desc->init_mutex);
@@ -3286,10 +3293,17 @@ static void acpi_nfit_put_table(void *table)
static void acpi_nfit_notify(acpi_handle handle, u32 event, void *data)
{
struct device *dev = data;
+ struct acpi_device *adev = to_acpi_device(dev);
- device_lock(dev);
- __acpi_nfit_notify(dev, handle, event);
- device_unlock(dev);
+ /*
+ * Locking is needed here for synchronization with driver probe and
+ * removal and the ACPI driver data pointer is NULL when teardown
+ * is in progress.
+ */
+ guard(mutex)(&acpi_notify_lock);
+
+ if (acpi_driver_data(adev))
+ __acpi_nfit_notify(dev, handle, event);
}
void acpi_nfit_shutdown(void *data)
@@ -3336,6 +3350,12 @@ static int acpi_nfit_add(struct acpi_device *adev)
acpi_size sz;
int rc = 0;
+ /*
+ * Prevent acpi_nfit_notify() from progressing until the probe is
+ * complete in case there is a concurrent event to process.
+ */
+ guard(mutex)(&acpi_notify_lock);
+
rc = devm_acpi_install_notify_handler(dev, ACPI_DEVICE_NOTIFY,
acpi_nfit_notify, dev);
if (rc)
@@ -3351,6 +3371,11 @@ static int acpi_nfit_add(struct acpi_device *adev)
* data in the format of a series of NFIT Structures.
*/
dev_dbg(dev, "failed to find NFIT at startup\n");
+ /*
+ * Let acpi_nfit_update_notify() run in case it will need to
+ * allocate the acpi_desc object.
+ */
+ adev->driver_data = dev;
return 0;
}
@@ -3368,7 +3393,7 @@ static int acpi_nfit_add(struct acpi_device *adev)
acpi_desc->acpi_header = *tbl;
/* Evaluate _FIT and override with that if present */
- status = acpi_evaluate_object(ACPI_HANDLE(dev), "_FIT", NULL, &buf);
+ status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf);
if (ACPI_SUCCESS(status) && buf.length > 0) {
union acpi_object *obj = buf.pointer;
@@ -3385,14 +3410,25 @@ static int acpi_nfit_add(struct acpi_device *adev)
+ sizeof(struct acpi_table_nfit),
sz - sizeof(struct acpi_table_nfit));
- if (rc)
+ if (rc) {
acpi_nfit_shutdown(acpi_desc);
+ return rc;
+ }
- return rc;
+ /*
+ * Let notify handlers operate (the actual value of the ACPI driver
+ * data pointer does not matter here so long as it is not NULL).
+ */
+ adev->driver_data = dev;
+ return 0;
}
static void acpi_nfit_remove(struct acpi_device *adev)
{
+ guard(mutex)(&acpi_notify_lock);
+
+ /* Make notify handlers bail out early going forward. */
+ adev->driver_data = NULL;
acpi_nfit_shutdown(dev_get_drvdata(&adev->dev));
}
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread