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 078a04d..4831f9d 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 bd4095c..96ae8c9 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 5e84951..0c6fd77 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 e7dce79..0483079 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 aff5516..fb2a112 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 3d7aec7..3715a0a 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 db1172d..e9ca83a 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 3ce3c66..95a98a2 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 cd6f637..9c4c3ec 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 *));