FAILED: patch "[PATCH] r8169: fix LED-related deadlock on module removal" failed to apply to 6.8-stable tree
[email protected]
maintainerThe patch below does not apply to the 6.8-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.8.y
git checkout FETCH_HEAD
git cherry-pick -x 19fa4f2a85d777a8052e869c1b892a2f7556569d
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024041459-lagging-tiny-7189@gregkh' --subject-prefix 'PATCH 6.8.y' HEAD^..
Possible dependencies:
19fa4f2a85d7 ("r8169: fix LED-related deadlock on module removal") be51ed104ba9 ("r8169: add LED support for RTL8125/RTL8126") 3907f1ffc0ec ("r8169: add support for RTL8126A")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 19fa4f2a85d777a8052e869c1b892a2f7556569d Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <[email protected]>
Date: Mon, 8 Apr 2024 20:47:40 +0200
Subject: [PATCH] r8169: fix LED-related deadlock on module removal
Binding devm_led_classdev_register() to the netdev is problematic because on module removal we get a RTNL-related deadlock. Fix this by avoiding the device-managed LED functions.
Note: We can safely call led_classdev_unregister() for a LED even if registering it failed, because led_classdev_unregister() detects this and is a no-op in this case.
drivers/net/ethernet/realtek/r8169.h +4 -2
@@ -73,6 +73,7 @@ enum mac_version { };struct rtl8169_private ; +struct r8169_led_classdev ;void r8169_apply_firmware (struct rtl8169_private *tp);u16 rtl8168h_2_get_adc_bias_ioffset (struct rtl8169_private *tp);
@@ -84,7 +85,8 @@ void r8169_get_led_name(struct rtl8169_private *tp, int idx, char *buf, int buf_len);int rtl8168_get_led_mode (struct rtl8169_private *tp);int rtl8168_led_mod_ctrl (struct rtl8169_private *tp,u16 mask,u16 val); -void rtl8168_init_leds (struct net_device *ndev); +struct r8169_led_classdev *rtl8168_init_leds (struct net_device *ndev);int rtl8125_get_led_mode (struct rtl8169_private *tp,int index);int rtl8125_set_led_mode (struct rtl8169_private *tp,int index,u16 mode); -void rtl8125_init_leds (struct net_device *ndev); +struct r8169_led_classdev *rtl8125_init_leds (struct net_device *ndev); +void r8169_remove_leds (struct r8169_led_classdev *leds);
drivers/net/ethernet/realtek/r8169_leds.c +23 -12
@@ -146,22 +146,22 @@ 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); +led_classdev_register (&ndev->dev, led_cdev); } -void rtl8168_init_leds (struct net_device *ndev) +struct r8169_led_classdev *rtl8168_init_leds (struct net_device *ndev) { -/* bind resource mgmt to netdev */ -struct device *dev = &ndev->dev;struct r8169_led_classdev *leds;int i; - leds =devm_kcalloc (dev,RTL8168_NUM_LEDS ,sizeof (*leds),GFP_KERNEL ); + leds =kcalloc (RTL8168_NUM_LEDS +1 ,sizeof (*leds),GFP_KERNEL );if (!leds) -return ; +return NULL ;for (i =0 ; i <RTL8168_NUM_LEDS ; i++)rtl8168_setup_ldev (leds + i, ndev, i); + +return leds; } static int rtl8125_led_hw_control_is_supported(struct led_classdev *led_cdev,
@@ -245,20 +245,31 @@ 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); +led_classdev_register (&ndev->dev, led_cdev); } -void rtl8125_init_leds (struct net_device *ndev) +struct r8169_led_classdev *rtl8125_init_leds (struct net_device *ndev) { -/* bind resource mgmt to netdev */ -struct device *dev = &ndev->dev;struct r8169_led_classdev *leds;int i; - leds =devm_kcalloc (dev,RTL8125_NUM_LEDS ,sizeof (*leds),GFP_KERNEL ); + leds =kcalloc (RTL8125_NUM_LEDS +1 ,sizeof (*leds),GFP_KERNEL );if (!leds) -return ; +return NULL ;for (i =0 ; i <RTL8125_NUM_LEDS ; i++)rtl8125_setup_led_ldev (leds + i, ndev, i); + +return leds; +} + +void r8169_remove_leds (struct r8169_led_classdev *leds) +{ +if (!leds) +return ; + +for (struct r8169_led_classdev *l = leds; l->ndev; l++) +led_classdev_unregister (&l->led); + +kfree (leds); }
drivers/net/ethernet/realtek/r8169_main.c +6 -2
@@ -647,6 +647,8 @@ struct rtl8169_private {const char *fw_name;struct rtl_fw *rtl_fw; +struct r8169_led_classdev *leds; +u32 ocp_base; };
@@ -5044,6 +5046,8 @@ static void rtl_remove_one(struct pci_dev *pdev)cancel_work_sync (&tp->wk.work); +r8169_remove_leds (tp->leds); +unregister_netdev (tp->dev);if (tp->dash_type !=RTL_DASH_NONE )
@@ -5501,9 +5505,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)if (IS_ENABLED (CONFIG_R8169_LEDS )) {if (rtl_is_8125 (tp)) -rtl8125_init_leds (dev); + tp->leds =rtl8125_init_leds (dev);else if (tp->mac_version >RTL_GIGA_MAC_VER_06 ) -rtl8168_init_leds (dev); + tp->leds =rtl8168_init_leds (dev); } netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",