generic: 6.6: backport upstream r8169 patches
authorÁlvaro Fernández Rojas <noltari@gmail.com>
Mon, 19 Aug 2024 15:55:00 +0000 (17:55 +0200)
committerÁlvaro Fernández Rojas <noltari@gmail.com>
Mon, 19 Aug 2024 18:40:59 +0000 (20:40 +0200)
- improve RTL8411b phy-down fixup
- remove not needed check in rtl_fw_write_firmware
- remove multicast filter limit
- improve handling task scheduling
- simplify EEE handling
- simplify code by using core-provided pcpu stats allocation
- add generic rtl_set_eee_txidle_timer function
- support setting the EEE tx idle timer on RTL8168h
- add support for returning tx_lpi_timer in ethtool get_eee
- annotate writes on dev->mtu from ndo_change_mtu()
- disable interrupt source RxOverflow
- remove detection of chip version 11 (early RTL8168b)

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
30 files changed:
target/linux/generic/backport-6.6/780-01-v6.8-r8169-add-support-for-LED-s-on-RTL8168-RTL8101.patch [deleted file]
target/linux/generic/backport-6.6/780-01-v6.8-r8169-improve-RTL8411b-phy-down-fixup.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-02-v6.8-r8169-fix-building-with-CONFIG_LEDS_CLASS-m.patch [deleted file]
target/linux/generic/backport-6.6/780-02-v6.8-r8169-remove-not-needed-check-in-rtl_fw_write_firmwa.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-03-v6.8-r8169-remove-multicast-filter-limit.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-03-v6.9-r8169-add-support-for-RTL8126A.patch [deleted file]
target/linux/generic/backport-6.6/780-04-v6.8-r8169-improve-handling-task-scheduling.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-04-v6.9-r8169-improve-checking-for-valid-LED-modes.patch [deleted file]
target/linux/generic/backport-6.6/780-05-v6.8-r8169-add-support-for-LED-s-on-RTL8168-RTL8101.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-05-v6.9-r8169-add-LED-support-for-RTL8125-RTL8126.patch [deleted file]
target/linux/generic/backport-6.6/780-06-v6.8-r8169-fix-building-with-CONFIG_LEDS_CLASS-m.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-06-v6.9-r8169-add-MODULE_FIRMWARE-entry-for-RTL8126A.patch [deleted file]
target/linux/generic/backport-6.6/780-07-v6.10-r8169-add-support-for-RTL8168M.patch [deleted file]
target/linux/generic/backport-6.6/780-07-v6.9-r8169-simplify-EEE-handling.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-08-v6.10-r8169-fix-LED-related-deadlock-on-module-removal.patch [deleted file]
target/linux/generic/backport-6.6/780-08-v6.9-r8169-add-support-for-RTL8126A.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-09-v6.10-r8169-add-missing-conditional-compiling-for-call-to-.patch [deleted file]
target/linux/generic/backport-6.6/780-09-v6.9-r8169-improve-checking-for-valid-LED-modes.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-10-v6.9-r8169-simplify-code-by-using-core-provided-pcpu-stat.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-11-v6.9-r8169-add-LED-support-for-RTL8125-RTL8126.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-12-v6.9-r8169-add-generic-rtl_set_eee_txidle_timer-function.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-13-v6.9-r8169-support-setting-the-EEE-tx-idle-timer-on-RTL81.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-14-v6.9-r8169-add-support-for-returning-tx_lpi_timer-in-etht.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-15-v6.9-r8169-add-MODULE_FIRMWARE-entry-for-RTL8126A.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-16-v6.9-r8169-fix-LED-related-deadlock-on-module-removal.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-17-v6.9-r8169-add-missing-conditional-compiling-for-call-to-.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-18-v6.10-r8169-add-support-for-RTL8168M.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-19-v6.10-net-annotate-writes-on-dev-mtu-from-ndo_change_mtu.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-20-v6.11-r8169-disable-interrupt-source-RxOverflow.patch [new file with mode: 0644]
target/linux/generic/backport-6.6/780-21-v6.11-r8169-remove-detection-of-chip-version-11-early-RTL8.patch [new file with mode: 0644]

