+Raju On 4/5/2023 2:56 PM, Marco Felsch wrote: > 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> For the change on AMD XGBE driver. Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@xxxxxxx> > --- > 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; > } >