lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250716100041.2833168-3-shaojijie@huawei.com>
Date: Wed, 16 Jul 2025 18:00:41 +0800
From: Jijie Shao <shaojijie@...wei.com>
To: <davem@...emloft.net>, <edumazet@...gle.com>, <kuba@...nel.org>,
	<pabeni@...hat.com>, <andrew+netdev@...n.ch>, <horms@...nel.org>,
	<Frank.Sae@...or-comm.com>, <hkallweit1@...il.com>, <linux@...linux.org.uk>
CC: <shenjian15@...wei.com>, <liuyonglong@...wei.com>,
	<chenhao418@...wei.com>, <jonathan.cameron@...wei.com>,
	<shameerali.kolothum.thodi@...wei.com>, <salil.mehta@...wei.com>,
	<netdev@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
	<shaojijie@...wei.com>
Subject: [PATCH net-next 2/2] net: hibmcge: Add support for PHY LEDs on YT8521

hibmcge is a PCIE EP device, and its controller is
not on the board. And board uses ACPI not DTS
to create the device tree.

So, this makes it impossible to add a "reg" property(used in of_phy_led())
for hibmcge. Therefore, the PHY_LED framework cannot be used directly.

This patch creates a separate LED device for hibmcge
and directly calls the phy->drv->led_hw**() function to
operate the related LEDs.

Signed-off-by: Jijie Shao <shaojijie@...wei.com>
---
 drivers/net/ethernet/hisilicon/Kconfig        |   8 ++
 .../net/ethernet/hisilicon/hibmcge/Makefile   |   1 +
 .../net/ethernet/hisilicon/hibmcge/hbg_led.c  | 132 ++++++++++++++++++
 .../net/ethernet/hisilicon/hibmcge/hbg_led.h  |  17 +++
 .../net/ethernet/hisilicon/hibmcge/hbg_main.c |   7 +
 5 files changed, 165 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hibmcge/hbg_led.c
 create mode 100644 drivers/net/ethernet/hisilicon/hibmcge/hbg_led.h

diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig
index 65302c41bfb1..143b25f329c7 100644
--- a/drivers/net/ethernet/hisilicon/Kconfig
+++ b/drivers/net/ethernet/hisilicon/Kconfig
@@ -157,4 +157,12 @@ config HIBMCGE
 
 	  If you are unsure, say N.
 
+config HIBMCGE_LEDS
+	def_bool LEDS_TRIGGER_NETDEV
+	depends on HIBMCGE && LEDS_CLASS
+	depends on LEDS_CLASS=y || HIBMCGE=m
+	help
+	  Optional support for controlling the NIC LED's with the netdev
+	  LED trigger.
+
 endif # NET_VENDOR_HISILICON
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/Makefile b/drivers/net/ethernet/hisilicon/hibmcge/Makefile
index 1a9da564b306..a78057208064 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/Makefile
+++ b/drivers/net/ethernet/hisilicon/hibmcge/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_HIBMCGE) += hibmcge.o
 
 hibmcge-objs = hbg_main.o hbg_hw.o hbg_mdio.o hbg_irq.o hbg_txrx.o hbg_ethtool.o \
 		hbg_debugfs.o hbg_err.o hbg_diagnose.o
