Takashi Iwai f97a5f
From 99aed9227073fb34ce2880cbc7063e04185a65e1 Mon Sep 17 00:00:00 2001
Takashi Iwai f97a5f
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Takashi Iwai f97a5f
Date: Thu, 22 Oct 2020 21:41:00 +0300
Takashi Iwai f97a5f
Subject: [PATCH] device property: Don't clear secondary pointer for shared primary firmware node
Takashi Iwai f97a5f
Git-commit: 99aed9227073fb34ce2880cbc7063e04185a65e1
Takashi Iwai f97a5f
Patch-mainline: v5.10-rc2
Takashi Iwai f97a5f
References: git-fixes
Takashi Iwai f97a5f
Takashi Iwai f97a5f
It appears that firmware nodes can be shared between devices. In such case
Takashi Iwai f97a5f
when a (child) device is about to be deleted, its firmware node may be shared
Takashi Iwai f97a5f
and ACPI_COMPANION_SET(..., NULL) call for it breaks the secondary link
Takashi Iwai f97a5f
of the shared primary firmware node.
Takashi Iwai f97a5f
Takashi Iwai f97a5f
In order to prevent that, check, if the device has a parent and parent's
Takashi Iwai f97a5f
firmware node is shared with its child, and avoid crashing the link.
Takashi Iwai f97a5f
Takashi Iwai f97a5f
Fixes: c15e1bdda436 ("device property: Fix the secondary firmware node handling in set_primary_fwnode()")
Takashi Iwai f97a5f
Reported-by: Ferry Toth <fntoth@gmail.com>
Takashi Iwai f97a5f
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Takashi Iwai f97a5f
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Takashi Iwai f97a5f
Tested-by: Ferry Toth <fntoth@gmail.com>
Takashi Iwai f97a5f
Cc: 5.9+ <stable@vger.kernel.org> # 5.9+
Takashi Iwai f97a5f
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Takashi Iwai f97a5f
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai f97a5f
Takashi Iwai f97a5f
---
Takashi Iwai f97a5f
 drivers/base/core.c | 4 +++-
Takashi Iwai f97a5f
 1 file changed, 3 insertions(+), 1 deletion(-)
Takashi Iwai f97a5f
Takashi Iwai f97a5f
diff --git a/drivers/base/core.c b/drivers/base/core.c
Takashi Iwai f97a5f
index 41feab679fa1..78114ddac755 100644
Takashi Iwai f97a5f
--- a/drivers/base/core.c
Takashi Iwai f97a5f
+++ b/drivers/base/core.c
Takashi Iwai f97a5f
@@ -4264,6 +4264,7 @@ static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
Takashi Iwai f97a5f
  */
Takashi Iwai f97a5f
 void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
Takashi Iwai f97a5f
 {
Takashi Iwai f97a5f
+	struct device *parent = dev->parent;
Takashi Iwai f97a5f
 	struct fwnode_handle *fn = dev->fwnode;
Takashi Iwai f97a5f
 
Takashi Iwai f97a5f
 	if (fwnode) {
Takashi Iwai f97a5f
@@ -4278,7 +4279,8 @@ void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
Takashi Iwai f97a5f
 	} else {
Takashi Iwai f97a5f
 		if (fwnode_is_primary(fn)) {
Takashi Iwai f97a5f
 			dev->fwnode = fn->secondary;
Takashi Iwai f97a5f
-			fn->secondary = ERR_PTR(-ENODEV);
Takashi Iwai f97a5f
+			if (!(parent && fn == parent->fwnode))
Takashi Iwai f97a5f
+				fn->secondary = ERR_PTR(-ENODEV);
Takashi Iwai f97a5f
 		} else {
Takashi Iwai f97a5f
 			dev->fwnode = NULL;
Takashi Iwai f97a5f
 		}
Takashi Iwai f97a5f
-- 
Takashi Iwai f97a5f
2.16.4
Takashi Iwai f97a5f