diff mbox series

[net] r8169: fix LED-related deadlock on module removal

Message ID bbcdbc1b-44bc-4cf8-86ef-6e6af2b009c3@gmail.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net] r8169: fix LED-related deadlock on module removal | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 942 this patch: 942
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 953 this patch: 953
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 953 this patch: 953
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 30 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-04-07--00-00 (tests: 956)

Commit Message

Heiner Kallweit April 5, 2024, 8:29 p.m. UTC
Binding devm_led_classdev_register() to the netdev is problematic
because on module removal we get a RTNL-related deadlock. Fix this
by using the parent device instead for device-managed resources.
This is cleaner anyway because then all device-managed resources in
the driver use the same device (the one belonging to the PCI device).

Fixes: 18764b883e15 ("r8169: add support for LED's on RTL8168/RTL8101")
Cc: stable@vger.kernel.org
Reported-by: Lukas Wunner <lukas@wunner.de>
Suggested-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/net/ethernet/realtek/r8169_leds.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

Comments

Andrew Lunn April 5, 2024, 8:50 p.m. UTC | #1
On Fri, Apr 05, 2024 at 10:29:15PM +0200, Heiner Kallweit wrote:
> Binding devm_led_classdev_register() to the netdev is problematic
> because on module removal we get a RTNL-related deadlock. Fix this
> by using the parent device instead for device-managed resources.
> This is cleaner anyway because then all device-managed resources in
> the driver use the same device (the one belonging to the PCI device).

I've been thinking a bit about devm for LEDs. At what point do the
entries in /sys/class/led disappears? When is the netdev trigger
removed? I think it is after the netdev has gone?

static int rtl8168_led_hw_control_set(struct led_classdev *led_cdev,
				      unsigned long flags)
{
	struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
	struct rtl8169_private *tp = netdev_priv(ldev->ndev);

Is this safe? I think the LED will only be destroyed after
rtl_remove_one() has completed.

I think to be safe, we cannot use devm_led_classdev_register(). The
LEDs need to be added and explicitly removed within the life cycle of
the netdev.

    Andrew
Lukas Wunner April 5, 2024, 8:59 p.m. UTC | #2
On Fri, Apr 05, 2024 at 10:29:15PM +0200, Heiner Kallweit wrote:
> --- a/drivers/net/ethernet/realtek/r8169_leds.c
> +++ b/drivers/net/ethernet/realtek/r8169_leds.c
> @@ -146,13 +146,12 @@ static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev,
>  	led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
>  
>  	/* ignore errors */
> -	devm_led_classdev_register(&ndev->dev, led_cdev);
> +	devm_led_classdev_register(ndev->dev.parent, led_cdev);

IIUC, devm_led_classdev_register() uses the first argument both
to manage unregistering on unbind, but also as parent of the LED device.

While the former is desired, the latter likely is not.
I assume the LEDs now appear as children of the PCI device in sysfs,
not as children of the netdev.  Probably not what you want.

The second patch I posted should handle that correctly.

Thanks,

Lukas
diff mbox series

Patch

diff --git a/drivers/net/ethernet/realtek/r8169_leds.c b/drivers/net/ethernet/realtek/r8169_leds.c
index 7c5dc9d0d..7f2b8a361 100644
--- a/drivers/net/ethernet/realtek/r8169_leds.c
+++ b/drivers/net/ethernet/realtek/r8169_leds.c
@@ -146,13 +146,12 @@  static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev,
 	led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
 
 	/* ignore errors */
-	devm_led_classdev_register(&ndev->dev, led_cdev);
+	devm_led_classdev_register(ndev->dev.parent, led_cdev);
 }
 
 void rtl8168_init_leds(struct net_device *ndev)
 {
-	/* bind resource mgmt to netdev */
-	struct device *dev = &ndev->dev;
+	struct device *dev = ndev->dev.parent;
 	struct r8169_led_classdev *leds;
 	int i;
 
@@ -245,13 +244,12 @@  static void rtl8125_setup_led_ldev(struct r8169_led_classdev *ldev,
 	led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
 
 	/* ignore errors */
-	devm_led_classdev_register(&ndev->dev, led_cdev);
+	devm_led_classdev_register(ndev->dev.parent, led_cdev);
 }
 
 void rtl8125_init_leds(struct net_device *ndev)
 {
-	/* bind resource mgmt to netdev */
-	struct device *dev = &ndev->dev;
+	struct device *dev = ndev->dev.parent;
 	struct r8169_led_classdev *leds;
 	int i;