net: ethernet: Add helper to remove a supported link mode
authorAndrew Lunn <andrew@lunn.ch>
Tue, 11 Sep 2018 23:53:14 +0000 (01:53 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 13 Sep 2018 03:24:21 +0000 (20:24 -0700)
Some MAC hardware cannot support a subset of link modes. e.g. often
1Gbps Full duplex is supported, but Half duplex is not. Add a helper
to remove such a link mode.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/microchip/lan743x_main.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/phy/phy_device.c
drivers/net/usb/lan78xx.c
include/linux/phy.h

index 078a04dc1182e9f6fe9d1316652307d7b9c5dc77..4831f9de59458a0c40b3d10ea655542fcf7fd5bb 100644 (file)
@@ -895,9 +895,9 @@ int xgene_enet_phy_connect(struct net_device *ndev)
        }
 
        pdata->phy_speed = SPEED_UNKNOWN;
-       phy_dev->supported &= ~SUPPORTED_10baseT_Half &
-                             ~SUPPORTED_100baseT_Half &
-                             ~SUPPORTED_1000baseT_Half;
+       phy_remove_link_mode(phy_dev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
+       phy_remove_link_mode(phy_dev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
+       phy_remove_link_mode(phy_dev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
        phy_dev->supported |= SUPPORTED_Pause |
                              SUPPORTED_Asym_Pause;
        phy_dev->advertising = phy_dev->supported;
index bd4095c3a0314f0217397a270a9a13b773264e2b..96ae8c99281042c81cd5d640ddd657335c46d3d2 100644 (file)
@@ -549,9 +549,8 @@ static int macb_mii_probe(struct net_device *dev)
                phy_set_max_speed(phydev, SPEED_100);
 
        if (bp->caps & MACB_CAPS_NO_GIGABIT_HALF)
-               phydev->supported &= ~SUPPORTED_1000baseT_Half;
-
-       phydev->advertising = phydev->supported;
+               phy_remove_link_mode(phydev,
+                                    ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
 
        bp->link = 0;
        bp->speed = 0;
index 5e849510c6897c5b2e17d3a4f85cc774da41c449..0c6fd77b6599751f74791e3a5259b76c90c0db7f 100644 (file)
@@ -1947,7 +1947,8 @@ static int fec_enet_mii_probe(struct net_device *ndev)
        /* mask with MAC supported features */
        if (fep->quirks & FEC_QUIRK_HAS_GBIT) {
                phy_set_max_speed(phy_dev, 1000);
-               phy_dev->supported &= ~SUPPORTED_1000baseT_Half;
+               phy_remove_link_mode(phy_dev,
+                                    ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
 #if !defined(CONFIG_M5272)
                phy_dev->supported |= SUPPORTED_Pause;
 #endif
index e7dce79ff2c910a090de7e55bf3e3efae3e0f2b7..048307959c01ce6191b1188a356d1d8dfc64fd6d 100644 (file)
@@ -1013,7 +1013,7 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
                goto return_error;
 
        /* MAC doesn't support 1000T Half */
-       phydev->supported &= ~SUPPORTED_1000baseT_Half;
+       phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
 
        /* support both flow controls */
        phy->fc_request_control = (FLOW_CTRL_RX | FLOW_CTRL_TX);
index aff5516b781e27067efc9c1cca19f11bea19dd19..fb2a1125780d00f234113c1a5470fb101014aea3 100644 (file)
@@ -1074,7 +1074,8 @@ static int ravb_phy_init(struct net_device *ndev)
        }
 
        /* 10BASE is not supported */
-       phydev->supported &= ~PHY_10BT_FEATURES;
+       phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
+       phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
 
        phy_attached_info(phydev);
 
index 3d7aec7a050bf28ce1baad80dbd00c04465b416c..3715a0a4af3cb527ac76974a69ba653ebc042337 100644 (file)
@@ -993,10 +993,14 @@ static int stmmac_init_phy(struct net_device *dev)
         * Half-duplex mode not supported with multiqueue
         * half-duplex can only works with single queue
         */
-       if (tx_cnt > 1)
-               phydev->supported &= ~(SUPPORTED_1000baseT_Half |
-                                      SUPPORTED_100baseT_Half |
-                                      SUPPORTED_10baseT_Half);
+       if (tx_cnt > 1) {
+               phy_remove_link_mode(phydev,
+                                    ETHTOOL_LINK_MODE_10baseT_Half_BIT);
+               phy_remove_link_mode(phydev,
+                                    ETHTOOL_LINK_MODE_100baseT_Half_BIT);
+               phy_remove_link_mode(phydev,
+                                    ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+       }
 
        /*
         * Broken HW is sometimes missing the pull-up resistor on the
index db1172db1e7cb7df0fed8a21b0a7757ae6c068b5..e9ca83a438b06dfc3a347dfadd09717ab7397ebb 100644 (file)
@@ -1765,6 +1765,24 @@ int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
 }
 EXPORT_SYMBOL(phy_set_max_speed);
 
+/**
+ * phy_remove_link_mode - Remove a supported link mode
+ * @phydev: phy_device structure to remove link mode from
+ * @link_mode: Link mode to be removed
+ *
+ * Description: Some MACs don't support all link modes which the PHY
+ * does.  e.g. a 1G MAC often does not support 1000Half. Add a helper
+ * to remove a link mode.
+ */
+void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode)
+{
+       WARN_ON(link_mode > 31);
+
+       phydev->supported &= ~BIT(link_mode);
+       phydev->advertising = phydev->supported;
+}
+EXPORT_SYMBOL(phy_remove_link_mode);
+
 static void of_set_phy_supported(struct phy_device *phydev)
 {
        struct device_node *node = phydev->mdio.dev.of_node;
index 3ce3c66559e4a8bf86a151d2518f1f3e48743c5b..95a98a20b2e35a824e34139cc202e569f8bfd91a 100644 (file)
@@ -2166,7 +2166,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
        }
 
        /* MAC doesn't support 1000T Half */
-       phydev->supported &= ~SUPPORTED_1000baseT_Half;
+       phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
 
        /* support both flow controls */
        dev->fc_request_control = (FLOW_CTRL_RX | FLOW_CTRL_TX);
index cd6f637cbbfb60a099713f0987bcd2db134ea1c2..9c4c3eca8cf2d33ea54173c93c74526c2e501f5e 100644 (file)
@@ -1049,6 +1049,7 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);
 int phy_start_interrupts(struct phy_device *phydev);
 void phy_print_status(struct phy_device *phydev);
 int phy_set_max_speed(struct phy_device *phydev, u32 max_speed);
+void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode);
 
 int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
                       int (*run)(struct phy_device *));