From: Andy Shevchenko <andriy.shevche...@linux.intel.com>

commit 99aed9227073fb34ce2880cbc7063e04185a65e1 upstream.

It appears that firmware nodes can be shared between devices. In such case
when a (child) device is about to be deleted, its firmware node may be shared
and ACPI_COMPANION_SET(..., NULL) call for it breaks the secondary link
of the shared primary firmware node.

In order to prevent that, check, if the device has a parent and parent's
firmware node is shared with its child, and avoid crashing the link.

Fixes: c15e1bdda436 ("device property: Fix the secondary firmware node handling 
in set_primary_fwnode()")
Reported-by: Ferry Toth <fnt...@gmail.com>
Signed-off-by: Andy Shevchenko <andriy.shevche...@linux.intel.com>
Reviewed-by: Heikki Krogerus <heikki.kroge...@linux.intel.com>
Tested-by: Ferry Toth <fnt...@gmail.com>
Cc: 5.9+ <sta...@vger.kernel.org> # 5.9+
Signed-off-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 drivers/base/core.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2344,6 +2344,7 @@ static inline bool fwnode_is_primary(str
  */
 void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
 {
+       struct device *parent = dev->parent;
        struct fwnode_handle *fn = dev->fwnode;
 
        if (fwnode) {
@@ -2355,7 +2356,8 @@ void set_primary_fwnode(struct device *d
        } else {
                if (fwnode_is_primary(fn)) {
                        dev->fwnode = fn->secondary;
-                       fn->secondary = ERR_PTR(-ENODEV);
+                       if (!(parent && fn == parent->fwnode))
+                               fn->secondary = ERR_PTR(-ENODEV);
                } else {
                        dev->fwnode = NULL;
                }


Reply via email to