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 <and...@lunn.ch>
Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c |  6 +++---
 drivers/net/ethernet/cadence/macb_main.c       |  5 ++---
 drivers/net/ethernet/freescale/fec_main.c      |  3 ++-
 drivers/net/ethernet/microchip/lan743x_main.c  |  2 +-
 drivers/net/ethernet/renesas/ravb_main.c       |  3 ++-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c  | 12 ++++++++----
 drivers/net/phy/phy_device.c                   | 18 ++++++++++++++++++
 drivers/net/usb/lan78xx.c                      |  2 +-
 include/linux/phy.h                            |  1 +
 9 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 078a04dc1182..4831f9de5945 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -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;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index bd4095c3a031..96ae8c992810 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -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;
diff --git a/drivers/net/ethernet/freescale/fec_main.c 
b/drivers/net/ethernet/freescale/fec_main.c
index 5e849510c689..0c6fd77b6599 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -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
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c 
b/drivers/net/ethernet/microchip/lan743x_main.c
index e7dce79ff2c9..048307959c01 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -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);
diff --git a/drivers/net/ethernet/renesas/ravb_main.c 
b/drivers/net/ethernet/renesas/ravb_main.c
index aff5516b781e..fb2a1125780d 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -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);
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3d7aec7a050b..3715a0a4af3c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -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
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index db1172db1e7c..e9ca83a438b0 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -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;
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 3ce3c66559e4..95a98a20b2e3 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -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);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index cd6f637cbbfb..9c4c3eca8cf2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -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 *));
-- 
2.19.0.rc1

Reply via email to