On Mon, 17 Aug 2020 14:49:09 +0100 Russell King - ARM Linux admin <li...@armlinux.org.uk> wrote:
> On Tue, Aug 11, 2020 at 12:06:41AM +0200, Marek Behún wrote: > > Hi Russell, > > > > this series should apply on linux-arm git repository, on branch > > clearfog. > > How about something like this - only build tested, and you may > encounter fuzz with this: > > diff --git a/drivers/net/phy/marvell10g.c > b/drivers/net/phy/marvell10g.c index 147b4cf4188e..bcbef68e0917 100644 > --- a/drivers/net/phy/marvell10g.c > +++ b/drivers/net/phy/marvell10g.c > @@ -117,6 +117,7 @@ enum { > MV_V2_PORT_CTRL_FT_1000BASEX = 0 << 3, > MV_V2_PORT_CTRL_FT_SGMII = 1 << 3, > MV_V2_PORT_CTRL_FT_10GBASER = 3 << 3, > + MV_V2_PORT_CTRL_MACTYPE = 7 << 0, > MV_V2_UIS = 0xf040, > MV_V2_PIS = 0xf042, > MV_V2_PIS_PI = BIT(0), > @@ -691,17 +692,44 @@ static bool mv3310_has_pma_ngbaset_quirk(struct > phy_device *phydev) MV_PHY_ALASKA_NBT_QUIRK_MASK) == > MV_PHY_ALASKA_NBT_QUIRK_REV; } > > +static int mv3310_select_mode(struct phy_device *phydev, > + unsigned long *host_interfaces) > +{ > + int mac_type = -1; > + > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, host_interfaces)) > + mac_type = 7; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, host_interfaces) > && > + test_bit(PHY_INTERFACE_MODE_10GBASER, > host_interfaces)) > + mac_type = 4; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, host_interfaces) > && > + test_bit(PHY_INTERFACE_MODE_RXAUI, host_interfaces)) > + mac_type = 0; > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, > host_interfaces)) > + mac_type = 6; > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, host_interfaces)) > + mac_type = 2; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, host_interfaces)) > + mac_type = 4; > + > + return mac_type; > +} > + > static int mv3310_config_init(struct phy_device *phydev) > { > - int err; > + int ret, err, mac_type = -1; > > /* Check that the PHY interface type is compatible */ > - if (phydev->interface != PHY_INTERFACE_MODE_SGMII && > - phydev->interface != PHY_INTERFACE_MODE_2500BASEX && > - phydev->interface != PHY_INTERFACE_MODE_XAUI && > - phydev->interface != PHY_INTERFACE_MODE_RXAUI && > - phydev->interface != PHY_INTERFACE_MODE_10GBASER) > + if (!phy_interface_empty(phydev->host_interfaces)) { > + mac_type = mv3310_select_mode(phydev, > phydev->host_interfaces); > + phydev_info(phydev, "mac_type=%d\n", mac_type); > + } else if (phydev->interface != PHY_INTERFACE_MODE_SGMII && > + phydev->interface != PHY_INTERFACE_MODE_2500BASEX > && > + phydev->interface != PHY_INTERFACE_MODE_XAUI && > + phydev->interface != PHY_INTERFACE_MODE_RXAUI && > + phydev->interface != PHY_INTERFACE_MODE_10GBASER) > { return -ENODEV; > + } > > phydev->mdix_ctrl = ETH_TP_MDI_AUTO; > > @@ -710,6 +738,20 @@ static int mv3310_config_init(struct phy_device > *phydev) if (err) > return err; > > + if (mac_type != -1) { > + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, > + MV_V2_PORT_CTRL, > + > MV_V2_PORT_CTRL_MACTYPE, mac_type); > + if (ret > 0) > + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, > + MV_V2_PORT_CTRL, > + MV_V2_PORT_CTRL_SWRST, > + MV_V2_PORT_CTRL_SWRST); When chaning mactype you also have to issue SWRST in the same register write. Otherwise it did not work for me. > + > + if (ret < 0) > + return ret; > + } > + > /* Enable EDPD mode - saving 600mW */ > err = mv3310_set_edpd(phydev, > ETHTOOL_PHY_EDPD_DFLT_TX_MSECS); if (err) > diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c > index 5785eb040f11..4ad64973432a 100644 > --- a/drivers/net/phy/phylink.c > +++ b/drivers/net/phy/phylink.c > @@ -2082,6 +2082,8 @@ static void phylink_sfp_detach(void *upstream, > struct sfp_bus *bus) sfp_bus_unlink_netdev(bus, pl->netdev); > } > > +static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); > + > static const phy_interface_t phylink_sfp_interface_preference[] = { > PHY_INTERFACE_MODE_USXGMII, > PHY_INTERFACE_MODE_10GBASER, > @@ -2091,6 +2093,18 @@ static const phy_interface_t > phylink_sfp_interface_preference[] = { PHY_INTERFACE_MODE_1000BASEX, > }; > > +static int __init phylink_init(void) > +{ > + int i; > + > + for (i = 0; i < > ARRAY_SIZE(phylink_sfp_interface_preference); i++) > + set_bit(phylink_sfp_interface_preference[i], > + phylink_sfp_interfaces); > + > + return 0; > +} > +module_init(phylink_init); > + > static phy_interface_t phylink_select_interface(struct phylink *pl, > const unsigned long > *intf, const char *intf_name) > @@ -2342,6 +2356,10 @@ static int phylink_sfp_connect_phy(void > *upstream, struct phy_device *phy) else > mode = MLO_AN_INBAND; > > + /* Set the PHY's host supported interfaces */ > + phy_interface_and(phy->host_interfaces, > phylink_sfp_interfaces, > + pl->config->supported_interfaces); > + > if (!phy_interface_empty(phy->supported_interfaces) && > !phy_interface_empty(pl->config->supported_interfaces)) { > interface = phylink_select_interface(pl, > diff --git a/include/linux/phy.h b/include/linux/phy.h > index 7408e2240c1e..14f73378f4e9 100644 > --- a/include/linux/phy.h > +++ b/include/linux/phy.h > @@ -527,6 +527,7 @@ struct phy_device { > > /* bitmap of supported interfaces */ > DECLARE_PHY_INTERFACE_MASK(supported_interfaces); > + DECLARE_PHY_INTERFACE_MASK(host_interfaces); > > /* Energy efficient ethernet modes which should be > prohibited */ u32 eee_broken_modes; > Otherwise it looks nice. I will test this. On what branch does this apply? Marek