generic: 6.1: backport patch adding support for LED PHY
authorChristian Marangi <ansuelsmth@gmail.com>
Wed, 16 Aug 2023 16:51:28 +0000 (18:51 +0200)
committerChristian Marangi <ansuelsmth@gmail.com>
Sat, 19 Aug 2023 10:51:08 +0000 (12:51 +0200)
Backport patch adding support for LED PHY directly in PHY ops struct.
Add new PHYLIB_LEDS config and refresh patches.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
target/linux/generic/backport-6.1/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch [new file with mode: 0644]
target/linux/generic/config-6.1
target/linux/generic/hack-6.1/700-swconfig_switch_drivers.patch

diff --git a/target/linux/generic/backport-6.1/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch b/target/linux/generic/backport-6.1/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch
new file mode 100644 (file)
index 0000000..09a8420
--- /dev/null
@@ -0,0 +1,65 @@
+From 4bb7aac70b5d8a4bddf4ee0791b834f9f56883d2 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Thu, 20 Apr 2023 10:45:51 +0200
+Subject: [PATCH] net: phy: fix circular LEDS_CLASS dependencies
+
+The CONFIG_PHYLIB symbol is selected by a number of device drivers that
+need PHY support, but it now has a dependency on CONFIG_LEDS_CLASS,
+which may not be enabled, causing build failures.
+
+Avoid the risk of missing and circular dependencies by guarding the
+phylib LED support itself in another Kconfig symbol that can only be
+enabled if the dependency is met.
+
+This could be made a hidden symbol and always enabled when both CONFIG_OF
+and CONFIG_LEDS_CLASS are reachable from the phylib, but there may be an
+advantage in having users see this option when they have a misconfigured
+kernel without built-in LED support.
+
+Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://lore.kernel.org/r/20230420084624.3005701-1-arnd@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/Kconfig      | 9 ++++++++-
+ drivers/net/phy/phy_device.c | 3 ++-
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -18,7 +18,6 @@ menuconfig PHYLIB
+       depends on NETDEVICES
+       select MDIO_DEVICE
+       select MDIO_DEVRES
+-      depends on LEDS_CLASS || LEDS_CLASS=n
+       help
+         Ethernet controllers are usually attached to PHY
+         devices.  This option provides infrastructure for
+@@ -45,6 +44,14 @@ config LED_TRIGGER_PHY
+               <Speed in megabits>Mbps OR <Speed in gigabits>Gbps OR link
+               for any speed known to the PHY.
++config PHYLIB_LEDS
++      bool "Support probing LEDs from device tree"
++      depends on LEDS_CLASS=y || LEDS_CLASS=PHYLIB
++      depends on OF
++      default y
++      help
++        When LED class support is enabled, phylib can automatically
++        probe LED setting from device tree.
+ config FIXED_PHY
+       tristate "MDIO Bus/PHY emulation with fixed speed/link PHYs"
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -3208,7 +3208,8 @@ static int phy_probe(struct device *dev)
+       /* Get the LEDs from the device tree, and instantiate standard
+        * LEDs for them.
+        */
+-      err = of_phy_leds(phydev);
++      if (IS_ENABLED(CONFIG_PHYLIB_LEDS))
++              err = of_phy_leds(phydev);
+ out:
+       /* Re-assert the reset signal on error */
diff --git a/target/linux/generic/backport-6.1/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch b/target/linux/generic/backport-6.1/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch
new file mode 100644 (file)
index 0000000..d6081d0
--- /dev/null
@@ -0,0 +1,43 @@
+From aed8fdad2152d946add50bec00a6b07c457bdcdf Mon Sep 17 00:00:00 2001
+From: Alexander Stein <alexander.stein@ew.tq-group.com>
+Date: Mon, 24 Apr 2023 16:16:48 +0200
+Subject: [PATCH] net: phy: Fix reading LED reg property
+
+'reg' is always encoded in 32 bits, thus it has to be read using the
+function with the corresponding bit width.
+
+Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs")
+Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Link: https://lore.kernel.org/r/20230424141648.317944-1-alexander.stein@ew.tq-group.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/phy_device.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -2971,6 +2971,7 @@ static int of_phy_led(struct phy_device
+       struct led_init_data init_data = {};
+       struct led_classdev *cdev;
+       struct phy_led *phyled;
++      u32 index;
+       int err;
+       phyled = devm_kzalloc(dev, sizeof(*phyled), GFP_KERNEL);
+@@ -2980,10 +2981,13 @@ static int of_phy_led(struct phy_device
+       cdev = &phyled->led_cdev;
+       phyled->phydev = phydev;
+-      err = of_property_read_u8(led, "reg", &phyled->index);
++      err = of_property_read_u32(led, "reg", &index);
+       if (err)
+               return err;
++      if (index > U8_MAX)
++              return -EINVAL;
++      phyled->index = index;
+       if (phydev->drv->led_brightness_set)
+               cdev->brightness_set_blocking = phy_led_set_brightness;
+       if (phydev->drv->led_blink_set)
diff --git a/target/linux/generic/backport-6.1/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch b/target/linux/generic/backport-6.1/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch
new file mode 100644 (file)
index 0000000..04939de
--- /dev/null
@@ -0,0 +1,67 @@
+From c938ab4da0eb1620ae3243b0b24c572ddfc318fc Mon Sep 17 00:00:00 2001
+From: Andrew Lunn <andrew@lunn.ch>
+Date: Sat, 17 Jun 2023 17:55:00 +0200
+Subject: [PATCH] net: phy: Manual remove LEDs to ensure correct ordering
+
+If the core is left to remove the LEDs via devm_, it is performed too
+late, after the PHY driver is removed from the PHY. This results in
+dereferencing a NULL pointer when the LED core tries to turn the LED
+off before destroying the LED.
+
+Manually unregister the LEDs at a safe point in phy_remove.
+
+Cc: stable@vger.kernel.org
+Reported-by: Florian Fainelli <f.fainelli@gmail.com>
+Suggested-by: Florian Fainelli <f.fainelli@gmail.com>
+Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs")
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/phy_device.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -2964,6 +2964,15 @@ static int phy_led_blink_set(struct led_
+       return err;
+ }
++static void phy_leds_unregister(struct phy_device *phydev)
++{
++      struct phy_led *phyled;
++
++      list_for_each_entry(phyled, &phydev->leds, list) {
++              led_classdev_unregister(&phyled->led_cdev);
++      }
++}
++
+ static int of_phy_led(struct phy_device *phydev,
+                     struct device_node *led)
+ {
+@@ -2997,7 +3006,7 @@ static int of_phy_led(struct phy_device
+       init_data.fwnode = of_fwnode_handle(led);
+       init_data.devname_mandatory = true;
+-      err = devm_led_classdev_register_ext(dev, cdev, &init_data);
++      err = led_classdev_register_ext(dev, cdev, &init_data);
+       if (err)
+               return err;
+@@ -3026,6 +3035,7 @@ static int of_phy_leds(struct phy_device
+               err = of_phy_led(phydev, led);
+               if (err) {
+                       of_node_put(led);
++                      phy_leds_unregister(phydev);
+                       return err;
+               }
+       }
+@@ -3229,6 +3239,9 @@ static int phy_remove(struct device *dev
+       cancel_delayed_work_sync(&phydev->state_queue);
++      if (IS_ENABLED(CONFIG_PHYLIB_LEDS))
++              phy_leds_unregister(phydev);
++
+       phydev->state = PHY_DOWN;
+       sfp_bus_del_upstream(phydev->sfp_bus);
diff --git a/target/linux/generic/backport-6.1/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch b/target/linux/generic/backport-6.1/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch
new file mode 100644 (file)
index 0000000..609115b
--- /dev/null
@@ -0,0 +1,44 @@
+From af7320ecae0ce646fd2c4a88341a3fbc243553da Mon Sep 17 00:00:00 2001
+From: Yang Li <yang.lee@linux.alibaba.com>
+Date: Thu, 11 May 2023 15:08:20 +0800
+Subject: [PATCH] leds: trigger: netdev: Remove NULL check before dev_{put,
+ hold}
+
+The call netdev_{put, hold} of dev_{put, hold} will check NULL,
+so there is no need to check before using dev_{put, hold},
+remove it to silence the warnings:
+
+./drivers/leds/trigger/ledtrig-netdev.c:291:3-10: WARNING: NULL check before dev_{put, hold} functions is not needed.
+./drivers/leds/trigger/ledtrig-netdev.c:401:2-9: WARNING: NULL check before dev_{put, hold} functions is not needed.
+
+Reported-by: Abaci Robot <abaci@linux.alibaba.com>
+Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=4929
+Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
+Link: https://lore.kernel.org/r/20230511070820.52731-1-yang.lee@linux.alibaba.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+---
+ drivers/leds/trigger/ledtrig-netdev.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/drivers/leds/trigger/ledtrig-netdev.c
++++ b/drivers/leds/trigger/ledtrig-netdev.c
+@@ -462,8 +462,7 @@ static int netdev_trig_notify(struct not
+               get_device_state(trigger_data);
+               fallthrough;
+       case NETDEV_REGISTER:
+-              if (trigger_data->net_dev)
+-                      dev_put(trigger_data->net_dev);
++              dev_put(trigger_data->net_dev);
+               dev_hold(dev);
+               trigger_data->net_dev = dev;
+               break;
+@@ -594,8 +593,7 @@ static void netdev_trig_deactivate(struc
+       cancel_delayed_work_sync(&trigger_data->work);
+-      if (trigger_data->net_dev)
+-              dev_put(trigger_data->net_dev);
++      dev_put(trigger_data->net_dev);
+       kfree(trigger_data);
+ }
diff --git a/target/linux/generic/backport-6.1/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch b/target/linux/generic/backport-6.1/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch
new file mode 100644 (file)
index 0000000..2f7a6ce
--- /dev/null
@@ -0,0 +1,31 @@
+From 97c5209b3d374a25ebdb4c2ea9e9c1b121768da0 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@linaro.org>
+Date: Wed, 14 Jun 2023 10:03:59 +0300
+Subject: [PATCH] leds: trigger: netdev: uninitialized variable in
+ netdev_trig_activate()
+
+The qca8k_cled_hw_control_get() function which implements ->hw_control_get
+sets the appropriate bits but does not clear them.  This leads to an
+uninitialized variable bug.  Fix this by setting mode to zero at the
+start.
+
+Fixes: e0256648c831 ("net: dsa: qca8k: implement hw_control ops")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Acked-by: Lee Jones <lee@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/leds/trigger/ledtrig-netdev.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/leds/trigger/ledtrig-netdev.c
++++ b/drivers/leds/trigger/ledtrig-netdev.c
+@@ -538,7 +538,7 @@ static void netdev_trig_work(struct work
+ static int netdev_trig_activate(struct led_classdev *led_cdev)
+ {
+       struct led_netdev_data *trigger_data;
+-      unsigned long mode;
++      unsigned long mode = 0;
+       struct device *dev;
+       int rc;
diff --git a/target/linux/generic/backport-6.1/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch b/target/linux/generic/backport-6.1/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch
new file mode 100644 (file)
index 0000000..dedf84c
--- /dev/null
@@ -0,0 +1,57 @@
+From 7df1f14c04cbb1950e79c19793420f87227c3e80 Mon Sep 17 00:00:00 2001
+From: Andrew Lunn <andrew@lunn.ch>
+Date: Tue, 8 Aug 2023 23:04:33 +0200
+Subject: [PATCH 1/4] led: trig: netdev: Fix requesting offload device
+
+When the netdev trigger is activates, it tries to determine what
+device the LED blinks for, and what the current blink mode is.
+
+The documentation for hw_control_get() says:
+
+        * Return 0 on success, a negative error number on failing parsing the
+        * initial mode. Error from this function is NOT FATAL as the device
+        * may be in a not supported initial state by the attached LED trigger.
+        */
+
+For the Marvell PHY and the Armada 370-rd board, the initial LED blink
+mode is not supported by the trigger, so it returns an error. This
+resulted in not getting the device the LED is blinking for. As a
+result, the device is unknown and offloaded is never performed.
+
+Change to condition to always get the device if offloading is
+supported, and reduce the scope of testing for an error from
+hw_control_get() to skip setting trigger internal state if there is an
+error.
+
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://lore.kernel.org/r/20230808210436.838995-2-andrew@lunn.ch
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/leds/trigger/ledtrig-netdev.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/leds/trigger/ledtrig-netdev.c
++++ b/drivers/leds/trigger/ledtrig-netdev.c
+@@ -564,15 +564,17 @@ static int netdev_trig_activate(struct l
+       /* Check if hw control is active by default on the LED.
+        * Init already enabled mode in hw control.
+        */
+-      if (supports_hw_control(led_cdev) &&
+-          !led_cdev->hw_control_get(led_cdev, &mode)) {
++      if (supports_hw_control(led_cdev)) {
+               dev = led_cdev->hw_control_get_device(led_cdev);
+               if (dev) {
+                       const char *name = dev_name(dev);
+                       set_device_name(trigger_data, name, strlen(name));
+                       trigger_data->hw_control = true;
+-                      trigger_data->mode = mode;
++
++                      rc = led_cdev->hw_control_get(led_cdev, &mode);
++                      if (!rc)
++                              trigger_data->mode = mode;
+               }
+       }
diff --git a/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch
new file mode 100644 (file)
index 0000000..6cd798f
--- /dev/null
@@ -0,0 +1,149 @@
+From 1dcc03c9a7a824a31eaaecdfaa03542fb25feb6c Mon Sep 17 00:00:00 2001
+From: Andrew Lunn <andrew@lunn.ch>
+Date: Tue, 8 Aug 2023 23:04:34 +0200
+Subject: [PATCH 2/4] net: phy: phy_device: Call into the PHY driver to set LED
+ offload
+
+Linux LEDs can be requested to perform hardware accelerated blinking
+to indicate link, RX, TX etc. Pass the rules for blinking to the PHY
+driver, if it implements the ops needed to determine if a given
+pattern can be offloaded, to offload it, and what the current offload
+is. Additionally implement the op needed to get what device the LED is
+for.
+
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://lore.kernel.org/r/20230808210436.838995-3-andrew@lunn.ch
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/phy_device.c | 68 ++++++++++++++++++++++++++++++++++++
+ include/linux/phy.h          | 33 +++++++++++++++++
+ 2 files changed, 101 insertions(+)
+
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -2964,6 +2964,61 @@ static int phy_led_blink_set(struct led_
+       return err;
+ }
++static __maybe_unused struct device *
++phy_led_hw_control_get_device(struct led_classdev *led_cdev)
++{
++      struct phy_led *phyled = to_phy_led(led_cdev);
++      struct phy_device *phydev = phyled->phydev;
++
++      if (phydev->attached_dev)
++              return &phydev->attached_dev->dev;
++      return NULL;
++}
++
++static int __maybe_unused
++phy_led_hw_control_get(struct led_classdev *led_cdev,
++                     unsigned long *rules)
++{
++      struct phy_led *phyled = to_phy_led(led_cdev);
++      struct phy_device *phydev = phyled->phydev;
++      int err;
++
++      mutex_lock(&phydev->lock);
++      err = phydev->drv->led_hw_control_get(phydev, phyled->index, rules);
++      mutex_unlock(&phydev->lock);
++
++      return err;
++}
++
++static int __maybe_unused
++phy_led_hw_control_set(struct led_classdev *led_cdev,
++                     unsigned long rules)
++{
++      struct phy_led *phyled = to_phy_led(led_cdev);
++      struct phy_device *phydev = phyled->phydev;
++      int err;
++
++      mutex_lock(&phydev->lock);
++      err = phydev->drv->led_hw_control_set(phydev, phyled->index, rules);
++      mutex_unlock(&phydev->lock);
++
++      return err;
++}
++
++static __maybe_unused int phy_led_hw_is_supported(struct led_classdev *led_cdev,
++                                                unsigned long rules)
++{
++      struct phy_led *phyled = to_phy_led(led_cdev);
++      struct phy_device *phydev = phyled->phydev;
++      int err;
++
++      mutex_lock(&phydev->lock);
++      err = phydev->drv->led_hw_is_supported(phydev, phyled->index, rules);
++      mutex_unlock(&phydev->lock);
++
++      return err;
++}
++
+ static void phy_leds_unregister(struct phy_device *phydev)
+ {
+       struct phy_led *phyled;
+@@ -3001,6 +3056,19 @@ static int of_phy_led(struct phy_device
+               cdev->brightness_set_blocking = phy_led_set_brightness;
+       if (phydev->drv->led_blink_set)
+               cdev->blink_set = phy_led_blink_set;
++
++#ifdef CONFIG_LEDS_TRIGGERS
++      if (phydev->drv->led_hw_is_supported &&
++          phydev->drv->led_hw_control_set &&
++          phydev->drv->led_hw_control_get) {
++              cdev->hw_control_is_supported = phy_led_hw_is_supported;
++              cdev->hw_control_set = phy_led_hw_control_set;
++              cdev->hw_control_get = phy_led_hw_control_get;
++              cdev->hw_control_trigger = "netdev";
++      }
++
++      cdev->hw_control_get_device = phy_led_hw_control_get_device;
++#endif
+       cdev->max_brightness = 1;
+       init_data.devicename = dev_name(&phydev->mdio.dev);
+       init_data.fwnode = of_fwnode_handle(led);
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -1013,6 +1013,39 @@ struct phy_driver {
+       int (*led_blink_set)(struct phy_device *dev, u8 index,
+                            unsigned long *delay_on,
+                            unsigned long *delay_off);
++      /**
++       * @led_hw_is_supported: Can the HW support the given rules.
++       * @dev: PHY device which has the LED
++       * @index: Which LED of the PHY device
++       * @rules The core is interested in these rules
++       *
++       * Return 0 if yes,  -EOPNOTSUPP if not, or an error code.
++       */
++      int (*led_hw_is_supported)(struct phy_device *dev, u8 index,
++                                 unsigned long rules);
++      /**
++       * @led_hw_control_set: Set the HW to control the LED
++       * @dev: PHY device which has the LED
++       * @index: Which LED of the PHY device
++       * @rules The rules used to control the LED
++       *
++       * Returns 0, or a an error code.
++       */
++      int (*led_hw_control_set)(struct phy_device *dev, u8 index,
++                                unsigned long rules);
++      /**
++       * @led_hw_control_get: Get how the HW is controlling the LED
++       * @dev: PHY device which has the LED
++       * @index: Which LED of the PHY device
++       * @rules Pointer to the rules used to control the LED
++       *
++       * Set *@rules to how the HW is currently blinking. Returns 0
++       * on success, or a error code if the current blinking cannot
++       * be represented in rules, or some other error happens.
++       */
++      int (*led_hw_control_get)(struct phy_device *dev, u8 index,
++                                unsigned long *rules);
++
+ };
+ #define to_phy_driver(d) container_of(to_mdio_common_driver(d),               \
+                                     struct phy_driver, mdiodrv)
diff --git a/target/linux/generic/backport-6.1/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch b/target/linux/generic/backport-6.1/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch
new file mode 100644 (file)
index 0000000..1300583
--- /dev/null
@@ -0,0 +1,344 @@
+From 460b0b648fab24f576c481424e0de5479ffb9786 Mon Sep 17 00:00:00 2001
+From: Andrew Lunn <andrew@lunn.ch>
+Date: Tue, 8 Aug 2023 23:04:35 +0200
+Subject: [PATCH 3/4] net: phy: marvell: Add support for offloading LED
+ blinking
+
+Add the code needed to indicate if a given blinking pattern can be
+offloaded, to offload a pattern and to try to return the current
+pattern.
+
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://lore.kernel.org/r/20230808210436.838995-4-andrew@lunn.ch
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/marvell.c | 281 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 281 insertions(+)
+
+--- a/drivers/net/phy/marvell.c
++++ b/drivers/net/phy/marvell.c
+@@ -2893,6 +2893,272 @@ static int m88e1318_led_blink_set(struct
+                              MII_88E1318S_PHY_LED_FUNC, reg);
+ }
++struct marvell_led_rules {
++      int mode;
++      unsigned long rules;
++};
++
++static const struct marvell_led_rules marvell_led0[] = {
++      {
++              .mode = 0,
++              .rules = BIT(TRIGGER_NETDEV_LINK),
++      },
++      {
++              .mode = 1,
++              .rules = (BIT(TRIGGER_NETDEV_LINK) |
++                        BIT(TRIGGER_NETDEV_RX) |
++                        BIT(TRIGGER_NETDEV_TX)),
++      },
++      {
++              .mode = 3,
++              .rules = (BIT(TRIGGER_NETDEV_RX) |
++                        BIT(TRIGGER_NETDEV_TX)),
++      },
++      {
++              .mode = 4,
++              .rules = (BIT(TRIGGER_NETDEV_RX) |
++                        BIT(TRIGGER_NETDEV_TX)),
++      },
++      {
++              .mode = 5,
++              .rules = BIT(TRIGGER_NETDEV_TX),
++      },
++      {
++              .mode = 6,
++              .rules = BIT(TRIGGER_NETDEV_LINK),
++      },
++      {
++              .mode = 7,
++              .rules = BIT(TRIGGER_NETDEV_LINK_1000),
++      },
++      {
++              .mode = 8,
++              .rules = 0,
++      },
++};
++
++static const struct marvell_led_rules marvell_led1[] = {
++      {
++              .mode = 1,
++              .rules = (BIT(TRIGGER_NETDEV_LINK) |
++                        BIT(TRIGGER_NETDEV_RX) |
++                        BIT(TRIGGER_NETDEV_TX)),
++      },
++      {
++              .mode = 2,
++              .rules = (BIT(TRIGGER_NETDEV_LINK) |
++                        BIT(TRIGGER_NETDEV_RX)),
++      },
++      {
++              .mode = 3,
++              .rules = (BIT(TRIGGER_NETDEV_RX) |
++                        BIT(TRIGGER_NETDEV_TX)),
++      },
++      {
++              .mode = 4,
++              .rules = (BIT(TRIGGER_NETDEV_RX) |
++                        BIT(TRIGGER_NETDEV_TX)),
++      },
++      {
++              .mode = 6,
++              .rules = (BIT(TRIGGER_NETDEV_LINK_100) |
++                        BIT(TRIGGER_NETDEV_LINK_1000)),
++      },
++      {
++              .mode = 7,
++              .rules = BIT(TRIGGER_NETDEV_LINK_100),
++      },
++      {
++              .mode = 8,
++              .rules = 0,
++      },
++};
++
++static const struct marvell_led_rules marvell_led2[] = {
++      {
++              .mode = 0,
++              .rules = BIT(TRIGGER_NETDEV_LINK),
++      },
++      {
++              .mode = 1,
++              .rules = (BIT(TRIGGER_NETDEV_LINK) |
++                        BIT(TRIGGER_NETDEV_RX) |
++                        BIT(TRIGGER_NETDEV_TX)),
++      },
++      {
++              .mode = 3,
++              .rules = (BIT(TRIGGER_NETDEV_RX) |
++                        BIT(TRIGGER_NETDEV_TX)),
++      },
++      {
++              .mode = 4,
++              .rules = (BIT(TRIGGER_NETDEV_RX) |
++                        BIT(TRIGGER_NETDEV_TX)),
++      },
++      {
++              .mode = 5,
++              .rules = BIT(TRIGGER_NETDEV_TX),
++      },
++      {
++              .mode = 6,
++              .rules = (BIT(TRIGGER_NETDEV_LINK_10) |
++                        BIT(TRIGGER_NETDEV_LINK_1000)),
++      },
++      {
++              .mode = 7,
++              .rules = BIT(TRIGGER_NETDEV_LINK_10),
++      },
++      {
++              .mode = 8,
++              .rules = 0,
++      },
++};
++
++static int marvell_find_led_mode(unsigned long rules,
++                               const struct marvell_led_rules *marvell_rules,
++                               int count,
++                               int *mode)
++{
++      int i;
++
++      for (i = 0; i < count; i++) {
++              if (marvell_rules[i].rules == rules) {
++                      *mode = marvell_rules[i].mode;
++                      return 0;
++              }
++      }
++      return -EOPNOTSUPP;
++}
++
++static int marvell_get_led_mode(u8 index, unsigned long rules, int *mode)
++{
++      int ret;
++
++      switch (index) {
++      case 0:
++              ret = marvell_find_led_mode(rules, marvell_led0,
++                                          ARRAY_SIZE(marvell_led0), mode);
++              break;
++      case 1:
++              ret = marvell_find_led_mode(rules, marvell_led1,
++                                          ARRAY_SIZE(marvell_led1), mode);
++              break;
++      case 2:
++              ret = marvell_find_led_mode(rules, marvell_led2,
++                                          ARRAY_SIZE(marvell_led2), mode);
++              break;
++      default:
++              ret = -EINVAL;
++      }
++
++      return ret;
++}
++
++static int marvell_find_led_rules(unsigned long *rules,
++                                const struct marvell_led_rules *marvell_rules,
++                                int count,
++                                int mode)
++{
++      int i;
++
++      for (i = 0; i < count; i++) {
++              if (marvell_rules[i].mode == mode) {
++                      *rules = marvell_rules[i].rules;
++                      return 0;
++              }
++      }
++      return -EOPNOTSUPP;
++}
++
++static int marvell_get_led_rules(u8 index, unsigned long *rules, int mode)
++{
++      int ret;
++
++      switch (index) {
++      case 0:
++              ret = marvell_find_led_rules(rules, marvell_led0,
++                                           ARRAY_SIZE(marvell_led0), mode);
++              break;
++      case 1:
++              ret = marvell_find_led_rules(rules, marvell_led1,
++                                           ARRAY_SIZE(marvell_led1), mode);
++              break;
++      case 2:
++              ret = marvell_find_led_rules(rules, marvell_led2,
++                                           ARRAY_SIZE(marvell_led2), mode);
++              break;
++      default:
++              ret = -EOPNOTSUPP;
++      }
++
++      return ret;
++}
++
++static int m88e1318_led_hw_is_supported(struct phy_device *phydev, u8 index,
++                                      unsigned long rules)
++{
++      int mode, ret;
++
++      switch (index) {
++      case 0:
++      case 1:
++      case 2:
++              ret = marvell_get_led_mode(index, rules, &mode);
++              break;
++      default:
++              ret = -EINVAL;
++      }
++
++      return ret;
++}
++
++static int m88e1318_led_hw_control_set(struct phy_device *phydev, u8 index,
++                                     unsigned long rules)
++{
++      int mode, ret, reg;
++
++      switch (index) {
++      case 0:
++      case 1:
++      case 2:
++              ret = marvell_get_led_mode(index, rules, &mode);
++              break;
++      default:
++              ret = -EINVAL;
++      }
++
++      if (ret < 0)
++              return ret;
++
++      reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE,
++                           MII_88E1318S_PHY_LED_FUNC);
++      if (reg < 0)
++              return reg;
++
++      reg &= ~(0xf << (4 * index));
++      reg |= mode << (4 * index);
++      return phy_write_paged(phydev, MII_MARVELL_LED_PAGE,
++                             MII_88E1318S_PHY_LED_FUNC, reg);
++}
++
++static int m88e1318_led_hw_control_get(struct phy_device *phydev, u8 index,
++                                     unsigned long *rules)
++{
++      int mode, reg;
++
++      if (index > 2)
++              return -EINVAL;
++
++      reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE,
++                           MII_88E1318S_PHY_LED_FUNC);
++      if (reg < 0)
++              return reg;
++
++      mode = (reg >> (4 * index)) & 0xf;
++
++      return marvell_get_led_rules(index, rules, mode);
++}
++
+ static int marvell_probe(struct phy_device *phydev)
+ {
+       struct marvell_priv *priv;
+@@ -3144,6 +3410,9 @@ static struct phy_driver marvell_drivers
+               .get_stats = marvell_get_stats,
+               .led_brightness_set = m88e1318_led_brightness_set,
+               .led_blink_set = m88e1318_led_blink_set,
++              .led_hw_is_supported = m88e1318_led_hw_is_supported,
++              .led_hw_control_set = m88e1318_led_hw_control_set,
++              .led_hw_control_get = m88e1318_led_hw_control_get,
+       },
+       {
+               .phy_id = MARVELL_PHY_ID_88E1145,
+@@ -3252,6 +3521,9 @@ static struct phy_driver marvell_drivers
+               .cable_test_get_status = marvell_vct7_cable_test_get_status,
+               .led_brightness_set = m88e1318_led_brightness_set,
+               .led_blink_set = m88e1318_led_blink_set,
++              .led_hw_is_supported = m88e1318_led_hw_is_supported,
++              .led_hw_control_set = m88e1318_led_hw_control_set,
++              .led_hw_control_get = m88e1318_led_hw_control_get,
+       },
+       {
+               .phy_id = MARVELL_PHY_ID_88E1540,
+@@ -3280,6 +3552,9 @@ static struct phy_driver marvell_drivers
+               .cable_test_get_status = marvell_vct7_cable_test_get_status,
+               .led_brightness_set = m88e1318_led_brightness_set,
+               .led_blink_set = m88e1318_led_blink_set,
++              .led_hw_is_supported = m88e1318_led_hw_is_supported,
++              .led_hw_control_set = m88e1318_led_hw_control_set,
++              .led_hw_control_get = m88e1318_led_hw_control_get,
+       },
+       {
+               .phy_id = MARVELL_PHY_ID_88E1545,
+@@ -3308,6 +3583,9 @@ static struct phy_driver marvell_drivers
+               .cable_test_get_status = marvell_vct7_cable_test_get_status,
+               .led_brightness_set = m88e1318_led_brightness_set,
+               .led_blink_set = m88e1318_led_blink_set,
++              .led_hw_is_supported = m88e1318_led_hw_is_supported,
++              .led_hw_control_set = m88e1318_led_hw_control_set,
++              .led_hw_control_get = m88e1318_led_hw_control_get,
+       },
+       {
+               .phy_id = MARVELL_PHY_ID_88E3016,
+@@ -3451,6 +3729,9 @@ static struct phy_driver marvell_drivers
+               .set_tunable = m88e1540_set_tunable,
+               .led_brightness_set = m88e1318_led_brightness_set,
+               .led_blink_set = m88e1318_led_blink_set,
++              .led_hw_is_supported = m88e1318_led_hw_is_supported,
++              .led_hw_control_set = m88e1318_led_hw_control_set,
++              .led_hw_control_get = m88e1318_led_hw_control_get,
+       },
+ };
diff --git a/target/linux/generic/backport-6.1/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch b/target/linux/generic/backport-6.1/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch
new file mode 100644 (file)
index 0000000..d6a69aa
--- /dev/null
@@ -0,0 +1,31 @@
+From e8fbcc47a8e935f36f044d85f21a99acecbd7bfb Mon Sep 17 00:00:00 2001
+From: Andrew Lunn <andrew@lunn.ch>
+Date: Tue, 8 Aug 2023 23:04:36 +0200
+Subject: [PATCH 4/4] leds: trig-netdev: Disable offload on deactivation of
+ trigger
+
+Ensure that the offloading of blinking is stopped when the trigger is
+deactivated. Calling led_set_brightness() is documented as stopping
+offload and setting the LED to a constant brightness.
+
+Suggested-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Tested-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://lore.kernel.org/r/20230808210436.838995-5-andrew@lunn.ch
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/leds/trigger/ledtrig-netdev.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/leds/trigger/ledtrig-netdev.c
++++ b/drivers/leds/trigger/ledtrig-netdev.c
+@@ -595,6 +595,8 @@ static void netdev_trig_deactivate(struc
+       cancel_delayed_work_sync(&trigger_data->work);
++      led_set_brightness(led_cdev, LED_OFF);
++
+       dev_put(trigger_data->net_dev);
+       kfree(trigger_data);
index 52a283237f0d9af4e4e094596ca5fd2b6d1711ab..29aa7292b80eadbf52ed0501479549007a691481 100644 (file)
@@ -4831,6 +4831,7 @@ CONFIG_PCI_SYSCALL=y
 # CONFIG_PHANTOM is not set
 # CONFIG_PHONET is not set
 # CONFIG_PHYLIB is not set
+# CONFIG_PHYLIB_LEDS is not set
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 # CONFIG_PHY_CADENCE_DP is not set
 # CONFIG_PHY_CADENCE_DPHY is not set
index 9d77efaca6ef99b9f4775f837b386cd52731ffae..5f49678a34b9795e8e59630f1633238feb1c0599 100644 (file)
@@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
-@@ -62,6 +62,80 @@ config SFP
+@@ -69,6 +69,80 @@ config SFP
        depends on HWMON || HWMON=n
        select MDIO_I2C