+hibmcge-$(CONFIG_HIBMCGE_LEDS) += hbg_led.o
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_led.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_led.c
new file mode 100644
index 000000000000..013eae1c54f2
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_led.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2025 Hisilicon Limited.
+
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+#include <linux/phy.h>
+#include "hbg_common.h"
+#include "hbg_led.h"
+
+#define PHY_ID_YT8521		0x0000011a
+
+#define to_hbg_led(lcdev) container_of(lcdev, struct hbg_led_classdev, led)
+#define to_hbg_phy_dev(lcdev) \
+	(((struct hbg_led_classdev *)to_hbg_led(lcdev))->priv->mac.phydev)
+
+static int hbg_led_hw_control_set(struct led_classdev *led_cdev,
+				  unsigned long rules)
+{
+	struct hbg_led_classdev *hbg_led = to_hbg_led(led_cdev);
+	struct phy_device *phydev = to_hbg_phy_dev(led_cdev);
+	int ret;
+
+	mutex_lock(&phydev->lock);
+	ret = phydev->drv->led_hw_control_set(phydev, hbg_led->index, rules);
+	mutex_unlock(&phydev->lock);
+
+	return ret;
+}
+
+static int hbg_led_hw_control_get(struct led_classdev *led_cdev,
+				  unsigned long *rules)
+{
+	struct hbg_led_classdev *hbg_led = to_hbg_led(led_cdev);
+	struct phy_device *phydev = to_hbg_phy_dev(led_cdev);
+	int ret;
+
+	mutex_lock(&phydev->lock);
+	ret = phydev->drv->led_hw_control_get(phydev, hbg_led->index, rules);
+	mutex_unlock(&phydev->lock);
+
+	return ret;
+}
+
+static int hbg_led_hw_is_supported(struct led_classdev *led_cdev,
+				   unsigned long rules)
+{
+	struct hbg_led_classdev *hbg_led = to_hbg_led(led_cdev);
+	struct phy_device *phydev = to_hbg_phy_dev(led_cdev);
+	int ret;
+
+	mutex_lock(&phydev->lock);
+	ret = phydev->drv->led_hw_is_supported(phydev, hbg_led->index, rules);
+	mutex_unlock(&phydev->lock);
+
+	return ret;
+}
+
+static struct device *
+	hbg_led_hw_control_get_device(struct led_classdev *led_cdev)
+{
+	struct hbg_led_classdev *hbg_led = to_hbg_led(led_cdev);
+
+	return &hbg_led->priv->netdev->dev;
+}
+
+static int hbg_setup_ldev(struct hbg_led_classdev *hbg_led)
+{
+	struct led_classdev *ldev = &hbg_led->led;
+	struct hbg_priv *priv = hbg_led->priv;
+	struct device *dev = &priv->pdev->dev;
+
+	ldev->name = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%d",
+				    dev_driver_string(dev),
+				    pci_name(priv->pdev), hbg_led->index);
+	if (!ldev->name)
+		return -ENOMEM;
+
+	ldev->hw_control_trigger = "netdev";
+	ldev->hw_control_set = hbg_led_hw_control_set;
+	ldev->hw_control_get = hbg_led_hw_control_get;
+	ldev->hw_control_is_supported = hbg_led_hw_is_supported;
+	ldev->hw_control_get_device = hbg_led_hw_control_get_device;
+
+	return devm_led_classdev_register(dev, ldev);
+}
+
+static u32 hbg_get_phy_max_led_count(struct hbg_priv *priv)
+{
+	struct phy_device *phydev = priv->mac.phydev;
+
+	if (!phydev->drv->led_hw_is_supported ||
+	    !phydev->drv->led_hw_control_set ||
+	    !phydev->drv->led_hw_control_get)
+		return 0;
+
+	/* YT8521, support 3 leds */
+	if (phydev->drv->phy_id == PHY_ID_YT8521)
+		return 3;
+
+	return 0;
+}
+
+int hbg_leds_init(struct hbg_priv *priv)
+{
+	u32 led_count = hbg_get_phy_max_led_count(priv);
+	struct phy_device *phydev = priv->mac.phydev;
+	struct hbg_led_classdev *leds;
+	int ret;
+	int i;
+
+	if (!led_count)
+		return 0;
+
+	leds = devm_kcalloc(&priv->pdev->dev, led_count,
+			    sizeof(*leds), GFP_KERNEL);
+	if (!leds)
+		return -ENOMEM;
+
+	for (i = 0; i < led_count; i++) {
+		/* for YT8521, we only have two lights, 0 and 2. */
+		if (phydev->drv->phy_id == PHY_ID_YT8521 && i == 1)
+			continue;
+
+		leds[i].priv = priv;
+		leds[i].index = i;
+		ret = hbg_setup_ldev(&leds[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_led.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_led.h
new file mode 100644
index 000000000000..463285077c91
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_led.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2025 Hisilicon Limited. */
+
+#ifndef __HBG_LED_H
+#define __HBG_LED_H
+
+#include "hbg_common.h"
+
+struct hbg_led_classdev {
+	struct hbg_priv *priv;
+	struct led_classdev led;
+	u32 index;
+};
+
+int hbg_leds_init(struct hbg_priv *priv);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
index 2e64dc1ab355..f2f8f651f3d2 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
@@ -12,6 +12,7 @@
 #include "hbg_ethtool.h"
 #include "hbg_hw.h"
 #include "hbg_irq.h"
+#include "hbg_led.h"
 #include "hbg_mdio.h"
 #include "hbg_txrx.h"
 #include "hbg_debugfs.h"
@@ -383,6 +384,12 @@ static int hbg_init(struct hbg_priv *priv)
 	if (ret)
 		return ret;
 
+	if (IS_ENABLED(CONFIG_HIBMCGE_LEDS)) {
+		ret = hbg_leds_init(priv);
+		if (ret)
+			return ret;
+	}
+
 	ret = hbg_mac_filter_init(priv);
 	if (ret)
 		return ret;
-- 
2.33.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