diff --git a/target/linux/generic/backport-6.6/780-01-v6.8-r8169-add-support-for-LED-s-on-RTL8168-RTL8101.patch b/target/linux/generic/backport-6.6/780-01-v6.8-r8169-add-support-for-LED-s-on-RTL8168-RTL8101.patch
deleted file mode 100644 (file)
index fe75a4e..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-From 18764b883e157e28126b54e7d4ba9dd487d5bf54 Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Sat, 16 Dec 2023 20:58:10 +0100
-Subject: [PATCH] r8169: add support for LED's on RTL8168/RTL8101
-
-This adds support for the LED's on most chip versions. Excluded are
-the old non-PCIe versions and RTL8125. RTL8125 has a different LED
-register layout, support for it will follow later.
-
-LED's can be controlled from userspace using the netdev LED trigger.
-
-Tested on RTL8168h.
-
-Note: The driver can't know which LED's are actually physically
-wired. Therefore not every LED device may represent a physically
-available LED.
-
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/realtek/Makefile     |   3 +
- drivers/net/ethernet/realtek/r8169.h      |   7 +
- drivers/net/ethernet/realtek/r8169_leds.c | 157 ++++++++++++++++++++++
- drivers/net/ethernet/realtek/r8169_main.c |  65 +++++++++
- 4 files changed, 232 insertions(+)
- create mode 100644 drivers/net/ethernet/realtek/r8169_leds.c
-
---- a/drivers/net/ethernet/realtek/Makefile
-+++ b/drivers/net/ethernet/realtek/Makefile
-@@ -7,4 +7,7 @@ obj-$(CONFIG_8139CP) += 8139cp.o
- obj-$(CONFIG_8139TOO) += 8139too.o
- obj-$(CONFIG_ATP) += atp.o
- r8169-objs += r8169_main.o r8169_firmware.o r8169_phy_config.o
-+ifdef CONFIG_LEDS_TRIGGER_NETDEV
-+r8169-objs += r8169_leds.o
-+endif
- obj-$(CONFIG_R8169) += r8169.o
---- a/drivers/net/ethernet/realtek/r8169.h
-+++ b/drivers/net/ethernet/realtek/r8169.h
-@@ -8,6 +8,7 @@
-  * See MAINTAINERS file for support contact information.
-  */
-+#include <linux/netdevice.h>
- #include <linux/types.h>
- #include <linux/phy.h>
-@@ -77,3 +78,9 @@ u16 rtl8168h_2_get_adc_bias_ioffset(stru
- u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr);
- void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
-                        enum mac_version ver);
-+
-+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);
---- /dev/null
-+++ b/drivers/net/ethernet/realtek/r8169_leds.c
-@@ -0,0 +1,157 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/* r8169_leds.c: Realtek 8169/8168/8101/8125 ethernet driver.
-+ *
-+ * Copyright (c) 2023 Heiner Kallweit <hkallweit1@gmail.com>
-+ *
-+ * See MAINTAINERS file for support contact information.
-+ */
-+
-+#include <linux/leds.h>
-+#include <linux/netdevice.h>
-+#include <uapi/linux/uleds.h>
-+
-+#include "r8169.h"
-+
-+#define RTL8168_LED_CTRL_OPTION2      BIT(15)
-+#define RTL8168_LED_CTRL_ACT          BIT(3)
-+#define RTL8168_LED_CTRL_LINK_1000    BIT(2)
-+#define RTL8168_LED_CTRL_LINK_100     BIT(1)
-+#define RTL8168_LED_CTRL_LINK_10      BIT(0)
-+
-+#define RTL8168_NUM_LEDS              3
-+
-+#define RTL8168_SUPPORTED_MODES \
-+      (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK_100) | \
-+       BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_RX) | \
-+       BIT(TRIGGER_NETDEV_TX))
-+
-+struct r8169_led_classdev {
-+      struct led_classdev led;
-+      struct net_device *ndev;
-+      int index;
-+};
-+
-+#define lcdev_to_r8169_ldev(lcdev) container_of(lcdev, struct r8169_led_classdev, led)
-+
-+static int rtl8168_led_hw_control_is_supported(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);
-+      int shift = ldev->index * 4;
-+      bool rx, tx;
-+
-+      if (flags & ~RTL8168_SUPPORTED_MODES)
-+              goto nosupp;
-+
-+      rx = flags & BIT(TRIGGER_NETDEV_RX);
-+      tx = flags & BIT(TRIGGER_NETDEV_TX);
-+      if (rx != tx)
-+              goto nosupp;
-+
-+      return 0;
-+
-+nosupp:
-+      /* Switch LED off to indicate that mode isn't supported */
-+      rtl8168_led_mod_ctrl(tp, 0x000f << shift, 0);
-+      return -EOPNOTSUPP;
-+}
-+
-+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);
-+      int shift = ldev->index * 4;
-+      u16 mode = 0;
-+
-+      if (flags & BIT(TRIGGER_NETDEV_LINK_10))
-+              mode |= RTL8168_LED_CTRL_LINK_10;
-+      if (flags & BIT(TRIGGER_NETDEV_LINK_100))
-+              mode |= RTL8168_LED_CTRL_LINK_100;
-+      if (flags & BIT(TRIGGER_NETDEV_LINK_1000))
-+              mode |= RTL8168_LED_CTRL_LINK_1000;
-+      if (flags & BIT(TRIGGER_NETDEV_TX))
-+              mode |= RTL8168_LED_CTRL_ACT;
-+
-+      return rtl8168_led_mod_ctrl(tp, 0x000f << shift, mode << shift);
-+}
-+
-+static int rtl8168_led_hw_control_get(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);
-+      int shift = ldev->index * 4;
-+      int mode;
-+
-+      mode = rtl8168_get_led_mode(tp);
-+      if (mode < 0)
-+              return mode;
-+
-+      if (mode & RTL8168_LED_CTRL_OPTION2) {
-+              rtl8168_led_mod_ctrl(tp, RTL8168_LED_CTRL_OPTION2, 0);
-+              netdev_notice(ldev->ndev, "Deactivating unsupported Option2 LED mode\n");
-+      }
-+
-+      mode = (mode >> shift) & 0x000f;
-+
-+      if (mode & RTL8168_LED_CTRL_ACT)
-+              *flags |= BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX);
-+
-+      if (mode & RTL8168_LED_CTRL_LINK_10)
-+              *flags |= BIT(TRIGGER_NETDEV_LINK_10);
-+      if (mode & RTL8168_LED_CTRL_LINK_100)
-+              *flags |= BIT(TRIGGER_NETDEV_LINK_100);
-+      if (mode & RTL8168_LED_CTRL_LINK_1000)
-+              *flags |= BIT(TRIGGER_NETDEV_LINK_1000);
-+
-+      return 0;
-+}
-+
-+static struct device *
-+      r8169_led_hw_control_get_device(struct led_classdev *led_cdev)
-+{
-+      struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
-+
-+      return &ldev->ndev->dev;
-+}
-+
-+static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev,
-+                             struct net_device *ndev, int index)
-+{
-+      struct rtl8169_private *tp = netdev_priv(ndev);
-+      struct led_classdev *led_cdev = &ldev->led;
-+      char led_name[LED_MAX_NAME_SIZE];
-+
-+      ldev->ndev = ndev;
-+      ldev->index = index;
-+
-+      r8169_get_led_name(tp, index, led_name, LED_MAX_NAME_SIZE);
-+      led_cdev->name = led_name;
-+      led_cdev->default_trigger = "netdev";
-+      led_cdev->hw_control_trigger = "netdev";
-+      led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN;
-+      led_cdev->hw_control_is_supported = rtl8168_led_hw_control_is_supported;
-+      led_cdev->hw_control_set = rtl8168_led_hw_control_set;
-+      led_cdev->hw_control_get = rtl8168_led_hw_control_get;
-+      led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
-+
-+      /* ignore errors */
-+      devm_led_classdev_register(&ndev->dev, led_cdev);
-+}
-+
-+void 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);
-+      if (!leds)
-+              return;
-+
-+      for (i = 0; i < RTL8168_NUM_LEDS; i++)
-+              rtl8168_setup_ldev(leds + i, ndev, i);
-+}
---- a/drivers/net/ethernet/realtek/r8169_main.c
-+++ b/drivers/net/ethernet/realtek/r8169_main.c
-@@ -289,6 +289,7 @@ enum rtl8168_8101_registers {
- };
- enum rtl8168_registers {
-+      LED_CTRL                = 0x18,
-       LED_FREQ                = 0x1a,
-       EEE_LED                 = 0x1b,
-       ERIDR                   = 0x70,
-@@ -620,6 +621,7 @@ struct rtl8169_private {
-       raw_spinlock_t config25_lock;
-       raw_spinlock_t mac_ocp_lock;
-+      struct mutex led_lock;  /* serialize LED ctrl RMW access */
-       raw_spinlock_t cfg9346_usage_lock;
-       int cfg9346_usage_count;
-@@ -792,6 +794,62 @@ static const struct rtl_cond name = {
-                                                       \
- static bool name ## _check(struct rtl8169_private *tp)
-+int rtl8168_led_mod_ctrl(struct rtl8169_private *tp, u16 mask, u16 val)
-+{
-+      struct device *dev = tp_to_dev(tp);
-+      int ret;
-+
-+      ret = pm_runtime_resume_and_get(dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      mutex_lock(&tp->led_lock);
-+      RTL_W16(tp, LED_CTRL, (RTL_R16(tp, LED_CTRL) & ~mask) | val);
-+      mutex_unlock(&tp->led_lock);
-+
-+      pm_runtime_put_sync(dev);
-+
-+      return 0;
-+}
-+
-+int rtl8168_get_led_mode(struct rtl8169_private *tp)
-+{
-+      struct device *dev = tp_to_dev(tp);
-+      int ret;
-+
-+      ret = pm_runtime_resume_and_get(dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = RTL_R16(tp, LED_CTRL);
-+
-+      pm_runtime_put_sync(dev);
-+
-+      return ret;
-+}
-+
-+void r8169_get_led_name(struct rtl8169_private *tp, int idx,
-+                      char *buf, int buf_len)
-+{
-+      struct pci_dev *pdev = tp->pci_dev;
-+      char pdom[8], pfun[8];
-+      int domain;
-+
-+      domain = pci_domain_nr(pdev->bus);
-+      if (domain)
-+              snprintf(pdom, sizeof(pdom), "P%d", domain);
-+      else
-+              pdom[0] = '\0';
-+
-+      if (pdev->multifunction)
-+              snprintf(pfun, sizeof(pfun), "f%d", PCI_FUNC(pdev->devfn));
-+      else
-+              pfun[0] = '\0';
-+
-+      snprintf(buf, buf_len, "en%sp%ds%d%s-%d::lan", pdom, pdev->bus->number,
-+               PCI_SLOT(pdev->devfn), pfun, idx);
-+}
-+
- static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int type)
- {
-       /* based on RTL8168FP_OOBMAC_BASE in vendor driver */
-@@ -5254,6 +5312,7 @@ static int rtl_init_one(struct pci_dev *
-       raw_spin_lock_init(&tp->cfg9346_usage_lock);
-       raw_spin_lock_init(&tp->config25_lock);
-       raw_spin_lock_init(&tp->mac_ocp_lock);
-+      mutex_init(&tp->led_lock);
-       dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
-                                                  struct pcpu_sw_netstats);
-@@ -5410,6 +5469,12 @@ static int rtl_init_one(struct pci_dev *
-       if (rc)
-               return rc;
-+#if IS_REACHABLE(CONFIG_LEDS_CLASS) && IS_ENABLED(CONFIG_LEDS_TRIGGER_NETDEV)
-+      if (tp->mac_version > RTL_GIGA_MAC_VER_06 &&
-+          tp->mac_version < RTL_GIGA_MAC_VER_61)
-+              rtl8168_init_leds(dev);
-+#endif
-+
-       netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
-                   rtl_chip_infos[chipset].name, dev->dev_addr, xid, tp->irq);
diff --git a/target/linux/generic/backport-6.6/780-01-v6.8-r8169-improve-RTL8411b-phy-down-fixup.patch b/target/linux/generic/backport-6.6/780-01-v6.8-r8169-improve-RTL8411b-phy-down-fixup.patch
new file mode 100644 (file)
index 0000000..9a17fe4
--- /dev/null
@@ -0,0 +1,173 @@
+From 055dd7511f675d26fa283b35bb3dadfc7f77ed97 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Mon, 13 Nov 2023 20:13:26 +0100
+Subject: [PATCH] r8169: improve RTL8411b phy-down fixup
+
+Mirsad proposed a patch to reduce the number of spinlock lock/unlock
+operations and the function code size. This can be further improved
+because the function sets a consecutive register block.
+
+Suggested-by: Mirsad Todorovac <mirsad.todorovac@alu.unizg.hr>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Mirsad Todorovac <mirsad.todorovac@alu.unizg.hr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 139 +++++-----------------
+ 1 file changed, 28 insertions(+), 111 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -3129,6 +3129,33 @@ static void rtl_hw_start_8168g_2(struct
+       rtl_ephy_init(tp, e_info_8168g_2);
+ }
++static void rtl8411b_fix_phy_down(struct rtl8169_private *tp)
++{
++      static const u16 fix_data[] = {
++/* 0xf800 */ 0xe008, 0xe00a, 0xe00c, 0xe00e, 0xe027, 0xe04f, 0xe05e, 0xe065,
++/* 0xf810 */ 0xc602, 0xbe00, 0x0000, 0xc502, 0xbd00, 0x074c, 0xc302, 0xbb00,
++/* 0xf820 */ 0x080a, 0x6420, 0x48c2, 0x8c20, 0xc516, 0x64a4, 0x49c0, 0xf009,
++/* 0xf830 */ 0x74a2, 0x8ca5, 0x74a0, 0xc50e, 0x9ca2, 0x1c11, 0x9ca0, 0xe006,
++/* 0xf840 */ 0x74f8, 0x48c4, 0x8cf8, 0xc404, 0xbc00, 0xc403, 0xbc00, 0x0bf2,
++/* 0xf850 */ 0x0c0a, 0xe434, 0xd3c0, 0x49d9, 0xf01f, 0xc526, 0x64a5, 0x1400,
++/* 0xf860 */ 0xf007, 0x0c01, 0x8ca5, 0x1c15, 0xc51b, 0x9ca0, 0xe013, 0xc519,
++/* 0xf870 */ 0x74a0, 0x48c4, 0x8ca0, 0xc516, 0x74a4, 0x48c8, 0x48ca, 0x9ca4,
++/* 0xf880 */ 0xc512, 0x1b00, 0x9ba0, 0x1b1c, 0x483f, 0x9ba2, 0x1b04, 0xc508,
++/* 0xf890 */ 0x9ba0, 0xc505, 0xbd00, 0xc502, 0xbd00, 0x0300, 0x051e, 0xe434,
++/* 0xf8a0 */ 0xe018, 0xe092, 0xde20, 0xd3c0, 0xc50f, 0x76a4, 0x49e3, 0xf007,
++/* 0xf8b0 */ 0x49c0, 0xf103, 0xc607, 0xbe00, 0xc606, 0xbe00, 0xc602, 0xbe00,
++/* 0xf8c0 */ 0x0c4c, 0x0c28, 0x0c2c, 0xdc00, 0xc707, 0x1d00, 0x8de2, 0x48c1,
++/* 0xf8d0 */ 0xc502, 0xbd00, 0x00aa, 0xe0c0, 0xc502, 0xbd00, 0x0132
++      };
++      unsigned long flags;
++      int i;
++
++      raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
++      for (i = 0; i < ARRAY_SIZE(fix_data); i++)
++              __r8168_mac_ocp_write(tp, 0xf800 + 2 * i, fix_data[i]);
++      raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
++}
++
+ static void rtl_hw_start_8411_2(struct rtl8169_private *tp)
+ {
+       static const struct ephy_info e_info_8411_2[] = {
+@@ -3162,117 +3189,7 @@ static void rtl_hw_start_8411_2(struct r
+       mdelay(3);
+       r8168_mac_ocp_write(tp, 0xFC26, 0x0000);
+-      r8168_mac_ocp_write(tp, 0xF800, 0xE008);
+-      r8168_mac_ocp_write(tp, 0xF802, 0xE00A);
+-      r8168_mac_ocp_write(tp, 0xF804, 0xE00C);
+-      r8168_mac_ocp_write(tp, 0xF806, 0xE00E);
+-      r8168_mac_ocp_write(tp, 0xF808, 0xE027);
+-      r8168_mac_ocp_write(tp, 0xF80A, 0xE04F);
+-      r8168_mac_ocp_write(tp, 0xF80C, 0xE05E);
+-      r8168_mac_ocp_write(tp, 0xF80E, 0xE065);
+-      r8168_mac_ocp_write(tp, 0xF810, 0xC602);
+-      r8168_mac_ocp_write(tp, 0xF812, 0xBE00);
+-      r8168_mac_ocp_write(tp, 0xF814, 0x0000);
+-      r8168_mac_ocp_write(tp, 0xF816, 0xC502);
+-      r8168_mac_ocp_write(tp, 0xF818, 0xBD00);
+-      r8168_mac_ocp_write(tp, 0xF81A, 0x074C);
+-      r8168_mac_ocp_write(tp, 0xF81C, 0xC302);
+-      r8168_mac_ocp_write(tp, 0xF81E, 0xBB00);
+-      r8168_mac_ocp_write(tp, 0xF820, 0x080A);
+-      r8168_mac_ocp_write(tp, 0xF822, 0x6420);
+-      r8168_mac_ocp_write(tp, 0xF824, 0x48C2);
+-      r8168_mac_ocp_write(tp, 0xF826, 0x8C20);
+-      r8168_mac_ocp_write(tp, 0xF828, 0xC516);
+-      r8168_mac_ocp_write(tp, 0xF82A, 0x64A4);
+-      r8168_mac_ocp_write(tp, 0xF82C, 0x49C0);
+-      r8168_mac_ocp_write(tp, 0xF82E, 0xF009);
+-      r8168_mac_ocp_write(tp, 0xF830, 0x74A2);
+-      r8168_mac_ocp_write(tp, 0xF832, 0x8CA5);
+-      r8168_mac_ocp_write(tp, 0xF834, 0x74A0);
+-      r8168_mac_ocp_write(tp, 0xF836, 0xC50E);
+-      r8168_mac_ocp_write(tp, 0xF838, 0x9CA2);
+-      r8168_mac_ocp_write(tp, 0xF83A, 0x1C11);
+-      r8168_mac_ocp_write(tp, 0xF83C, 0x9CA0);
+-      r8168_mac_ocp_write(tp, 0xF83E, 0xE006);
+-      r8168_mac_ocp_write(tp, 0xF840, 0x74F8);
+-      r8168_mac_ocp_write(tp, 0xF842, 0x48C4);
+-      r8168_mac_ocp_write(tp, 0xF844, 0x8CF8);
+-      r8168_mac_ocp_write(tp, 0xF846, 0xC404);
+-      r8168_mac_ocp_write(tp, 0xF848, 0xBC00);
+-      r8168_mac_ocp_write(tp, 0xF84A, 0xC403);
+-      r8168_mac_ocp_write(tp, 0xF84C, 0xBC00);
+-      r8168_mac_ocp_write(tp, 0xF84E, 0x0BF2);
+-      r8168_mac_ocp_write(tp, 0xF850, 0x0C0A);
+-      r8168_mac_ocp_write(tp, 0xF852, 0xE434);
+-      r8168_mac_ocp_write(tp, 0xF854, 0xD3C0);
+-      r8168_mac_ocp_write(tp, 0xF856, 0x49D9);
+-      r8168_mac_ocp_write(tp, 0xF858, 0xF01F);
+-      r8168_mac_ocp_write(tp, 0xF85A, 0xC526);
+-      r8168_mac_ocp_write(tp, 0xF85C, 0x64A5);
+-      r8168_mac_ocp_write(tp, 0xF85E, 0x1400);
+-      r8168_mac_ocp_write(tp, 0xF860, 0xF007);
+-      r8168_mac_ocp_write(tp, 0xF862, 0x0C01);
+-      r8168_mac_ocp_write(tp, 0xF864, 0x8CA5);
+-      r8168_mac_ocp_write(tp, 0xF866, 0x1C15);
+-      r8168_mac_ocp_write(tp, 0xF868, 0xC51B);
+-      r8168_mac_ocp_write(tp, 0xF86A, 0x9CA0);
+-      r8168_mac_ocp_write(tp, 0xF86C, 0xE013);
+-      r8168_mac_ocp_write(tp, 0xF86E, 0xC519);
+-      r8168_mac_ocp_write(tp, 0xF870, 0x74A0);
+-      r8168_mac_ocp_write(tp, 0xF872, 0x48C4);
+-      r8168_mac_ocp_write(tp, 0xF874, 0x8CA0);
+-      r8168_mac_ocp_write(tp, 0xF876, 0xC516);
+-      r8168_mac_ocp_write(tp, 0xF878, 0x74A4);
+-      r8168_mac_ocp_write(tp, 0xF87A, 0x48C8);
+-      r8168_mac_ocp_write(tp, 0xF87C, 0x48CA);
+-      r8168_mac_ocp_write(tp, 0xF87E, 0x9CA4);
+-      r8168_mac_ocp_write(tp, 0xF880, 0xC512);
+-      r8168_mac_ocp_write(tp, 0xF882, 0x1B00);
+-      r8168_mac_ocp_write(tp, 0xF884, 0x9BA0);
+-      r8168_mac_ocp_write(tp, 0xF886, 0x1B1C);
+-      r8168_mac_ocp_write(tp, 0xF888, 0x483F);
+-      r8168_mac_ocp_write(tp, 0xF88A, 0x9BA2);
+-      r8168_mac_ocp_write(tp, 0xF88C, 0x1B04);
+-      r8168_mac_ocp_write(tp, 0xF88E, 0xC508);
+-      r8168_mac_ocp_write(tp, 0xF890, 0x9BA0);
+-      r8168_mac_ocp_write(tp, 0xF892, 0xC505);
+-      r8168_mac_ocp_write(tp, 0xF894, 0xBD00);
+-      r8168_mac_ocp_write(tp, 0xF896, 0xC502);
+-      r8168_mac_ocp_write(tp, 0xF898, 0xBD00);
+-      r8168_mac_ocp_write(tp, 0xF89A, 0x0300);
+-      r8168_mac_ocp_write(tp, 0xF89C, 0x051E);
+-      r8168_mac_ocp_write(tp, 0xF89E, 0xE434);
+-      r8168_mac_ocp_write(tp, 0xF8A0, 0xE018);
+-      r8168_mac_ocp_write(tp, 0xF8A2, 0xE092);
+-      r8168_mac_ocp_write(tp, 0xF8A4, 0xDE20);
+-      r8168_mac_ocp_write(tp, 0xF8A6, 0xD3C0);
+-      r8168_mac_ocp_write(tp, 0xF8A8, 0xC50F);
+-      r8168_mac_ocp_write(tp, 0xF8AA, 0x76A4);
+-      r8168_mac_ocp_write(tp, 0xF8AC, 0x49E3);
+-      r8168_mac_ocp_write(tp, 0xF8AE, 0xF007);
+-      r8168_mac_ocp_write(tp, 0xF8B0, 0x49C0);
+-      r8168_mac_ocp_write(tp, 0xF8B2, 0xF103);
+-      r8168_mac_ocp_write(tp, 0xF8B4, 0xC607);
+-      r8168_mac_ocp_write(tp, 0xF8B6, 0xBE00);
+-      r8168_mac_ocp_write(tp, 0xF8B8, 0xC606);
+-      r8168_mac_ocp_write(tp, 0xF8BA, 0xBE00);
+-      r8168_mac_ocp_write(tp, 0xF8BC, 0xC602);
+-      r8168_mac_ocp_write(tp, 0xF8BE, 0xBE00);
+-      r8168_mac_ocp_write(tp, 0xF8C0, 0x0C4C);
+-      r8168_mac_ocp_write(tp, 0xF8C2, 0x0C28);
+-      r8168_mac_ocp_write(tp, 0xF8C4, 0x0C2C);
+-      r8168_mac_ocp_write(tp, 0xF8C6, 0xDC00);
+-      r8168_mac_ocp_write(tp, 0xF8C8, 0xC707);
+-      r8168_mac_ocp_write(tp, 0xF8CA, 0x1D00);
+-      r8168_mac_ocp_write(tp, 0xF8CC, 0x8DE2);
+-      r8168_mac_ocp_write(tp, 0xF8CE, 0x48C1);
+-      r8168_mac_ocp_write(tp, 0xF8D0, 0xC502);
+-      r8168_mac_ocp_write(tp, 0xF8D2, 0xBD00);
+-      r8168_mac_ocp_write(tp, 0xF8D4, 0x00AA);
+-      r8168_mac_ocp_write(tp, 0xF8D6, 0xE0C0);
+-      r8168_mac_ocp_write(tp, 0xF8D8, 0xC502);
+-      r8168_mac_ocp_write(tp, 0xF8DA, 0xBD00);
+-      r8168_mac_ocp_write(tp, 0xF8DC, 0x0132);
++      rtl8411b_fix_phy_down(tp);
+       r8168_mac_ocp_write(tp, 0xFC26, 0x8000);
diff --git a/target/linux/generic/backport-6.6/780-02-v6.8-r8169-fix-building-with-CONFIG_LEDS_CLASS-m.patch b/target/linux/generic/backport-6.6/780-02-v6.8-r8169-fix-building-with-CONFIG_LEDS_CLASS-m.patch
deleted file mode 100644 (file)
index 1b83cf4..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-From a2634a5ffcafc31c343c6153ae487eb184c433a6 Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Wed, 3 Jan 2024 16:52:04 +0100
-Subject: [PATCH] r8169: fix building with CONFIG_LEDS_CLASS=m
-
-When r8169 is built-in but LED support is a loadable module, the new
-code to drive the LED causes a link failure:
-
-ld: drivers/net/ethernet/realtek/r8169_leds.o: in function `rtl8168_init_leds':
-r8169_leds.c:(.text+0x36c): undefined reference to `devm_led_classdev_register_ext'
-
-LED support is an optional feature, so fix this issue by adding a Kconfig
-symbol R8169_LEDS that is guaranteed to be false if r8169 is built-in
-and LED core support is a module. As a positive side effect of this change
-r8169_leds.o no longer is built under this configuration.
-
-Fixes: 18764b883e15 ("r8169: add support for LED's on RTL8168/RTL8101")
-Reported-by: kernel test robot <lkp@intel.com>
-Closes: https://lore.kernel.org/oe-kbuild-all/202312281159.9TPeXbNd-lkp@intel.com/
-Suggested-by: Arnd Bergmann <arnd@arndb.de>
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Reviewed-by: Simon Horman <horms@kernel.org>
-Tested-by: Simon Horman <horms@kernel.org> # build-tested
-Tested-by: Arnd Bergmann <arnd@arndb.de>
-Link: https://lore.kernel.org/r/d055aeb5-fe5c-4ccf-987f-5af93a17537b@gmail.com
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
----
- drivers/net/ethernet/realtek/Kconfig      | 7 +++++++
- drivers/net/ethernet/realtek/Makefile     | 6 ++----
- drivers/net/ethernet/realtek/r8169_main.c | 5 ++---
- 3 files changed, 11 insertions(+), 7 deletions(-)
-
---- a/drivers/net/ethernet/realtek/Kconfig
-+++ b/drivers/net/ethernet/realtek/Kconfig
-@@ -113,4 +113,11 @@ config R8169
-         To compile this driver as a module, choose M here: the module
-         will be called r8169.  This is recommended.
-+config R8169_LEDS
-+      def_bool R8169 && LEDS_TRIGGER_NETDEV
-+      depends on !(R8169=y && LEDS_CLASS=m)
-+      help
-+        Optional support for controlling the NIC LED's with the netdev
-+        LED trigger.
-+
- endif # NET_VENDOR_REALTEK
---- a/drivers/net/ethernet/realtek/Makefile
-+++ b/drivers/net/ethernet/realtek/Makefile
-@@ -6,8 +6,6 @@
- obj-$(CONFIG_8139CP) += 8139cp.o
- obj-$(CONFIG_8139TOO) += 8139too.o
- obj-$(CONFIG_ATP) += atp.o
--r8169-objs += r8169_main.o r8169_firmware.o r8169_phy_config.o
--ifdef CONFIG_LEDS_TRIGGER_NETDEV
--r8169-objs += r8169_leds.o
--endif
-+r8169-y += r8169_main.o r8169_firmware.o r8169_phy_config.o
-+r8169-$(CONFIG_R8169_LEDS) += r8169_leds.o
- obj-$(CONFIG_R8169) += r8169.o
---- a/drivers/net/ethernet/realtek/r8169_main.c
-+++ b/drivers/net/ethernet/realtek/r8169_main.c
-@@ -5469,11 +5469,10 @@ static int rtl_init_one(struct pci_dev *
-       if (rc)
-               return rc;
--#if IS_REACHABLE(CONFIG_LEDS_CLASS) && IS_ENABLED(CONFIG_LEDS_TRIGGER_NETDEV)
--      if (tp->mac_version > RTL_GIGA_MAC_VER_06 &&
-+      if (IS_ENABLED(CONFIG_R8169_LEDS) &&
-+          tp->mac_version > RTL_GIGA_MAC_VER_06 &&
-           tp->mac_version < RTL_GIGA_MAC_VER_61)
-               rtl8168_init_leds(dev);
--#endif
-       netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
-                   rtl_chip_infos[chipset].name, dev->dev_addr, xid, tp->irq);
diff --git a/target/linux/generic/backport-6.6/780-02-v6.8-r8169-remove-not-needed-check-in-rtl_fw_write_firmwa.patch b/target/linux/generic/backport-6.6/780-02-v6.8-r8169-remove-not-needed-check-in-rtl_fw_write_firmwa.patch
new file mode 100644 (file)
index 0000000..de10d30
--- /dev/null
@@ -0,0 +1,27 @@
+From 3a767b482cacd9bfeac786837fcac419af315995 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Thu, 23 Nov 2023 10:53:26 +0100
+Subject: [PATCH] r8169: remove not needed check in rtl_fw_write_firmware
+
+This check can never be true for a firmware file with a correct format.
+Existing checks in rtl_fw_data_ok() are sufficient, no problems with
+invalid firmware files are known.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/realtek/r8169_firmware.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_firmware.c
++++ b/drivers/net/ethernet/realtek/r8169_firmware.c
+@@ -151,9 +151,6 @@ void rtl_fw_write_firmware(struct rtl816
+               u32 regno = (action & 0x0fff0000) >> 16;
+               enum rtl_fw_opcode opcode = action >> 28;
+-              if (!action)
+-                      break;
+-
+               switch (opcode) {
+               case PHY_READ:
+                       predata = fw_read(tp, regno);
diff --git a/target/linux/generic/backport-6.6/780-03-v6.8-r8169-remove-multicast-filter-limit.patch b/target/linux/generic/backport-6.6/780-03-v6.8-r8169-remove-multicast-filter-limit.patch
new file mode 100644 (file)
index 0000000..4186e14
--- /dev/null
@@ -0,0 +1,47 @@
+From cd04b44bf055c4cd6bcee2ebfa6932fb20ef369d Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Mon, 27 Nov 2023 21:16:10 +0100
+Subject: [PATCH] r8169: remove multicast filter limit
+
+Once upon a time, when r8169 was new, the multicast filter limit code
+was copied from RTL8139 driver. There the filter limit is even
+user-configurable.
+The filtering is hash-based and we don't have perfect filtering.
+Actually the mc filtering on RTL8125 still seems to be the same
+as used on 8390/NE2000. So it's not clear to me which benefit it
+should bring when switching to all-multi mode once a certain number
+of filter bits is set. More the opposite: Filtering out at least
+some unwanted mc traffic is better than no filtering.
+Also the available chip documentation doesn't mention any restriction.
+Therefore remove the filter limit.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/57076c05-3730-40d1-ab9a-5334b263e41a@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -56,10 +56,6 @@
+ #define FIRMWARE_8125A_3      "rtl_nic/rtl8125a-3.fw"
+ #define FIRMWARE_8125B_2      "rtl_nic/rtl8125b-2.fw"
+-/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+-   The RTL chips use a 64 element hash table based on the Ethernet CRC. */
+-#define       MC_FILTER_LIMIT 32
+-
+ #define TX_DMA_BURST  7       /* Maximum PCI burst, '7' is unlimited */
+ #define InterFrameGap 0x03    /* 3 means InterFrameGap = the shortest one */
+@@ -2626,8 +2622,7 @@ static void rtl_set_rx_mode(struct net_d
+               rx_mode |= AcceptAllPhys;
+       } else if (!(dev->flags & IFF_MULTICAST)) {
+               rx_mode &= ~AcceptMulticast;
+-      } else if (netdev_mc_count(dev) > MC_FILTER_LIMIT ||
+-                 dev->flags & IFF_ALLMULTI ||
++      } else if (dev->flags & IFF_ALLMULTI ||
+                  tp->mac_version == RTL_GIGA_MAC_VER_35) {
+               /* accept all multicasts */
+       } else if (netdev_mc_empty(dev)) {
diff --git a/target/linux/generic/backport-6.6/780-03-v6.9-r8169-add-support-for-RTL8126A.patch b/target/linux/generic/backport-6.6/780-03-v6.9-r8169-add-support-for-RTL8126A.patch
deleted file mode 100644 (file)
index ab38b0c..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-From 3907f1ffc0ecf466d5c04aadc44c4b9203f3ec9a Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Thu, 1 Feb 2024 22:38:01 +0100
-Subject: [PATCH] r8169: add support for RTL8126A
-
-This adds support for the RTL8126A found on Asus z790 Maximus Formula.
-It was successfully tested w/o the firmware at 1000Mbps. Firmware file
-has been provided by Realtek and submitted to linux-firmware.
-2.5G and 5G modes are untested.
-
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/realtek/r8169.h          |   1 +
- drivers/net/ethernet/realtek/r8169_main.c     | 105 ++++++++++++++----
- .../net/ethernet/realtek/r8169_phy_config.c   |   7 ++
- 3 files changed, 89 insertions(+), 24 deletions(-)
-
---- a/drivers/net/ethernet/realtek/r8169.h
-+++ b/drivers/net/ethernet/realtek/r8169.h
-@@ -68,6 +68,7 @@ enum mac_version {
-       /* support for RTL_GIGA_MAC_VER_60 has been removed */
-       RTL_GIGA_MAC_VER_61,
-       RTL_GIGA_MAC_VER_63,
-+      RTL_GIGA_MAC_VER_65,
-       RTL_GIGA_MAC_NONE
- };
---- a/drivers/net/ethernet/realtek/r8169_main.c
-+++ b/drivers/net/ethernet/realtek/r8169_main.c
-@@ -55,6 +55,7 @@
- #define FIRMWARE_8107E_2      "rtl_nic/rtl8107e-2.fw"
- #define FIRMWARE_8125A_3      "rtl_nic/rtl8125a-3.fw"
- #define FIRMWARE_8125B_2      "rtl_nic/rtl8125b-2.fw"
-+#define FIRMWARE_8126A_2      "rtl_nic/rtl8126a-2.fw"
- /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
-    The RTL chips use a 64 element hash table based on the Ethernet CRC. */
-@@ -140,6 +141,7 @@ static const struct {
-       [RTL_GIGA_MAC_VER_61] = {"RTL8125A",            FIRMWARE_8125A_3},
-       /* reserve 62 for CFG_METHOD_4 in the vendor driver */
-       [RTL_GIGA_MAC_VER_63] = {"RTL8125B",            FIRMWARE_8125B_2},
-+      [RTL_GIGA_MAC_VER_65] = {"RTL8126A",            FIRMWARE_8126A_2},
- };
- static const struct pci_device_id rtl8169_pci_tbl[] = {
-@@ -162,6 +164,7 @@ static const struct pci_device_id rtl816
-       { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024 },
-       { 0x0001, 0x8168, PCI_ANY_ID, 0x2410 },
-       { PCI_VDEVICE(REALTEK,  0x8125) },
-+      { PCI_VDEVICE(REALTEK,  0x8126) },
-       { PCI_VDEVICE(REALTEK,  0x3000) },
-       {}
- };
-@@ -331,8 +334,12 @@ enum rtl8168_registers {
- };
- enum rtl8125_registers {
-+      INT_CFG0_8125           = 0x34,
-+#define INT_CFG0_ENABLE_8125          BIT(0)
-+#define INT_CFG0_CLKREQEN             BIT(3)
-       IntrMask_8125           = 0x38,
-       IntrStatus_8125         = 0x3c,
-+      INT_CFG1_8125           = 0x7a,
-       TxPoll_8125             = 0x90,
-       MAC0_BKP                = 0x19e0,
-       EEE_TXIDLE_TIMER_8125   = 0x6048,
-@@ -1144,7 +1151,7 @@ static void rtl_writephy(struct rtl8169_
-       case RTL_GIGA_MAC_VER_31:
-               r8168dp_2_mdio_write(tp, location, val);
-               break;
--      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
-               r8168g_mdio_write(tp, location, val);
-               break;
-       default:
-@@ -1159,7 +1166,7 @@ static int rtl_readphy(struct rtl8169_pr
-       case RTL_GIGA_MAC_VER_28:
-       case RTL_GIGA_MAC_VER_31:
-               return r8168dp_2_mdio_read(tp, location);
--      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
-               return r8168g_mdio_read(tp, location);
-       default:
-               return r8169_mdio_read(tp, location);
-@@ -1368,7 +1375,7 @@ static void rtl_set_d3_pll_down(struct r
-       case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
-       case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
-       case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_37:
--      case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_65:
-               if (enable)
-                       RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~D3_NO_PLL_DOWN);
-               else
-@@ -1535,7 +1542,7 @@ static void __rtl8169_set_wol(struct rtl
-               break;
-       case RTL_GIGA_MAC_VER_34:
-       case RTL_GIGA_MAC_VER_37:
--      case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_65:
-               if (wolopts)
-                       rtl_mod_config2(tp, 0, PME_SIGNAL);
-               else
-@@ -2122,6 +2129,9 @@ static enum mac_version rtl8169_get_mac_
-               u16 val;
-               enum mac_version ver;
-       } mac_info[] = {
-+              /* 8126A family. */
-+              { 0x7cf, 0x649, RTL_GIGA_MAC_VER_65 },
-+
-               /* 8125B family. */
-               { 0x7cf, 0x641, RTL_GIGA_MAC_VER_63 },
-@@ -2392,6 +2402,7 @@ static void rtl_init_rxcfg(struct rtl816
-               RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
-               break;
-       case RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_65:
-               RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST |
-                       RX_PAUSE_SLOT_ON);
-               break;
-@@ -2578,7 +2589,7 @@ static void rtl_wait_txrx_fifo_empty(str
-       case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_61:
-               rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
-               break;
--      case RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_65:
-               RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
-               rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
-               rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42);
-@@ -2822,7 +2833,7 @@ static void rtl_enable_exit_l1(struct rt
-       case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_38:
-               rtl_eri_set_bits(tp, 0xd4, 0x0c00);
-               break;
--      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
-               r8168_mac_ocp_modify(tp, 0xc0ac, 0, 0x1f80);
-               break;
-       default:
-@@ -2836,7 +2847,7 @@ static void rtl_disable_exit_l1(struct r
-       case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
-               rtl_eri_clear_bits(tp, 0xd4, 0x1f00);
-               break;
--      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
-               r8168_mac_ocp_modify(tp, 0xc0ac, 0x1f80, 0);
-               break;
-       default:
-@@ -2846,6 +2857,8 @@ static void rtl_disable_exit_l1(struct r
- static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
- {
-+      u8 val8;
-+
-       if (tp->mac_version < RTL_GIGA_MAC_VER_32)
-               return;
-@@ -2859,11 +2872,19 @@ static void rtl_hw_aspm_clkreq_enable(st
-                       return;
-               rtl_mod_config5(tp, 0, ASPM_en);
--              rtl_mod_config2(tp, 0, ClkReqEn);
-+              switch (tp->mac_version) {
-+              case RTL_GIGA_MAC_VER_65:
-+                      val8 = RTL_R8(tp, INT_CFG0_8125) | INT_CFG0_CLKREQEN;
-+                      RTL_W8(tp, INT_CFG0_8125, val8);
-+                      break;
-+              default:
-+                      rtl_mod_config2(tp, 0, ClkReqEn);
-+                      break;
-+              }
-               switch (tp->mac_version) {
-               case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
--              case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
-+              case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
-                       /* reset ephy tx/rx disable timer */
-                       r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0);
-                       /* chip can trigger L1.2 */
-@@ -2875,14 +2896,22 @@ static void rtl_hw_aspm_clkreq_enable(st
-       } else {
-               switch (tp->mac_version) {
-               case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
--              case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
-+              case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
-                       r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0);
-                       break;
-               default:
-                       break;
-               }
--              rtl_mod_config2(tp, ClkReqEn, 0);
-+              switch (tp->mac_version) {
-+              case RTL_GIGA_MAC_VER_65:
-+                      val8 = RTL_R8(tp, INT_CFG0_8125) & ~INT_CFG0_CLKREQEN;
-+                      RTL_W8(tp, INT_CFG0_8125, val8);
-+                      break;
-+              default:
-+                      rtl_mod_config2(tp, ClkReqEn, 0);
-+                      break;
-+              }
-               rtl_mod_config5(tp, ASPM_en, 0);
-       }
- }
-@@ -3678,10 +3707,15 @@ static void rtl_hw_start_8125_common(str
-       /* disable new tx descriptor format */
-       r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000);
--      if (tp->mac_version == RTL_GIGA_MAC_VER_63)
-+      if (tp->mac_version == RTL_GIGA_MAC_VER_65)
-+              RTL_W8(tp, 0xD8, RTL_R8(tp, 0xD8) & ~0x02);
-+
-+      if (tp->mac_version == RTL_GIGA_MAC_VER_65)
-+              r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400);
-+      else if (tp->mac_version == RTL_GIGA_MAC_VER_63)
-               r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200);
-       else
--              r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400);
-+              r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0300);
-       if (tp->mac_version == RTL_GIGA_MAC_VER_63)
-               r8168_mac_ocp_modify(tp, 0xe63e, 0x0c30, 0x0000);
-@@ -3694,6 +3728,10 @@ static void rtl_hw_start_8125_common(str
-       r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0030);
-       r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000);
-       r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001);
-+      if (tp->mac_version == RTL_GIGA_MAC_VER_65)
-+              r8168_mac_ocp_modify(tp, 0xea1c, 0x0300, 0x0000);
-+      else
-+              r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000);
-       r8168_mac_ocp_modify(tp, 0xe0c0, 0x4f0f, 0x4403);
-       r8168_mac_ocp_modify(tp, 0xe052, 0x0080, 0x0068);
-       r8168_mac_ocp_modify(tp, 0xd430, 0x0fff, 0x047f);
-@@ -3708,10 +3746,10 @@ static void rtl_hw_start_8125_common(str
-       rtl_loop_wait_low(tp, &rtl_mac_ocp_e00e_cond, 1000, 10);
--      if (tp->mac_version == RTL_GIGA_MAC_VER_63)
--              rtl8125b_config_eee_mac(tp);
--      else
-+      if (tp->mac_version == RTL_GIGA_MAC_VER_61)
-               rtl8125a_config_eee_mac(tp);
-+      else
-+              rtl8125b_config_eee_mac(tp);
-       rtl_disable_rxdvgate(tp);
- }
-@@ -3755,6 +3793,12 @@ static void rtl_hw_start_8125b(struct rt
-       rtl_hw_start_8125_common(tp);
- }
-+static void rtl_hw_start_8126a(struct rtl8169_private *tp)
-+{
-+      rtl_set_def_aspm_entry_latency(tp);
-+      rtl_hw_start_8125_common(tp);
-+}
-+
- static void rtl_hw_config(struct rtl8169_private *tp)
- {
-       static const rtl_generic_fct hw_configs[] = {
-@@ -3797,6 +3841,7 @@ static void rtl_hw_config(struct rtl8169
-               [RTL_GIGA_MAC_VER_53] = rtl_hw_start_8117,
-               [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2,
-               [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b,
-+              [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8126a,
-       };
-       if (hw_configs[tp->mac_version])
-@@ -3807,9 +3852,23 @@ static void rtl_hw_start_8125(struct rtl
- {
-       int i;
-+      RTL_W8(tp, INT_CFG0_8125, 0x00);
-+
-       /* disable interrupt coalescing */
--      for (i = 0xa00; i < 0xb00; i += 4)
--              RTL_W32(tp, i, 0);
-+      switch (tp->mac_version) {
-+      case RTL_GIGA_MAC_VER_61:
-+              for (i = 0xa00; i < 0xb00; i += 4)
-+                      RTL_W32(tp, i, 0);
-+              break;
-+      case RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_65:
-+              for (i = 0xa00; i < 0xa80; i += 4)
-+                      RTL_W32(tp, i, 0);
-+              RTL_W16(tp, INT_CFG1_8125, 0x0000);
-+              break;
-+      default:
-+              break;
-+      }
-       rtl_hw_config(tp);
- }
-@@ -3887,8 +3946,7 @@ static int rtl8169_change_mtu(struct net
-       rtl_jumbo_config(tp);
-       switch (tp->mac_version) {
--      case RTL_GIGA_MAC_VER_61:
--      case RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
-               rtl8125_set_eee_txidle_timer(tp);
-               break;
-       default:
-@@ -4037,7 +4095,7 @@ static void rtl8169_cleanup(struct rtl81
-               RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
-               rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
-               break;
--      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
-               rtl_enable_rxdvgate(tp);
-               fsleep(2000);
-               break;
-@@ -4188,8 +4246,7 @@ static unsigned int rtl_quirk_packet_pad
-       switch (tp->mac_version) {
-       case RTL_GIGA_MAC_VER_34:
--      case RTL_GIGA_MAC_VER_61:
--      case RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
-               padto = max_t(unsigned int, padto, ETH_ZLEN);
-               break;
-       default:
-@@ -5221,7 +5278,7 @@ static void rtl_hw_initialize(struct rtl
-       case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48:
-               rtl_hw_init_8168g(tp);
-               break;
--      case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
-+      case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
-               rtl_hw_init_8125(tp);
-               break;
-       default:
---- a/drivers/net/ethernet/realtek/r8169_phy_config.c
-+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c
-@@ -1102,6 +1102,12 @@ static void rtl8125b_hw_phy_config(struc
-       rtl8125b_config_eee_phy(phydev);
- }
-+static void rtl8126a_hw_phy_config(struct rtl8169_private *tp,
-+                                 struct phy_device *phydev)
-+{
-+      r8169_apply_firmware(tp);
-+}
-+
- void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
-                        enum mac_version ver)
- {
-@@ -1152,6 +1158,7 @@ void r8169_hw_phy_config(struct rtl8169_
-               [RTL_GIGA_MAC_VER_53] = rtl8117_hw_phy_config,
-               [RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config,
-               [RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config,
-+              [RTL_GIGA_MAC_VER_65] = rtl8126a_hw_phy_config,
-       };
-       if (phy_configs[ver])
diff --git a/target/linux/generic/backport-6.6/780-04-v6.8-r8169-improve-handling-task-scheduling.patch b/target/linux/generic/backport-6.6/780-04-v6.8-r8169-improve-handling-task-scheduling.patch
new file mode 100644 (file)
index 0000000..a809e82
--- /dev/null
@@ -0,0 +1,41 @@
+From 127532cd0f060ebc3c4cbca81b6438728ad5896e Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Mon, 27 Nov 2023 18:20:11 +0100
+Subject: [PATCH] r8169: improve handling task scheduling
+
+If we know that the task is going to be a no-op, don't even schedule it.
+And remove the check for netif_running() in the worker function, the
+check for flag RTL_FLAG_TASK_ENABLED is sufficient. Note that we can't
+remove the check for flag RTL_FLAG_TASK_ENABLED in the worker function
+because we have no guarantee when it will be executed.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Link: https://lore.kernel.org/r/c65873a3-7394-4107-99a7-83f20030779c@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2252,6 +2252,9 @@ u16 rtl8168h_2_get_adc_bias_ioffset(stru
+ static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
+ {
++      if (!test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
++              return;
++
+       set_bit(flag, tp->wk.flags);
+       schedule_work(&tp->wk.work);
+ }
+@@ -4491,8 +4494,7 @@ static void rtl_task(struct work_struct
+       rtnl_lock();
+-      if (!netif_running(tp->dev) ||
+-          !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
++      if (!test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
+               goto out_unlock;
+       if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) {
diff --git a/target/linux/generic/backport-6.6/780-04-v6.9-r8169-improve-checking-for-valid-LED-modes.patch b/target/linux/generic/backport-6.6/780-04-v6.9-r8169-improve-checking-for-valid-LED-modes.patch
deleted file mode 100644 (file)
index ae0c821..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-From 4c49b6824a607af4760fac4f5c0b9954ab902cef Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Wed, 7 Feb 2024 08:16:40 +0100
-Subject: [PATCH] r8169: improve checking for valid LED modes
-
-After 3a2746320403 ("leds: trigger: netdev: Display only supported link
-speed attribute") the check for valid link modes can be simplified.
-In addition factor it out, so that it can be re-used by the upcoming
-LED support for RTL8125.
-
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Reviewed-by: Simon Horman <horms@kernel.org>
-Link: https://lore.kernel.org/r/8876a9f4-7a2d-48c3-8eae-0d834f5c27c5@gmail.com
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
----
- drivers/net/ethernet/realtek/r8169_leds.c | 38 ++++++++++++-----------
- 1 file changed, 20 insertions(+), 18 deletions(-)
-
---- a/drivers/net/ethernet/realtek/r8169_leds.c
-+++ b/drivers/net/ethernet/realtek/r8169_leds.c
-@@ -20,11 +20,6 @@
- #define RTL8168_NUM_LEDS              3
--#define RTL8168_SUPPORTED_MODES \
--      (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK_100) | \
--       BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_RX) | \
--       BIT(TRIGGER_NETDEV_TX))
--
- struct r8169_led_classdev {
-       struct led_classdev led;
-       struct net_device *ndev;
-@@ -33,28 +28,35 @@ struct r8169_led_classdev {
- #define lcdev_to_r8169_ldev(lcdev) container_of(lcdev, struct r8169_led_classdev, led)
-+static bool r8169_trigger_mode_is_valid(unsigned long flags)
-+{
-+      bool rx, tx;
-+
-+      if (flags & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
-+              return false;
-+      if (flags & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
-+              return false;
-+
-+      rx = flags & BIT(TRIGGER_NETDEV_RX);
-+      tx = flags & BIT(TRIGGER_NETDEV_TX);
-+
-+      return rx == tx;
-+}
-+
- static int rtl8168_led_hw_control_is_supported(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);
-       int shift = ldev->index * 4;
--      bool rx, tx;
--      if (flags & ~RTL8168_SUPPORTED_MODES)
--              goto nosupp;
--
--      rx = flags & BIT(TRIGGER_NETDEV_RX);
--      tx = flags & BIT(TRIGGER_NETDEV_TX);
--      if (rx != tx)
--              goto nosupp;
-+      if (!r8169_trigger_mode_is_valid(flags)) {
-+              /* Switch LED off to indicate that mode isn't supported */
-+              rtl8168_led_mod_ctrl(tp, 0x000f << shift, 0);
-+              return -EOPNOTSUPP;
-+      }
-       return 0;
--
--nosupp:
--      /* Switch LED off to indicate that mode isn't supported */
--      rtl8168_led_mod_ctrl(tp, 0x000f << shift, 0);
--      return -EOPNOTSUPP;
- }
- static int rtl8168_led_hw_control_set(struct led_classdev *led_cdev,
diff --git a/target/linux/generic/backport-6.6/780-05-v6.8-r8169-add-support-for-LED-s-on-RTL8168-RTL8101.patch b/target/linux/generic/backport-6.6/780-05-v6.8-r8169-add-support-for-LED-s-on-RTL8168-RTL8101.patch
new file mode 100644 (file)
index 0000000..7a5d5a6
--- /dev/null
@@ -0,0 +1,319 @@
+From 18764b883e157e28126b54e7d4ba9dd487d5bf54 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Sat, 16 Dec 2023 20:58:10 +0100
+Subject: [PATCH] r8169: add support for LED's on RTL8168/RTL8101
+
+This adds support for the LED's on most chip versions. Excluded are
+the old non-PCIe versions and RTL8125. RTL8125 has a different LED
+register layout, support for it will follow later.
+
+LED's can be controlled from userspace using the netdev LED trigger.
+
+Tested on RTL8168h.
+
+Note: The driver can't know which LED's are actually physically
+wired. Therefore not every LED device may represent a physically
+available LED.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/realtek/Makefile     |   3 +
+ drivers/net/ethernet/realtek/r8169.h      |   7 +
+ drivers/net/ethernet/realtek/r8169_leds.c | 157 ++++++++++++++++++++++
+ drivers/net/ethernet/realtek/r8169_main.c |  65 +++++++++
+ 4 files changed, 232 insertions(+)
+ create mode 100644 drivers/net/ethernet/realtek/r8169_leds.c
+
+--- a/drivers/net/ethernet/realtek/Makefile
++++ b/drivers/net/ethernet/realtek/Makefile
+@@ -7,4 +7,7 @@ obj-$(CONFIG_8139CP) += 8139cp.o
+ obj-$(CONFIG_8139TOO) += 8139too.o
+ obj-$(CONFIG_ATP) += atp.o
+ r8169-objs += r8169_main.o r8169_firmware.o r8169_phy_config.o
++ifdef CONFIG_LEDS_TRIGGER_NETDEV
++r8169-objs += r8169_leds.o
++endif
+ obj-$(CONFIG_R8169) += r8169.o
+--- a/drivers/net/ethernet/realtek/r8169.h
++++ b/drivers/net/ethernet/realtek/r8169.h
+@@ -8,6 +8,7 @@
+  * See MAINTAINERS file for support contact information.
+  */
++#include <linux/netdevice.h>
+ #include <linux/types.h>
+ #include <linux/phy.h>
+@@ -77,3 +78,9 @@ u16 rtl8168h_2_get_adc_bias_ioffset(stru
+ u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr);
+ void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
+                        enum mac_version ver);
++
++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);
+--- /dev/null
++++ b/drivers/net/ethernet/realtek/r8169_leds.c
+@@ -0,0 +1,157 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/* r8169_leds.c: Realtek 8169/8168/8101/8125 ethernet driver.
++ *
++ * Copyright (c) 2023 Heiner Kallweit <hkallweit1@gmail.com>
++ *
++ * See MAINTAINERS file for support contact information.
++ */
++
++#include <linux/leds.h>
++#include <linux/netdevice.h>
++#include <uapi/linux/uleds.h>
++
++#include "r8169.h"
++
++#define RTL8168_LED_CTRL_OPTION2      BIT(15)
++#define RTL8168_LED_CTRL_ACT          BIT(3)
++#define RTL8168_LED_CTRL_LINK_1000    BIT(2)
++#define RTL8168_LED_CTRL_LINK_100     BIT(1)
++#define RTL8168_LED_CTRL_LINK_10      BIT(0)
++
++#define RTL8168_NUM_LEDS              3
++
++#define RTL8168_SUPPORTED_MODES \
++      (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK_100) | \
++       BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_RX) | \
++       BIT(TRIGGER_NETDEV_TX))
++
++struct r8169_led_classdev {
++      struct led_classdev led;
++      struct net_device *ndev;
++      int index;
++};
++
++#define lcdev_to_r8169_ldev(lcdev) container_of(lcdev, struct r8169_led_classdev, led)
++
++static int rtl8168_led_hw_control_is_supported(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);
++      int shift = ldev->index * 4;
++      bool rx, tx;
++
++      if (flags & ~RTL8168_SUPPORTED_MODES)
++              goto nosupp;
++
++      rx = flags & BIT(TRIGGER_NETDEV_RX);
++      tx = flags & BIT(TRIGGER_NETDEV_TX);
++      if (rx != tx)
++              goto nosupp;
++
++      return 0;
++
++nosupp:
++      /* Switch LED off to indicate that mode isn't supported */
++      rtl8168_led_mod_ctrl(tp, 0x000f << shift, 0);
++      return -EOPNOTSUPP;
++}
++
++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);
++      int shift = ldev->index * 4;
++      u16 mode = 0;
++
++      if (flags & BIT(TRIGGER_NETDEV_LINK_10))
++              mode |= RTL8168_LED_CTRL_LINK_10;
++      if (flags & BIT(TRIGGER_NETDEV_LINK_100))
++              mode |= RTL8168_LED_CTRL_LINK_100;
++      if (flags & BIT(TRIGGER_NETDEV_LINK_1000))
++              mode |= RTL8168_LED_CTRL_LINK_1000;
++      if (flags & BIT(TRIGGER_NETDEV_TX))
++              mode |= RTL8168_LED_CTRL_ACT;
++
++      return rtl8168_led_mod_ctrl(tp, 0x000f << shift, mode << shift);
++}
++
++static int rtl8168_led_hw_control_get(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);
++      int shift = ldev->index * 4;
++      int mode;
++
++      mode = rtl8168_get_led_mode(tp);
++      if (mode < 0)
++              return mode;
++
++      if (mode & RTL8168_LED_CTRL_OPTION2) {
++              rtl8168_led_mod_ctrl(tp, RTL8168_LED_CTRL_OPTION2, 0);
++              netdev_notice(ldev->ndev, "Deactivating unsupported Option2 LED mode\n");
++      }
++
++      mode = (mode >> shift) & 0x000f;
++
++      if (mode & RTL8168_LED_CTRL_ACT)
++              *flags |= BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX);
++
++      if (mode & RTL8168_LED_CTRL_LINK_10)
++              *flags |= BIT(TRIGGER_NETDEV_LINK_10);
++      if (mode & RTL8168_LED_CTRL_LINK_100)
++              *flags |= BIT(TRIGGER_NETDEV_LINK_100);
++      if (mode & RTL8168_LED_CTRL_LINK_1000)
++              *flags |= BIT(TRIGGER_NETDEV_LINK_1000);
++
++      return 0;
++}
++
++static struct device *
++      r8169_led_hw_control_get_device(struct led_classdev *led_cdev)
++{
++      struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
++
++      return &ldev->ndev->dev;
++}
++
++static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev,
++                             struct net_device *ndev, int index)
++{
++      struct rtl8169_private *tp = netdev_priv(ndev);
++      struct led_classdev *led_cdev = &ldev->led;
++      char led_name[LED_MAX_NAME_SIZE];
++
++      ldev->ndev = ndev;
++      ldev->index = index;
++
++      r8169_get_led_name(tp, index, led_name, LED_MAX_NAME_SIZE);
++      led_cdev->name = led_name;
++      led_cdev->default_trigger = "netdev";
++      led_cdev->hw_control_trigger = "netdev";
++      led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN;
++      led_cdev->hw_control_is_supported = rtl8168_led_hw_control_is_supported;
++      led_cdev->hw_control_set = rtl8168_led_hw_control_set;
++      led_cdev->hw_control_get = rtl8168_led_hw_control_get;
++      led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
++
++      /* ignore errors */
++      devm_led_classdev_register(&ndev->dev, led_cdev);
++}
++
++void 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);
++      if (!leds)
++              return;
++
++      for (i = 0; i < RTL8168_NUM_LEDS; i++)
++              rtl8168_setup_ldev(leds + i, ndev, i);
++}
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -285,6 +285,7 @@ enum rtl8168_8101_registers {
+ };
+ enum rtl8168_registers {
++      LED_CTRL                = 0x18,
+       LED_FREQ                = 0x1a,
+       EEE_LED                 = 0x1b,
+       ERIDR                   = 0x70,
+@@ -616,6 +617,7 @@ struct rtl8169_private {
+       raw_spinlock_t config25_lock;
+       raw_spinlock_t mac_ocp_lock;
++      struct mutex led_lock;  /* serialize LED ctrl RMW access */
+       raw_spinlock_t cfg9346_usage_lock;
+       int cfg9346_usage_count;
+@@ -788,6 +790,62 @@ static const struct rtl_cond name = {
+                                                       \
+ static bool name ## _check(struct rtl8169_private *tp)
++int rtl8168_led_mod_ctrl(struct rtl8169_private *tp, u16 mask, u16 val)
++{
++      struct device *dev = tp_to_dev(tp);
++      int ret;
++
++      ret = pm_runtime_resume_and_get(dev);
++      if (ret < 0)
++              return ret;
++
++      mutex_lock(&tp->led_lock);
++      RTL_W16(tp, LED_CTRL, (RTL_R16(tp, LED_CTRL) & ~mask) | val);
++      mutex_unlock(&tp->led_lock);
++
++      pm_runtime_put_sync(dev);
++
++      return 0;
++}
++
++int rtl8168_get_led_mode(struct rtl8169_private *tp)
++{
++      struct device *dev = tp_to_dev(tp);
++      int ret;
++
++      ret = pm_runtime_resume_and_get(dev);
++      if (ret < 0)
++              return ret;
++
++      ret = RTL_R16(tp, LED_CTRL);
++
++      pm_runtime_put_sync(dev);
++
++      return ret;
++}
++
++void r8169_get_led_name(struct rtl8169_private *tp, int idx,
++                      char *buf, int buf_len)
++{
++      struct pci_dev *pdev = tp->pci_dev;
++      char pdom[8], pfun[8];
++      int domain;
++
++      domain = pci_domain_nr(pdev->bus);
++      if (domain)
++              snprintf(pdom, sizeof(pdom), "P%d", domain);
++      else
++              pdom[0] = '\0';
++
++      if (pdev->multifunction)
++              snprintf(pfun, sizeof(pfun), "f%d", PCI_FUNC(pdev->devfn));
++      else
++              pfun[0] = '\0';
++
++      snprintf(buf, buf_len, "en%sp%ds%d%s-%d::lan", pdom, pdev->bus->number,
++               PCI_SLOT(pdev->devfn), pfun, idx);
++}
++
+ static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int type)
+ {
+       /* based on RTL8168FP_OOBMAC_BASE in vendor driver */
+@@ -5168,6 +5226,7 @@ static int rtl_init_one(struct pci_dev *
+       raw_spin_lock_init(&tp->cfg9346_usage_lock);
+       raw_spin_lock_init(&tp->config25_lock);
+       raw_spin_lock_init(&tp->mac_ocp_lock);
++      mutex_init(&tp->led_lock);
+       dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
+                                                  struct pcpu_sw_netstats);
+@@ -5324,6 +5383,12 @@ static int rtl_init_one(struct pci_dev *
+       if (rc)
+               return rc;
++#if IS_REACHABLE(CONFIG_LEDS_CLASS) && IS_ENABLED(CONFIG_LEDS_TRIGGER_NETDEV)
++      if (tp->mac_version > RTL_GIGA_MAC_VER_06 &&
++          tp->mac_version < RTL_GIGA_MAC_VER_61)
++              rtl8168_init_leds(dev);
++#endif
++
+       netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
+                   rtl_chip_infos[chipset].name, dev->dev_addr, xid, tp->irq);
diff --git a/target/linux/generic/backport-6.6/780-05-v6.9-r8169-add-LED-support-for-RTL8125-RTL8126.patch b/target/linux/generic/backport-6.6/780-05-v6.9-r8169-add-LED-support-for-RTL8125-RTL8126.patch
deleted file mode 100644 (file)
index b897e04..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-From be51ed104ba9929c741afb718ef7198dbcecef94 Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Mon, 12 Feb 2024 19:44:11 +0100
-Subject: [PATCH] r8169: add LED support for RTL8125/RTL8126
-
-This adds LED support for RTL8125/RTL8126.
-
-Note: Due to missing datasheets changing the 5Gbps link mode isn't
-supported for RTL8126.
-
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Reviewed-by: Andrew Lunn <andrew@lunn.ch>
-Link: https://lore.kernel.org/r/f982602c-9de3-4ca6-85a3-2c1d118dcb15@gmail.com
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
----
- drivers/net/ethernet/realtek/r8169.h      |   3 +
- drivers/net/ethernet/realtek/r8169_leds.c | 106 ++++++++++++++++++++++
- drivers/net/ethernet/realtek/r8169_main.c |  61 ++++++++++++-
- 3 files changed, 166 insertions(+), 4 deletions(-)
-
---- a/drivers/net/ethernet/realtek/r8169.h
-+++ b/drivers/net/ethernet/realtek/r8169.h
-@@ -85,3 +85,6 @@ void r8169_get_led_name(struct rtl8169_p
- 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);
-+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);
---- a/drivers/net/ethernet/realtek/r8169_leds.c
-+++ b/drivers/net/ethernet/realtek/r8169_leds.c
-@@ -18,7 +18,14 @@
- #define RTL8168_LED_CTRL_LINK_100     BIT(1)
- #define RTL8168_LED_CTRL_LINK_10      BIT(0)
-+#define RTL8125_LED_CTRL_ACT          BIT(9)
-+#define RTL8125_LED_CTRL_LINK_2500    BIT(5)
-+#define RTL8125_LED_CTRL_LINK_1000    BIT(3)
-+#define RTL8125_LED_CTRL_LINK_100     BIT(1)
-+#define RTL8125_LED_CTRL_LINK_10      BIT(0)
-+
- #define RTL8168_NUM_LEDS              3
-+#define RTL8125_NUM_LEDS              4
- struct r8169_led_classdev {
-       struct led_classdev led;
-@@ -157,3 +164,102 @@ void rtl8168_init_leds(struct net_device
-       for (i = 0; i < RTL8168_NUM_LEDS; i++)
-               rtl8168_setup_ldev(leds + i, ndev, i);
- }
-+
-+static int rtl8125_led_hw_control_is_supported(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);
-+
-+      if (!r8169_trigger_mode_is_valid(flags)) {
-+              /* Switch LED off to indicate that mode isn't supported */
-+              rtl8125_set_led_mode(tp, ldev->index, 0);
-+              return -EOPNOTSUPP;
-+      }
-+
-+      return 0;
-+}
-+
-+static int rtl8125_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);
-+      u16 mode = 0;
-+
-+      if (flags & BIT(TRIGGER_NETDEV_LINK_10))
-+              mode |= RTL8125_LED_CTRL_LINK_10;
-+      if (flags & BIT(TRIGGER_NETDEV_LINK_100))
-+              mode |= RTL8125_LED_CTRL_LINK_100;
-+      if (flags & BIT(TRIGGER_NETDEV_LINK_1000))
-+              mode |= RTL8125_LED_CTRL_LINK_1000;
-+      if (flags & BIT(TRIGGER_NETDEV_LINK_2500))
-+              mode |= RTL8125_LED_CTRL_LINK_2500;
-+      if (flags & (BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX)))
-+              mode |= RTL8125_LED_CTRL_ACT;
-+
-+      return rtl8125_set_led_mode(tp, ldev->index, mode);
-+}
-+
-+static int rtl8125_led_hw_control_get(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);
-+      int mode;
-+
-+      mode = rtl8125_get_led_mode(tp, ldev->index);
-+      if (mode < 0)
-+              return mode;
-+
-+      if (mode & RTL8125_LED_CTRL_LINK_10)
-+              *flags |= BIT(TRIGGER_NETDEV_LINK_10);
-+      if (mode & RTL8125_LED_CTRL_LINK_100)
-+              *flags |= BIT(TRIGGER_NETDEV_LINK_100);
-+      if (mode & RTL8125_LED_CTRL_LINK_1000)
-+              *flags |= BIT(TRIGGER_NETDEV_LINK_1000);
-+      if (mode & RTL8125_LED_CTRL_LINK_2500)
-+              *flags |= BIT(TRIGGER_NETDEV_LINK_2500);
-+      if (mode & RTL8125_LED_CTRL_ACT)
-+              *flags |= BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX);
-+
-+      return 0;
-+}
-+
-+static void rtl8125_setup_led_ldev(struct r8169_led_classdev *ldev,
-+                                 struct net_device *ndev, int index)
-+{
-+      struct rtl8169_private *tp = netdev_priv(ndev);
-+      struct led_classdev *led_cdev = &ldev->led;
-+      char led_name[LED_MAX_NAME_SIZE];
-+
-+      ldev->ndev = ndev;
-+      ldev->index = index;
-+
-+      r8169_get_led_name(tp, index, led_name, LED_MAX_NAME_SIZE);
-+      led_cdev->name = led_name;
-+      led_cdev->hw_control_trigger = "netdev";
-+      led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN;
-+      led_cdev->hw_control_is_supported = rtl8125_led_hw_control_is_supported;
-+      led_cdev->hw_control_set = rtl8125_led_hw_control_set;
-+      led_cdev->hw_control_get = rtl8125_led_hw_control_get;
-+      led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
-+
-+      /* ignore errors */
-+      devm_led_classdev_register(&ndev->dev, led_cdev);
-+}
-+
-+void 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);
-+      if (!leds)
-+              return;
-+
-+      for (i = 0; i < RTL8125_NUM_LEDS; i++)
-+              rtl8125_setup_led_ldev(leds + i, ndev, i);
-+}
---- a/drivers/net/ethernet/realtek/r8169_main.c
-+++ b/drivers/net/ethernet/realtek/r8169_main.c
-@@ -334,17 +334,23 @@ enum rtl8168_registers {
- };
- enum rtl8125_registers {
-+      LEDSEL0                 = 0x18,
-       INT_CFG0_8125           = 0x34,
- #define INT_CFG0_ENABLE_8125          BIT(0)
- #define INT_CFG0_CLKREQEN             BIT(3)
-       IntrMask_8125           = 0x38,
-       IntrStatus_8125         = 0x3c,
-       INT_CFG1_8125           = 0x7a,
-+      LEDSEL2                 = 0x84,
-+      LEDSEL1                 = 0x86,
-       TxPoll_8125             = 0x90,
-+      LEDSEL3                 = 0x96,
-       MAC0_BKP                = 0x19e0,
-       EEE_TXIDLE_TIMER_8125   = 0x6048,
- };
-+#define LEDSEL_MASK_8125      0x23f
-+
- #define RX_VLAN_INNER_8125    BIT(22)
- #define RX_VLAN_OUTER_8125    BIT(23)
- #define RX_VLAN_8125          (RX_VLAN_INNER_8125 | RX_VLAN_OUTER_8125)
-@@ -835,6 +841,51 @@ int rtl8168_get_led_mode(struct rtl8169_
-       return ret;
- }
-+static int rtl8125_get_led_reg(int index)
-+{
-+      static const int led_regs[] = { LEDSEL0, LEDSEL1, LEDSEL2, LEDSEL3 };
-+
-+      return led_regs[index];
-+}
-+
-+int rtl8125_set_led_mode(struct rtl8169_private *tp, int index, u16 mode)
-+{
-+      int reg = rtl8125_get_led_reg(index);
-+      struct device *dev = tp_to_dev(tp);
-+      int ret;
-+      u16 val;
-+
-+      ret = pm_runtime_resume_and_get(dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      mutex_lock(&tp->led_lock);
-+      val = RTL_R16(tp, reg) & ~LEDSEL_MASK_8125;
-+      RTL_W16(tp, reg, val | mode);
-+      mutex_unlock(&tp->led_lock);
-+
-+      pm_runtime_put_sync(dev);
-+
-+      return 0;
-+}
-+
-+int rtl8125_get_led_mode(struct rtl8169_private *tp, int index)
-+{
-+      int reg = rtl8125_get_led_reg(index);
-+      struct device *dev = tp_to_dev(tp);
-+      int ret;
-+
-+      ret = pm_runtime_resume_and_get(dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = RTL_R16(tp, reg);
-+
-+      pm_runtime_put_sync(dev);
-+
-+      return ret;
-+}
-+
- void r8169_get_led_name(struct rtl8169_private *tp, int idx,
-                       char *buf, int buf_len)
- {
-@@ -5526,10 +5577,12 @@ static int rtl_init_one(struct pci_dev *
-       if (rc)
-               return rc;
--      if (IS_ENABLED(CONFIG_R8169_LEDS) &&
--          tp->mac_version > RTL_GIGA_MAC_VER_06 &&
--          tp->mac_version < RTL_GIGA_MAC_VER_61)
--              rtl8168_init_leds(dev);
-+      if (IS_ENABLED(CONFIG_R8169_LEDS)) {
-+              if (rtl_is_8125(tp))
-+                      rtl8125_init_leds(dev);
-+              else if (tp->mac_version > RTL_GIGA_MAC_VER_06)
-+                      rtl8168_init_leds(dev);
-+      }
-       netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
-                   rtl_chip_infos[chipset].name, dev->dev_addr, xid, tp->irq);
diff --git a/target/linux/generic/backport-6.6/780-06-v6.8-r8169-fix-building-with-CONFIG_LEDS_CLASS-m.patch b/target/linux/generic/backport-6.6/780-06-v6.8-r8169-fix-building-with-CONFIG_LEDS_CLASS-m.patch
new file mode 100644 (file)
index 0000000..67f215c
--- /dev/null
@@ -0,0 +1,75 @@
+From a2634a5ffcafc31c343c6153ae487eb184c433a6 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Wed, 3 Jan 2024 16:52:04 +0100
+Subject: [PATCH] r8169: fix building with CONFIG_LEDS_CLASS=m
+
+When r8169 is built-in but LED support is a loadable module, the new
+code to drive the LED causes a link failure:
+
+ld: drivers/net/ethernet/realtek/r8169_leds.o: in function `rtl8168_init_leds':
+r8169_leds.c:(.text+0x36c): undefined reference to `devm_led_classdev_register_ext'
+
+LED support is an optional feature, so fix this issue by adding a Kconfig
+symbol R8169_LEDS that is guaranteed to be false if r8169 is built-in
+and LED core support is a module. As a positive side effect of this change
+r8169_leds.o no longer is built under this configuration.
+
+Fixes: 18764b883e15 ("r8169: add support for LED's on RTL8168/RTL8101")
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202312281159.9TPeXbNd-lkp@intel.com/
+Suggested-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Simon Horman <horms@kernel.org> # build-tested
+Tested-by: Arnd Bergmann <arnd@arndb.de>
+Link: https://lore.kernel.org/r/d055aeb5-fe5c-4ccf-987f-5af93a17537b@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/Kconfig      | 7 +++++++
+ drivers/net/ethernet/realtek/Makefile     | 6 ++----
+ drivers/net/ethernet/realtek/r8169_main.c | 5 ++---
+ 3 files changed, 11 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/Kconfig
++++ b/drivers/net/ethernet/realtek/Kconfig
+@@ -113,4 +113,11 @@ config R8169
+         To compile this driver as a module, choose M here: the module
+         will be called r8169.  This is recommended.
++config R8169_LEDS
++      def_bool R8169 && LEDS_TRIGGER_NETDEV
++      depends on !(R8169=y && LEDS_CLASS=m)
++      help
++        Optional support for controlling the NIC LED's with the netdev
++        LED trigger.
++
+ endif # NET_VENDOR_REALTEK
+--- a/drivers/net/ethernet/realtek/Makefile
++++ b/drivers/net/ethernet/realtek/Makefile
+@@ -6,8 +6,6 @@
+ obj-$(CONFIG_8139CP) += 8139cp.o
+ obj-$(CONFIG_8139TOO) += 8139too.o
+ obj-$(CONFIG_ATP) += atp.o
+-r8169-objs += r8169_main.o r8169_firmware.o r8169_phy_config.o
+-ifdef CONFIG_LEDS_TRIGGER_NETDEV
+-r8169-objs += r8169_leds.o
+-endif
++r8169-y += r8169_main.o r8169_firmware.o r8169_phy_config.o
++r8169-$(CONFIG_R8169_LEDS) += r8169_leds.o
+ obj-$(CONFIG_R8169) += r8169.o
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -5383,11 +5383,10 @@ static int rtl_init_one(struct pci_dev *
+       if (rc)
+               return rc;
+-#if IS_REACHABLE(CONFIG_LEDS_CLASS) && IS_ENABLED(CONFIG_LEDS_TRIGGER_NETDEV)
+-      if (tp->mac_version > RTL_GIGA_MAC_VER_06 &&
++      if (IS_ENABLED(CONFIG_R8169_LEDS) &&
++          tp->mac_version > RTL_GIGA_MAC_VER_06 &&
+           tp->mac_version < RTL_GIGA_MAC_VER_61)
+               rtl8168_init_leds(dev);
+-#endif
+       netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
+                   rtl_chip_infos[chipset].name, dev->dev_addr, xid, tp->irq);
diff --git a/target/linux/generic/backport-6.6/780-06-v6.9-r8169-add-MODULE_FIRMWARE-entry-for-RTL8126A.patch b/target/linux/generic/backport-6.6/780-06-v6.9-r8169-add-MODULE_FIRMWARE-entry-for-RTL8126A.patch
deleted file mode 100644 (file)
index a6175c8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From f4d3e595c0000ce39dec7e4799ea42ce42ab6867 Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Sat, 17 Feb 2024 15:48:23 +0100
-Subject: [PATCH] r8169: add MODULE_FIRMWARE entry for RTL8126A
-
-Add the missing MODULE_FIRMWARE entry for RTL8126A.
-
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Reviewed-by: Simon Horman <horms@kernel.org>
-Link: https://lore.kernel.org/r/47ef79d2-59c4-4d44-9595-366c70c4ad87@gmail.com
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
----
- drivers/net/ethernet/realtek/r8169_main.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/ethernet/realtek/r8169_main.c
-+++ b/drivers/net/ethernet/realtek/r8169_main.c
-@@ -680,6 +680,7 @@ MODULE_FIRMWARE(FIRMWARE_8168FP_3);
- MODULE_FIRMWARE(FIRMWARE_8107E_2);
- MODULE_FIRMWARE(FIRMWARE_8125A_3);
- MODULE_FIRMWARE(FIRMWARE_8125B_2);
-+MODULE_FIRMWARE(FIRMWARE_8126A_2);
- static inline struct device *tp_to_dev(struct rtl8169_private *tp)
- {
diff --git a/target/linux/generic/backport-6.6/780-07-v6.10-r8169-add-support-for-RTL8168M.patch b/target/linux/generic/backport-6.6/780-07-v6.10-r8169-add-support-for-RTL8168M.patch
deleted file mode 100644 (file)
index 557b8b1..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 39f59c72ad3a1eaab9a60f0671bc94d2bc826d21 Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Sun, 7 Apr 2024 23:19:25 +0200
-Subject: [PATCH] r8169: add support for RTL8168M
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-A user reported an unknown chip version. According to the r8168 vendor
-driver it's called RTL8168M, but handling is identical to RTL8168H.
-So let's simply treat it as RTL8168H.
-
-Tested-by: Евгений <octobergun@gmail.com>
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/realtek/r8169_main.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/net/ethernet/realtek/r8169_main.c
-+++ b/drivers/net/ethernet/realtek/r8169_main.c
-@@ -2212,6 +2212,8 @@ static enum mac_version rtl8169_get_mac_
-                * the wild. Let's disable detection.
-                * { 0x7cf, 0x540,      RTL_GIGA_MAC_VER_45 },
-                */
-+              /* Realtek calls it RTL8168M, but it's handled like RTL8168H */
-+              { 0x7cf, 0x6c0, RTL_GIGA_MAC_VER_46 },
-               /* 8168G family. */
-               { 0x7cf, 0x5c8, RTL_GIGA_MAC_VER_44 },
diff --git a/target/linux/generic/backport-6.6/780-07-v6.9-r8169-simplify-EEE-handling.patch b/target/linux/generic/backport-6.6/780-07-v6.9-r8169-simplify-EEE-handling.patch
new file mode 100644 (file)
index 0000000..bdd3330
--- /dev/null
@@ -0,0 +1,96 @@
+From f5d59230ec26aa5e8b59e9f4a4d288703a737479 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Wed, 31 Jan 2024 21:31:01 +0100
+Subject: [PATCH] r8169: simplify EEE handling
+
+We don't have to store the EEE modes to be advertised in the driver,
+phylib does this for us and stores it in phydev->advertising_eee.
+phylib also takes care of properly handling the EEE advertisement.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/27c336a8-ea47-483d-815b-02c45ae41da2@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 32 +++--------------------
+ 1 file changed, 4 insertions(+), 28 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -629,7 +629,6 @@ struct rtl8169_private {
+       struct rtl8169_counters *counters;
+       struct rtl8169_tc_offsets tc_offset;
+       u32 saved_wolopts;
+-      int eee_adv;
+       const char *fw_name;
+       struct rtl_fw *rtl_fw;
+@@ -2010,17 +2009,11 @@ static int rtl8169_get_eee(struct net_de
+ static int rtl8169_set_eee(struct net_device *dev, struct ethtool_eee *data)
+ {
+       struct rtl8169_private *tp = netdev_priv(dev);
+-      int ret;
+       if (!rtl_supports_eee(tp))
+               return -EOPNOTSUPP;
+-      ret = phy_ethtool_set_eee(tp->phydev, data);
+-
+-      if (!ret)
+-              tp->eee_adv = phy_read_mmd(dev->phydev, MDIO_MMD_AN,
+-                                         MDIO_AN_EEE_ADV);
+-      return ret;
++      return phy_ethtool_set_eee(tp->phydev, data);
+ }
+ static void rtl8169_get_ringparam(struct net_device *dev,
+@@ -2085,21 +2078,6 @@ static const struct ethtool_ops rtl8169_
+       .set_pauseparam         = rtl8169_set_pauseparam,
+ };
+-static void rtl_enable_eee(struct rtl8169_private *tp)
+-{
+-      struct phy_device *phydev = tp->phydev;
+-      int adv;
+-
+-      /* respect EEE advertisement the user may have set */
+-      if (tp->eee_adv >= 0)
+-              adv = tp->eee_adv;
+-      else
+-              adv = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
+-
+-      if (adv >= 0)
+-              phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
+-}
+-
+ static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
+ {
+       /*
+@@ -2336,9 +2314,6 @@ static void rtl8169_init_phy(struct rtl8
+       /* We may have called phy_speed_down before */
+       phy_speed_up(tp->phydev);
+-      if (rtl_supports_eee(tp))
+-              rtl_enable_eee(tp);
+-
+       genphy_soft_reset(tp->phydev);
+ }
+@@ -5085,7 +5060,9 @@ static int r8169_mdio_register(struct rt
+       }
+       tp->phydev->mac_managed_pm = true;
+-
++      if (rtl_supports_eee(tp))
++              linkmode_copy(tp->phydev->advertising_eee,
++                            tp->phydev->supported_eee);
+       phy_support_asym_pause(tp->phydev);
+       /* PHY will be woken up in rtl_open() */
+@@ -5220,7 +5197,6 @@ static int rtl_init_one(struct pci_dev *
+       tp->dev = dev;
+       tp->pci_dev = pdev;
+       tp->supports_gmii = ent->driver_data == RTL_CFG_NO_GBIT ? 0 : 1;
+-      tp->eee_adv = -1;
+       tp->ocp_base = OCP_STD_PHY_BASE;
+       raw_spin_lock_init(&tp->cfg9346_usage_lock);
diff --git a/target/linux/generic/backport-6.6/780-08-v6.10-r8169-fix-LED-related-deadlock-on-module-removal.patch b/target/linux/generic/backport-6.6/780-08-v6.10-r8169-fix-LED-related-deadlock-on-module-removal.patch
deleted file mode 100644 (file)
index c179a37..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-From 19fa4f2a85d777a8052e869c1b892a2f7556569d Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-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.
-
-Fixes: 18764b883e15 ("r8169: add support for LED's on RTL8168/RTL8101")
-Cc: stable@vger.kernel.org
-Reported-by: Lukas Wunner <lukas@wunner.de>
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Reviewed-by: Andrew Lunn <andrew@lunn.ch>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/realtek/r8169.h      |  6 ++--
- drivers/net/ethernet/realtek/r8169_leds.c | 35 +++++++++++++++--------
- drivers/net/ethernet/realtek/r8169_main.c |  8 ++++--
- 3 files changed, 33 insertions(+), 16 deletions(-)
-
---- a/drivers/net/ethernet/realtek/r8169.h
-+++ b/drivers/net/ethernet/realtek/r8169.h
-@@ -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_p
-                       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);
---- a/drivers/net/ethernet/realtek/r8169_leds.c
-+++ b/drivers/net/ethernet/realtek/r8169_leds.c
-@@ -147,22 +147,22 @@ static void rtl8168_setup_ldev(struct r8
-       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,
-@@ -246,20 +246,31 @@ static void rtl8125_setup_led_ldev(struc
-       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);
- }
---- a/drivers/net/ethernet/realtek/r8169_main.c
-+++ b/drivers/net/ethernet/realtek/r8169_main.c
-@@ -651,6 +651,8 @@ struct rtl8169_private {
-       const char *fw_name;
-       struct rtl_fw *rtl_fw;
-+      struct r8169_led_classdev *leds;
-+
-       u32 ocp_base;
- };
-@@ -5122,6 +5124,8 @@ static void rtl_remove_one(struct pci_de
-       cancel_work_sync(&tp->wk.work);
-+      r8169_remove_leds(tp->leds);
-+
-       unregister_netdev(tp->dev);
-       if (tp->dash_type != RTL_DASH_NONE)
-@@ -5582,9 +5586,9 @@ static int rtl_init_one(struct pci_dev *
-       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",
diff --git a/target/linux/generic/backport-6.6/780-08-v6.9-r8169-add-support-for-RTL8126A.patch b/target/linux/generic/backport-6.6/780-08-v6.9-r8169-add-support-for-RTL8126A.patch
new file mode 100644 (file)
index 0000000..65aa544
--- /dev/null
@@ -0,0 +1,355 @@
+From 3907f1ffc0ecf466d5c04aadc44c4b9203f3ec9a Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Thu, 1 Feb 2024 22:38:01 +0100
+Subject: [PATCH] r8169: add support for RTL8126A
+
+This adds support for the RTL8126A found on Asus z790 Maximus Formula.
+It was successfully tested w/o the firmware at 1000Mbps. Firmware file
+has been provided by Realtek and submitted to linux-firmware.
+2.5G and 5G modes are untested.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/realtek/r8169.h          |   1 +
+ drivers/net/ethernet/realtek/r8169_main.c     | 105 ++++++++++++++----
+ .../net/ethernet/realtek/r8169_phy_config.c   |   7 ++
+ 3 files changed, 89 insertions(+), 24 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169.h
++++ b/drivers/net/ethernet/realtek/r8169.h
+@@ -68,6 +68,7 @@ enum mac_version {
+       /* support for RTL_GIGA_MAC_VER_60 has been removed */
+       RTL_GIGA_MAC_VER_61,
+       RTL_GIGA_MAC_VER_63,
++      RTL_GIGA_MAC_VER_65,
+       RTL_GIGA_MAC_NONE
+ };
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -55,6 +55,7 @@
+ #define FIRMWARE_8107E_2      "rtl_nic/rtl8107e-2.fw"
+ #define FIRMWARE_8125A_3      "rtl_nic/rtl8125a-3.fw"
+ #define FIRMWARE_8125B_2      "rtl_nic/rtl8125b-2.fw"
++#define FIRMWARE_8126A_2      "rtl_nic/rtl8126a-2.fw"
+ #define TX_DMA_BURST  7       /* Maximum PCI burst, '7' is unlimited */
+ #define InterFrameGap 0x03    /* 3 means InterFrameGap = the shortest one */
+@@ -136,6 +137,7 @@ static const struct {
+       [RTL_GIGA_MAC_VER_61] = {"RTL8125A",            FIRMWARE_8125A_3},
+       /* reserve 62 for CFG_METHOD_4 in the vendor driver */
+       [RTL_GIGA_MAC_VER_63] = {"RTL8125B",            FIRMWARE_8125B_2},
++      [RTL_GIGA_MAC_VER_65] = {"RTL8126A",            FIRMWARE_8126A_2},
+ };
+ static const struct pci_device_id rtl8169_pci_tbl[] = {
+@@ -158,6 +160,7 @@ static const struct pci_device_id rtl816
+       { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024 },
+       { 0x0001, 0x8168, PCI_ANY_ID, 0x2410 },
+       { PCI_VDEVICE(REALTEK,  0x8125) },
++      { PCI_VDEVICE(REALTEK,  0x8126) },
+       { PCI_VDEVICE(REALTEK,  0x3000) },
+       {}
+ };
+@@ -327,8 +330,12 @@ enum rtl8168_registers {
+ };
+ enum rtl8125_registers {
++      INT_CFG0_8125           = 0x34,
++#define INT_CFG0_ENABLE_8125          BIT(0)
++#define INT_CFG0_CLKREQEN             BIT(3)
+       IntrMask_8125           = 0x38,
+       IntrStatus_8125         = 0x3c,
++      INT_CFG1_8125           = 0x7a,
+       TxPoll_8125             = 0x90,
+       MAC0_BKP                = 0x19e0,
+       EEE_TXIDLE_TIMER_8125   = 0x6048,
+@@ -1139,7 +1146,7 @@ static void rtl_writephy(struct rtl8169_
+       case RTL_GIGA_MAC_VER_31:
+               r8168dp_2_mdio_write(tp, location, val);
+               break;
+-      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
+               r8168g_mdio_write(tp, location, val);
+               break;
+       default:
+@@ -1154,7 +1161,7 @@ static int rtl_readphy(struct rtl8169_pr
+       case RTL_GIGA_MAC_VER_28:
+       case RTL_GIGA_MAC_VER_31:
+               return r8168dp_2_mdio_read(tp, location);
+-      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
+               return r8168g_mdio_read(tp, location);
+       default:
+               return r8169_mdio_read(tp, location);
+@@ -1363,7 +1370,7 @@ static void rtl_set_d3_pll_down(struct r
+       case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
+       case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
+       case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_37:
+-      case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_65:
+               if (enable)
+                       RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~D3_NO_PLL_DOWN);
+               else
+@@ -1530,7 +1537,7 @@ static void __rtl8169_set_wol(struct rtl
+               break;
+       case RTL_GIGA_MAC_VER_34:
+       case RTL_GIGA_MAC_VER_37:
+-      case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_65:
+               if (wolopts)
+                       rtl_mod_config2(tp, 0, PME_SIGNAL);
+               else
+@@ -2096,6 +2103,9 @@ static enum mac_version rtl8169_get_mac_
+               u16 val;
+               enum mac_version ver;
+       } mac_info[] = {
++              /* 8126A family. */
++              { 0x7cf, 0x649, RTL_GIGA_MAC_VER_65 },
++
+               /* 8125B family. */
+               { 0x7cf, 0x641, RTL_GIGA_MAC_VER_63 },
+@@ -2366,6 +2376,7 @@ static void rtl_init_rxcfg(struct rtl816
+               RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
+               break;
+       case RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_65:
+               RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST |
+                       RX_PAUSE_SLOT_ON);
+               break;
+@@ -2552,7 +2563,7 @@ static void rtl_wait_txrx_fifo_empty(str
+       case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_61:
+               rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
+               break;
+-      case RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_65:
+               RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
+               rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
+               rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42);
+@@ -2795,7 +2806,7 @@ static void rtl_enable_exit_l1(struct rt
+       case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_38:
+               rtl_eri_set_bits(tp, 0xd4, 0x0c00);
+               break;
+-      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
+               r8168_mac_ocp_modify(tp, 0xc0ac, 0, 0x1f80);
+               break;
+       default:
+@@ -2809,7 +2820,7 @@ static void rtl_disable_exit_l1(struct r
+       case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
+               rtl_eri_clear_bits(tp, 0xd4, 0x1f00);
+               break;
+-      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
+               r8168_mac_ocp_modify(tp, 0xc0ac, 0x1f80, 0);
+               break;
+       default:
+@@ -2819,6 +2830,8 @@ static void rtl_disable_exit_l1(struct r
+ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
+ {
++      u8 val8;
++
+       if (tp->mac_version < RTL_GIGA_MAC_VER_32)
+               return;
+@@ -2832,11 +2845,19 @@ static void rtl_hw_aspm_clkreq_enable(st
+                       return;
+               rtl_mod_config5(tp, 0, ASPM_en);
+-              rtl_mod_config2(tp, 0, ClkReqEn);
++              switch (tp->mac_version) {
++              case RTL_GIGA_MAC_VER_65:
++                      val8 = RTL_R8(tp, INT_CFG0_8125) | INT_CFG0_CLKREQEN;
++                      RTL_W8(tp, INT_CFG0_8125, val8);
++                      break;
++              default:
++                      rtl_mod_config2(tp, 0, ClkReqEn);
++                      break;
++              }
+               switch (tp->mac_version) {
+               case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
+-              case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
++              case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
+                       /* reset ephy tx/rx disable timer */
+                       r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0);
+                       /* chip can trigger L1.2 */
+@@ -2848,14 +2869,22 @@ static void rtl_hw_aspm_clkreq_enable(st
+       } else {
+               switch (tp->mac_version) {
+               case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
+-              case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
++              case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
+                       r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0);
+                       break;
+               default:
+                       break;
+               }
+-              rtl_mod_config2(tp, ClkReqEn, 0);
++              switch (tp->mac_version) {
++              case RTL_GIGA_MAC_VER_65:
++                      val8 = RTL_R8(tp, INT_CFG0_8125) & ~INT_CFG0_CLKREQEN;
++                      RTL_W8(tp, INT_CFG0_8125, val8);
++                      break;
++              default:
++                      rtl_mod_config2(tp, ClkReqEn, 0);
++                      break;
++              }
+               rtl_mod_config5(tp, ASPM_en, 0);
+       }
+ }
+@@ -3568,10 +3597,15 @@ static void rtl_hw_start_8125_common(str
+       /* disable new tx descriptor format */
+       r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000);
+-      if (tp->mac_version == RTL_GIGA_MAC_VER_63)
++      if (tp->mac_version == RTL_GIGA_MAC_VER_65)
++              RTL_W8(tp, 0xD8, RTL_R8(tp, 0xD8) & ~0x02);
++
++      if (tp->mac_version == RTL_GIGA_MAC_VER_65)
++              r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400);
++      else if (tp->mac_version == RTL_GIGA_MAC_VER_63)
+               r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200);
+       else
+-              r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400);
++              r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0300);
+       if (tp->mac_version == RTL_GIGA_MAC_VER_63)
+               r8168_mac_ocp_modify(tp, 0xe63e, 0x0c30, 0x0000);
+@@ -3584,6 +3618,10 @@ static void rtl_hw_start_8125_common(str
+       r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0030);
+       r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000);
+       r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001);
++      if (tp->mac_version == RTL_GIGA_MAC_VER_65)
++              r8168_mac_ocp_modify(tp, 0xea1c, 0x0300, 0x0000);
++      else
++              r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000);
+       r8168_mac_ocp_modify(tp, 0xe0c0, 0x4f0f, 0x4403);
+       r8168_mac_ocp_modify(tp, 0xe052, 0x0080, 0x0068);
+       r8168_mac_ocp_modify(tp, 0xd430, 0x0fff, 0x047f);
+@@ -3598,10 +3636,10 @@ static void rtl_hw_start_8125_common(str
+       rtl_loop_wait_low(tp, &rtl_mac_ocp_e00e_cond, 1000, 10);
+-      if (tp->mac_version == RTL_GIGA_MAC_VER_63)
+-              rtl8125b_config_eee_mac(tp);
+-      else
++      if (tp->mac_version == RTL_GIGA_MAC_VER_61)
+               rtl8125a_config_eee_mac(tp);
++      else
++              rtl8125b_config_eee_mac(tp);
+       rtl_disable_rxdvgate(tp);
+ }
+@@ -3645,6 +3683,12 @@ static void rtl_hw_start_8125b(struct rt
+       rtl_hw_start_8125_common(tp);
+ }
++static void rtl_hw_start_8126a(struct rtl8169_private *tp)
++{
++      rtl_set_def_aspm_entry_latency(tp);
++      rtl_hw_start_8125_common(tp);
++}
++
+ static void rtl_hw_config(struct rtl8169_private *tp)
+ {
+       static const rtl_generic_fct hw_configs[] = {
+@@ -3687,6 +3731,7 @@ static void rtl_hw_config(struct rtl8169
+               [RTL_GIGA_MAC_VER_53] = rtl_hw_start_8117,
+               [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2,
+               [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b,
++              [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8126a,
+       };
+       if (hw_configs[tp->mac_version])
+@@ -3697,9 +3742,23 @@ static void rtl_hw_start_8125(struct rtl
+ {
+       int i;
++      RTL_W8(tp, INT_CFG0_8125, 0x00);
++
+       /* disable interrupt coalescing */
+-      for (i = 0xa00; i < 0xb00; i += 4)
+-              RTL_W32(tp, i, 0);
++      switch (tp->mac_version) {
++      case RTL_GIGA_MAC_VER_61:
++              for (i = 0xa00; i < 0xb00; i += 4)
++                      RTL_W32(tp, i, 0);
++              break;
++      case RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_65:
++              for (i = 0xa00; i < 0xa80; i += 4)
++                      RTL_W32(tp, i, 0);
++              RTL_W16(tp, INT_CFG1_8125, 0x0000);
++              break;
++      default:
++              break;
++      }
+       rtl_hw_config(tp);
+ }
+@@ -3777,8 +3836,7 @@ static int rtl8169_change_mtu(struct net
+       rtl_jumbo_config(tp);
+       switch (tp->mac_version) {
+-      case RTL_GIGA_MAC_VER_61:
+-      case RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
+               rtl8125_set_eee_txidle_timer(tp);
+               break;
+       default:
+@@ -3927,7 +3985,7 @@ static void rtl8169_cleanup(struct rtl81
+               RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
+               rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
+               break;
+-      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_65:
+               rtl_enable_rxdvgate(tp);
+               fsleep(2000);
+               break;
+@@ -4078,8 +4136,7 @@ static unsigned int rtl_quirk_packet_pad
+       switch (tp->mac_version) {
+       case RTL_GIGA_MAC_VER_34:
+-      case RTL_GIGA_MAC_VER_61:
+-      case RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
+               padto = max_t(unsigned int, padto, ETH_ZLEN);
+               break;
+       default:
+@@ -5112,7 +5169,7 @@ static void rtl_hw_initialize(struct rtl
+       case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48:
+               rtl_hw_init_8168g(tp);
+               break;
+-      case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
+               rtl_hw_init_8125(tp);
+               break;
+       default:
+--- a/drivers/net/ethernet/realtek/r8169_phy_config.c
++++ b/drivers/net/ethernet/realtek/r8169_phy_config.c
+@@ -1102,6 +1102,12 @@ static void rtl8125b_hw_phy_config(struc
+       rtl8125b_config_eee_phy(phydev);
+ }
++static void rtl8126a_hw_phy_config(struct rtl8169_private *tp,
++                                 struct phy_device *phydev)
++{
++      r8169_apply_firmware(tp);
++}
++
+ void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
+                        enum mac_version ver)
+ {
+@@ -1152,6 +1158,7 @@ void r8169_hw_phy_config(struct rtl8169_
+               [RTL_GIGA_MAC_VER_53] = rtl8117_hw_phy_config,
+               [RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config,
+               [RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config,
++              [RTL_GIGA_MAC_VER_65] = rtl8126a_hw_phy_config,
+       };
+       if (phy_configs[ver])
diff --git a/target/linux/generic/backport-6.6/780-09-v6.10-r8169-add-missing-conditional-compiling-for-call-to-.patch b/target/linux/generic/backport-6.6/780-09-v6.10-r8169-add-missing-conditional-compiling-for-call-to-.patch
deleted file mode 100644 (file)
index abd7d1c..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From 97e176fcbbf3c0f2bd410c9b241177c051f57176 Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Wed, 10 Apr 2024 15:11:28 +0200
-Subject: [PATCH] r8169: add missing conditional compiling for call to
- r8169_remove_leds
-
-Add missing dependency on CONFIG_R8169_LEDS. As-is a link error occurs
-if config option CONFIG_R8169_LEDS isn't enabled.
-
-Fixes: 19fa4f2a85d7 ("r8169: fix LED-related deadlock on module removal")
-Reported-by: Venkat Rao Bagalkote <venkat88@linux.vnet.ibm.com>
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Tested-By: Venkat Rao Bagalkote <venkat88@linux.vnet.ibm.com>
-Link: https://lore.kernel.org/r/d080038c-eb6b-45ac-9237-b8c1cdd7870f@gmail.com
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
----
- drivers/net/ethernet/realtek/r8169_main.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/net/ethernet/realtek/r8169_main.c
-+++ b/drivers/net/ethernet/realtek/r8169_main.c
-@@ -5124,7 +5124,8 @@ static void rtl_remove_one(struct pci_de
-       cancel_work_sync(&tp->wk.work);
--      r8169_remove_leds(tp->leds);
-+      if (IS_ENABLED(CONFIG_R8169_LEDS))
-+              r8169_remove_leds(tp->leds);
-       unregister_netdev(tp->dev);
diff --git a/target/linux/generic/backport-6.6/780-09-v6.9-r8169-improve-checking-for-valid-LED-modes.patch b/target/linux/generic/backport-6.6/780-09-v6.9-r8169-improve-checking-for-valid-LED-modes.patch
new file mode 100644 (file)
index 0000000..ae0c821
--- /dev/null
@@ -0,0 +1,81 @@
+From 4c49b6824a607af4760fac4f5c0b9954ab902cef Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Wed, 7 Feb 2024 08:16:40 +0100
+Subject: [PATCH] r8169: improve checking for valid LED modes
+
+After 3a2746320403 ("leds: trigger: netdev: Display only supported link
+speed attribute") the check for valid link modes can be simplified.
+In addition factor it out, so that it can be re-used by the upcoming
+LED support for RTL8125.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/8876a9f4-7a2d-48c3-8eae-0d834f5c27c5@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_leds.c | 38 ++++++++++++-----------
+ 1 file changed, 20 insertions(+), 18 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_leds.c
++++ b/drivers/net/ethernet/realtek/r8169_leds.c
+@@ -20,11 +20,6 @@
+ #define RTL8168_NUM_LEDS              3
+-#define RTL8168_SUPPORTED_MODES \
+-      (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK_100) | \
+-       BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_RX) | \
+-       BIT(TRIGGER_NETDEV_TX))
+-
+ struct r8169_led_classdev {
+       struct led_classdev led;
+       struct net_device *ndev;
+@@ -33,28 +28,35 @@ struct r8169_led_classdev {
+ #define lcdev_to_r8169_ldev(lcdev) container_of(lcdev, struct r8169_led_classdev, led)
++static bool r8169_trigger_mode_is_valid(unsigned long flags)
++{
++      bool rx, tx;
++
++      if (flags & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
++              return false;
++      if (flags & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
++              return false;
++
++      rx = flags & BIT(TRIGGER_NETDEV_RX);
++      tx = flags & BIT(TRIGGER_NETDEV_TX);
++
++      return rx == tx;
++}
++
+ static int rtl8168_led_hw_control_is_supported(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);
+       int shift = ldev->index * 4;
+-      bool rx, tx;
+-      if (flags & ~RTL8168_SUPPORTED_MODES)
+-              goto nosupp;
+-
+-      rx = flags & BIT(TRIGGER_NETDEV_RX);
+-      tx = flags & BIT(TRIGGER_NETDEV_TX);
+-      if (rx != tx)
+-              goto nosupp;
++      if (!r8169_trigger_mode_is_valid(flags)) {
++              /* Switch LED off to indicate that mode isn't supported */
++              rtl8168_led_mod_ctrl(tp, 0x000f << shift, 0);
++              return -EOPNOTSUPP;
++      }
+       return 0;
+-
+-nosupp:
+-      /* Switch LED off to indicate that mode isn't supported */
+-      rtl8168_led_mod_ctrl(tp, 0x000f << shift, 0);
+-      return -EOPNOTSUPP;
+ }
+ static int rtl8168_led_hw_control_set(struct led_classdev *led_cdev,
diff --git a/target/linux/generic/backport-6.6/780-10-v6.9-r8169-simplify-code-by-using-core-provided-pcpu-stat.patch b/target/linux/generic/backport-6.6/780-10-v6.9-r8169-simplify-code-by-using-core-provided-pcpu-stat.patch
new file mode 100644 (file)
index 0000000..5101237
--- /dev/null
@@ -0,0 +1,39 @@
+From 400909df6e6543cb5cce3db9bbcd413d59125327 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Sat, 10 Feb 2024 17:58:29 +0100
+Subject: [PATCH] r8169: simplify code by using core-provided pcpu stats
+ allocation
+
+Use core-provided pcpu stats allocation instead of open-coding it in
+the driver.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/03f5bb3b-d7f4-48be-ae8a-54862ec4566c@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -5261,11 +5261,6 @@ static int rtl_init_one(struct pci_dev *
+       raw_spin_lock_init(&tp->mac_ocp_lock);
+       mutex_init(&tp->led_lock);
+-      dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
+-                                                 struct pcpu_sw_netstats);
+-      if (!dev->tstats)
+-              return -ENOMEM;
+-
+       /* Get the *optional* external "ether_clk" used on some boards */
+       tp->clk = devm_clk_get_optional_enabled(&pdev->dev, "ether_clk");
+       if (IS_ERR(tp->clk))
+@@ -5380,6 +5375,8 @@ static int rtl_init_one(struct pci_dev *
+       dev->hw_features |= NETIF_F_RXALL;
+       dev->hw_features |= NETIF_F_RXFCS;
++      dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
++
+       netdev_sw_irq_coalesce_default_on(dev);
+       /* configure chip for default features */
diff --git a/target/linux/generic/backport-6.6/780-11-v6.9-r8169-add-LED-support-for-RTL8125-RTL8126.patch b/target/linux/generic/backport-6.6/780-11-v6.9-r8169-add-LED-support-for-RTL8125-RTL8126.patch
new file mode 100644 (file)
index 0000000..2059551
--- /dev/null
@@ -0,0 +1,244 @@
+From be51ed104ba9929c741afb718ef7198dbcecef94 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Mon, 12 Feb 2024 19:44:11 +0100
+Subject: [PATCH] r8169: add LED support for RTL8125/RTL8126
+
+This adds LED support for RTL8125/RTL8126.
+
+Note: Due to missing datasheets changing the 5Gbps link mode isn't
+supported for RTL8126.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://lore.kernel.org/r/f982602c-9de3-4ca6-85a3-2c1d118dcb15@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169.h      |   3 +
+ drivers/net/ethernet/realtek/r8169_leds.c | 106 ++++++++++++++++++++++
+ drivers/net/ethernet/realtek/r8169_main.c |  61 ++++++++++++-
+ 3 files changed, 166 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169.h
++++ b/drivers/net/ethernet/realtek/r8169.h
+@@ -85,3 +85,6 @@ void r8169_get_led_name(struct rtl8169_p
+ 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);
++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);
+--- a/drivers/net/ethernet/realtek/r8169_leds.c
++++ b/drivers/net/ethernet/realtek/r8169_leds.c
+@@ -18,7 +18,14 @@
+ #define RTL8168_LED_CTRL_LINK_100     BIT(1)
+ #define RTL8168_LED_CTRL_LINK_10      BIT(0)
++#define RTL8125_LED_CTRL_ACT          BIT(9)
++#define RTL8125_LED_CTRL_LINK_2500    BIT(5)
++#define RTL8125_LED_CTRL_LINK_1000    BIT(3)
++#define RTL8125_LED_CTRL_LINK_100     BIT(1)
++#define RTL8125_LED_CTRL_LINK_10      BIT(0)
++
+ #define RTL8168_NUM_LEDS              3
++#define RTL8125_NUM_LEDS              4
+ struct r8169_led_classdev {
+       struct led_classdev led;
+@@ -157,3 +164,102 @@ void rtl8168_init_leds(struct net_device
+       for (i = 0; i < RTL8168_NUM_LEDS; i++)
+               rtl8168_setup_ldev(leds + i, ndev, i);
+ }
++
++static int rtl8125_led_hw_control_is_supported(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);
++
++      if (!r8169_trigger_mode_is_valid(flags)) {
++              /* Switch LED off to indicate that mode isn't supported */
++              rtl8125_set_led_mode(tp, ldev->index, 0);
++              return -EOPNOTSUPP;
++      }
++
++      return 0;
++}
++
++static int rtl8125_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);
++      u16 mode = 0;
++
++      if (flags & BIT(TRIGGER_NETDEV_LINK_10))
++              mode |= RTL8125_LED_CTRL_LINK_10;
++      if (flags & BIT(TRIGGER_NETDEV_LINK_100))
++              mode |= RTL8125_LED_CTRL_LINK_100;
++      if (flags & BIT(TRIGGER_NETDEV_LINK_1000))
++              mode |= RTL8125_LED_CTRL_LINK_1000;
++      if (flags & BIT(TRIGGER_NETDEV_LINK_2500))
++              mode |= RTL8125_LED_CTRL_LINK_2500;
++      if (flags & (BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX)))
++              mode |= RTL8125_LED_CTRL_ACT;
++
++      return rtl8125_set_led_mode(tp, ldev->index, mode);
++}
++
++static int rtl8125_led_hw_control_get(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);
++      int mode;
++
++      mode = rtl8125_get_led_mode(tp, ldev->index);
++      if (mode < 0)
++              return mode;
++
++      if (mode & RTL8125_LED_CTRL_LINK_10)
++              *flags |= BIT(TRIGGER_NETDEV_LINK_10);
++      if (mode & RTL8125_LED_CTRL_LINK_100)
++              *flags |= BIT(TRIGGER_NETDEV_LINK_100);
++      if (mode & RTL8125_LED_CTRL_LINK_1000)
++              *flags |= BIT(TRIGGER_NETDEV_LINK_1000);
++      if (mode & RTL8125_LED_CTRL_LINK_2500)
++              *flags |= BIT(TRIGGER_NETDEV_LINK_2500);
++      if (mode & RTL8125_LED_CTRL_ACT)
++              *flags |= BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX);
++
++      return 0;
++}
++
++static void rtl8125_setup_led_ldev(struct r8169_led_classdev *ldev,
++                                 struct net_device *ndev, int index)
++{
++      struct rtl8169_private *tp = netdev_priv(ndev);
++      struct led_classdev *led_cdev = &ldev->led;
++      char led_name[LED_MAX_NAME_SIZE];
++
++      ldev->ndev = ndev;
++      ldev->index = index;
++
++      r8169_get_led_name(tp, index, led_name, LED_MAX_NAME_SIZE);
++      led_cdev->name = led_name;
++      led_cdev->hw_control_trigger = "netdev";
++      led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN;
++      led_cdev->hw_control_is_supported = rtl8125_led_hw_control_is_supported;
++      led_cdev->hw_control_set = rtl8125_led_hw_control_set;
++      led_cdev->hw_control_get = rtl8125_led_hw_control_get;
++      led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
++
++      /* ignore errors */
++      devm_led_classdev_register(&ndev->dev, led_cdev);
++}
++
++void 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);
++      if (!leds)
++              return;
++
++      for (i = 0; i < RTL8125_NUM_LEDS; i++)
++              rtl8125_setup_led_ldev(leds + i, ndev, i);
++}
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -330,17 +330,23 @@ enum rtl8168_registers {
+ };
+ enum rtl8125_registers {
++      LEDSEL0                 = 0x18,
+       INT_CFG0_8125           = 0x34,
+ #define INT_CFG0_ENABLE_8125          BIT(0)
+ #define INT_CFG0_CLKREQEN             BIT(3)
+       IntrMask_8125           = 0x38,
+       IntrStatus_8125         = 0x3c,
+       INT_CFG1_8125           = 0x7a,
++      LEDSEL2                 = 0x84,
++      LEDSEL1                 = 0x86,
+       TxPoll_8125             = 0x90,
++      LEDSEL3                 = 0x96,
+       MAC0_BKP                = 0x19e0,
+       EEE_TXIDLE_TIMER_8125   = 0x6048,
+ };
++#define LEDSEL_MASK_8125      0x23f
++
+ #define RX_VLAN_INNER_8125    BIT(22)
+ #define RX_VLAN_OUTER_8125    BIT(23)
+ #define RX_VLAN_8125          (RX_VLAN_INNER_8125 | RX_VLAN_OUTER_8125)
+@@ -830,6 +836,51 @@ int rtl8168_get_led_mode(struct rtl8169_
+       return ret;
+ }
++static int rtl8125_get_led_reg(int index)
++{
++      static const int led_regs[] = { LEDSEL0, LEDSEL1, LEDSEL2, LEDSEL3 };
++
++      return led_regs[index];
++}
++
++int rtl8125_set_led_mode(struct rtl8169_private *tp, int index, u16 mode)
++{
++      int reg = rtl8125_get_led_reg(index);
++      struct device *dev = tp_to_dev(tp);
++      int ret;
++      u16 val;
++
++      ret = pm_runtime_resume_and_get(dev);
++      if (ret < 0)
++              return ret;
++
++      mutex_lock(&tp->led_lock);
++      val = RTL_R16(tp, reg) & ~LEDSEL_MASK_8125;
++      RTL_W16(tp, reg, val | mode);
++      mutex_unlock(&tp->led_lock);
++
++      pm_runtime_put_sync(dev);
++
++      return 0;
++}
++
++int rtl8125_get_led_mode(struct rtl8169_private *tp, int index)
++{
++      int reg = rtl8125_get_led_reg(index);
++      struct device *dev = tp_to_dev(tp);
++      int ret;
++
++      ret = pm_runtime_resume_and_get(dev);
++      if (ret < 0)
++              return ret;
++
++      ret = RTL_R16(tp, reg);
++
++      pm_runtime_put_sync(dev);
++
++      return ret;
++}
++
+ void r8169_get_led_name(struct rtl8169_private *tp, int idx,
+                       char *buf, int buf_len)
+ {
+@@ -5413,10 +5464,12 @@ static int rtl_init_one(struct pci_dev *
+       if (rc)
+               return rc;
+-      if (IS_ENABLED(CONFIG_R8169_LEDS) &&
+-          tp->mac_version > RTL_GIGA_MAC_VER_06 &&
+-          tp->mac_version < RTL_GIGA_MAC_VER_61)
+-              rtl8168_init_leds(dev);
++      if (IS_ENABLED(CONFIG_R8169_LEDS)) {
++              if (rtl_is_8125(tp))
++                      rtl8125_init_leds(dev);
++              else if (tp->mac_version > RTL_GIGA_MAC_VER_06)
++                      rtl8168_init_leds(dev);
++      }
+       netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
+                   rtl_chip_infos[chipset].name, dev->dev_addr, xid, tp->irq);
diff --git a/target/linux/generic/backport-6.6/780-12-v6.9-r8169-add-generic-rtl_set_eee_txidle_timer-function.patch b/target/linux/generic/backport-6.6/780-12-v6.9-r8169-add-generic-rtl_set_eee_txidle_timer-function.patch
new file mode 100644 (file)
index 0000000..1a7eed1
--- /dev/null
@@ -0,0 +1,91 @@
+From 2ce30993831041b9dcd31eb12896be6611e8b7e2 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Mon, 12 Feb 2024 19:57:46 +0100
+Subject: [PATCH] r8169: add generic rtl_set_eee_txidle_timer function
+
+Add a generic setter for the EEE tx idle timer and use it with all
+RTL8125/RTL8126 chip versions, in line with the vendor driver.
+This prepares for adding EEE tx idle timer support for additional
+chip versions.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://lore.kernel.org/r/39beed72-0dc4-4c45-8899-b72c43ab62a7@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 34 +++++++++++++----------
+ 1 file changed, 20 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -619,6 +619,7 @@ struct rtl8169_private {
+       struct page *Rx_databuff[NUM_RX_DESC];  /* Rx data buffers */
+       struct ring_info tx_skb[NUM_TX_DESC];   /* Tx data buffers */
+       u16 cp_cmd;
++      u16 tx_lpi_timer;
+       u32 irq_mask;
+       int irq;
+       struct clk *clk;
+@@ -2054,6 +2055,22 @@ static int rtl_set_coalesce(struct net_d
+       return 0;
+ }
++static void rtl_set_eee_txidle_timer(struct rtl8169_private *tp)
++{
++      unsigned int timer_val = READ_ONCE(tp->dev->mtu) + ETH_HLEN + 0x20;
++
++      switch (tp->mac_version) {
++      case RTL_GIGA_MAC_VER_61:
++      case RTL_GIGA_MAC_VER_63:
++      case RTL_GIGA_MAC_VER_65:
++              tp->tx_lpi_timer = timer_val;
++              RTL_W16(tp, EEE_TXIDLE_TIMER_8125, timer_val);
++              break;
++      default:
++              break;
++      }
++}
++
+ static int rtl8169_get_eee(struct net_device *dev, struct ethtool_eee *data)
+ {
+       struct rtl8169_private *tp = netdev_priv(dev);
+@@ -2312,14 +2329,8 @@ static void rtl8125a_config_eee_mac(stru
+       r8168_mac_ocp_modify(tp, 0xeb62, 0, BIT(2) | BIT(1));
+ }
+-static void rtl8125_set_eee_txidle_timer(struct rtl8169_private *tp)
+-{
+-      RTL_W16(tp, EEE_TXIDLE_TIMER_8125, tp->dev->mtu + ETH_HLEN + 0x20);
+-}
+-
+ static void rtl8125b_config_eee_mac(struct rtl8169_private *tp)
+ {
+-      rtl8125_set_eee_txidle_timer(tp);
+       r8168_mac_ocp_modify(tp, 0xe040, 0, BIT(1) | BIT(0));
+ }
+@@ -3852,6 +3863,8 @@ static void rtl_hw_start(struct  rtl8169
+       rtl_hw_aspm_clkreq_enable(tp, false);
+       RTL_W16(tp, CPlusCmd, tp->cp_cmd);
++      rtl_set_eee_txidle_timer(tp);
++
+       if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+               rtl_hw_start_8169(tp);
+       else if (rtl_is_8125(tp))
+@@ -3885,14 +3898,7 @@ static int rtl8169_change_mtu(struct net
+       dev->mtu = new_mtu;
+       netdev_update_features(dev);
+       rtl_jumbo_config(tp);
+-
+-      switch (tp->mac_version) {
+-      case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_65:
+-              rtl8125_set_eee_txidle_timer(tp);
+-              break;
+-      default:
+-              break;
+-      }
++      rtl_set_eee_txidle_timer(tp);
+       return 0;
+ }
diff --git a/target/linux/generic/backport-6.6/780-13-v6.9-r8169-support-setting-the-EEE-tx-idle-timer-on-RTL81.patch b/target/linux/generic/backport-6.6/780-13-v6.9-r8169-support-setting-the-EEE-tx-idle-timer-on-RTL81.patch
new file mode 100644 (file)
index 0000000..917c7c1
--- /dev/null
@@ -0,0 +1,30 @@
+From 57d2d2c8f132c830565058a5cdd8138350e068ec Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Mon, 12 Feb 2024 19:58:47 +0100
+Subject: [PATCH] r8169: support setting the EEE tx idle timer on
+ RTL8168h
+
+Support setting the EEE tx idle timer also on RTL8168h.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://lore.kernel.org/r/cfb69ec9-24c4-4aad-9909-fdae3088add4@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2060,6 +2060,11 @@ static void rtl_set_eee_txidle_timer(str
+       unsigned int timer_val = READ_ONCE(tp->dev->mtu) + ETH_HLEN + 0x20;
+       switch (tp->mac_version) {
++      case RTL_GIGA_MAC_VER_46:
++      case RTL_GIGA_MAC_VER_48:
++              tp->tx_lpi_timer = timer_val;
++              r8168_mac_ocp_write(tp, 0xe048, timer_val);
++              break;
+       case RTL_GIGA_MAC_VER_61:
+       case RTL_GIGA_MAC_VER_63:
+       case RTL_GIGA_MAC_VER_65:
diff --git a/target/linux/generic/backport-6.6/780-14-v6.9-r8169-add-support-for-returning-tx_lpi_timer-in-etht.patch b/target/linux/generic/backport-6.6/780-14-v6.9-r8169-add-support-for-returning-tx_lpi_timer-in-etht.patch
new file mode 100644 (file)
index 0000000..51477d0
--- /dev/null
@@ -0,0 +1,55 @@
+From 9c50139727265c088f936e496777bf588850e9f1 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Mon, 12 Feb 2024 19:59:26 +0100
+Subject: [PATCH] r8169: add support for returning tx_lpi_timer in
+ ethtool get_eee
+
+Add support for returning the tx_lpi_timer value to userspace.
+This is supported by few chip versions only: RTL8168h/RTL8125/RTL8126
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://lore.kernel.org/r/4eee9c34-c5d6-4c96-9b05-455896dea59a@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 22 +++++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2076,14 +2076,34 @@ static void rtl_set_eee_txidle_timer(str
+       }
+ }
++static unsigned int r8169_get_tx_lpi_timer_us(struct rtl8169_private *tp)
++{
++      unsigned int speed = tp->phydev->speed;
++      unsigned int timer = tp->tx_lpi_timer;
++
++      if (!timer || speed == SPEED_UNKNOWN)
++              return 0;
++
++      /* tx_lpi_timer value is in bytes */
++      return DIV_ROUND_CLOSEST(timer * BITS_PER_BYTE, speed);
++}
++
+ static int rtl8169_get_eee(struct net_device *dev, struct ethtool_eee *data)
+ {
+       struct rtl8169_private *tp = netdev_priv(dev);
++      int ret;
+       if (!rtl_supports_eee(tp))
+               return -EOPNOTSUPP;
+-      return phy_ethtool_get_eee(tp->phydev, data);
++      ret = phy_ethtool_get_eee(tp->phydev, data);
++      if (ret)
++              return ret;
++
++      data->tx_lpi_timer = r8169_get_tx_lpi_timer_us(tp);
++      data->tx_lpi_enabled = data->tx_lpi_timer ? data->eee_enabled : false;
++
++      return 0;
+ }
+ static int rtl8169_set_eee(struct net_device *dev, struct ethtool_eee *data)
diff --git a/target/linux/generic/backport-6.6/780-15-v6.9-r8169-add-MODULE_FIRMWARE-entry-for-RTL8126A.patch b/target/linux/generic/backport-6.6/780-15-v6.9-r8169-add-MODULE_FIRMWARE-entry-for-RTL8126A.patch
new file mode 100644 (file)
index 0000000..6a7ebc8
--- /dev/null
@@ -0,0 +1,25 @@
+From f4d3e595c0000ce39dec7e4799ea42ce42ab6867 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Sat, 17 Feb 2024 15:48:23 +0100
+Subject: [PATCH] r8169: add MODULE_FIRMWARE entry for RTL8126A
+
+Add the missing MODULE_FIRMWARE entry for RTL8126A.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/47ef79d2-59c4-4d44-9595-366c70c4ad87@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -676,6 +676,7 @@ MODULE_FIRMWARE(FIRMWARE_8168FP_3);
+ MODULE_FIRMWARE(FIRMWARE_8107E_2);
+ MODULE_FIRMWARE(FIRMWARE_8125A_3);
+ MODULE_FIRMWARE(FIRMWARE_8125B_2);
++MODULE_FIRMWARE(FIRMWARE_8126A_2);
+ static inline struct device *tp_to_dev(struct rtl8169_private *tp)
+ {
diff --git a/target/linux/generic/backport-6.6/780-16-v6.9-r8169-fix-LED-related-deadlock-on-module-removal.patch b/target/linux/generic/backport-6.6/780-16-v6.9-r8169-fix-LED-related-deadlock-on-module-removal.patch
new file mode 100644 (file)
index 0000000..d8e4a4f
--- /dev/null
@@ -0,0 +1,147 @@
+From 19fa4f2a85d777a8052e869c1b892a2f7556569d Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+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.
+
+Fixes: 18764b883e15 ("r8169: add support for LED's on RTL8168/RTL8101")
+Cc: stable@vger.kernel.org
+Reported-by: Lukas Wunner <lukas@wunner.de>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/realtek/r8169.h      |  6 ++--
+ drivers/net/ethernet/realtek/r8169_leds.c | 35 +++++++++++++++--------
+ drivers/net/ethernet/realtek/r8169_main.c |  8 ++++--
+ 3 files changed, 33 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169.h
++++ b/drivers/net/ethernet/realtek/r8169.h
+@@ -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_p
+                       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);
+--- a/drivers/net/ethernet/realtek/r8169_leds.c
++++ b/drivers/net/ethernet/realtek/r8169_leds.c
+@@ -147,22 +147,22 @@ static void rtl8168_setup_ldev(struct r8
+       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,
+@@ -246,20 +246,31 @@ static void rtl8125_setup_led_ldev(struc
+       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);
+ }
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -647,6 +647,8 @@ struct rtl8169_private {
+       const char *fw_name;
+       struct rtl_fw *rtl_fw;
++      struct r8169_led_classdev *leds;
++
+       u32 ocp_base;
+ };
+@@ -5040,6 +5042,8 @@ static void rtl_remove_one(struct pci_de
+       cancel_work_sync(&tp->wk.work);
++      r8169_remove_leds(tp->leds);
++
+       unregister_netdev(tp->dev);
+       if (tp->dash_type != RTL_DASH_NONE)
+@@ -5498,9 +5502,9 @@ static int rtl_init_one(struct pci_dev *
+       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",
diff --git a/target/linux/generic/backport-6.6/780-17-v6.9-r8169-add-missing-conditional-compiling-for-call-to-.patch b/target/linux/generic/backport-6.6/780-17-v6.9-r8169-add-missing-conditional-compiling-for-call-to-.patch
new file mode 100644 (file)
index 0000000..366ae80
--- /dev/null
@@ -0,0 +1,31 @@
+From 97e176fcbbf3c0f2bd410c9b241177c051f57176 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Wed, 10 Apr 2024 15:11:28 +0200
+Subject: [PATCH] r8169: add missing conditional compiling for call to
+ r8169_remove_leds
+
+Add missing dependency on CONFIG_R8169_LEDS. As-is a link error occurs
+if config option CONFIG_R8169_LEDS isn't enabled.
+
+Fixes: 19fa4f2a85d7 ("r8169: fix LED-related deadlock on module removal")
+Reported-by: Venkat Rao Bagalkote <venkat88@linux.vnet.ibm.com>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Tested-By: Venkat Rao Bagalkote <venkat88@linux.vnet.ibm.com>
+Link: https://lore.kernel.org/r/d080038c-eb6b-45ac-9237-b8c1cdd7870f@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -5042,7 +5042,8 @@ static void rtl_remove_one(struct pci_de
+       cancel_work_sync(&tp->wk.work);
+-      r8169_remove_leds(tp->leds);
++      if (IS_ENABLED(CONFIG_R8169_LEDS))
++              r8169_remove_leds(tp->leds);
+       unregister_netdev(tp->dev);
diff --git a/target/linux/generic/backport-6.6/780-18-v6.10-r8169-add-support-for-RTL8168M.patch b/target/linux/generic/backport-6.6/780-18-v6.10-r8169-add-support-for-RTL8168M.patch
new file mode 100644 (file)
index 0000000..2abbe2c
--- /dev/null
@@ -0,0 +1,30 @@
+From 39f59c72ad3a1eaab9a60f0671bc94d2bc826d21 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Sun, 7 Apr 2024 23:19:25 +0200
+Subject: [PATCH] r8169: add support for RTL8168M
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+A user reported an unknown chip version. According to the r8168 vendor
+driver it's called RTL8168M, but handling is identical to RTL8168H.
+So let's simply treat it as RTL8168H.
+
+Tested-by: Евгений <octobergun@gmail.com>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2230,6 +2230,8 @@ static enum mac_version rtl8169_get_mac_
+                * the wild. Let's disable detection.
+                * { 0x7cf, 0x540,      RTL_GIGA_MAC_VER_45 },
+                */
++              /* Realtek calls it RTL8168M, but it's handled like RTL8168H */
++              { 0x7cf, 0x6c0, RTL_GIGA_MAC_VER_46 },
+               /* 8168G family. */
+               { 0x7cf, 0x5c8, RTL_GIGA_MAC_VER_44 },
diff --git a/target/linux/generic/backport-6.6/780-19-v6.10-net-annotate-writes-on-dev-mtu-from-ndo_change_mtu.patch b/target/linux/generic/backport-6.6/780-19-v6.10-net-annotate-writes-on-dev-mtu-from-ndo_change_mtu.patch
new file mode 100644 (file)
index 0000000..cad1210
--- /dev/null
@@ -0,0 +1,60 @@
+From 1eb2cded45b35816085c1f962933c187d970f9dc Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Mon, 6 May 2024 10:28:12 +0000
+Subject: [PATCH] net: annotate writes on dev->mtu from ndo_change_mtu()
+
+Simon reported that ndo_change_mtu() methods were never
+updated to use WRITE_ONCE(dev->mtu, new_mtu) as hinted
+in commit 501a90c94510 ("inet: protect against too small
+mtu values.")
+
+We read dev->mtu without holding RTNL in many places,
+with READ_ONCE() annotations.
+
+It is time to take care of ndo_change_mtu() methods
+to use corresponding WRITE_ONCE()
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Simon Horman <horms@kernel.org>
+Closes: https://lore.kernel.org/netdev/20240505144608.GB67882@kernel.org/
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Acked-by: Shannon Nelson <shannon.nelson@amd.com>
+Link: https://lore.kernel.org/r/20240506102812.3025432-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/8139cp.c     | 4 ++--
+ drivers/net/ethernet/realtek/r8169_main.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/8139cp.c
++++ b/drivers/net/ethernet/realtek/8139cp.c
+@@ -1277,14 +1277,14 @@ static int cp_change_mtu(struct net_devi
+       /* if network interface not up, no need for complexity */
+       if (!netif_running(dev)) {
+-              dev->mtu = new_mtu;
++              WRITE_ONCE(dev->mtu, new_mtu);
+               cp_set_rxbufsize(cp);   /* set new rx buf size */
+               return 0;
+       }
+       /* network IS up, close it, reset MTU, and come up again. */
+       cp_close(dev);
+-      dev->mtu = new_mtu;
++      WRITE_ONCE(dev->mtu, new_mtu);
+       cp_set_rxbufsize(cp);
+       return cp_open(dev);
+ }
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -3925,7 +3925,7 @@ static int rtl8169_change_mtu(struct net
+ {
+       struct rtl8169_private *tp = netdev_priv(dev);
+-      dev->mtu = new_mtu;
++      WRITE_ONCE(dev->mtu, new_mtu);
+       netdev_update_features(dev);
+       rtl_jumbo_config(tp);
+       rtl_set_eee_txidle_timer(tp);
diff --git a/target/linux/generic/backport-6.6/780-20-v6.11-r8169-disable-interrupt-source-RxOverflow.patch b/target/linux/generic/backport-6.6/780-20-v6.11-r8169-disable-interrupt-source-RxOverflow.patch
new file mode 100644 (file)
index 0000000..cef5d95
--- /dev/null
@@ -0,0 +1,34 @@
+From 6994520a332887f1688464f250c9ec8002a89a8e Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Mon, 27 May 2024 21:16:56 +0200
+Subject: [PATCH] r8169: disable interrupt source RxOverflow
+
+Vendor driver calls this bit RxDescUnavail. All we do in the interrupt
+handler in this case is scheduling NAPI. If we should be out of
+RX descriptors, then NAPI is scheduled anyway. Therefore remove this
+interrupt source. Tested on RTL8168h.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Sunil Goutham <sgoutham@marvell.com>
+Link: https://lore.kernel.org/r/9b2054b2-0548-4f48-bf91-b646572093b4@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -5083,12 +5083,10 @@ static void rtl_set_irq_mask(struct rtl8
+       tp->irq_mask = RxOK | RxErr | TxOK | TxErr | LinkChg;
+       if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+-              tp->irq_mask |= SYSErr | RxOverflow | RxFIFOOver;
++              tp->irq_mask |= SYSErr | RxFIFOOver;
+       else if (tp->mac_version == RTL_GIGA_MAC_VER_11)
+               /* special workaround needed */
+               tp->irq_mask |= RxFIFOOver;
+-      else
+-              tp->irq_mask |= RxOverflow;
+ }
+ static int rtl_alloc_irq(struct rtl8169_private *tp)
diff --git a/target/linux/generic/backport-6.6/780-21-v6.11-r8169-remove-detection-of-chip-version-11-early-RTL8.patch b/target/linux/generic/backport-6.6/780-21-v6.11-r8169-remove-detection-of-chip-version-11-early-RTL8.patch
new file mode 100644 (file)
index 0000000..7f0f23f
--- /dev/null
@@ -0,0 +1,32 @@
+From 982300c115d229565d7af8e8b38aa1ee7bb1f5bd Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Mon, 27 May 2024 21:20:16 +0200
+Subject: [PATCH] r8169: remove detection of chip version 11 (early
+ RTL8168b)
+
+This early RTL8168b version was the first PCIe chip version, and it's
+quite quirky. Last sign of life is from more than 15 yrs ago.
+Let's remove detection of this chip version, we'll see whether anybody
+complains. If not, support for this chip version can be removed a few
+kernel versions later.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/875cdcf4-843c-420a-ad5d-417447b68572@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2275,7 +2275,9 @@ static enum mac_version rtl8169_get_mac_
+               /* 8168B family. */
+               { 0x7c8, 0x380, RTL_GIGA_MAC_VER_17 },
+-              { 0x7c8, 0x300, RTL_GIGA_MAC_VER_11 },
++              /* This one is very old and rare, let's see if anybody complains.
++               * { 0x7c8, 0x300,      RTL_GIGA_MAC_VER_11 },
++               */
+               /* 8101 family. */
+               { 0x7c8, 0x448, RTL_GIGA_MAC_VER_39 },