2021-06-11 10:57:58

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 00/15] ACPI support for dpaa2 driver

From: Ioana Ciornei <[email protected]>

This patch set provides ACPI support to DPAA2 network drivers.

It also introduces new fwnode based APIs to support phylink and phy
layers
Following functions are defined:
phylink_fwnode_phy_connect()
fwnode_mdiobus_register_phy()
fwnode_get_phy_id()
fwnode_phy_find_device()
device_phy_find_device()
fwnode_get_phy_node()
fwnode_mdio_find_device()
acpi_get_local_address()

First one helps in connecting phy to phylink instance.
Next three helps in getting phy_id and registering phy to mdiobus
Next two help in finding a phy on a mdiobus.
Next one helps in getting phy_node from a fwnode.
Last one is used to get local address from _ADR object.

Corresponding OF functions are refactored.

Tested-on: LX2160ARDB

Changes in v9:
- merged some minimal changes requested in the wording of the commit
messages
- fixed some build problems in patch 8/15 by moving the removal of
of_find_mii_timestamper from patch 8/15 to 9/15.

Changes in v8:
- fixed some checkpatch warnings/checks
- included linux/fwnode_mdio.h in fwnode_mdio.c (fixed the build warnings)
- added fwnode_find_mii_timestamper() and
fwnode_mdiobus_phy_device_register() in order to get rid of the cycle
dependency.
- change to 'depends on (ACPI || OF) || COMPILE_TEST (for FWNODE_MDIO)
- remove the fwnode_mdiobus_register from fwnode_mdio.c since it
introduces a cycle of dependencies.

Changes in v7:
- correct fwnode_mdio_find_device() description
- check NULL in unregister_mii_timestamper()
- Call unregister_mii_timestamper() without NULL check
- Create fwnode_mdio.c and move fwnode_mdiobus_register_phy()
- include fwnode_mdio.h
- Include headers directly used in acpi_mdio.c
- Move fwnode_mdiobus_register() to fwnode_mdio.c
- Include fwnode_mdio.h
- Alphabetically sort header inclusions
- remove unnecassary checks

Changes in v6:
- Minor cleanup
- fix warning for function parameter of fwnode_mdio_find_device()
- Initialize mii_ts to NULL
- use GENMASK() and ACPI_COMPANION_SET()
- some cleanup
- remove unwanted header inclusion
- remove OF check for fixed-link
- use dev_fwnode()
- remove useless else
- replace of_device_is_available() to fwnode_device_is_available()

Changes in v5:
- More cleanup
- Replace fwnode_get_id() with acpi_get_local_address()
- add missing MODULE_LICENSE()
- replace fwnode_get_id() with OF and ACPI function calls
- replace fwnode_get_id() with OF and ACPI function calls

Changes in v4:
- More cleanup
- Improve code structure to handle all cases
- Remove redundant else from fwnode_mdiobus_register()
- Cleanup xgmac_mdio_probe()
- call phy_device_free() before returning

Changes in v3:
- Add more info on legacy DT properties "phy" and "phy-device"
- Redefine fwnode_phy_find_device() to follow of_phy_find_device()
- Use traditional comparison pattern
- Use GENMASK
- Modified to retrieve reg property value for ACPI as well
- Resolved compilation issue with CONFIG_ACPI = n
- Added more info into documentation
- Use acpi_mdiobus_register()
- Avoid unnecessary line removal
- Remove unused inclusion of acpi.h

Changes in v2:
- Updated with more description in document
- use reverse christmas tree ordering for local variables
- Refactor OF functions to use fwnode functions

Calvin Johnson (15):
Documentation: ACPI: DSD: Document MDIO PHY
net: phy: Introduce fwnode_mdio_find_device()
net: phy: Introduce phy related fwnode functions
of: mdio: Refactor of_phy_find_device()
net: phy: Introduce fwnode_get_phy_id()
of: mdio: Refactor of_get_phy_id()
net: mii_timestamper: check NULL in unregister_mii_timestamper()
net: mdiobus: Introduce fwnode_mdiobus_register_phy()
of: mdio: Refactor of_mdiobus_register_phy()
ACPI: utils: Introduce acpi_get_local_address()
net: mdio: Add ACPI support code for mdio
net/fsl: Use [acpi|of]_mdiobus_register
net: phylink: introduce phylink_fwnode_phy_connect()
net: phylink: Refactor phylink_of_phy_connect()
net: dpaa2-mac: Add ACPI support for DPAA2 MAC driver

Documentation/firmware-guide/acpi/dsd/phy.rst | 133 ++++++++++++++++
MAINTAINERS | 2 +
drivers/acpi/utils.c | 14 ++
.../net/ethernet/freescale/dpaa2/dpaa2-mac.c | 88 ++++++-----
.../net/ethernet/freescale/dpaa2/dpaa2-mac.h | 2 +-
drivers/net/ethernet/freescale/xgmac_mdio.c | 30 ++--
drivers/net/mdio/Kconfig | 14 ++
drivers/net/mdio/Makefile | 4 +-
drivers/net/mdio/acpi_mdio.c | 58 +++++++
drivers/net/mdio/fwnode_mdio.c | 144 ++++++++++++++++++
drivers/net/mdio/of_mdio.c | 138 ++---------------
drivers/net/phy/mii_timestamper.c | 3 +
drivers/net/phy/phy_device.c | 109 ++++++++++++-
drivers/net/phy/phylink.c | 41 +++--
include/linux/acpi.h | 7 +
include/linux/acpi_mdio.h | 26 ++++
include/linux/fwnode_mdio.h | 35 +++++
include/linux/phy.h | 32 ++++
include/linux/phylink.h | 3 +
19 files changed, 693 insertions(+), 190 deletions(-)
create mode 100644 Documentation/firmware-guide/acpi/dsd/phy.rst
create mode 100644 drivers/net/mdio/acpi_mdio.c
create mode 100644 drivers/net/mdio/fwnode_mdio.c
create mode 100644 include/linux/acpi_mdio.h
create mode 100644 include/linux/fwnode_mdio.h

--
2.31.1


2021-06-11 10:58:09

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 06/15] of: mdio: Refactor of_get_phy_id()

From: Calvin Johnson <[email protected]>

With the introduction of fwnode_get_phy_id(), refactor of_get_phy_id()
to use fwnode equivalent.

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9: None
Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

drivers/net/mdio/of_mdio.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index 0ba1158796d9..29f121cba314 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -29,17 +29,7 @@ MODULE_LICENSE("GPL");
* ethernet-phy-idAAAA.BBBB */
static int of_get_phy_id(struct device_node *device, u32 *phy_id)
{
- struct property *prop;
- const char *cp;
- unsigned int upper, lower;
-
- of_property_for_each_string(device, "compatible", prop, cp) {
- if (sscanf(cp, "ethernet-phy-id%4x.%4x", &upper, &lower) == 2) {
- *phy_id = ((upper & 0xFFFF) << 16) | (lower & 0xFFFF);
- return 0;
- }
- }
- return -EINVAL;
+ return fwnode_get_phy_id(of_fwnode_handle(device), phy_id);
}

static struct mii_timestamper *of_find_mii_timestamper(struct device_node *node)
--
2.31.1

2021-06-11 10:58:09

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 11/15] net: mdio: Add ACPI support code for mdio

From: Calvin Johnson <[email protected]>

Define acpi_mdiobus_register() to Register mii_bus and create PHYs for
each ACPI child node.

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Rafael J. Wysocki <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9:
- Add some more info about what is expected to be passed to
acpi_mdiobus_register() as fwnode

Changes in v8: None
Changes in v7:
- Include headers directly used in acpi_mdio.c

Changes in v6:
- use GENMASK() and ACPI_COMPANION_SET()
- some cleanup
- remove unwanted header inclusion

Changes in v5:
- add missing MODULE_LICENSE()
- replace fwnode_get_id() with OF and ACPI function calls

Changes in v4: None
Changes in v3: None
Changes in v2: None


MAINTAINERS | 1 +
drivers/net/mdio/Kconfig | 7 +++++
drivers/net/mdio/Makefile | 1 +
drivers/net/mdio/acpi_mdio.c | 58 ++++++++++++++++++++++++++++++++++++
include/linux/acpi_mdio.h | 26 ++++++++++++++++
5 files changed, 93 insertions(+)
create mode 100644 drivers/net/mdio/acpi_mdio.c
create mode 100644 include/linux/acpi_mdio.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e8f8b6c33a51..2172f594be8f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6811,6 +6811,7 @@ F: Documentation/devicetree/bindings/net/mdio*
F: Documentation/devicetree/bindings/net/qca,ar803x.yaml
F: Documentation/networking/phy.rst
F: drivers/net/mdio/
+F: drivers/net/mdio/acpi_mdio.c
F: drivers/net/mdio/fwnode_mdio.c
F: drivers/net/mdio/of_mdio.c
F: drivers/net/pcs/
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index 422e9e042a3c..99a6c13a11af 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -34,6 +34,13 @@ config OF_MDIO
help
OpenFirmware MDIO bus (Ethernet PHY) accessors

+config ACPI_MDIO
+ def_tristate PHYLIB
+ depends on ACPI
+ depends on PHYLIB
+ help
+ ACPI MDIO bus (Ethernet PHY) accessors
+
if MDIO_BUS

config MDIO_DEVRES
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index 2e6813c709eb..15f8dc4042ce 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for Linux MDIO bus drivers

+obj-$(CONFIG_ACPI_MDIO) += acpi_mdio.o
obj-$(CONFIG_FWNODE_MDIO) += fwnode_mdio.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o

diff --git a/drivers/net/mdio/acpi_mdio.c b/drivers/net/mdio/acpi_mdio.c
new file mode 100644
index 000000000000..d77c987fda9c
--- /dev/null
+++ b/drivers/net/mdio/acpi_mdio.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ACPI helpers for the MDIO (Ethernet PHY) API
+ *
+ * This file provides helper functions for extracting PHY device information
+ * out of the ACPI ASL and using it to populate an mii_bus.
+ */
+
+#include <linux/acpi.h>
+#include <linux/acpi_mdio.h>
+#include <linux/bits.h>
+#include <linux/dev_printk.h>
+#include <linux/fwnode_mdio.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+MODULE_AUTHOR("Calvin Johnson <[email protected]>");
+MODULE_LICENSE("GPL");
+
+/**
+ * acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL.
+ * @mdio: pointer to mii_bus structure
+ * @fwnode: pointer to fwnode of MDIO bus. This fwnode is expected to represent
+ * an ACPI device object corresponding to the MDIO bus and its children are
+ * expected to correspond to the PHY devices on that bus.
+ *
+ * This function registers the mii_bus structure and registers a phy_device
+ * for each child node of @fwnode.
+ */
+int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
+{
+ struct fwnode_handle *child;
+ u32 addr;
+ int ret;
+
+ /* Mask out all PHYs from auto probing. */
+ mdio->phy_mask = GENMASK(31, 0);
+ ret = mdiobus_register(mdio);
+ if (ret)
+ return ret;
+
+ ACPI_COMPANION_SET(&mdio->dev, to_acpi_device_node(fwnode));
+
+ /* Loop over the child nodes and register a phy_device for each PHY */
+ fwnode_for_each_child_node(fwnode, child) {
+ ret = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), &addr);
+ if (ret || addr >= PHY_MAX_ADDR)
+ continue;
+
+ ret = fwnode_mdiobus_register_phy(mdio, child, addr);
+ if (ret == -ENODEV)
+ dev_err(&mdio->dev,
+ "MDIO device at address %d is missing.\n",
+ addr);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(acpi_mdiobus_register);
diff --git a/include/linux/acpi_mdio.h b/include/linux/acpi_mdio.h
new file mode 100644
index 000000000000..0a24ab7cb66f
--- /dev/null
+++ b/include/linux/acpi_mdio.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * ACPI helper for the MDIO (Ethernet PHY) API
+ */
+
+#ifndef __LINUX_ACPI_MDIO_H
+#define __LINUX_ACPI_MDIO_H
+
+#include <linux/phy.h>
+
+#if IS_ENABLED(CONFIG_ACPI_MDIO)
+int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode);
+#else /* CONFIG_ACPI_MDIO */
+static inline int
+acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
+{
+ /*
+ * Fall back to mdiobus_register() function to register a bus.
+ * This way, we don't have to keep compat bits around in drivers.
+ */
+
+ return mdiobus_register(mdio);
+}
+#endif
+
+#endif /* __LINUX_ACPI_MDIO_H */
--
2.31.1

2021-06-11 10:58:15

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 07/15] net: mii_timestamper: check NULL in unregister_mii_timestamper()

From: Calvin Johnson <[email protected]>

Callers of unregister_mii_timestamper() currently check for NULL
value of mii_ts before calling it.

Place the NULL check inside unregister_mii_timestamper() and update
the callers accordingly.

Signed-off-by: Calvin Johnson <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
Suggested-by: Andy Shevchenko <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9: None
Changes in v8: None
Changes in v7:
- check NULL in unregister_mii_timestamper()

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None


drivers/net/mdio/of_mdio.c | 6 ++----
drivers/net/phy/mii_timestamper.c | 3 +++
drivers/net/phy/phy_device.c | 3 +--
3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index 29f121cba314..d73c0570f19c 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -115,15 +115,13 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio,
else
phy = get_phy_device(mdio, addr, is_c45);
if (IS_ERR(phy)) {
- if (mii_ts)
- unregister_mii_timestamper(mii_ts);
+ unregister_mii_timestamper(mii_ts);
return PTR_ERR(phy);
}

rc = of_mdiobus_phy_device_register(mdio, phy, child, addr);
if (rc) {
- if (mii_ts)
- unregister_mii_timestamper(mii_ts);
+ unregister_mii_timestamper(mii_ts);
phy_device_free(phy);
return rc;
}
diff --git a/drivers/net/phy/mii_timestamper.c b/drivers/net/phy/mii_timestamper.c
index b71b7456462d..51ae0593a04f 100644
--- a/drivers/net/phy/mii_timestamper.c
+++ b/drivers/net/phy/mii_timestamper.c
@@ -111,6 +111,9 @@ void unregister_mii_timestamper(struct mii_timestamper *mii_ts)
struct mii_timestamping_desc *desc;
struct list_head *this;

+ if (!mii_ts)
+ return;
+
/* mii_timestamper statically registered by the PHY driver won't use the
* register_mii_timestamper() and thus don't have ->device set. Don't
* try to unregister these.
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index f7472a0cf771..85734309b580 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -957,8 +957,7 @@ EXPORT_SYMBOL(phy_device_register);
*/
void phy_device_remove(struct phy_device *phydev)
{
- if (phydev->mii_ts)
- unregister_mii_timestamper(phydev->mii_ts);
+ unregister_mii_timestamper(phydev->mii_ts);

device_del(&phydev->mdio.dev);

--
2.31.1

2021-06-11 10:58:43

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 09/15] of: mdio: Refactor of_mdiobus_register_phy()

From: Calvin Johnson <[email protected]>

Refactor of_mdiobus_register_phy() to use fwnode_mdiobus_register_phy().
Also, remove the of_find_mii_timestamper() since the fwnode variant is
used instead.

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9:
- remove the of_find_mii_timestamper() in this patch rather the previous
one

Changes in v8: None
Changes in v7:
- include fwnode_mdio.h

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None



drivers/net/mdio/of_mdio.c | 56 +-------------------------------------
1 file changed, 1 insertion(+), 55 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index 17327bbc1de4..8744b1e1c2b1 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -33,24 +33,6 @@ static int of_get_phy_id(struct device_node *device, u32 *phy_id)
return fwnode_get_phy_id(of_fwnode_handle(device), phy_id);
}

-static struct mii_timestamper *of_find_mii_timestamper(struct device_node *node)
-{
- struct of_phandle_args arg;
- int err;
-
- err = of_parse_phandle_with_fixed_args(node, "timestamper", 1, 0, &arg);
-
- if (err == -ENOENT)
- return NULL;
- else if (err)
- return ERR_PTR(err);
-
- if (arg.args_count != 1)
- return ERR_PTR(-EINVAL);
-
- return register_mii_timestamper(arg.np, arg.args[0]);
-}
-
int of_mdiobus_phy_device_register(struct mii_bus *mdio, struct phy_device *phy,
struct device_node *child, u32 addr)
{
@@ -63,43 +45,7 @@ EXPORT_SYMBOL(of_mdiobus_phy_device_register);
static int of_mdiobus_register_phy(struct mii_bus *mdio,
struct device_node *child, u32 addr)
{
- struct mii_timestamper *mii_ts;
- struct phy_device *phy;
- bool is_c45;
- int rc;
- u32 phy_id;
-
- mii_ts = of_find_mii_timestamper(child);
- if (IS_ERR(mii_ts))
- return PTR_ERR(mii_ts);
-
- is_c45 = of_device_is_compatible(child,
- "ethernet-phy-ieee802.3-c45");
-
- if (!is_c45 && !of_get_phy_id(child, &phy_id))
- phy = phy_device_create(mdio, addr, phy_id, 0, NULL);
- else
- phy = get_phy_device(mdio, addr, is_c45);
- if (IS_ERR(phy)) {
- unregister_mii_timestamper(mii_ts);
- return PTR_ERR(phy);
- }
-
- rc = of_mdiobus_phy_device_register(mdio, phy, child, addr);
- if (rc) {
- unregister_mii_timestamper(mii_ts);
- phy_device_free(phy);
- return rc;
- }
-
- /* phy->mii_ts may already be defined by the PHY driver. A
- * mii_timestamper probed via the device tree will still have
- * precedence.
- */
- if (mii_ts)
- phy->mii_ts = mii_ts;
-
- return 0;
+ return fwnode_mdiobus_register_phy(mdio, of_fwnode_handle(child), addr);
}

static int of_mdiobus_register_device(struct mii_bus *mdio,
--
2.31.1

2021-06-11 10:59:23

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 02/15] net: phy: Introduce fwnode_mdio_find_device()

From: Calvin Johnson <[email protected]>

Define fwnode_mdio_find_device() to get a pointer to the
mdio_device from fwnode passed to the function.

Refactor of_mdio_find_device() to use fwnode_mdio_find_device().

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9: None
Changes in v8: None
Changes in v7:
- correct fwnode_mdio_find_device() description

Changes in v6:
- fix warning for function parameter of fwnode_mdio_find_device()

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None


drivers/net/mdio/of_mdio.c | 11 +----------
drivers/net/phy/phy_device.c | 23 +++++++++++++++++++++++
include/linux/phy.h | 7 +++++++
3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index 8e97d5b825f5..6ef8b6e40189 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -347,16 +347,7 @@ EXPORT_SYMBOL(of_mdiobus_register);
*/
struct mdio_device *of_mdio_find_device(struct device_node *np)
{
- struct device *d;
-
- if (!np)
- return NULL;
-
- d = bus_find_device_by_of_node(&mdio_bus_type, np);
- if (!d)
- return NULL;
-
- return to_mdio_device(d);
+ return fwnode_mdio_find_device(of_fwnode_handle(np));
}
EXPORT_SYMBOL(of_mdio_find_device);

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 495d86b4af7c..dca454b5c209 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2875,6 +2875,29 @@ static bool phy_drv_supports_irq(struct phy_driver *phydrv)
return phydrv->config_intr && phydrv->handle_interrupt;
}

+/**
+ * fwnode_mdio_find_device - Given a fwnode, find the mdio_device
+ * @fwnode: pointer to the mdio_device's fwnode
+ *
+ * If successful, returns a pointer to the mdio_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure.
+ * The caller should call put_device() on the mdio_device after its use.
+ */
+struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
+{
+ struct device *d;
+
+ if (!fwnode)
+ return NULL;
+
+ d = bus_find_device_by_fwnode(&mdio_bus_type, fwnode);
+ if (!d)
+ return NULL;
+
+ return to_mdio_device(d);
+}
+EXPORT_SYMBOL(fwnode_mdio_find_device);
+
/**
* phy_probe - probe and init a PHY device
* @dev: device to probe and init
diff --git a/include/linux/phy.h b/include/linux/phy.h
index ed332ac92e25..7aa97f4e5387 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1377,10 +1377,17 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
bool is_c45,
struct phy_c45_device_ids *c45_ids);
#if IS_ENABLED(CONFIG_PHYLIB)
+struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode);
struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
int phy_device_register(struct phy_device *phy);
void phy_device_free(struct phy_device *phydev);
#else
+static inline
+struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
+{
+ return 0;
+}
+
static inline
struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
{
--
2.31.1

2021-06-11 10:59:56

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 14/15] net: phylink: Refactor phylink_of_phy_connect()

From: Calvin Johnson <[email protected]>

Refactor phylink_of_phy_connect() to use phylink_fwnode_phy_connect().

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9: None
Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

drivers/net/phy/phylink.c | 39 +--------------------------------------
1 file changed, 1 insertion(+), 38 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 9cc0f69faafe..bb9eeb74f70a 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1085,44 +1085,7 @@ EXPORT_SYMBOL_GPL(phylink_connect_phy);
int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
u32 flags)
{
- struct device_node *phy_node;
- struct phy_device *phy_dev;
- int ret;
-
- /* Fixed links and 802.3z are handled without needing a PHY */
- if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
- (pl->cfg_link_an_mode == MLO_AN_INBAND &&
- phy_interface_mode_is_8023z(pl->link_interface)))
- return 0;
-
- phy_node = of_parse_phandle(dn, "phy-handle", 0);
- if (!phy_node)
- phy_node = of_parse_phandle(dn, "phy", 0);
- if (!phy_node)
- phy_node = of_parse_phandle(dn, "phy-device", 0);
-
- if (!phy_node) {
- if (pl->cfg_link_an_mode == MLO_AN_PHY)
- return -ENODEV;
- return 0;
- }
-
- phy_dev = of_phy_find_device(phy_node);
- /* We're done with the phy_node handle */
- of_node_put(phy_node);
- if (!phy_dev)
- return -ENODEV;
-
- ret = phy_attach_direct(pl->netdev, phy_dev, flags,
- pl->link_interface);
- if (ret)
- return ret;
-
- ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface);
- if (ret)
- phy_detach(phy_dev);
-
- return ret;
+ return phylink_fwnode_phy_connect(pl, of_fwnode_handle(dn), flags);
}
EXPORT_SYMBOL_GPL(phylink_of_phy_connect);

--
2.31.1

2021-06-11 11:00:08

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 15/15] net: dpaa2-mac: Add ACPI support for DPAA2 MAC driver

From: Calvin Johnson <[email protected]>

Modify dpaa2_mac_get_node() to get the dpmac fwnode from either
DT or ACPI.

Modify dpaa2_mac_get_if_mode() to get interface mode from dpmac_node
which is a fwnode.

Modify dpaa2_pcs_create() to create pcs from dpmac_node fwnode.

Modify dpaa2_mac_connect() to support ACPI along with DT.

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Rafael J. Wysocki <[email protected]> # from the ACPI side
Acked-by: Grant Likely <[email protected]>
---

Changes in v9: None
Changes in v8:
- adjust code over latest changes applied on the driver

Changes in v7:
- remove unnecassary checks

Changes in v6:
- use dev_fwnode()
- remove useless else
- replace of_device_is_available() to fwnode_device_is_available()

Changes in v5:
- replace fwnode_get_id() with OF and ACPI function calls

Changes in v4: None
Changes in v3: None
Changes in v2:
- Refactor OF functions to use fwnode functions


.../net/ethernet/freescale/dpaa2/dpaa2-mac.c | 88 +++++++++++--------
.../net/ethernet/freescale/dpaa2/dpaa2-mac.h | 2 +-
2 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index 4dfadf2b70d6..ae6d382d8735 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/* Copyright 2019 NXP */

+#include <linux/acpi.h>
+#include <linux/property.h>
+
#include "dpaa2-eth.h"
#include "dpaa2-mac.h"

@@ -34,39 +37,51 @@ static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode)
return 0;
}

-/* Caller must call of_node_put on the returned value */
-static struct device_node *dpaa2_mac_get_node(u16 dpmac_id)
+static struct fwnode_handle *dpaa2_mac_get_node(struct device *dev,
+ u16 dpmac_id)
{
- struct device_node *dpmacs, *dpmac = NULL;
- u32 id;
+ struct fwnode_handle *fwnode, *parent, *child = NULL;
+ struct device_node *dpmacs = NULL;
int err;
+ u32 id;

- dpmacs = of_find_node_by_name(NULL, "dpmacs");
- if (!dpmacs)
- return NULL;
+ fwnode = dev_fwnode(dev->parent);
+ if (is_of_node(fwnode)) {
+ dpmacs = of_find_node_by_name(NULL, "dpmacs");
+ if (!dpmacs)
+ return NULL;
+ parent = of_fwnode_handle(dpmacs);
+ } else if (is_acpi_node(fwnode)) {
+ parent = fwnode;
+ }

- while ((dpmac = of_get_next_child(dpmacs, dpmac)) != NULL) {
- err = of_property_read_u32(dpmac, "reg", &id);
+ fwnode_for_each_child_node(parent, child) {
+ err = -EINVAL;
+ if (is_acpi_device_node(child))
+ err = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), &id);
+ else if (is_of_node(child))
+ err = of_property_read_u32(to_of_node(child), "reg", &id);
if (err)
continue;
- if (id == dpmac_id)
- break;
- }

+ if (id == dpmac_id) {
+ of_node_put(dpmacs);
+ return child;
+ }
+ }
of_node_put(dpmacs);
-
- return dpmac;
+ return NULL;
}

-static int dpaa2_mac_get_if_mode(struct device_node *node,
+static int dpaa2_mac_get_if_mode(struct fwnode_handle *dpmac_node,
struct dpmac_attr attr)
{
phy_interface_t if_mode;
int err;

- err = of_get_phy_mode(node, &if_mode);
- if (!err)
- return if_mode;
+ err = fwnode_get_phy_mode(dpmac_node);
+ if (err > 0)
+ return err;

err = phy_mode(attr.eth_if, &if_mode);
if (!err)
@@ -235,26 +250,27 @@ static const struct phylink_mac_ops dpaa2_mac_phylink_ops = {
};

static int dpaa2_pcs_create(struct dpaa2_mac *mac,
- struct device_node *dpmac_node, int id)
+ struct fwnode_handle *dpmac_node,
+ int id)
{
struct mdio_device *mdiodev;
- struct device_node *node;
+ struct fwnode_handle *node;

- node = of_parse_phandle(dpmac_node, "pcs-handle", 0);
- if (!node) {
+ node = fwnode_find_reference(dpmac_node, "pcs-handle", 0);
+ if (IS_ERR(node)) {
/* do not error out on old DTS files */
netdev_warn(mac->net_dev, "pcs-handle node not found\n");
return 0;
}

- if (!of_device_is_available(node)) {
+ if (!fwnode_device_is_available(node)) {
netdev_err(mac->net_dev, "pcs-handle node not available\n");
- of_node_put(node);
+ fwnode_handle_put(node);
return -ENODEV;
}

- mdiodev = of_mdio_find_device(node);
- of_node_put(node);
+ mdiodev = fwnode_mdio_find_device(node);
+ fwnode_handle_put(node);
if (!mdiodev)
return -EPROBE_DEFER;

@@ -283,13 +299,13 @@ static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
int dpaa2_mac_connect(struct dpaa2_mac *mac)
{
struct net_device *net_dev = mac->net_dev;
- struct device_node *dpmac_node;
+ struct fwnode_handle *dpmac_node;
struct phylink *phylink;
int err;

mac->if_link_type = mac->attr.link_type;

- dpmac_node = mac->of_node;
+ dpmac_node = mac->fw_node;
if (!dpmac_node) {
netdev_err(net_dev, "No dpmac@%d node found.\n", mac->attr.id);
return -ENODEV;
@@ -304,7 +320,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
* error out if the interface mode requests them and there is no PHY
* to act upon them
*/
- if (of_phy_is_fixed_link(dpmac_node) &&
+ if (of_phy_is_fixed_link(to_of_node(dpmac_node)) &&
(mac->if_mode == PHY_INTERFACE_MODE_RGMII_ID ||
mac->if_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
mac->if_mode == PHY_INTERFACE_MODE_RGMII_TXID)) {
@@ -324,7 +340,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
mac->phylink_config.type = PHYLINK_NETDEV;

phylink = phylink_create(&mac->phylink_config,
- of_fwnode_handle(dpmac_node), mac->if_mode,
+ dpmac_node, mac->if_mode,
&dpaa2_mac_phylink_ops);
if (IS_ERR(phylink)) {
err = PTR_ERR(phylink);
@@ -335,9 +351,9 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
if (mac->pcs)
phylink_set_pcs(mac->phylink, &mac->pcs->pcs);

- err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0);
+ err = phylink_fwnode_phy_connect(mac->phylink, dpmac_node, 0);
if (err) {
- netdev_err(net_dev, "phylink_of_phy_connect() = %d\n", err);
+ netdev_err(net_dev, "phylink_fwnode_phy_connect() = %d\n", err);
goto err_phylink_destroy;
}

@@ -384,8 +400,8 @@ int dpaa2_mac_open(struct dpaa2_mac *mac)
/* Find the device node representing the MAC device and link the device
* behind the associated netdev to it.
*/
- mac->of_node = dpaa2_mac_get_node(mac->attr.id);
- net_dev->dev.of_node = mac->of_node;
+ mac->fw_node = dpaa2_mac_get_node(&mac->mc_dev->dev, mac->attr.id);
+ net_dev->dev.of_node = to_of_node(mac->fw_node);

return 0;

@@ -399,8 +415,8 @@ void dpaa2_mac_close(struct dpaa2_mac *mac)
struct fsl_mc_device *dpmac_dev = mac->mc_dev;

dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
- if (mac->of_node)
- of_node_put(mac->of_node);
+ if (mac->fw_node)
+ fwnode_handle_put(mac->fw_node);
}

static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = {
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
index 8ebcb3420d02..7842cbb2207a 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
@@ -24,7 +24,7 @@ struct dpaa2_mac {
phy_interface_t if_mode;
enum dpmac_link_type if_link_type;
struct lynx_pcs *pcs;
- struct device_node *of_node;
+ struct fwnode_handle *fw_node;
};

bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev,
--
2.31.1

2021-06-11 11:00:21

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 12/15] net/fsl: Use [acpi|of]_mdiobus_register

From: Calvin Johnson <[email protected]>

Depending on the device node type, call the specific OF or ACPI
mdiobus_register function.

Note: For both ACPI and DT cases, endianness of MDIO controllers
need to be specified using the "little-endian" property.

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9: none
Changes in v8:
- Directly call the OF or ACPI variants of registering the MDIO bus.
This is needed because the fwnode_mdio.c module should only implement
features which can be achieved without going back to the OF/ACPI
variants. Without this restrictions we directly end up in a dependency
cycle: of_mdio -> fwnode_mdio -> of_mdio.
- Changed the commit title since the fwnode_mdiobus_register() is no
longer available

Changes in v7:
- Include fwnode_mdio.h
- Alphabetically sort header inclusions

Changes in v6: None
Changes in v5: None
Changes in v4:
- Cleanup xgmac_mdio_probe()

Changes in v3:
- Avoid unnecessary line removal
- Remove unused inclusion of acpi.h

Changes in v2: None



drivers/net/ethernet/freescale/xgmac_mdio.c | 30 ++++++++++++++-------
1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c
index bfa2826c5545..0b68852379da 100644
--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
+++ b/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -2,6 +2,7 @@
* QorIQ 10G MDIO Controller
*
* Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2021 NXP
*
* Authors: Andy Fleming <[email protected]>
* Timur Tabi <[email protected]>
@@ -11,15 +12,17 @@
* kind, whether express or implied.
*/

-#include <linux/kernel.h>
-#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/acpi_mdio.h>
#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/phy.h>
+#include <linux/kernel.h>
#include <linux/mdio.h>
+#include <linux/module.h>
#include <linux/of_address.h>
-#include <linux/of_platform.h>
#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/slab.h>

/* Number of microseconds to wait for a register to respond */
#define TIMEOUT 1000
@@ -243,10 +246,10 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)

static int xgmac_mdio_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
- struct mii_bus *bus;
- struct resource *res;
+ struct fwnode_handle *fwnode;
struct mdio_fsl_priv *priv;
+ struct resource *res;
+ struct mii_bus *bus;
int ret;

/* In DPAA-1, MDIO is one of the many FMan sub-devices. The FMan
@@ -279,13 +282,22 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
goto err_ioremap;
}

+ /* For both ACPI and DT cases, endianness of MDIO controller
+ * needs to be specified using "little-endian" property.
+ */
priv->is_little_endian = device_property_read_bool(&pdev->dev,
"little-endian");

priv->has_a011043 = device_property_read_bool(&pdev->dev,
"fsl,erratum-a011043");

- ret = of_mdiobus_register(bus, np);
+ fwnode = pdev->dev.fwnode;
+ if (is_of_node(fwnode))
+ ret = of_mdiobus_register(bus, to_of_node(fwnode));
+ else if (is_acpi_node(fwnode))
+ ret = acpi_mdiobus_register(bus, fwnode);
+ else
+ ret = -EINVAL;
if (ret) {
dev_err(&pdev->dev, "cannot register MDIO bus\n");
goto err_registration;
--
2.31.1

2021-06-11 11:00:22

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 01/15] Documentation: ACPI: DSD: Document MDIO PHY

From: Calvin Johnson <[email protected]>

Introduce a mechanism based on generic ACPI _DSD device properties
definition [1] to get PHYs registered on a MDIO bus and provide them to
be connected to MAC.

[1] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf

Describe properties "phy-handle" and "phy-mode".

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Rafael J. Wysocki <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9:
- Reworded the commit message

Changes in v8: None
Changes in v7: None
Changes in v6:
- Minor cleanup

Changes in v5:
- More cleanup

Changes in v4:
- More cleanup

Changes in v3: None
Changes in v2:
- Updated with more description in document


Documentation/firmware-guide/acpi/dsd/phy.rst | 133 ++++++++++++++++++
1 file changed, 133 insertions(+)
create mode 100644 Documentation/firmware-guide/acpi/dsd/phy.rst

diff --git a/Documentation/firmware-guide/acpi/dsd/phy.rst b/Documentation/firmware-guide/acpi/dsd/phy.rst
new file mode 100644
index 000000000000..7d01ae8b3cc6
--- /dev/null
+++ b/Documentation/firmware-guide/acpi/dsd/phy.rst
@@ -0,0 +1,133 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========================
+MDIO bus and PHYs in ACPI
+=========================
+
+The PHYs on an MDIO bus [1] are probed and registered using
+fwnode_mdiobus_register_phy().
+
+Later, for connecting these PHYs to their respective MACs, the PHYs registered
+on the MDIO bus have to be referenced.
+
+This document introduces two _DSD properties that are to be used
+for connecting PHYs on the MDIO bus [3] to the MAC layer.
+
+These properties are defined in accordance with the "Device
+Properties UUID For _DSD" [2] document and the
+daffd814-6eba-4d8c-8a91-bc9bbf4aa301 UUID must be used in the Device
+Data Descriptors containing them.
+
+phy-handle
+----------
+For each MAC node, a device property "phy-handle" is used to reference
+the PHY that is registered on an MDIO bus. This is mandatory for
+network interfaces that have PHYs connected to MAC via MDIO bus.
+
+During the MDIO bus driver initialization, PHYs on this bus are probed
+using the _ADR object as shown below and are registered on the MDIO bus.
+
+::
+ Scope(\_SB.MDI0)
+ {
+ Device(PHY1) {
+ Name (_ADR, 0x1)
+ } // end of PHY1
+
+ Device(PHY2) {
+ Name (_ADR, 0x2)
+ } // end of PHY2
+ }
+
+Later, during the MAC driver initialization, the registered PHY devices
+have to be retrieved from the MDIO bus. For this, the MAC driver needs
+references to the previously registered PHYs which are provided
+as device object references (e.g. \_SB.MDI0.PHY1).
+
+phy-mode
+--------
+The "phy-mode" _DSD property is used to describe the connection to
+the PHY. The valid values for "phy-mode" are defined in [4].
+
+The following ASL example illustrates the usage of these properties.
+
+DSDT entry for MDIO node
+------------------------
+
+The MDIO bus has an SoC component (MDIO controller) and a platform
+component (PHYs on the MDIO bus).
+
+a) Silicon Component
+This node describes the MDIO controller, MDI0
+---------------------------------------------
+::
+ Scope(_SB)
+ {
+ Device(MDI0) {
+ Name(_HID, "NXP0006")
+ Name(_CCA, 1)
+ Name(_UID, 0)
+ Name(_CRS, ResourceTemplate() {
+ Memory32Fixed(ReadWrite, MDI0_BASE, MDI_LEN)
+ Interrupt(ResourceConsumer, Level, ActiveHigh, Shared)
+ {
+ MDI0_IT
+ }
+ }) // end of _CRS for MDI0
+ } // end of MDI0
+ }
+
+b) Platform Component
+The PHY1 and PHY2 nodes represent the PHYs connected to MDIO bus MDI0
+---------------------------------------------------------------------
+::
+ Scope(\_SB.MDI0)
+ {
+ Device(PHY1) {
+ Name (_ADR, 0x1)
+ } // end of PHY1
+
+ Device(PHY2) {
+ Name (_ADR, 0x2)
+ } // end of PHY2
+ }
+
+DSDT entries representing MAC nodes
+-----------------------------------
+
+Below are the MAC nodes where PHY nodes are referenced.
+phy-mode and phy-handle are used as explained earlier.
+------------------------------------------------------
+::
+ Scope(\_SB.MCE0.PR17)
+ {
+ Name (_DSD, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package (2) {"phy-mode", "rgmii-id"},
+ Package (2) {"phy-handle", \_SB.MDI0.PHY1}
+ }
+ })
+ }
+
+ Scope(\_SB.MCE0.PR18)
+ {
+ Name (_DSD, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package (2) {"phy-mode", "rgmii-id"},
+ Package (2) {"phy-handle", \_SB.MDI0.PHY2}}
+ }
+ })
+ }
+
+References
+==========
+
+[1] Documentation/networking/phy.rst
+
+[2] https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
+
+[3] Documentation/firmware-guide/acpi/DSD-properties-rules.rst
+
+[4] Documentation/devicetree/bindings/net/ethernet-controller.yaml
--
2.31.1

2021-06-11 11:00:44

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 08/15] net: mdiobus: Introduce fwnode_mdiobus_register_phy()

From: Calvin Johnson <[email protected]>

Introduce fwnode_mdiobus_register_phy() to register PHYs on the
mdiobus. From the compatible string, identify whether the PHY is
c45 and based on this create a PHY device instance which is
registered on the mdiobus.

Along with fwnode_mdiobus_register_phy() also introduce
fwnode_find_mii_timestamper() and fwnode_mdiobus_phy_device_register()
since they are needed.
While at it, also use the newly introduced fwnode operation in
of_mdiobus_phy_device_register().

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9:
- fixed the build issue by not removing of_find_mii_timestamper() in
this patch but rather in the next one

Changes in v8:
- fixed some checkpatch warnings/checks
- included linux/fwnode_mdio.h in fwnode_mdio.c (fixed the build warnings)
- added fwnode_find_mii_timestamper() and fwnode_mdiobus_phy_device_register()
in order to get rid of the cycle dependency.
- change to 'depends on (ACPI || OF) || COMPILE_TEST

Changes in v7:
- Call unregister_mii_timestamper() without NULL check
- Create fwnode_mdio.c and move fwnode_mdiobus_register_phy()

Changes in v6:
- Initialize mii_ts to NULL

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None


MAINTAINERS | 1 +
drivers/net/mdio/Kconfig | 7 ++
drivers/net/mdio/Makefile | 3 +-
drivers/net/mdio/fwnode_mdio.c | 144 +++++++++++++++++++++++++++++++++
drivers/net/mdio/of_mdio.c | 44 ++--------
include/linux/fwnode_mdio.h | 35 ++++++++
6 files changed, 194 insertions(+), 40 deletions(-)
create mode 100644 drivers/net/mdio/fwnode_mdio.c
create mode 100644 include/linux/fwnode_mdio.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e69c1991ec3b..e8f8b6c33a51 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6811,6 +6811,7 @@ F: Documentation/devicetree/bindings/net/mdio*
F: Documentation/devicetree/bindings/net/qca,ar803x.yaml
F: Documentation/networking/phy.rst
F: drivers/net/mdio/
+F: drivers/net/mdio/fwnode_mdio.c
F: drivers/net/mdio/of_mdio.c
F: drivers/net/pcs/
F: drivers/net/phy/
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index d06e06f5e31a..422e9e042a3c 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -19,6 +19,13 @@ config MDIO_BUS
reflects whether the mdio_bus/mdio_device code is built as a
loadable module or built-in.

+config FWNODE_MDIO
+ def_tristate PHYLIB
+ depends on (ACPI || OF) || COMPILE_TEST
+ select FIXED_PHY
+ help
+ FWNODE MDIO bus (Ethernet PHY) accessors
+
config OF_MDIO
def_tristate PHYLIB
depends on OF
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index c3ec0ef989df..2e6813c709eb 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for Linux MDIO bus drivers

-obj-$(CONFIG_OF_MDIO) += of_mdio.o
+obj-$(CONFIG_FWNODE_MDIO) += fwnode_mdio.o
+obj-$(CONFIG_OF_MDIO) += of_mdio.o

obj-$(CONFIG_MDIO_ASPEED) += mdio-aspeed.o
obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o
diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c
new file mode 100644
index 000000000000..e96766da8de4
--- /dev/null
+++ b/drivers/net/mdio/fwnode_mdio.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * fwnode helpers for the MDIO (Ethernet PHY) API
+ *
+ * This file provides helper functions for extracting PHY device information
+ * out of the fwnode and using it to populate an mii_bus.
+ */
+
+#include <linux/acpi.h>
+#include <linux/fwnode_mdio.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+
+MODULE_AUTHOR("Calvin Johnson <[email protected]>");
+MODULE_LICENSE("GPL");
+
+static struct mii_timestamper *
+fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
+{
+ struct of_phandle_args arg;
+ int err;
+
+ if (is_acpi_node(fwnode))
+ return NULL;
+
+ err = of_parse_phandle_with_fixed_args(to_of_node(fwnode),
+ "timestamper", 1, 0, &arg);
+ if (err == -ENOENT)
+ return NULL;
+ else if (err)
+ return ERR_PTR(err);
+
+ if (arg.args_count != 1)
+ return ERR_PTR(-EINVAL);
+
+ return register_mii_timestamper(arg.np, arg.args[0]);
+}
+
+int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
+ struct phy_device *phy,
+ struct fwnode_handle *child, u32 addr)
+{
+ int rc;
+
+ rc = fwnode_irq_get(child, 0);
+ if (rc == -EPROBE_DEFER)
+ return rc;
+
+ if (rc > 0) {
+ phy->irq = rc;
+ mdio->irq[addr] = rc;
+ } else {
+ phy->irq = mdio->irq[addr];
+ }
+
+ if (fwnode_property_read_bool(child, "broken-turn-around"))
+ mdio->phy_ignore_ta_mask |= 1 << addr;
+
+ fwnode_property_read_u32(child, "reset-assert-us",
+ &phy->mdio.reset_assert_delay);
+ fwnode_property_read_u32(child, "reset-deassert-us",
+ &phy->mdio.reset_deassert_delay);
+
+ /* Associate the fwnode with the device structure so it
+ * can be looked up later
+ */
+ fwnode_handle_get(child);
+ phy->mdio.dev.fwnode = child;
+
+ /* All data is now stored in the phy struct;
+ * register it
+ */
+ rc = phy_device_register(phy);
+ if (rc) {
+ fwnode_handle_put(child);
+ return rc;
+ }
+
+ dev_dbg(&mdio->dev, "registered phy %p fwnode at address %i\n",
+ child, addr);
+ return 0;
+}
+EXPORT_SYMBOL(fwnode_mdiobus_phy_device_register);
+
+int fwnode_mdiobus_register_phy(struct mii_bus *bus,
+ struct fwnode_handle *child, u32 addr)
+{
+ struct mii_timestamper *mii_ts = NULL;
+ struct phy_device *phy;
+ bool is_c45 = false;
+ u32 phy_id;
+ int rc;
+
+ mii_ts = fwnode_find_mii_timestamper(child);
+ if (IS_ERR(mii_ts))
+ return PTR_ERR(mii_ts);
+
+ rc = fwnode_property_match_string(child, "compatible",
+ "ethernet-phy-ieee802.3-c45");
+ if (rc >= 0)
+ is_c45 = true;
+
+ if (is_c45 || fwnode_get_phy_id(child, &phy_id))
+ phy = get_phy_device(bus, addr, is_c45);
+ else
+ phy = phy_device_create(bus, addr, phy_id, 0, NULL);
+ if (IS_ERR(phy)) {
+ unregister_mii_timestamper(mii_ts);
+ return PTR_ERR(phy);
+ }
+
+ if (is_acpi_node(child)) {
+ phy->irq = bus->irq[addr];
+
+ /* Associate the fwnode with the device structure so it
+ * can be looked up later.
+ */
+ phy->mdio.dev.fwnode = child;
+
+ /* All data is now stored in the phy struct, so register it */
+ rc = phy_device_register(phy);
+ if (rc) {
+ phy_device_free(phy);
+ fwnode_handle_put(phy->mdio.dev.fwnode);
+ return rc;
+ }
+ } else if (is_of_node(child)) {
+ rc = fwnode_mdiobus_phy_device_register(bus, phy, child, addr);
+ if (rc) {
+ unregister_mii_timestamper(mii_ts);
+ phy_device_free(phy);
+ return rc;
+ }
+ }
+
+ /* phy->mii_ts may already be defined by the PHY driver. A
+ * mii_timestamper probed via the device tree will still have
+ * precedence.
+ */
+ if (mii_ts)
+ phy->mii_ts = mii_ts;
+ return 0;
+}
+EXPORT_SYMBOL(fwnode_mdiobus_register_phy);
diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index d73c0570f19c..17327bbc1de4 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -10,6 +10,7 @@

#include <linux/device.h>
#include <linux/err.h>
+#include <linux/fwnode_mdio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
@@ -51,46 +52,11 @@ static struct mii_timestamper *of_find_mii_timestamper(struct device_node *node)
}

int of_mdiobus_phy_device_register(struct mii_bus *mdio, struct phy_device *phy,
- struct device_node *child, u32 addr)
+ struct device_node *child, u32 addr)
{
- int rc;
-
- rc = of_irq_get(child, 0);
- if (rc == -EPROBE_DEFER)
- return rc;
-
- if (rc > 0) {
- phy->irq = rc;
- mdio->irq[addr] = rc;
- } else {
- phy->irq = mdio->irq[addr];
- }
-
- if (of_property_read_bool(child, "broken-turn-around"))
- mdio->phy_ignore_ta_mask |= 1 << addr;
-
- of_property_read_u32(child, "reset-assert-us",
- &phy->mdio.reset_assert_delay);
- of_property_read_u32(child, "reset-deassert-us",
- &phy->mdio.reset_deassert_delay);
-
- /* Associate the OF node with the device structure so it
- * can be looked up later */
- of_node_get(child);
- phy->mdio.dev.of_node = child;
- phy->mdio.dev.fwnode = of_fwnode_handle(child);
-
- /* All data is now stored in the phy struct;
- * register it */
- rc = phy_device_register(phy);
- if (rc) {
- of_node_put(child);
- return rc;
- }
-
- dev_dbg(&mdio->dev, "registered phy %pOFn at address %i\n",
- child, addr);
- return 0;
+ return fwnode_mdiobus_phy_device_register(mdio, phy,
+ of_fwnode_handle(child),
+ addr);
}
EXPORT_SYMBOL(of_mdiobus_phy_device_register);

diff --git a/include/linux/fwnode_mdio.h b/include/linux/fwnode_mdio.h
new file mode 100644
index 000000000000..faf603c48c86
--- /dev/null
+++ b/include/linux/fwnode_mdio.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * FWNODE helper for the MDIO (Ethernet PHY) API
+ */
+
+#ifndef __LINUX_FWNODE_MDIO_H
+#define __LINUX_FWNODE_MDIO_H
+
+#include <linux/phy.h>
+
+#if IS_ENABLED(CONFIG_FWNODE_MDIO)
+int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
+ struct phy_device *phy,
+ struct fwnode_handle *child, u32 addr);
+
+int fwnode_mdiobus_register_phy(struct mii_bus *bus,
+ struct fwnode_handle *child, u32 addr);
+
+#else /* CONFIG_FWNODE_MDIO */
+int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
+ struct phy_device *phy,
+ struct fwnode_handle *child, u32 addr)
+{
+ return -EINVAL;
+}
+
+static inline int fwnode_mdiobus_register_phy(struct mii_bus *bus,
+ struct fwnode_handle *child,
+ u32 addr)
+{
+ return -EINVAL;
+}
+#endif
+
+#endif /* __LINUX_FWNODE_MDIO_H */
--
2.31.1

2021-06-11 11:00:52

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 04/15] of: mdio: Refactor of_phy_find_device()

From: Calvin Johnson <[email protected]>

Refactor of_phy_find_device() to use fwnode_phy_find_device().

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9: None
Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

drivers/net/mdio/of_mdio.c | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index 6ef8b6e40189..0ba1158796d9 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -360,18 +360,7 @@ EXPORT_SYMBOL(of_mdio_find_device);
*/
struct phy_device *of_phy_find_device(struct device_node *phy_np)
{
- struct mdio_device *mdiodev;
-
- mdiodev = of_mdio_find_device(phy_np);
- if (!mdiodev)
- return NULL;
-
- if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
- return to_phy_device(&mdiodev->dev);
-
- put_device(&mdiodev->dev);
-
- return NULL;
+ return fwnode_phy_find_device(of_fwnode_handle(phy_np));
}
EXPORT_SYMBOL(of_phy_find_device);

--
2.31.1

2021-06-11 11:00:55

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 13/15] net: phylink: introduce phylink_fwnode_phy_connect()

From: Calvin Johnson <[email protected]>

Define phylink_fwnode_phy_connect() to connect phy specified by
a fwnode to a phylink instance.

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9: None
Changes in v8: None
Changes in v7: None
Changes in v6:
- remove OF check for fixed-link

Changes in v5: None
Changes in v4:
- call phy_device_free() before returning

Changes in v3: None
Changes in v2: None



drivers/net/phy/phylink.c | 54 +++++++++++++++++++++++++++++++++++++++
include/linux/phylink.h | 3 +++
2 files changed, 57 insertions(+)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 96d8e88b4e46..9cc0f69faafe 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2015 Russell King
*/
+#include <linux/acpi.h>
#include <linux/ethtool.h>
#include <linux/export.h>
#include <linux/gpio/consumer.h>
@@ -1125,6 +1126,59 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
}
EXPORT_SYMBOL_GPL(phylink_of_phy_connect);

+/**
+ * phylink_fwnode_phy_connect() - connect the PHY specified in the fwnode.
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ * @fwnode: a pointer to a &struct fwnode_handle.
+ * @flags: PHY-specific flags to communicate to the PHY device driver
+ *
+ * Connect the phy specified @fwnode to the phylink instance specified
+ * by @pl.
+ *
+ * Returns 0 on success or a negative errno.
+ */
+int phylink_fwnode_phy_connect(struct phylink *pl,
+ struct fwnode_handle *fwnode,
+ u32 flags)
+{
+ struct fwnode_handle *phy_fwnode;
+ struct phy_device *phy_dev;
+ int ret;
+
+ /* Fixed links and 802.3z are handled without needing a PHY */
+ if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
+ (pl->cfg_link_an_mode == MLO_AN_INBAND &&
+ phy_interface_mode_is_8023z(pl->link_interface)))
+ return 0;
+
+ phy_fwnode = fwnode_get_phy_node(fwnode);
+ if (IS_ERR(phy_fwnode)) {
+ if (pl->cfg_link_an_mode == MLO_AN_PHY)
+ return -ENODEV;
+ return 0;
+ }
+
+ phy_dev = fwnode_phy_find_device(phy_fwnode);
+ /* We're done with the phy_node handle */
+ fwnode_handle_put(phy_fwnode);
+ if (!phy_dev)
+ return -ENODEV;
+
+ ret = phy_attach_direct(pl->netdev, phy_dev, flags,
+ pl->link_interface);
+ if (ret) {
+ phy_device_free(phy_dev);
+ return ret;
+ }
+
+ ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface);
+ if (ret)
+ phy_detach(phy_dev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phylink_fwnode_phy_connect);
+
/**
* phylink_disconnect_phy() - disconnect any PHY attached to the phylink
* instance.
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index fd2acfd9b597..afb3ded0b691 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -441,6 +441,9 @@ void phylink_destroy(struct phylink *);

int phylink_connect_phy(struct phylink *, struct phy_device *);
int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
+int phylink_fwnode_phy_connect(struct phylink *pl,
+ struct fwnode_handle *fwnode,
+ u32 flags);
void phylink_disconnect_phy(struct phylink *);

void phylink_mac_change(struct phylink *, bool up);
--
2.31.1

2021-06-11 11:00:57

by Ioana Ciornei

[permalink] [raw]
Subject: [PATCH net-next v9 03/15] net: phy: Introduce phy related fwnode functions

From: Calvin Johnson <[email protected]>

Define fwnode_phy_find_device() to iterate an mdiobus and find the
phy device of the provided phy fwnode. Additionally define
device_phy_find_device() to find phy device of provided device.

Define fwnode_get_phy_node() to get phy_node using named reference.

Signed-off-by: Calvin Johnson <[email protected]>
Signed-off-by: Ioana Ciornei <[email protected]>
Acked-by: Grant Likely <[email protected]>
---

Changes in v9: None
Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
- Add more info on legacy DT properties "phy" and "phy-device"
- Redefine fwnode_phy_find_device() to follow of_phy_find_device()

Changes in v2:
- use reverse christmas tree ordering for local variables


drivers/net/phy/phy_device.c | 62 ++++++++++++++++++++++++++++++++++++
include/linux/phy.h | 20 ++++++++++++
2 files changed, 82 insertions(+)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index dca454b5c209..786f464216dd 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -9,6 +9,7 @@

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

+#include <linux/acpi.h>
#include <linux/bitmap.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -2898,6 +2899,67 @@ struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
}
EXPORT_SYMBOL(fwnode_mdio_find_device);

+/**
+ * fwnode_phy_find_device - For provided phy_fwnode, find phy_device.
+ *
+ * @phy_fwnode: Pointer to the phy's fwnode.
+ *
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure.
+ */
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)
+{
+ struct mdio_device *mdiodev;
+
+ mdiodev = fwnode_mdio_find_device(phy_fwnode);
+ if (!mdiodev)
+ return NULL;
+
+ if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
+ return to_phy_device(&mdiodev->dev);
+
+ put_device(&mdiodev->dev);
+
+ return NULL;
+}
+EXPORT_SYMBOL(fwnode_phy_find_device);
+
+/**
+ * device_phy_find_device - For the given device, get the phy_device
+ * @dev: Pointer to the given device
+ *
+ * Refer return conditions of fwnode_phy_find_device().
+ */
+struct phy_device *device_phy_find_device(struct device *dev)
+{
+ return fwnode_phy_find_device(dev_fwnode(dev));
+}
+EXPORT_SYMBOL_GPL(device_phy_find_device);
+
+/**
+ * fwnode_get_phy_node - Get the phy_node using the named reference.
+ * @fwnode: Pointer to fwnode from which phy_node has to be obtained.
+ *
+ * Refer return conditions of fwnode_find_reference().
+ * For ACPI, only "phy-handle" is supported. Legacy DT properties "phy"
+ * and "phy-device" are not supported in ACPI. DT supports all the three
+ * named references to the phy node.
+ */
+struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
+{
+ struct fwnode_handle *phy_node;
+
+ /* Only phy-handle is used for ACPI */
+ phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
+ if (is_acpi_node(fwnode) || !IS_ERR(phy_node))
+ return phy_node;
+ phy_node = fwnode_find_reference(fwnode, "phy", 0);
+ if (IS_ERR(phy_node))
+ phy_node = fwnode_find_reference(fwnode, "phy-device", 0);
+ return phy_node;
+}
+EXPORT_SYMBOL_GPL(fwnode_get_phy_node);
+
/**
* phy_probe - probe and init a PHY device
* @dev: device to probe and init
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7aa97f4e5387..f9b5fb099fa6 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1378,6 +1378,9 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
struct phy_c45_device_ids *c45_ids);
#if IS_ENABLED(CONFIG_PHYLIB)
struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode);
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode);
+struct phy_device *device_phy_find_device(struct device *dev);
+struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode);
struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
int phy_device_register(struct phy_device *phy);
void phy_device_free(struct phy_device *phydev);
@@ -1388,6 +1391,23 @@ struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
return 0;
}

+static inline
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)
+{
+ return NULL;
+}
+
+static inline struct phy_device *device_phy_find_device(struct device *dev)
+{
+ return NULL;
+}
+
+static inline
+struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+
static inline
struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
{
--
2.31.1

2021-06-11 11:19:50

by Russell King (Oracle)

[permalink] [raw]
Subject: Re: [PATCH net-next v9 14/15] net: phylink: Refactor phylink_of_phy_connect()

On Fri, Jun 11, 2021 at 01:54:00PM +0300, Ioana Ciornei wrote:
> From: Calvin Johnson <[email protected]>
>
> Refactor phylink_of_phy_connect() to use phylink_fwnode_phy_connect().
>
> Signed-off-by: Calvin Johnson <[email protected]>
> Signed-off-by: Ioana Ciornei <[email protected]>
> Acked-by: Grant Likely <[email protected]>

Reviewed-by: Russell King (Oracle) <[email protected]>

Thanks.

--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

2021-06-11 11:21:22

by Russell King (Oracle)

[permalink] [raw]
Subject: Re: [PATCH net-next v9 13/15] net: phylink: introduce phylink_fwnode_phy_connect()

On Fri, Jun 11, 2021 at 01:53:59PM +0300, Ioana Ciornei wrote:
> From: Calvin Johnson <[email protected]>
>
> Define phylink_fwnode_phy_connect() to connect phy specified by
> a fwnode to a phylink instance.
>
> Signed-off-by: Calvin Johnson <[email protected]>
> Signed-off-by: Ioana Ciornei <[email protected]>
> Acked-by: Grant Likely <[email protected]>

Reviewed-by: Russell King (Oracle) <[email protected]>

Thanks.

> ---
>
> Changes in v9: None
> Changes in v8: None
> Changes in v7: None
> Changes in v6:
> - remove OF check for fixed-link
>
> Changes in v5: None
> Changes in v4:
> - call phy_device_free() before returning
>
> Changes in v3: None
> Changes in v2: None
>
>
>
> drivers/net/phy/phylink.c | 54 +++++++++++++++++++++++++++++++++++++++
> include/linux/phylink.h | 3 +++
> 2 files changed, 57 insertions(+)
>
> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index 96d8e88b4e46..9cc0f69faafe 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c
> @@ -5,6 +5,7 @@
> *
> * Copyright (C) 2015 Russell King
> */
> +#include <linux/acpi.h>
> #include <linux/ethtool.h>
> #include <linux/export.h>
> #include <linux/gpio/consumer.h>
> @@ -1125,6 +1126,59 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
> }
> EXPORT_SYMBOL_GPL(phylink_of_phy_connect);
>
> +/**
> + * phylink_fwnode_phy_connect() - connect the PHY specified in the fwnode.
> + * @pl: a pointer to a &struct phylink returned from phylink_create()
> + * @fwnode: a pointer to a &struct fwnode_handle.
> + * @flags: PHY-specific flags to communicate to the PHY device driver
> + *
> + * Connect the phy specified @fwnode to the phylink instance specified
> + * by @pl.
> + *
> + * Returns 0 on success or a negative errno.
> + */
> +int phylink_fwnode_phy_connect(struct phylink *pl,
> + struct fwnode_handle *fwnode,
> + u32 flags)
> +{
> + struct fwnode_handle *phy_fwnode;
> + struct phy_device *phy_dev;
> + int ret;
> +
> + /* Fixed links and 802.3z are handled without needing a PHY */
> + if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
> + (pl->cfg_link_an_mode == MLO_AN_INBAND &&
> + phy_interface_mode_is_8023z(pl->link_interface)))
> + return 0;
> +
> + phy_fwnode = fwnode_get_phy_node(fwnode);
> + if (IS_ERR(phy_fwnode)) {
> + if (pl->cfg_link_an_mode == MLO_AN_PHY)
> + return -ENODEV;
> + return 0;
> + }
> +
> + phy_dev = fwnode_phy_find_device(phy_fwnode);
> + /* We're done with the phy_node handle */
> + fwnode_handle_put(phy_fwnode);
> + if (!phy_dev)
> + return -ENODEV;
> +
> + ret = phy_attach_direct(pl->netdev, phy_dev, flags,
> + pl->link_interface);
> + if (ret) {
> + phy_device_free(phy_dev);
> + return ret;
> + }
> +
> + ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface);
> + if (ret)
> + phy_detach(phy_dev);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(phylink_fwnode_phy_connect);
> +
> /**
> * phylink_disconnect_phy() - disconnect any PHY attached to the phylink
> * instance.
> diff --git a/include/linux/phylink.h b/include/linux/phylink.h
> index fd2acfd9b597..afb3ded0b691 100644
> --- a/include/linux/phylink.h
> +++ b/include/linux/phylink.h
> @@ -441,6 +441,9 @@ void phylink_destroy(struct phylink *);
>
> int phylink_connect_phy(struct phylink *, struct phy_device *);
> int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
> +int phylink_fwnode_phy_connect(struct phylink *pl,
> + struct fwnode_handle *fwnode,
> + u32 flags);
> void phylink_disconnect_phy(struct phylink *);
>
> void phylink_mac_change(struct phylink *, bool up);
> --
> 2.31.1
>
>

--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

2021-06-11 11:24:17

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH net-next v9 02/15] net: phy: Introduce fwnode_mdio_find_device()

On Fri, Jun 11, 2021 at 1:54 PM Ioana Ciornei <[email protected]> wrote:
>
> From: Calvin Johnson <[email protected]>
>
> Define fwnode_mdio_find_device() to get a pointer to the
> mdio_device from fwnode passed to the function.

> Refactor of_mdio_find_device() to use fwnode_mdio_find_device().

That's what I meant. Is this series converting two users to use
fwnode_mdio_find_device()? If not, it should do this and kill
of_mdio_find_device() completely.

--
With Best Regards,
Andy Shevchenko

2021-06-11 11:30:15

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH net-next v9 03/15] net: phy: Introduce phy related fwnode functions

On Fri, Jun 11, 2021 at 1:54 PM Ioana Ciornei <[email protected]> wrote:
>
> From: Calvin Johnson <[email protected]>
>
> Define fwnode_phy_find_device() to iterate an mdiobus and find the
> phy device of the provided phy fwnode. Additionally define
> device_phy_find_device() to find phy device of provided device.
>
> Define fwnode_get_phy_node() to get phy_node using named reference.

using a named

...

> +struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
> +{
> + struct fwnode_handle *phy_node;
> +
> + /* Only phy-handle is used for ACPI */
> + phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
> + if (is_acpi_node(fwnode) || !IS_ERR(phy_node))
> + return phy_node;
> + phy_node = fwnode_find_reference(fwnode, "phy", 0);
> + if (IS_ERR(phy_node))
> + phy_node = fwnode_find_reference(fwnode, "phy-device", 0);
> + return phy_node;

Looking into the patterns in this code I would perhaps refactor it the
following way:

/* First try "phy-handle" as most common in use */
phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
/* Only phy-handle is used for ACPI */
if (is_acpi_node(fwnode))
return phy_node;
if (!IS_ERR(phy_node))
return phy_node;
/* Try "phy" reference */
phy_node = fwnode_find_reference(fwnode, "phy", 0);
if (!IS_ERR(phy_node))
return phy_node;
/* At last try "phy-device" reference */
return fwnode_find_reference(fwnode, "phy-device", 0);

> +}


--
With Best Regards,
Andy Shevchenko

2021-06-11 11:31:50

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH net-next v9 04/15] of: mdio: Refactor of_phy_find_device()

On Fri, Jun 11, 2021 at 1:54 PM Ioana Ciornei <[email protected]> wrote:
>
> From: Calvin Johnson <[email protected]>
>
> Refactor of_phy_find_device() to use fwnode_phy_find_device().

I see that there are many users of this, but I think eventually we
should kill of_phy_find_device() completely.

--
With Best Regards,
Andy Shevchenko

2021-06-11 11:32:42

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH net-next v9 04/15] of: mdio: Refactor of_phy_find_device()

On Fri, Jun 11, 2021 at 2:28 PM Andy Shevchenko
<[email protected]> wrote:
> On Fri, Jun 11, 2021 at 1:54 PM Ioana Ciornei <[email protected]> wrote:
> >
> > From: Calvin Johnson <[email protected]>
> >
> > Refactor of_phy_find_device() to use fwnode_phy_find_device().
>
> I see that there are many users of this, but I think eventually we
> should kill of_phy_find_device() completely.

Looking into other examples of such I think this series may not touch
them right now, but clearly state that it's the plan in the future to
kill this kind of OF APIs that call fwnode underneath.


--
With Best Regards,
Andy Shevchenko

2021-06-11 11:39:00

by Russell King (Oracle)

[permalink] [raw]
Subject: Re: [PATCH net-next v9 04/15] of: mdio: Refactor of_phy_find_device()

On Fri, Jun 11, 2021 at 02:30:19PM +0300, Andy Shevchenko wrote:
> On Fri, Jun 11, 2021 at 2:28 PM Andy Shevchenko
> <[email protected]> wrote:
> > On Fri, Jun 11, 2021 at 1:54 PM Ioana Ciornei <[email protected]> wrote:
> > >
> > > From: Calvin Johnson <[email protected]>
> > >
> > > Refactor of_phy_find_device() to use fwnode_phy_find_device().
> >
> > I see that there are many users of this, but I think eventually we
> > should kill of_phy_find_device() completely.
>
> Looking into other examples of such I think this series may not touch
> them right now, but clearly state that it's the plan in the future to
> kill this kind of OF APIs that call fwnode underneath.

That's something I most definitely support - once we have the fwnode
APIs in place, the OF specific APIs become an additional maintenance
burden that we don't need. So, I would also like to see the old APIs
killed.

--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

2021-06-11 11:44:36

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [PATCH net-next v9 03/15] net: phy: Introduce phy related fwnode functions

On Fri, Jun 11, 2021 at 1:26 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Fri, Jun 11, 2021 at 1:54 PM Ioana Ciornei <[email protected]> wrote:
> >
> > From: Calvin Johnson <[email protected]>
> >
> > Define fwnode_phy_find_device() to iterate an mdiobus and find the
> > phy device of the provided phy fwnode. Additionally define
> > device_phy_find_device() to find phy device of provided device.
> >
> > Define fwnode_get_phy_node() to get phy_node using named reference.
>
> using a named
>
> ...
>
> > +struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
> > +{
> > + struct fwnode_handle *phy_node;
> > +
> > + /* Only phy-handle is used for ACPI */
> > + phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
> > + if (is_acpi_node(fwnode) || !IS_ERR(phy_node))
> > + return phy_node;
> > + phy_node = fwnode_find_reference(fwnode, "phy", 0);
> > + if (IS_ERR(phy_node))
> > + phy_node = fwnode_find_reference(fwnode, "phy-device", 0);
> > + return phy_node;
>
> Looking into the patterns in this code I would perhaps refactor it the
> following way:
>
> /* First try "phy-handle" as most common in use */
> phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
> /* Only phy-handle is used for ACPI */
> if (is_acpi_node(fwnode))
> return phy_node;
> if (!IS_ERR(phy_node))
> return phy_node;

I'm not sure why you want the above to be two if () statements instead of one?

I would change the ordering anyway, that is

if (!IS_ERR(phy_node) || is_acpi_node(fwnode))
return phy_node;

And I think that the is_acpi_node() check is there to return the error
code right away so as to avoid returning a "not found" error later.

But I'm not sure if this is really necessary. Namely, if nothing
depends on the specific error code returned by this function, it would
be somewhat cleaner to let the code below run if phy_node is an error
pointer in the ACPI case, because in that case the code below will
produce an error pointer anyway.

> /* Try "phy" reference */
> phy_node = fwnode_find_reference(fwnode, "phy", 0);
> if (!IS_ERR(phy_node))
> return phy_node;
> /* At last try "phy-device" reference */
> return fwnode_find_reference(fwnode, "phy-device", 0);
>
> > +}

2021-06-11 12:10:50

by Russell King (Oracle)

[permalink] [raw]
Subject: Re: [PATCH net-next v9 03/15] net: phy: Introduce phy related fwnode functions

On Fri, Jun 11, 2021 at 01:40:59PM +0200, Rafael J. Wysocki wrote:
> I'm not sure why you want the above to be two if () statements instead of one?
>
> I would change the ordering anyway, that is
>
> if (!IS_ERR(phy_node) || is_acpi_node(fwnode))
> return phy_node;
>
> And I think that the is_acpi_node() check is there to return the error
> code right away so as to avoid returning a "not found" error later.
>
> But I'm not sure if this is really necessary. Namely, if nothing
> depends on the specific error code returned by this function, it would
> be somewhat cleaner to let the code below run if phy_node is an error
> pointer in the ACPI case, because in that case the code below will
> produce an error pointer anyway.

However, that opens the door to someone shipping "working" ACPI with
one of these names that we've taken the decision not to support on
ACPI firmware. Surely, it's much better that we don't accept the
legacy names so we don't allow such configurations to work.


--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

2021-06-11 12:33:38

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [PATCH net-next v9 03/15] net: phy: Introduce phy related fwnode functions

On Fri, Jun 11, 2021 at 2:08 PM Russell King (Oracle)
<[email protected]> wrote:
>
> On Fri, Jun 11, 2021 at 01:40:59PM +0200, Rafael J. Wysocki wrote:
> > I'm not sure why you want the above to be two if () statements instead of one?
> >
> > I would change the ordering anyway, that is
> >
> > if (!IS_ERR(phy_node) || is_acpi_node(fwnode))
> > return phy_node;
> >
> > And I think that the is_acpi_node() check is there to return the error
> > code right away so as to avoid returning a "not found" error later.
> >
> > But I'm not sure if this is really necessary. Namely, if nothing
> > depends on the specific error code returned by this function, it would
> > be somewhat cleaner to let the code below run if phy_node is an error
> > pointer in the ACPI case, because in that case the code below will
> > produce an error pointer anyway.
>
> However, that opens the door to someone shipping "working" ACPI with
> one of these names that we've taken the decision not to support on
> ACPI firmware. Surely, it's much better that we don't accept the
> legacy names so we don't allow such configurations to work.

Fair enough.

2021-06-11 20:24:05

by patchwork-bot+netdevbpf

[permalink] [raw]
Subject: Re: [PATCH net-next v9 00/15] ACPI support for dpaa2 driver

Hello:

This series was applied to netdev/net-next.git (refs/heads/master):

On Fri, 11 Jun 2021 13:53:46 +0300 you wrote:
> From: Ioana Ciornei <[email protected]>
>
> This patch set provides ACPI support to DPAA2 network drivers.
>
> It also introduces new fwnode based APIs to support phylink and phy
> layers
> Following functions are defined:
> phylink_fwnode_phy_connect()
> fwnode_mdiobus_register_phy()
> fwnode_get_phy_id()
> fwnode_phy_find_device()
> device_phy_find_device()
> fwnode_get_phy_node()
> fwnode_mdio_find_device()
> acpi_get_local_address()
>
> [...]

Here is the summary with links:
- [net-next,v9,01/15] Documentation: ACPI: DSD: Document MDIO PHY
https://git.kernel.org/netdev/net-next/c/e71305acd81c
- [net-next,v9,02/15] net: phy: Introduce fwnode_mdio_find_device()
https://git.kernel.org/netdev/net-next/c/0fb169767651
- [net-next,v9,03/15] net: phy: Introduce phy related fwnode functions
https://git.kernel.org/netdev/net-next/c/425775ed31a6
- [net-next,v9,04/15] of: mdio: Refactor of_phy_find_device()
https://git.kernel.org/netdev/net-next/c/2d7b8bf1fa7a
- [net-next,v9,05/15] net: phy: Introduce fwnode_get_phy_id()
https://git.kernel.org/netdev/net-next/c/114dea60043b
- [net-next,v9,06/15] of: mdio: Refactor of_get_phy_id()
https://git.kernel.org/netdev/net-next/c/cf99686072a1
- [net-next,v9,07/15] net: mii_timestamper: check NULL in unregister_mii_timestamper()
https://git.kernel.org/netdev/net-next/c/b9926da003ca
- [net-next,v9,08/15] net: mdiobus: Introduce fwnode_mdiobus_register_phy()
https://git.kernel.org/netdev/net-next/c/bc1bee3b87ee
- [net-next,v9,09/15] of: mdio: Refactor of_mdiobus_register_phy()
https://git.kernel.org/netdev/net-next/c/8d2cb3ad3118
- [net-next,v9,10/15] ACPI: utils: Introduce acpi_get_local_address()
https://git.kernel.org/netdev/net-next/c/7ec16433cf1e
- [net-next,v9,11/15] net: mdio: Add ACPI support code for mdio
https://git.kernel.org/netdev/net-next/c/803ca24d2f92
- [net-next,v9,12/15] net/fsl: Use [acpi|of]_mdiobus_register
https://git.kernel.org/netdev/net-next/c/15e7064e8793
- [net-next,v9,13/15] net: phylink: introduce phylink_fwnode_phy_connect()
https://git.kernel.org/netdev/net-next/c/25396f680dd6
- [net-next,v9,14/15] net: phylink: Refactor phylink_of_phy_connect()
https://git.kernel.org/netdev/net-next/c/423e6e8946f5
- [net-next,v9,15/15] net: dpaa2-mac: Add ACPI support for DPAA2 MAC driver
https://git.kernel.org/netdev/net-next/c/3264f599c1a8

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html


2021-06-15 20:18:55

by andy

[permalink] [raw]
Subject: Re: [PATCH net-next v9 08/15] net: mdiobus: Introduce fwnode_mdiobus_register_phy()

Fri, Jun 11, 2021 at 01:53:54PM +0300, Ioana Ciornei kirjoitti:
> From: Calvin Johnson <[email protected]>
>
> Introduce fwnode_mdiobus_register_phy() to register PHYs on the
> mdiobus. From the compatible string, identify whether the PHY is
> c45 and based on this create a PHY device instance which is
> registered on the mdiobus.
>
> Along with fwnode_mdiobus_register_phy() also introduce
> fwnode_find_mii_timestamper() and fwnode_mdiobus_phy_device_register()
> since they are needed.
> While at it, also use the newly introduced fwnode operation in
> of_mdiobus_phy_device_register().

I understand that this patch series is applied, but I think we have a problem
that has to be fixed before the release. See below for the details.

...

> +int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
> + struct phy_device *phy,
> + struct fwnode_handle *child, u32 addr)
> +{
> + int rc;
> +
> + rc = fwnode_irq_get(child, 0);
> + if (rc == -EPROBE_DEFER)
> + return rc;
> +
> + if (rc > 0) {
> + phy->irq = rc;
> + mdio->irq[addr] = rc;
> + } else {
> + phy->irq = mdio->irq[addr];
> + }
> +
> + if (fwnode_property_read_bool(child, "broken-turn-around"))
> + mdio->phy_ignore_ta_mask |= 1 << addr;
> +
> + fwnode_property_read_u32(child, "reset-assert-us",
> + &phy->mdio.reset_assert_delay);
> + fwnode_property_read_u32(child, "reset-deassert-us",
> + &phy->mdio.reset_deassert_delay);
> +
> + /* Associate the fwnode with the device structure so it
> + * can be looked up later
> + */

> + fwnode_handle_get(child);

We take a reference counting here.
Who and when should drop it?

> + phy->mdio.dev.fwnode = child;
> +
> + /* All data is now stored in the phy struct;
> + * register it
> + */
> + rc = phy_device_register(phy);
> + if (rc) {
> + fwnode_handle_put(child);
> + return rc;
> + }
> +
> + dev_dbg(&mdio->dev, "registered phy %p fwnode at address %i\n",
> + child, addr);
> + return 0;
> +}
> +EXPORT_SYMBOL(fwnode_mdiobus_phy_device_register);
> +
> +int fwnode_mdiobus_register_phy(struct mii_bus *bus,
> + struct fwnode_handle *child, u32 addr)
> +{
> + struct mii_timestamper *mii_ts = NULL;
> + struct phy_device *phy;
> + bool is_c45 = false;
> + u32 phy_id;
> + int rc;
> +
> + mii_ts = fwnode_find_mii_timestamper(child);
> + if (IS_ERR(mii_ts))
> + return PTR_ERR(mii_ts);
> +
> + rc = fwnode_property_match_string(child, "compatible",
> + "ethernet-phy-ieee802.3-c45");
> + if (rc >= 0)
> + is_c45 = true;
> +
> + if (is_c45 || fwnode_get_phy_id(child, &phy_id))
> + phy = get_phy_device(bus, addr, is_c45);
> + else
> + phy = phy_device_create(bus, addr, phy_id, 0, NULL);
> + if (IS_ERR(phy)) {
> + unregister_mii_timestamper(mii_ts);
> + return PTR_ERR(phy);
> + }
> +
> + if (is_acpi_node(child)) {
> + phy->irq = bus->irq[addr];
> +
> + /* Associate the fwnode with the device structure so it
> + * can be looked up later.
> + */
> + phy->mdio.dev.fwnode = child;
> +
> + /* All data is now stored in the phy struct, so register it */
> + rc = phy_device_register(phy);
> + if (rc) {
> + phy_device_free(phy);

> + fwnode_handle_put(phy->mdio.dev.fwnode);

We dropped reference counting here, but who and when acquired it?

> + return rc;
> + }
> + } else if (is_of_node(child)) {
> + rc = fwnode_mdiobus_phy_device_register(bus, phy, child, addr);
> + if (rc) {
> + unregister_mii_timestamper(mii_ts);
> + phy_device_free(phy);
> + return rc;
> + }
> + }
> +
> + /* phy->mii_ts may already be defined by the PHY driver. A
> + * mii_timestamper probed via the device tree will still have
> + * precedence.
> + */
> + if (mii_ts)
> + phy->mii_ts = mii_ts;
> + return 0;
> +}

--
With Best Regards,
Andy Shevchenko


2021-06-15 20:23:11

by andy

[permalink] [raw]
Subject: Re: [PATCH net-next v9 13/15] net: phylink: introduce phylink_fwnode_phy_connect()

Fri, Jun 11, 2021 at 01:53:59PM +0300, Ioana Ciornei kirjoitti:
> From: Calvin Johnson <[email protected]>
>
> Define phylink_fwnode_phy_connect() to connect phy specified by
> a fwnode to a phylink instance.

...

> +/**
> + * phylink_fwnode_phy_connect() - connect the PHY specified in the fwnode.
> + * @pl: a pointer to a &struct phylink returned from phylink_create()
> + * @fwnode: a pointer to a &struct fwnode_handle.
> + * @flags: PHY-specific flags to communicate to the PHY device driver
> + *
> + * Connect the phy specified @fwnode to the phylink instance specified
> + * by @pl.
> + *
> + * Returns 0 on success or a negative errno.
> + */
> +int phylink_fwnode_phy_connect(struct phylink *pl,
> + struct fwnode_handle *fwnode,
> + u32 flags)
> +{
> + struct fwnode_handle *phy_fwnode;
> + struct phy_device *phy_dev;
> + int ret;
> +
> + /* Fixed links and 802.3z are handled without needing a PHY */
> + if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
> + (pl->cfg_link_an_mode == MLO_AN_INBAND &&
> + phy_interface_mode_is_8023z(pl->link_interface)))
> + return 0;
> +
> + phy_fwnode = fwnode_get_phy_node(fwnode);
> + if (IS_ERR(phy_fwnode)) {
> + if (pl->cfg_link_an_mode == MLO_AN_PHY)
> + return -ENODEV;
> + return 0;
> + }
> +
> + phy_dev = fwnode_phy_find_device(phy_fwnode);
> + /* We're done with the phy_node handle */
> + fwnode_handle_put(phy_fwnode);

As per previous mail, who and when acquire this reference counting? Can it be
possible that caller will never call phylink_fwnode_phy_connect() and hence
reference counting will become disbalances?

We need to fix all this before the release.

> + if (!phy_dev)
> + return -ENODEV;
> +
> + ret = phy_attach_direct(pl->netdev, phy_dev, flags,
> + pl->link_interface);
> + if (ret) {
> + phy_device_free(phy_dev);
> + return ret;
> + }
> +
> + ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface);
> + if (ret)
> + phy_detach(phy_dev);
> +
> + return ret;
> +}

--
With Best Regards,
Andy Shevchenko