* [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part
@ 2026-03-09 17:01 Heiner Kallweit
2026-03-09 17:02 ` [PATCH v2 net-next 1/5] net: phy: move mdio_device reset handling functions in the code Heiner Kallweit
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Heiner Kallweit @ 2026-03-09 17:01 UTC (permalink / raw)
To: Andrew Lunn, Russell King - ARM Linux, Paolo Abeni,
Jakub Kicinski, David Miller, Eric Dumazet, Bjorn Andersson,
Michael Turquette, Stephen Boyd, Vinod Koul, Neil Armstrong
Cc: netdev@vger.kernel.org, Philipp Zabel, linux-arm-msm, linux-clk,
linux-phy
This series aims at further decoupling the provider and consumer part
in phylib.
v2:
- patch 2: add needed Kconfig dependency changes
- patch 5: explain false positive checkpatch error
Heiner Kallweit (5):
net: phy: move mdio_device reset handling functions in the code
net: phy: make mdio_device.c part of libphy
net: phy: move (of_)mdio_find_bus to mdio_bus_provider.c
net: phy: move registering mdio_bus_class and mdio_bus_type to libphy
net: phy: move remaining provider code to mdio_bus_provider.c
drivers/clk/qcom/Kconfig | 2 +-
drivers/net/phy/Makefile | 6 +-
drivers/net/phy/mdio-private.h | 11 -
drivers/net/phy/mdio_bus.c | 385 ----------------------------
drivers/net/phy/mdio_bus_provider.c | 319 +++++++++++++++++++++++
drivers/net/phy/mdio_device.c | 165 +++++++-----
drivers/net/phy/phy_device.c | 13 +
drivers/net/phy/phylib-internal.h | 7 +
drivers/phy/broadcom/Kconfig | 4 +-
include/linux/mdio.h | 2 -
include/linux/phy.h | 3 -
11 files changed, 444 insertions(+), 473 deletions(-)
delete mode 100644 drivers/net/phy/mdio-private.h
--
2.53.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 net-next 1/5] net: phy: move mdio_device reset handling functions in the code
2026-03-09 17:01 [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part Heiner Kallweit
@ 2026-03-09 17:02 ` Heiner Kallweit
2026-03-09 17:03 ` [PATCH v2 net-next 2/5] net: phy: make mdio_device.c part of libphy Heiner Kallweit
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2026-03-09 17:02 UTC (permalink / raw)
To: Andrew Lunn, Russell King - ARM Linux, Paolo Abeni,
Jakub Kicinski, David Miller, Eric Dumazet, Bjorn Andersson,
Michael Turquette, Stephen Boyd, Vinod Koul, Neil Armstrong
Cc: netdev@vger.kernel.org, Philipp Zabel, linux-arm-msm, linux-clk,
linux-phy
In preparation of a follow-up patch this moves reset-related functions
in the code.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
drivers/net/phy/mdio_device.c | 162 +++++++++++++++++-----------------
1 file changed, 81 insertions(+), 81 deletions(-)
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index b8a5a183819..da4fb7484c7 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -24,6 +24,87 @@
#include <linux/property.h>
#include "mdio-private.h"
+/**
+ * mdio_device_register_reset - Read and initialize the reset properties of
+ * an mdio device
+ * @mdiodev: mdio_device structure
+ *
+ * Return: Zero if successful, negative error code on failure
+ */
+int mdio_device_register_reset(struct mdio_device *mdiodev)
+{
+ struct reset_control *reset;
+
+ /* Deassert the optional reset signal */
+ mdiodev->reset_gpio = gpiod_get_optional(&mdiodev->dev,
+ "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(mdiodev->reset_gpio))
+ return PTR_ERR(mdiodev->reset_gpio);
+
+ if (mdiodev->reset_gpio)
+ gpiod_set_consumer_name(mdiodev->reset_gpio, "PHY reset");
+
+ reset = reset_control_get_optional_exclusive(&mdiodev->dev, "phy");
+ if (IS_ERR(reset)) {
+ gpiod_put(mdiodev->reset_gpio);
+ mdiodev->reset_gpio = NULL;
+ return PTR_ERR(reset);
+ }
+
+ mdiodev->reset_ctrl = reset;
+
+ /* Read optional firmware properties */
+ device_property_read_u32(&mdiodev->dev, "reset-assert-us",
+ &mdiodev->reset_assert_delay);
+ device_property_read_u32(&mdiodev->dev, "reset-deassert-us",
+ &mdiodev->reset_deassert_delay);
+
+ return 0;
+}
+
+/**
+ * mdio_device_unregister_reset - uninitialize the reset properties of
+ * an mdio device
+ * @mdiodev: mdio_device structure
+ */
+void mdio_device_unregister_reset(struct mdio_device *mdiodev)
+{
+ gpiod_put(mdiodev->reset_gpio);
+ mdiodev->reset_gpio = NULL;
+ reset_control_put(mdiodev->reset_ctrl);
+ mdiodev->reset_ctrl = NULL;
+ mdiodev->reset_assert_delay = 0;
+ mdiodev->reset_deassert_delay = 0;
+}
+
+void mdio_device_reset(struct mdio_device *mdiodev, int value)
+{
+ unsigned int d;
+
+ if (!mdiodev->reset_gpio && !mdiodev->reset_ctrl)
+ return;
+
+ if (mdiodev->reset_state == value)
+ return;
+
+ if (mdiodev->reset_gpio)
+ gpiod_set_value_cansleep(mdiodev->reset_gpio, value);
+
+ if (mdiodev->reset_ctrl) {
+ if (value)
+ reset_control_assert(mdiodev->reset_ctrl);
+ else
+ reset_control_deassert(mdiodev->reset_ctrl);
+ }
+
+ d = value ? mdiodev->reset_assert_delay : mdiodev->reset_deassert_delay;
+ if (d)
+ fsleep(d);
+
+ mdiodev->reset_state = value;
+}
+EXPORT_SYMBOL(mdio_device_reset);
+
void mdio_device_free(struct mdio_device *mdiodev)
{
put_device(&mdiodev->dev);
@@ -108,87 +189,6 @@ void mdio_device_remove(struct mdio_device *mdiodev)
}
EXPORT_SYMBOL(mdio_device_remove);
-/**
- * mdio_device_register_reset - Read and initialize the reset properties of
- * an mdio device
- * @mdiodev: mdio_device structure
- *
- * Return: Zero if successful, negative error code on failure
- */
-int mdio_device_register_reset(struct mdio_device *mdiodev)
-{
- struct reset_control *reset;
-
- /* Deassert the optional reset signal */
- mdiodev->reset_gpio = gpiod_get_optional(&mdiodev->dev,
- "reset", GPIOD_OUT_LOW);
- if (IS_ERR(mdiodev->reset_gpio))
- return PTR_ERR(mdiodev->reset_gpio);
-
- if (mdiodev->reset_gpio)
- gpiod_set_consumer_name(mdiodev->reset_gpio, "PHY reset");
-
- reset = reset_control_get_optional_exclusive(&mdiodev->dev, "phy");
- if (IS_ERR(reset)) {
- gpiod_put(mdiodev->reset_gpio);
- mdiodev->reset_gpio = NULL;
- return PTR_ERR(reset);
- }
-
- mdiodev->reset_ctrl = reset;
-
- /* Read optional firmware properties */
- device_property_read_u32(&mdiodev->dev, "reset-assert-us",
- &mdiodev->reset_assert_delay);
- device_property_read_u32(&mdiodev->dev, "reset-deassert-us",
- &mdiodev->reset_deassert_delay);
-
- return 0;
-}
-
-/**
- * mdio_device_unregister_reset - uninitialize the reset properties of
- * an mdio device
- * @mdiodev: mdio_device structure
- */
-void mdio_device_unregister_reset(struct mdio_device *mdiodev)
-{
- gpiod_put(mdiodev->reset_gpio);
- mdiodev->reset_gpio = NULL;
- reset_control_put(mdiodev->reset_ctrl);
- mdiodev->reset_ctrl = NULL;
- mdiodev->reset_assert_delay = 0;
- mdiodev->reset_deassert_delay = 0;
-}
-
-void mdio_device_reset(struct mdio_device *mdiodev, int value)
-{
- unsigned int d;
-
- if (!mdiodev->reset_gpio && !mdiodev->reset_ctrl)
- return;
-
- if (mdiodev->reset_state == value)
- return;
-
- if (mdiodev->reset_gpio)
- gpiod_set_value_cansleep(mdiodev->reset_gpio, value);
-
- if (mdiodev->reset_ctrl) {
- if (value)
- reset_control_assert(mdiodev->reset_ctrl);
- else
- reset_control_deassert(mdiodev->reset_ctrl);
- }
-
- d = value ? mdiodev->reset_assert_delay : mdiodev->reset_deassert_delay;
- if (d)
- fsleep(d);
-
- mdiodev->reset_state = value;
-}
-EXPORT_SYMBOL(mdio_device_reset);
-
/**
* mdio_probe - probe an MDIO device
* @dev: device to probe
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 net-next 2/5] net: phy: make mdio_device.c part of libphy
2026-03-09 17:01 [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part Heiner Kallweit
2026-03-09 17:02 ` [PATCH v2 net-next 1/5] net: phy: move mdio_device reset handling functions in the code Heiner Kallweit
@ 2026-03-09 17:03 ` Heiner Kallweit
2026-03-12 11:06 ` Paolo Abeni
2026-03-09 17:04 ` [PATCH v2 net-next 3/5] net: phy: move (of_)mdio_find_bus to mdio_bus_provider.c Heiner Kallweit
` (3 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Heiner Kallweit @ 2026-03-09 17:03 UTC (permalink / raw)
To: Andrew Lunn, Russell King - ARM Linux, Paolo Abeni,
Jakub Kicinski, David Miller, Eric Dumazet, Bjorn Andersson,
Michael Turquette, Stephen Boyd, Vinod Koul, Neil Armstrong
Cc: netdev@vger.kernel.org, Philipp Zabel, linux-arm-msm, linux-clk,
linux-phy
This patch
- makes mdio_device.c part of libphy
- makes mdio_device_(un)register_reset() static
- moves mdiobus_(un)register_device() from mdio_bus.c to mdio_device.c,
stops exporting both functions and makes them private to phylib
This further decouples the MDIO consumer functionality from libphy.
Note: This makes MDIO driver registration part of phylib, therefore
adjust Kconfig dependencies where needed.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- add needed Kconfig dependency changes
---
drivers/clk/qcom/Kconfig | 2 +-
drivers/net/phy/Makefile | 6 ++---
drivers/net/phy/mdio-private.h | 11 ---------
drivers/net/phy/mdio_bus.c | 36 ----------------------------
drivers/net/phy/mdio_device.c | 39 ++++++++++++++++++++++++++++---
drivers/net/phy/phylib-internal.h | 4 ++++
drivers/phy/broadcom/Kconfig | 4 ++--
include/linux/mdio.h | 2 --
8 files changed, 46 insertions(+), 58 deletions(-)
delete mode 100644 drivers/net/phy/mdio-private.h
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index a8a86ea6bb7..a277c434d64 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -392,7 +392,7 @@ config IPQ_NSSCC_9574
config IPQ_NSSCC_QCA8K
tristate "QCA8K(QCA8386 or QCA8084) NSS Clock Controller"
- depends on MDIO_BUS
+ depends on PHYLIB
help
Support for NSS(Network SubSystem) clock controller on
qca8386/qca8084 chip.
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 3a34917adea..8d262b4e2be 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -3,8 +3,8 @@
libphy-y := phy.o phy-c45.o phy-core.o phy_device.o \
linkmode.o phy_link_topology.o \
- phy_caps.o mdio_bus_provider.o phy_port.o
-mdio-bus-y += mdio_bus.o mdio_device.o
+ phy_caps.o mdio_bus_provider.o phy_port.o \
+ mdio_device.o
ifdef CONFIG_PHYLIB
# built-in whenever PHYLIB is built-in or module
@@ -15,7 +15,7 @@ libphy-$(CONFIG_SWPHY) += swphy.o
libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_led_triggers.o
libphy-$(CONFIG_OPEN_ALLIANCE_HELPERS) += open_alliance_helpers.o
-obj-$(CONFIG_MDIO_BUS) += mdio-bus.o
+obj-$(CONFIG_MDIO_BUS) += mdio_bus.o
obj-$(CONFIG_PHYLINK) += phylink.o
obj-$(CONFIG_PHYLIB) += libphy.o
obj-$(CONFIG_PHYLIB) += mdio_devres.o
diff --git a/drivers/net/phy/mdio-private.h b/drivers/net/phy/mdio-private.h
deleted file mode 100644
index 8bc6d9088af..00000000000
--- a/drivers/net/phy/mdio-private.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef __MDIO_PRIVATE_H
-#define __MDIO_PRIVATE_H
-
-/* MDIO internal helpers
- */
-
-int mdio_device_register_reset(struct mdio_device *mdiodev);
-void mdio_device_unregister_reset(struct mdio_device *mdiodev);
-
-#endif /* __MDIO_PRIVATE_H */
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 48c0447e6a8..a30c679feec 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -29,46 +29,10 @@
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
-#include "mdio-private.h"
#define CREATE_TRACE_POINTS
#include <trace/events/mdio.h>
-int mdiobus_register_device(struct mdio_device *mdiodev)
-{
- int err;
-
- if (mdiodev->bus->mdio_map[mdiodev->addr])
- return -EBUSY;
-
- if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) {
- err = mdio_device_register_reset(mdiodev);
- if (err)
- return err;
-
- /* Assert the reset signal */
- mdio_device_reset(mdiodev, 1);
- }
-
- mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev;
-
- return 0;
-}
-EXPORT_SYMBOL(mdiobus_register_device);
-
-int mdiobus_unregister_device(struct mdio_device *mdiodev)
-{
- if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
- return -EINVAL;
-
- mdio_device_unregister_reset(mdiodev);
-
- mdiodev->bus->mdio_map[mdiodev->addr] = NULL;
-
- return 0;
-}
-EXPORT_SYMBOL(mdiobus_unregister_device);
-
static struct mdio_device *mdiobus_find_device(struct mii_bus *bus, int addr)
{
bool addr_valid = addr >= 0 && addr < ARRAY_SIZE(bus->mdio_map);
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index da4fb7484c7..56080d3d2d2 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -22,7 +22,7 @@
#include <linux/string.h>
#include <linux/unistd.h>
#include <linux/property.h>
-#include "mdio-private.h"
+#include "phylib-internal.h"
/**
* mdio_device_register_reset - Read and initialize the reset properties of
@@ -31,7 +31,7 @@
*
* Return: Zero if successful, negative error code on failure
*/
-int mdio_device_register_reset(struct mdio_device *mdiodev)
+static int mdio_device_register_reset(struct mdio_device *mdiodev)
{
struct reset_control *reset;
@@ -67,7 +67,7 @@ int mdio_device_register_reset(struct mdio_device *mdiodev)
* an mdio device
* @mdiodev: mdio_device structure
*/
-void mdio_device_unregister_reset(struct mdio_device *mdiodev)
+static void mdio_device_unregister_reset(struct mdio_device *mdiodev)
{
gpiod_put(mdiodev->reset_gpio);
mdiodev->reset_gpio = NULL;
@@ -189,6 +189,39 @@ void mdio_device_remove(struct mdio_device *mdiodev)
}
EXPORT_SYMBOL(mdio_device_remove);
+int mdiobus_register_device(struct mdio_device *mdiodev)
+{
+ int err;
+
+ if (mdiodev->bus->mdio_map[mdiodev->addr])
+ return -EBUSY;
+
+ if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) {
+ err = mdio_device_register_reset(mdiodev);
+ if (err)
+ return err;
+
+ /* Assert the reset signal */
+ mdio_device_reset(mdiodev, 1);
+ }
+
+ mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev;
+
+ return 0;
+}
+
+int mdiobus_unregister_device(struct mdio_device *mdiodev)
+{
+ if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
+ return -EINVAL;
+
+ mdio_device_unregister_reset(mdiodev);
+
+ mdiodev->bus->mdio_map[mdiodev->addr] = NULL;
+
+ return 0;
+}
+
/**
* mdio_probe - probe an MDIO device
* @dev: device to probe
diff --git a/drivers/net/phy/phylib-internal.h b/drivers/net/phy/phylib-internal.h
index dc9592c6bb8..bfb1aa82386 100644
--- a/drivers/net/phy/phylib-internal.h
+++ b/drivers/net/phy/phylib-internal.h
@@ -6,6 +6,7 @@
#ifndef __PHYLIB_INTERNAL_H
#define __PHYLIB_INTERNAL_H
+struct mdio_device;
struct phy_device;
/*
@@ -20,6 +21,9 @@ void of_set_phy_timing_role(struct phy_device *phydev);
int phy_speed_down_core(struct phy_device *phydev);
void phy_check_downshift(struct phy_device *phydev);
+int mdiobus_register_device(struct mdio_device *mdiodev);
+int mdiobus_unregister_device(struct mdio_device *mdiodev);
+
int genphy_c45_read_eee_adv(struct phy_device *phydev, unsigned long *adv);
#endif /* __PHYLIB_INTERNAL_H */
diff --git a/drivers/phy/broadcom/Kconfig b/drivers/phy/broadcom/Kconfig
index 1d89a2fd9b7..46371a8940d 100644
--- a/drivers/phy/broadcom/Kconfig
+++ b/drivers/phy/broadcom/Kconfig
@@ -52,7 +52,7 @@ config PHY_BCM_NS_USB3
tristate "Broadcom Northstar USB 3.0 PHY Driver"
depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on HAS_IOMEM && OF
- depends on MDIO_BUS
+ depends on PHYLIB
select GENERIC_PHY
help
Enable this to support Broadcom USB 3.0 PHY connected to the USB
@@ -60,7 +60,7 @@ config PHY_BCM_NS_USB3
config PHY_NS2_PCIE
tristate "Broadcom Northstar2 PCIe PHY driver"
- depends on (OF && MDIO_BUS_MUX_BCM_IPROC) || (COMPILE_TEST && MDIO_BUS)
+ depends on (OF && MDIO_BUS_MUX_BCM_IPROC) || (COMPILE_TEST && PHYLIB)
select GENERIC_PHY
default ARCH_BCM_IPROC
help
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 5d1203b9af2..f4f9d960944 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -688,8 +688,6 @@ static inline int mdiodev_c45_write(struct mdio_device *mdiodev, u32 devad,
val);
}
-int mdiobus_register_device(struct mdio_device *mdiodev);
-int mdiobus_unregister_device(struct mdio_device *mdiodev);
bool mdiobus_is_registered_device(struct mii_bus *bus, int addr);
struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr);
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 net-next 3/5] net: phy: move (of_)mdio_find_bus to mdio_bus_provider.c
2026-03-09 17:01 [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part Heiner Kallweit
2026-03-09 17:02 ` [PATCH v2 net-next 1/5] net: phy: move mdio_device reset handling functions in the code Heiner Kallweit
2026-03-09 17:03 ` [PATCH v2 net-next 2/5] net: phy: make mdio_device.c part of libphy Heiner Kallweit
@ 2026-03-09 17:04 ` Heiner Kallweit
2026-03-09 17:04 ` [PATCH v2 net-next 4/5] net: phy: move registering mdio_bus_class and mdio_bus_type to libphy Heiner Kallweit
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2026-03-09 17:04 UTC (permalink / raw)
To: Andrew Lunn, Russell King - ARM Linux, Paolo Abeni,
Jakub Kicinski, David Miller, Eric Dumazet, Bjorn Andersson,
Michael Turquette, Stephen Boyd, Vinod Koul, Neil Armstrong
Cc: netdev@vger.kernel.org, Philipp Zabel, linux-arm-msm, linux-clk,
linux-phy
Functionality outside libphy shouldn't access mdio_bus_class directly.
So move both functions to the provider side. This is a step towards
making mdio_bus_class private to libphy.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
drivers/net/phy/mdio_bus.c | 44 -----------------------------
drivers/net/phy/mdio_bus_provider.c | 44 +++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 44 deletions(-)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index a30c679feec..c9a495390d2 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -276,50 +276,6 @@ const struct class mdio_bus_class = {
};
EXPORT_SYMBOL_GPL(mdio_bus_class);
-/**
- * mdio_find_bus - Given the name of a mdiobus, find the mii_bus.
- * @mdio_name: The name of a mdiobus.
- *
- * Return: a reference to the mii_bus, or NULL if none found. The
- * embedded struct device will have its reference count incremented,
- * and this must be put_deviced'ed once the bus is finished with.
- */
-struct mii_bus *mdio_find_bus(const char *mdio_name)
-{
- struct device *d;
-
- d = class_find_device_by_name(&mdio_bus_class, mdio_name);
- return d ? to_mii_bus(d) : NULL;
-}
-EXPORT_SYMBOL(mdio_find_bus);
-
-#if IS_ENABLED(CONFIG_OF_MDIO)
-/**
- * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
- * @mdio_bus_np: Pointer to the mii_bus.
- *
- * Return: a reference to the mii_bus, or NULL if none found. The
- * embedded struct device will have its reference count incremented,
- * and this must be put once the bus is finished with.
- *
- * Because the association of a device_node and mii_bus is made via
- * of_mdiobus_register(), the mii_bus cannot be found before it is
- * registered with of_mdiobus_register().
- *
- */
-struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np)
-{
- struct device *d;
-
- if (!mdio_bus_np)
- return NULL;
-
- d = class_find_device_by_of_node(&mdio_bus_class, mdio_bus_np);
- return d ? to_mii_bus(d) : NULL;
-}
-EXPORT_SYMBOL(of_mdio_find_bus);
-#endif
-
static void mdiobus_stats_acct(struct mdio_bus_stats *stats, bool op, int ret)
{
preempt_disable();
diff --git a/drivers/net/phy/mdio_bus_provider.c b/drivers/net/phy/mdio_bus_provider.c
index 4b063740574..d50fe6eb4b0 100644
--- a/drivers/net/phy/mdio_bus_provider.c
+++ b/drivers/net/phy/mdio_bus_provider.c
@@ -440,3 +440,47 @@ void mdiobus_free(struct mii_bus *bus)
put_device(&bus->dev);
}
EXPORT_SYMBOL(mdiobus_free);
+
+/**
+ * mdio_find_bus - Given the name of a mdiobus, find the mii_bus.
+ * @mdio_name: The name of a mdiobus.
+ *
+ * Return: a reference to the mii_bus, or NULL if none found. The
+ * embedded struct device will have its reference count incremented,
+ * and this must be put_deviced'ed once the bus is finished with.
+ */
+struct mii_bus *mdio_find_bus(const char *mdio_name)
+{
+ struct device *d;
+
+ d = class_find_device_by_name(&mdio_bus_class, mdio_name);
+ return d ? to_mii_bus(d) : NULL;
+}
+EXPORT_SYMBOL(mdio_find_bus);
+
+#if IS_ENABLED(CONFIG_OF_MDIO)
+/**
+ * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
+ * @mdio_bus_np: Pointer to the mii_bus.
+ *
+ * Return: a reference to the mii_bus, or NULL if none found. The
+ * embedded struct device will have its reference count incremented,
+ * and this must be put once the bus is finished with.
+ *
+ * Because the association of a device_node and mii_bus is made via
+ * of_mdiobus_register(), the mii_bus cannot be found before it is
+ * registered with of_mdiobus_register().
+ *
+ */
+struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np)
+{
+ struct device *d;
+
+ if (!mdio_bus_np)
+ return NULL;
+
+ d = class_find_device_by_of_node(&mdio_bus_class, mdio_bus_np);
+ return d ? to_mii_bus(d) : NULL;
+}
+EXPORT_SYMBOL(of_mdio_find_bus);
+#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 net-next 4/5] net: phy: move registering mdio_bus_class and mdio_bus_type to libphy
2026-03-09 17:01 [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part Heiner Kallweit
` (2 preceding siblings ...)
2026-03-09 17:04 ` [PATCH v2 net-next 3/5] net: phy: move (of_)mdio_find_bus to mdio_bus_provider.c Heiner Kallweit
@ 2026-03-09 17:04 ` Heiner Kallweit
2026-03-09 17:06 ` [PATCH v2 net-next 5/5] net: phy: move remaining provider code to mdio_bus_provider.c Heiner Kallweit
2026-03-14 19:30 ` [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part patchwork-bot+netdevbpf
5 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2026-03-09 17:04 UTC (permalink / raw)
To: Andrew Lunn, Russell King - ARM Linux, Paolo Abeni,
Jakub Kicinski, David Miller, Eric Dumazet, Bjorn Andersson,
Michael Turquette, Stephen Boyd, Vinod Koul, Neil Armstrong
Cc: netdev@vger.kernel.org, Philipp Zabel, linux-arm-msm, linux-clk,
linux-phy
The MDIO consumer side shouldn't register class and bus_type.
Therefore move this to libphy.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
drivers/net/phy/mdio_bus.c | 23 -----------------------
drivers/net/phy/phy_device.c | 13 +++++++++++++
2 files changed, 13 insertions(+), 23 deletions(-)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index c9a495390d2..9fb47332602 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -905,28 +905,5 @@ const struct bus_type mdio_bus_type = {
};
EXPORT_SYMBOL(mdio_bus_type);
-static int __init mdio_bus_init(void)
-{
- int ret;
-
- ret = class_register(&mdio_bus_class);
- if (!ret) {
- ret = bus_register(&mdio_bus_type);
- if (ret)
- class_unregister(&mdio_bus_class);
- }
-
- return ret;
-}
-
-static void __exit mdio_bus_exit(void)
-{
- class_unregister(&mdio_bus_class);
- bus_unregister(&mdio_bus_type);
-}
-
-subsys_initcall(mdio_bus_init);
-module_exit(mdio_bus_exit);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MDIO bus/device layer");
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index d1cbcfc3d2a..0edff47478c 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -3913,6 +3913,14 @@ static int __init phy_init(void)
{
int rc;
+ rc = class_register(&mdio_bus_class);
+ if (rc)
+ return rc;
+
+ rc = bus_register(&mdio_bus_type);
+ if (rc)
+ goto err_class;
+
rtnl_lock();
ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
phylib_register_stubs();
@@ -3941,6 +3949,9 @@ static int __init phy_init(void)
phylib_unregister_stubs();
ethtool_set_ethtool_phy_ops(NULL);
rtnl_unlock();
+ bus_unregister(&mdio_bus_type);
+err_class:
+ class_unregister(&mdio_bus_class);
return rc;
}
@@ -3953,6 +3964,8 @@ static void __exit phy_exit(void)
phylib_unregister_stubs();
ethtool_set_ethtool_phy_ops(NULL);
rtnl_unlock();
+ bus_unregister(&mdio_bus_type);
+ class_unregister(&mdio_bus_class);
}
subsys_initcall(phy_init);
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 net-next 5/5] net: phy: move remaining provider code to mdio_bus_provider.c
2026-03-09 17:01 [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part Heiner Kallweit
` (3 preceding siblings ...)
2026-03-09 17:04 ` [PATCH v2 net-next 4/5] net: phy: move registering mdio_bus_class and mdio_bus_type to libphy Heiner Kallweit
@ 2026-03-09 17:06 ` Heiner Kallweit
2026-03-14 19:30 ` [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part patchwork-bot+netdevbpf
5 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2026-03-09 17:06 UTC (permalink / raw)
To: Andrew Lunn, Russell King - ARM Linux, Paolo Abeni,
Jakub Kicinski, David Miller, Eric Dumazet, Bjorn Andersson,
Michael Turquette, Stephen Boyd, Vinod Koul, Neil Armstrong
Cc: netdev@vger.kernel.org, Philipp Zabel, linux-arm-msm, linux-clk,
linux-phy
This moves definition of mdio_bus class and bus_type to the provider
side, what allows to make them private to libphy.
As a prerequisite MDIO statistics handling is moved to the
provider side as well.
Note: This patch causes a checkpatch error "Macros with complex values
should be enclosed in parentheses" for
MDIO_BUS_STATS_ADDR_ATTR_GROUP. I consider this a false positive
here, in addition the patch just moves existing code.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- explain false positive checkpatch error
---
drivers/net/phy/mdio_bus.c | 282 ----------------------------
drivers/net/phy/mdio_bus_provider.c | 275 +++++++++++++++++++++++++++
drivers/net/phy/phylib-internal.h | 3 +
include/linux/phy.h | 3 -
4 files changed, 278 insertions(+), 285 deletions(-)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 9fb47332602..00d0e4159e9 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -10,20 +10,14 @@
#include <linux/device.h>
#include <linux/errno.h>
-#include <linux/etherdevice.h>
#include <linux/ethtool.h>
-#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mii.h>
#include <linux/mm.h>
#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/of_device.h>
-#include <linux/of_mdio.h>
#include <linux/phy.h>
-#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
@@ -64,218 +58,6 @@ bool mdiobus_is_registered_device(struct mii_bus *bus, int addr)
}
EXPORT_SYMBOL(mdiobus_is_registered_device);
-/**
- * mdiobus_release - mii_bus device release callback
- * @d: the target struct device that contains the mii_bus
- *
- * Description: called when the last reference to an mii_bus is
- * dropped, to free the underlying memory.
- */
-static void mdiobus_release(struct device *d)
-{
- struct mii_bus *bus = to_mii_bus(d);
-
- WARN(bus->state != MDIOBUS_RELEASED &&
- /* for compatibility with error handling in drivers */
- bus->state != MDIOBUS_ALLOCATED,
- "%s: not in RELEASED or ALLOCATED state\n",
- bus->id);
-
- if (bus->state == MDIOBUS_RELEASED)
- fwnode_handle_put(dev_fwnode(d));
-
- kfree(bus);
-}
-
-struct mdio_bus_stat_attr {
- struct device_attribute attr;
- int address;
- unsigned int field_offset;
-};
-
-static struct mdio_bus_stat_attr *to_sattr(struct device_attribute *attr)
-{
- return container_of(attr, struct mdio_bus_stat_attr, attr);
-}
-
-static u64 mdio_bus_get_stat(struct mdio_bus_stats *s, unsigned int offset)
-{
- const u64_stats_t *stats = (const void *)s + offset;
- unsigned int start;
- u64 val = 0;
-
- do {
- start = u64_stats_fetch_begin(&s->syncp);
- val = u64_stats_read(stats);
- } while (u64_stats_fetch_retry(&s->syncp, start));
-
- return val;
-}
-
-static ssize_t mdio_bus_stat_field_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct mdio_bus_stat_attr *sattr = to_sattr(attr);
- struct mii_bus *bus = to_mii_bus(dev);
- u64 val = 0;
-
- if (sattr->address < 0) {
- /* get global stats */
- for (int i = 0; i < PHY_MAX_ADDR; i++)
- val += mdio_bus_get_stat(&bus->stats[i],
- sattr->field_offset);
- } else {
- val = mdio_bus_get_stat(&bus->stats[sattr->address],
- sattr->field_offset);
- }
-
- return sysfs_emit(buf, "%llu\n", val);
-}
-
-static ssize_t mdio_bus_device_stat_field_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct mdio_bus_stat_attr *sattr = to_sattr(attr);
- struct mdio_device *mdiodev = to_mdio_device(dev);
- struct mii_bus *bus = mdiodev->bus;
- int addr = mdiodev->addr;
- u64 val;
-
- val = mdio_bus_get_stat(&bus->stats[addr], sattr->field_offset);
-
- return sysfs_emit(buf, "%llu\n", val);
-}
-
-#define MDIO_BUS_STATS_ATTR(field) \
-static const struct mdio_bus_stat_attr dev_attr_mdio_bus_##field = { \
- .attr = __ATTR(field, 0444, mdio_bus_stat_field_show, NULL), \
- .address = -1, \
- .field_offset = offsetof(struct mdio_bus_stats, field), \
-}; \
-static const struct mdio_bus_stat_attr dev_attr_mdio_bus_device_##field = { \
- .attr = __ATTR(field, 0444, mdio_bus_device_stat_field_show, NULL), \
- .field_offset = offsetof(struct mdio_bus_stats, field), \
-}
-
-MDIO_BUS_STATS_ATTR(transfers);
-MDIO_BUS_STATS_ATTR(errors);
-MDIO_BUS_STATS_ATTR(writes);
-MDIO_BUS_STATS_ATTR(reads);
-
-#define MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, file) \
-static const struct mdio_bus_stat_attr \
-dev_attr_mdio_bus_addr_##field##_##addr = { \
- .attr = { .attr = { .name = file, .mode = 0444 }, \
- .show = mdio_bus_stat_field_show, \
- }, \
- .address = addr, \
- .field_offset = offsetof(struct mdio_bus_stats, field), \
-}
-
-#define MDIO_BUS_STATS_ADDR_ATTR(field, addr) \
- MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, \
- __stringify(field) "_" __stringify(addr))
-
-#define MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(addr) \
- MDIO_BUS_STATS_ADDR_ATTR(transfers, addr); \
- MDIO_BUS_STATS_ADDR_ATTR(errors, addr); \
- MDIO_BUS_STATS_ADDR_ATTR(writes, addr); \
- MDIO_BUS_STATS_ADDR_ATTR(reads, addr) \
-
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(0);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(1);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(2);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(3);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(4);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(5);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(6);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(7);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(8);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(9);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(10);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(11);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(12);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(13);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(14);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(15);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(16);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(17);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(18);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(19);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(20);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(21);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(22);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(23);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(24);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(25);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(26);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(27);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(28);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(29);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(30);
-MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(31);
-
-#define MDIO_BUS_STATS_ADDR_ATTR_GROUP(addr) \
- &dev_attr_mdio_bus_addr_transfers_##addr.attr.attr, \
- &dev_attr_mdio_bus_addr_errors_##addr.attr.attr, \
- &dev_attr_mdio_bus_addr_writes_##addr.attr.attr, \
- &dev_attr_mdio_bus_addr_reads_##addr.attr.attr \
-
-static const struct attribute *const mdio_bus_statistics_attrs[] = {
- &dev_attr_mdio_bus_transfers.attr.attr,
- &dev_attr_mdio_bus_errors.attr.attr,
- &dev_attr_mdio_bus_writes.attr.attr,
- &dev_attr_mdio_bus_reads.attr.attr,
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(0),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(1),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(2),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(3),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(4),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(5),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(6),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(7),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(8),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(9),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(10),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(11),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(12),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(13),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(14),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(15),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(16),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(17),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(18),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(19),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(20),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(21),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(22),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(23),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(24),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(25),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(26),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(27),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(28),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(29),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(30),
- MDIO_BUS_STATS_ADDR_ATTR_GROUP(31),
- NULL,
-};
-
-static const struct attribute_group mdio_bus_statistics_group = {
- .name = "statistics",
- .attrs_const = mdio_bus_statistics_attrs,
-};
-__ATTRIBUTE_GROUPS(mdio_bus_statistics);
-
-const struct class mdio_bus_class = {
- .name = "mdio_bus",
- .dev_release = mdiobus_release,
- .dev_groups = mdio_bus_statistics_groups,
-};
-EXPORT_SYMBOL_GPL(mdio_bus_class);
-
static void mdiobus_stats_acct(struct mdio_bus_stats *stats, bool op, int ret)
{
preempt_disable();
@@ -841,69 +623,5 @@ int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad,
}
EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed);
-/**
- * mdio_bus_match - determine if given MDIO driver supports the given
- * MDIO device
- * @dev: target MDIO device
- * @drv: given MDIO driver
- *
- * Return: 1 if the driver supports the device, 0 otherwise
- *
- * Description: This may require calling the devices own match function,
- * since different classes of MDIO devices have different match criteria.
- */
-static int mdio_bus_match(struct device *dev, const struct device_driver *drv)
-{
- const struct mdio_driver *mdiodrv = to_mdio_driver(drv);
- struct mdio_device *mdio = to_mdio_device(dev);
-
- /* Both the driver and device must type-match */
- if (!(mdiodrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY) !=
- !(mdio->flags & MDIO_DEVICE_FLAG_PHY))
- return 0;
-
- if (of_driver_match_device(dev, drv))
- return 1;
-
- if (mdio->bus_match)
- return mdio->bus_match(dev, drv);
-
- return 0;
-}
-
-static int mdio_uevent(const struct device *dev, struct kobj_uevent_env *env)
-{
- int rc;
-
- /* Some devices have extra OF data and an OF-style MODALIAS */
- rc = of_device_uevent_modalias(dev, env);
- if (rc != -ENODEV)
- return rc;
-
- return 0;
-}
-
-static const struct attribute *const mdio_bus_device_statistics_attrs[] = {
- &dev_attr_mdio_bus_device_transfers.attr.attr,
- &dev_attr_mdio_bus_device_errors.attr.attr,
- &dev_attr_mdio_bus_device_writes.attr.attr,
- &dev_attr_mdio_bus_device_reads.attr.attr,
- NULL,
-};
-
-static const struct attribute_group mdio_bus_device_statistics_group = {
- .name = "statistics",
- .attrs_const = mdio_bus_device_statistics_attrs,
-};
-__ATTRIBUTE_GROUPS(mdio_bus_device_statistics);
-
-const struct bus_type mdio_bus_type = {
- .name = "mdio_bus",
- .dev_groups = mdio_bus_device_statistics_groups,
- .match = mdio_bus_match,
- .uevent = mdio_uevent,
-};
-EXPORT_SYMBOL(mdio_bus_type);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MDIO bus/device layer");
diff --git a/drivers/net/phy/mdio_bus_provider.c b/drivers/net/phy/mdio_bus_provider.c
index d50fe6eb4b0..041576eba47 100644
--- a/drivers/net/phy/mdio_bus_provider.c
+++ b/drivers/net/phy/mdio_bus_provider.c
@@ -28,6 +28,281 @@
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
+#include "phylib-internal.h"
+
+/**
+ * mdiobus_release - mii_bus device release callback
+ * @d: the target struct device that contains the mii_bus
+ *
+ * Description: called when the last reference to an mii_bus is
+ * dropped, to free the underlying memory.
+ */
+static void mdiobus_release(struct device *d)
+{
+ struct mii_bus *bus = to_mii_bus(d);
+
+ WARN(bus->state != MDIOBUS_RELEASED &&
+ /* for compatibility with error handling in drivers */
+ bus->state != MDIOBUS_ALLOCATED,
+ "%s: not in RELEASED or ALLOCATED state\n",
+ bus->id);
+
+ if (bus->state == MDIOBUS_RELEASED)
+ fwnode_handle_put(dev_fwnode(d));
+
+ kfree(bus);
+}
+
+struct mdio_bus_stat_attr {
+ struct device_attribute attr;
+ int address;
+ unsigned int field_offset;
+};
+
+static struct mdio_bus_stat_attr *to_sattr(struct device_attribute *attr)
+{
+ return container_of(attr, struct mdio_bus_stat_attr, attr);
+}
+
+static u64 mdio_bus_get_stat(struct mdio_bus_stats *s, unsigned int offset)
+{
+ const u64_stats_t *stats = (const void *)s + offset;
+ unsigned int start;
+ u64 val = 0;
+
+ do {
+ start = u64_stats_fetch_begin(&s->syncp);
+ val = u64_stats_read(stats);
+ } while (u64_stats_fetch_retry(&s->syncp, start));
+
+ return val;
+}
+
+static ssize_t mdio_bus_stat_field_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mdio_bus_stat_attr *sattr = to_sattr(attr);
+ struct mii_bus *bus = to_mii_bus(dev);
+ u64 val = 0;
+
+ if (sattr->address < 0) {
+ /* get global stats */
+ for (int i = 0; i < PHY_MAX_ADDR; i++)
+ val += mdio_bus_get_stat(&bus->stats[i],
+ sattr->field_offset);
+ } else {
+ val = mdio_bus_get_stat(&bus->stats[sattr->address],
+ sattr->field_offset);
+ }
+
+ return sysfs_emit(buf, "%llu\n", val);
+}
+
+static ssize_t mdio_bus_device_stat_field_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mdio_bus_stat_attr *sattr = to_sattr(attr);
+ struct mdio_device *mdiodev = to_mdio_device(dev);
+ struct mii_bus *bus = mdiodev->bus;
+ int addr = mdiodev->addr;
+ u64 val;
+
+ val = mdio_bus_get_stat(&bus->stats[addr], sattr->field_offset);
+
+ return sysfs_emit(buf, "%llu\n", val);
+}
+
+#define MDIO_BUS_STATS_ATTR(field) \
+static const struct mdio_bus_stat_attr dev_attr_mdio_bus_##field = { \
+ .attr = __ATTR(field, 0444, mdio_bus_stat_field_show, NULL), \
+ .address = -1, \
+ .field_offset = offsetof(struct mdio_bus_stats, field), \
+}; \
+static const struct mdio_bus_stat_attr dev_attr_mdio_bus_device_##field = { \
+ .attr = __ATTR(field, 0444, mdio_bus_device_stat_field_show, NULL), \
+ .field_offset = offsetof(struct mdio_bus_stats, field), \
+}
+
+MDIO_BUS_STATS_ATTR(transfers);
+MDIO_BUS_STATS_ATTR(errors);
+MDIO_BUS_STATS_ATTR(writes);
+MDIO_BUS_STATS_ATTR(reads);
+
+#define MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, file) \
+static const struct mdio_bus_stat_attr \
+dev_attr_mdio_bus_addr_##field##_##addr = { \
+ .attr = { .attr = { .name = file, .mode = 0444 }, \
+ .show = mdio_bus_stat_field_show, \
+ }, \
+ .address = addr, \
+ .field_offset = offsetof(struct mdio_bus_stats, field), \
+}
+
+#define MDIO_BUS_STATS_ADDR_ATTR(field, addr) \
+ MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, \
+ __stringify(field) "_" __stringify(addr))
+
+#define MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(addr) \
+ MDIO_BUS_STATS_ADDR_ATTR(transfers, addr); \
+ MDIO_BUS_STATS_ADDR_ATTR(errors, addr); \
+ MDIO_BUS_STATS_ADDR_ATTR(writes, addr); \
+ MDIO_BUS_STATS_ADDR_ATTR(reads, addr) \
+
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(0);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(1);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(2);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(3);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(4);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(5);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(6);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(7);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(8);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(9);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(10);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(11);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(12);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(13);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(14);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(15);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(16);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(17);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(18);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(19);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(20);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(21);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(22);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(23);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(24);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(25);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(26);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(27);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(28);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(29);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(30);
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(31);
+
+#define MDIO_BUS_STATS_ADDR_ATTR_GROUP(addr) \
+ &(dev_attr_mdio_bus_addr_transfers_##addr).attr.attr, \
+ &(dev_attr_mdio_bus_addr_errors_##addr).attr.attr, \
+ &(dev_attr_mdio_bus_addr_writes_##addr).attr.attr, \
+ &(dev_attr_mdio_bus_addr_reads_##addr).attr.attr \
+
+static const struct attribute *const mdio_bus_statistics_attrs[] = {
+ &dev_attr_mdio_bus_transfers.attr.attr,
+ &dev_attr_mdio_bus_errors.attr.attr,
+ &dev_attr_mdio_bus_writes.attr.attr,
+ &dev_attr_mdio_bus_reads.attr.attr,
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(0),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(1),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(2),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(3),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(4),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(5),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(6),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(7),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(8),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(9),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(10),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(11),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(12),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(13),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(14),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(15),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(16),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(17),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(18),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(19),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(20),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(21),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(22),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(23),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(24),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(25),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(26),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(27),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(28),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(29),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(30),
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(31),
+ NULL,
+};
+
+static const struct attribute_group mdio_bus_statistics_group = {
+ .name = "statistics",
+ .attrs_const = mdio_bus_statistics_attrs,
+};
+__ATTRIBUTE_GROUPS(mdio_bus_statistics);
+
+const struct class mdio_bus_class = {
+ .name = "mdio_bus",
+ .dev_release = mdiobus_release,
+ .dev_groups = mdio_bus_statistics_groups,
+};
+
+/**
+ * mdio_bus_match - determine if given MDIO driver supports the given
+ * MDIO device
+ * @dev: target MDIO device
+ * @drv: given MDIO driver
+ *
+ * Return: 1 if the driver supports the device, 0 otherwise
+ *
+ * Description: This may require calling the devices own match function,
+ * since different classes of MDIO devices have different match criteria.
+ */
+static int mdio_bus_match(struct device *dev, const struct device_driver *drv)
+{
+ const struct mdio_driver *mdiodrv = to_mdio_driver(drv);
+ struct mdio_device *mdio = to_mdio_device(dev);
+
+ /* Both the driver and device must type-match */
+ if (!(mdiodrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY) !=
+ !(mdio->flags & MDIO_DEVICE_FLAG_PHY))
+ return 0;
+
+ if (of_driver_match_device(dev, drv))
+ return 1;
+
+ if (mdio->bus_match)
+ return mdio->bus_match(dev, drv);
+
+ return 0;
+}
+
+static int mdio_uevent(const struct device *dev, struct kobj_uevent_env *env)
+{
+ int rc;
+
+ /* Some devices have extra OF data and an OF-style MODALIAS */
+ rc = of_device_uevent_modalias(dev, env);
+ if (rc != -ENODEV)
+ return rc;
+
+ return 0;
+}
+
+static const struct attribute *const mdio_bus_device_statistics_attrs[] = {
+ &dev_attr_mdio_bus_device_transfers.attr.attr,
+ &dev_attr_mdio_bus_device_errors.attr.attr,
+ &dev_attr_mdio_bus_device_writes.attr.attr,
+ &dev_attr_mdio_bus_device_reads.attr.attr,
+ NULL,
+};
+
+static const struct attribute_group mdio_bus_device_statistics_group = {
+ .name = "statistics",
+ .attrs_const = mdio_bus_device_statistics_attrs,
+};
+__ATTRIBUTE_GROUPS(mdio_bus_device_statistics);
+
+const struct bus_type mdio_bus_type = {
+ .name = "mdio_bus",
+ .dev_groups = mdio_bus_device_statistics_groups,
+ .match = mdio_bus_match,
+ .uevent = mdio_uevent,
+};
/**
* mdiobus_alloc_size - allocate a mii_bus structure
diff --git a/drivers/net/phy/phylib-internal.h b/drivers/net/phy/phylib-internal.h
index bfb1aa82386..664ed7faa51 100644
--- a/drivers/net/phy/phylib-internal.h
+++ b/drivers/net/phy/phylib-internal.h
@@ -9,6 +9,9 @@
struct mdio_device;
struct phy_device;
+extern const struct bus_type mdio_bus_type;
+extern const struct class mdio_bus_class;
+
/*
* phy_supported_speeds - return all speeds currently supported by a PHY device
*/
diff --git a/include/linux/phy.h b/include/linux/phy.h
index e9b0d7427b0..5de4b172cd0 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -2446,9 +2446,6 @@ int __phy_hwtstamp_set(struct phy_device *phydev,
struct phy_port *phy_get_sfp_port(struct phy_device *phydev);
-extern const struct bus_type mdio_bus_type;
-extern const struct class mdio_bus_class;
-
/**
* phy_module_driver() - Helper macro for registering PHY drivers
* @__phy_drivers: array of PHY drivers to register
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 net-next 2/5] net: phy: make mdio_device.c part of libphy
2026-03-09 17:03 ` [PATCH v2 net-next 2/5] net: phy: make mdio_device.c part of libphy Heiner Kallweit
@ 2026-03-12 11:06 ` Paolo Abeni
0 siblings, 0 replies; 8+ messages in thread
From: Paolo Abeni @ 2026-03-12 11:06 UTC (permalink / raw)
To: Heiner Kallweit, Bjorn Andersson, Michael Turquette, Stephen Boyd
Cc: netdev@vger.kernel.org, Philipp Zabel, linux-arm-msm, linux-clk,
linux-phy, Andrew Lunn, Russell King - ARM Linux, Jakub Kicinski,
David Miller, Eric Dumazet, Vinod Koul, Neil Armstrong
On 3/9/26 6:03 PM, Heiner Kallweit wrote:
> This patch
> - makes mdio_device.c part of libphy
> - makes mdio_device_(un)register_reset() static
> - moves mdiobus_(un)register_device() from mdio_bus.c to mdio_device.c,
> stops exporting both functions and makes them private to phylib
>
> This further decouples the MDIO consumer functionality from libphy.
>
> Note: This makes MDIO driver registration part of phylib, therefore
> adjust Kconfig dependencies where needed.
>
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
> ---
> v2:
> - add needed Kconfig dependency changes
> ---
> drivers/clk/qcom/Kconfig | 2 +-
> drivers/net/phy/Makefile | 6 ++---
> drivers/net/phy/mdio-private.h | 11 ---------
> drivers/net/phy/mdio_bus.c | 36 ----------------------------
> drivers/net/phy/mdio_device.c | 39 ++++++++++++++++++++++++++++---
> drivers/net/phy/phylib-internal.h | 4 ++++
> drivers/phy/broadcom/Kconfig | 4 ++--
> include/linux/mdio.h | 2 --
> 8 files changed, 46 insertions(+), 58 deletions(-)
> delete mode 100644 drivers/net/phy/mdio-private.h
>
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index a8a86ea6bb7..a277c434d64 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -392,7 +392,7 @@ config IPQ_NSSCC_9574
>
> config IPQ_NSSCC_QCA8K
> tristate "QCA8K(QCA8386 or QCA8084) NSS Clock Controller"
> - depends on MDIO_BUS
> + depends on PHYLIB
> help
> Support for NSS(Network SubSystem) clock controller on
> qca8386/qca8084 chip.
Bjorn, Micahel, Stephen: are you ok with this change?
Thanks,
Paolo
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part
2026-03-09 17:01 [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part Heiner Kallweit
` (4 preceding siblings ...)
2026-03-09 17:06 ` [PATCH v2 net-next 5/5] net: phy: move remaining provider code to mdio_bus_provider.c Heiner Kallweit
@ 2026-03-14 19:30 ` patchwork-bot+netdevbpf
5 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-03-14 19:30 UTC (permalink / raw)
To: Heiner Kallweit
Cc: andrew, linux, pabeni, kuba, davem, edumazet, andersson,
mturquette, sboyd, vkoul, neil.armstrong, netdev, p.zabel,
linux-arm-msm, linux-clk, linux-phy
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Mon, 9 Mar 2026 18:01:16 +0100 you wrote:
> This series aims at further decoupling the provider and consumer part
> in phylib.
>
> v2:
> - patch 2: add needed Kconfig dependency changes
> - patch 5: explain false positive checkpatch error
>
> [...]
Here is the summary with links:
- [v2,net-next,1/5] net: phy: move mdio_device reset handling functions in the code
https://git.kernel.org/netdev/net-next/c/2d7bebc9dd79
- [v2,net-next,2/5] net: phy: make mdio_device.c part of libphy
https://git.kernel.org/netdev/net-next/c/6df1459605ce
- [v2,net-next,3/5] net: phy: move (of_)mdio_find_bus to mdio_bus_provider.c
https://git.kernel.org/netdev/net-next/c/b69ceb387aca
- [v2,net-next,4/5] net: phy: move registering mdio_bus_class and mdio_bus_type to libphy
https://git.kernel.org/netdev/net-next/c/25b23d828318
- [v2,net-next,5/5] net: phy: move remaining provider code to mdio_bus_provider.c
https://git.kernel.org/netdev/net-next/c/c4399af5e556
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-03-14 19:30 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-09 17:01 [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part Heiner Kallweit
2026-03-09 17:02 ` [PATCH v2 net-next 1/5] net: phy: move mdio_device reset handling functions in the code Heiner Kallweit
2026-03-09 17:03 ` [PATCH v2 net-next 2/5] net: phy: make mdio_device.c part of libphy Heiner Kallweit
2026-03-12 11:06 ` Paolo Abeni
2026-03-09 17:04 ` [PATCH v2 net-next 3/5] net: phy: move (of_)mdio_find_bus to mdio_bus_provider.c Heiner Kallweit
2026-03-09 17:04 ` [PATCH v2 net-next 4/5] net: phy: move registering mdio_bus_class and mdio_bus_type to libphy Heiner Kallweit
2026-03-09 17:06 ` [PATCH v2 net-next 5/5] net: phy: move remaining provider code to mdio_bus_provider.c Heiner Kallweit
2026-03-14 19:30 ` [PATCH v2 net-next 0/5] net: phy: further decouple provider from consumer part patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox