[PATCH 04/12] net: phy: unify get_phy_device and phy_device_create parameter list

From: Marco Felsch
Date: Wed Apr 05 2023 - 05:32:42 EST


Currently these two public APIs are used to create a 'struct phy_device'
device. In addition to that the device get_phy_device() can adapt the
is_c45 parameter as well if supprted by the mii bus.

Both APIs do have a different set of parameters which can be unified to
upcoming API extension. For this the 'struct phy_device_config' is
introduced which is the only parameter for both functions. This new
mechnism also adds the possiblity to read the configuration back within
the driver for possible validation checks.

Signed-off-by: Marco Felsch <m.felsch@xxxxxxxxxxxxxx>
---
drivers/net/ethernet/adi/adin1110.c | 6 ++-
drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 8 +++-
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 11 +++--
drivers/net/ethernet/socionext/netsec.c | 7 ++-
drivers/net/mdio/fwnode_mdio.c | 13 +++---
drivers/net/mdio/mdio-xgene.c | 6 ++-
drivers/net/phy/fixed_phy.c | 6 ++-
drivers/net/phy/mdio_bus.c | 7 ++-
drivers/net/phy/nxp-tja11xx.c | 23 +++++-----
drivers/net/phy/phy_device.c | 55 ++++++++++++-----------
drivers/net/phy/sfp.c | 7 ++-
include/linux/phy.h | 29 +++++++++---
12 files changed, 121 insertions(+), 57 deletions(-)

diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c
index 3f316a0f4158..01b0c2a3a294 100644
--- a/drivers/net/ethernet/adi/adin1110.c
+++ b/drivers/net/ethernet/adi/adin1110.c
@@ -1565,6 +1565,9 @@ static int adin1110_probe_netdevs(struct adin1110_priv *priv)
{
struct device *dev = &priv->spidev->dev;
struct adin1110_port_priv *port_priv;
+ struct phy_device_config config = {
+ .mii_bus = priv->mii_bus,
+ };
struct net_device *netdev;
int ret;
int i;
@@ -1599,7 +1602,8 @@ static int adin1110_probe_netdevs(struct adin1110_priv *priv)
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->features |= NETIF_F_NETNS_LOCAL;

- port_priv->phydev = get_phy_device(priv->mii_bus, i + 1, false);
+ config.phy_addr = i + 1;
+ port_priv->phydev = get_phy_device(&config);
if (IS_ERR(port_priv->phydev)) {
netdev_err(netdev, "Could not find PHY with device address: %d.\n", i);
return PTR_ERR(port_priv->phydev);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 16e7fb2c0dae..27ba903bbd0a 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1056,6 +1056,10 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
{
struct ethtool_link_ksettings *lks = &pdata->phy.lks;
struct xgbe_phy_data *phy_data = pdata->phy_data;
+ struct phy_device_config config = {
+ .mii_bus = phy_data->mii,
+ .phy_addr = phy_data->mdio_addr,
+ };
struct phy_device *phydev;
int ret;

@@ -1086,8 +1090,8 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
}

/* Create and connect to the PHY device */
- phydev = get_phy_device(phy_data->mii, phy_data->mdio_addr,
- (phy_data->phydev_mode == XGBE_MDIO_MODE_CL45));
+ config.is_c45 = phy_data->phydev_mode == XGBE_MDIO_MODE_CL45;
+ phydev = get_phy_device(&config);
if (IS_ERR(phydev)) {
netdev_err(pdata->netdev, "get_phy_device failed\n");
return -ENODEV;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
index 928d934cb21a..3c41c4db5d9b 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -687,9 +687,12 @@ static int
hns_mac_register_phydev(struct mii_bus *mdio, struct hns_mac_cb *mac_cb,
u32 addr)
{
+ struct phy_device_config config = {
+ .mii_bus = mdio,
+ .phy_addr = addr,
+ };
struct phy_device *phy;
const char *phy_type;
- bool is_c45;
int rc;

rc = fwnode_property_read_string(mac_cb->fw_port,
@@ -698,13 +701,13 @@ hns_mac_register_phydev(struct mii_bus *mdio, struct hns_mac_cb *mac_cb,
return rc;

if (!strcmp(phy_type, phy_modes(PHY_INTERFACE_MODE_XGMII)))
- is_c45 = true;
+ config.is_c45 = true;
else if (!strcmp(phy_type, phy_modes(PHY_INTERFACE_MODE_SGMII)))
- is_c45 = false;
+ config.is_c45 = false;
else
return -ENODATA;

- phy = get_phy_device(mdio, addr, is_c45);
+ phy = get_phy_device(&config);
if (!phy || IS_ERR(phy))
return -EIO;

diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 2d7347b71c41..a0786dfb827a 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -1948,6 +1948,11 @@ static int netsec_register_mdio(struct netsec_priv *priv, u32 phy_addr)
return ret;
}
} else {
+ struct phy_device_config config = {
+ .mii_bus = bus,
+ .phy_addr = phy_addr,
+ };
+
/* Mask out all PHYs from auto probing. */
bus->phy_mask = ~0;
ret = mdiobus_register(bus);
@@ -1956,7 +1961,7 @@ static int netsec_register_mdio(struct netsec_priv *priv, u32 phy_addr)
return ret;
}

- priv->phydev = get_phy_device(bus, phy_addr, false);
+ priv->phydev = get_phy_device(&config);
if (IS_ERR(priv->phydev)) {
ret = PTR_ERR(priv->phydev);
dev_err(priv->dev, "get_phy_device err(%d)\n", ret);
diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c
index 1183ef5e203e..47ef702d4ffd 100644
--- a/drivers/net/mdio/fwnode_mdio.c
+++ b/drivers/net/mdio/fwnode_mdio.c
@@ -112,10 +112,13 @@ EXPORT_SYMBOL(fwnode_mdiobus_phy_device_register);
int fwnode_mdiobus_register_phy(struct mii_bus *bus,
struct fwnode_handle *child, u32 addr)
{
+ struct phy_device_config config = {
+ .mii_bus = bus,
+ .phy_addr = addr,
+ };
struct mii_timestamper *mii_ts = NULL;
struct pse_control *psec = NULL;
struct phy_device *phy;
- bool is_c45;
u32 phy_id;
int rc;

@@ -129,11 +132,11 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
goto clean_pse;
}

- is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45");
- if (is_c45 || fwnode_get_phy_id(child, &phy_id))
- phy = get_phy_device(bus, addr, is_c45);
+ config.is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45");
+ if (config.is_c45 || fwnode_get_phy_id(child, &config.phy_id))
+ phy = get_phy_device(&config);
else
- phy = phy_device_create(bus, addr, phy_id, 0, NULL);
+ phy = phy_device_create(&config);
if (IS_ERR(phy)) {
rc = PTR_ERR(phy);
goto clean_mii_ts;
diff --git a/drivers/net/mdio/mdio-xgene.c b/drivers/net/mdio/mdio-xgene.c
index 7aafc221b5cf..6754c35aa6c3 100644
--- a/drivers/net/mdio/mdio-xgene.c
+++ b/drivers/net/mdio/mdio-xgene.c
@@ -262,9 +262,13 @@ static int xgene_xfi_mdio_read(struct mii_bus *bus, int phy_id, int reg)

struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr)
{
+ struct phy_device_config config = {
+ .mii_bus = bus,
+ .phy_addr = phy_addr,
+ };
struct phy_device *phy_dev;

- phy_dev = get_phy_device(bus, phy_addr, false);
+ phy_dev = get_phy_device(&config);
if (!phy_dev || IS_ERR(phy_dev))
return NULL;

diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index aef739c20ac4..d217301a71d1 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -229,6 +229,9 @@ static struct phy_device *__fixed_phy_register(unsigned int irq,
struct gpio_desc *gpiod)
{
struct fixed_mdio_bus *fmb = &platform_fmb;
+ struct phy_device_config config = {
+ .mii_bus = fmb->mii_bus,
+ };
struct phy_device *phy;
int phy_addr;
int ret;
@@ -254,7 +257,8 @@ static struct phy_device *__fixed_phy_register(unsigned int irq,
return ERR_PTR(ret);
}

- phy = get_phy_device(fmb->mii_bus, phy_addr, false);
+ config.phy_addr = phy_addr;
+ phy = get_phy_device(&config);
if (IS_ERR(phy)) {
fixed_phy_del(phy_addr);
return ERR_PTR(-EINVAL);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 389f33a12534..8390db7ae4bc 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -516,9 +516,14 @@ static int mdiobus_create_device(struct mii_bus *bus,
static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45)
{
struct phy_device *phydev = ERR_PTR(-ENODEV);
+ struct phy_device_config config = {
+ .mii_bus = bus,
+ .phy_addr = addr,
+ .is_c45 = c45,
+ };
int err;

- phydev = get_phy_device(bus, addr, c45);
+ phydev = get_phy_device(&config);
if (IS_ERR(phydev))
return phydev;

diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
index ec91e671f8aa..b5e03d66b7f5 100644
--- a/drivers/net/phy/nxp-tja11xx.c
+++ b/drivers/net/phy/nxp-tja11xx.c
@@ -554,17 +554,20 @@ static void tja1102_p1_register(struct work_struct *work)
struct device *dev = &phydev_phy0->mdio.dev;
struct device_node *np = dev->of_node;
struct device_node *child;
- int ret;

for_each_available_child_of_node(np, child) {
+ struct phy_device_config config = {
+ .mii_bus = bus,
+ /* Real PHY ID of Port 1 is 0 */
+ .phy_id = PHY_ID_TJA1102,
+ };
struct phy_device *phy;
- int addr;

- addr = of_mdio_parse_addr(dev, child);
- if (addr < 0) {
+ config.phy_addr = of_mdio_parse_addr(dev, child);
+ if (config.phy_addr < 0) {
dev_err(dev, "Can't parse addr\n");
continue;
- } else if (addr != phydev_phy0->mdio.addr + 1) {
+ } else if (config.phy_addr != phydev_phy0->mdio.addr + 1) {
/* Currently we care only about double PHY chip TJA1102.
* If some day NXP will decide to bring chips with more
* PHYs, this logic should be reworked.
@@ -574,16 +577,15 @@ static void tja1102_p1_register(struct work_struct *work)
continue;
}

- if (mdiobus_is_registered_device(bus, addr)) {
+ if (mdiobus_is_registered_device(bus, config.phy_addr)) {
dev_err(dev, "device is already registered\n");
continue;
}

- /* Real PHY ID of Port 1 is 0 */
- phy = phy_device_create(bus, addr, PHY_ID_TJA1102, false, NULL);
+ phy = phy_device_create(&config);
if (IS_ERR(phy)) {
dev_err(dev, "Can't create PHY device for Port 1: %i\n",
- addr);
+ config.phy_addr);
continue;
}

@@ -592,7 +594,8 @@ static void tja1102_p1_register(struct work_struct *work)
*/
phy->mdio.dev.parent = dev;

- ret = of_mdiobus_phy_device_register(bus, phy, child, addr);
+ ret = of_mdiobus_phy_device_register(bus, phy, child,
+ config.phy_addr);
if (ret) {
/* All resources needed for Port 1 should be already
* available for Port 0. Both ports use the same
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index e4d08dcfed70..bb465a324eef 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -629,8 +629,10 @@ static int phy_request_driver_module(struct phy_device *dev, u32 phy_id)
return 0;
}

-static struct phy_device *phy_device_alloc(struct mii_bus *bus, int addr)
+static struct phy_device *phy_device_alloc(struct phy_device_config *config)
{
+ struct mii_bus *bus = config->mii_bus;
+ int addr = config->phy_addr;
struct phy_device *dev;
struct mdio_device *mdiodev;

@@ -656,9 +658,15 @@ static struct phy_device *phy_device_alloc(struct mii_bus *bus, int addr)
return dev;
}

-static int phy_device_init(struct phy_device *dev, u32 phy_id, bool is_c45,
- struct phy_c45_device_ids *c45_ids)
+static int phy_device_init(struct phy_device *dev,
+ struct phy_device_config *config)
{
+ struct phy_c45_device_ids *c45_ids = &config->c45_ids;
+ struct mii_bus *bus = config->mii_bus;
+ bool is_c45 = config->is_c45;
+ u32 phy_id = config->phy_id;
+ int addr = config->phy_addr;
+
dev->speed = SPEED_UNKNOWN;
dev->duplex = DUPLEX_UNKNOWN;
dev->pause = 0;
@@ -711,18 +719,16 @@ static int phy_device_init(struct phy_device *dev, u32 phy_id, bool is_c45,
return phy_request_driver_module(dev, phy_id);
}

-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)
+struct phy_device *phy_device_create(struct phy_device_config *config)
{
struct phy_device *dev;
int ret;

- dev = phy_device_alloc(bus, addr);
+ dev = phy_device_alloc(config);
if (IS_ERR(dev))
return dev;

- ret = phy_device_init(dev, phy_id, is_c45, c45_ids);
+ ret = phy_device_init(dev, config);
if (ret) {
put_device(&dev->mdio.dev);
dev = ERR_PTR(ret);
@@ -954,12 +960,16 @@ int fwnode_get_phy_id(struct fwnode_handle *fwnode, u32 *phy_id)
}
EXPORT_SYMBOL(fwnode_get_phy_id);

-static int phy_device_detect(struct mii_bus *bus, int addr, bool *is_c45,
- u32 *phy_id, struct phy_c45_device_ids *c45_ids)
+static int phy_device_detect(struct phy_device_config *config)
{
+ struct phy_c45_device_ids *c45_ids = &config->c45_ids;
+ struct mii_bus *bus = config->mii_bus;
+ u32 *phy_id = &config->phy_id;
+ bool is_c45 = config->is_c45;
+ int addr = config->phy_addr;
int r;

- if (*is_c45)
+ if (is_c45)
r = get_phy_c45_ids(bus, addr, c45_ids);
else
r = get_phy_c22_id(bus, addr, phy_id);
@@ -972,8 +982,8 @@ static int phy_device_detect(struct mii_bus *bus, int addr, bool *is_c45,
* probe with C45 to see if we're able to get a valid PHY ID in the C45
* space, if successful, create the C45 PHY device.
*/
- if (!*is_c45 && *phy_id == 0 && bus->read_c45) {
- *is_c45 = true;
+ if (!is_c45 && *phy_id == 0 && bus->read_c45) {
+ config->is_c45 = true;
return get_phy_c45_ids(bus, addr, c45_ids);
}

@@ -983,11 +993,9 @@ static int phy_device_detect(struct mii_bus *bus, int addr, bool *is_c45,
/**
* get_phy_device - reads the specified PHY device and returns its @phy_device
* struct
- * @bus: the target MII bus
- * @addr: PHY address on the MII bus
- * @is_c45: If true the PHY uses the 802.3 clause 45 protocol
+ * @config: The PHY device config
*
- * Probe for a PHY at @addr on @bus.
+ * Use the @config parameters to probe for a PHY.
*
* When probing for a clause 22 PHY, then read the ID registers. If we find
* a valid ID, allocate and return a &struct phy_device.
@@ -999,21 +1007,18 @@ static int phy_device_detect(struct mii_bus *bus, int addr, bool *is_c45,
* Returns an allocated &struct phy_device on success, %-ENODEV if there is
* no PHY present, or %-EIO on bus access error.
*/
-struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
+struct phy_device *get_phy_device(struct phy_device_config *config)
{
- struct phy_c45_device_ids c45_ids;
- u32 phy_id = 0;
+ struct phy_c45_device_ids *c45_ids = &config->c45_ids;
int r;

- c45_ids.devices_in_package = 0;
- c45_ids.mmds_present = 0;
- memset(c45_ids.device_ids, 0xff, sizeof(c45_ids.device_ids));
+ memset(c45_ids->device_ids, 0xff, sizeof(c45_ids->device_ids));

- r = phy_device_detect(bus, addr, &is_c45, &phy_id, &c45_ids);
+ r = phy_device_detect(config);
if (r)
return ERR_PTR(r);

- return phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);
+ return phy_device_create(config);
}
EXPORT_SYMBOL(get_phy_device);

diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index f0fcb06fbe82..8fb0a1a49aaf 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -1635,10 +1635,15 @@ static void sfp_sm_phy_detach(struct sfp *sfp)

static int sfp_sm_probe_phy(struct sfp *sfp, int addr, bool is_c45)
{
+ struct phy_device_config config = {
+ .mii_bus = sfp->i2c_mii,
+ .phy_addr = addr,
+ .is_c45 = is_c45,
+ };
struct phy_device *phy;
int err;

- phy = get_phy_device(sfp->i2c_mii, addr, is_c45);
+ phy = get_phy_device(&config);
if (phy == ERR_PTR(-ENODEV))
return PTR_ERR(phy);
if (IS_ERR(phy)) {
diff --git a/include/linux/phy.h b/include/linux/phy.h
index c17a98712555..498f4dc7669d 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -756,6 +756,27 @@ static inline struct phy_device *to_phy_device(const struct device *dev)
return container_of(to_mdio_device(dev), struct phy_device, mdio);
}

+/**
+ * struct phy_device_config - Configuration of a PHY
+ *
+ * @mii_bus: The target MII bus the PHY is connected to
+ * @phy_addr: PHY address on the MII bus
+ * @phy_id: UID for this device found during discovery
+ * @c45_ids: 802.3-c45 Device Identifiers if is_c45.
+ * @is_c45: If true the PHY uses the 802.3 clause 45 protocol
+ *
+ * The struct contain possible configuration parameters for a PHY device which
+ * are used to setup the struct phy_device.
+ */
+
+struct phy_device_config {
+ struct mii_bus *mii_bus;
+ int phy_addr;
+ u32 phy_id;
+ struct phy_c45_device_ids c45_ids;
+ bool is_c45;
+};
+
/**
* struct phy_tdr_config - Configuration of a TDR raw test
*
@@ -1538,9 +1559,7 @@ int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum,
int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
u16 mask, u16 set);

-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);
+struct phy_device *phy_device_create(struct phy_device_config *config);
void phy_device_set_miits(struct phy_device *phydev,
struct mii_timestamper *mii_ts);
#if IS_ENABLED(CONFIG_PHYLIB)
@@ -1549,7 +1568,7 @@ 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(const struct fwnode_handle *fwnode);
-struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
+struct phy_device *get_phy_device(struct phy_device_config *config);
int phy_device_register(struct phy_device *phy);
void phy_device_free(struct phy_device *phydev);
#else
@@ -1581,7 +1600,7 @@ struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
}

static inline
-struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
+struct phy_device *get_phy_device(struct phy_device_config *config)
{
return NULL;
}

--
2.39.2