lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 14 Sep 2018 23:38:55 +0200
From:   Andrew Lunn <andrew@...n.ch>
To:     netdev <netdev@...r.kernel.org>
Cc:     Florian Fainelli <f.fainelli@...il.com>,
        Andrew Lunn <andrew@...n.ch>
Subject: [PATH RFC net-next 7/8] net: phy: Replace phy driver features u32 with link_mode bitmap

This is one step in allowing phylib to make use of link_mode bitmaps,
instead of u32 for supported and advertised features. Convert the phy
drivers to use bitmaps to indicates the features they support. This
requires some macro magic in order to construct constant bitmaps used
to initialise the driver structures.

Some new PHY_*_FEATURES are added, to indicate FIBRE is supported, and
that all media ports are supported. This is done since bitmaps cannot
be ORed together at compile time.

Within phylib, the features bitmap is currently turned back into a
u32.  The MAC API to phylib needs to be cleaned up before the core of
phylib can be converted to using bitmaps instead of u32.

Signed-off-by: Andrew Lunn <andrew@...n.ch>
---
 drivers/net/ethernet/marvell/pxa168_eth.c |   4 +-
 drivers/net/phy/aquantia.c                |  12 +-
 drivers/net/phy/bcm63xx.c                 |   9 +-
 drivers/net/phy/marvell.c                 |   2 +-
 drivers/net/phy/marvell10g.c              |  11 +-
 drivers/net/phy/microchip_t1.c            |   2 +-
 drivers/net/phy/phy_device.c              | 204 +++++++++++++++++++++-
 include/linux/phy.h                       |  24 ++-
 8 files changed, 229 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 3a9730612a70..b406395bbb37 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -988,8 +988,8 @@ static int pxa168_init_phy(struct net_device *dev)
 	cmd.base.phy_address = pep->phy_addr;
 	cmd.base.speed = pep->phy_speed;
 	cmd.base.duplex = pep->phy_duplex;
-	ethtool_convert_legacy_u32_to_link_mode(cmd.link_modes.advertising,
-						PHY_BASIC_FEATURES);
+	bitmap_copy(cmd.link_modes.advertising, PHY_BASIC_FEATURES,
+		    __ETHTOOL_LINK_MODE_MASK_NBITS);
 	cmd.base.autoneg = AUTONEG_ENABLE;
 
 	if (cmd.base.speed != 0)
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 319edc9c8ec7..632472cab3bb 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -115,7 +115,7 @@ static struct phy_driver aquantia_driver[] = {
 	.phy_id		= PHY_ID_AQ1202,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Aquantia AQ1202",
-	.features	= PHY_AQUANTIA_FEATURES,
+	.features	= PHY_10GBIT_FULL_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.aneg_done	= genphy_c45_aneg_done,
 	.config_aneg    = aquantia_config_aneg,
@@ -127,7 +127,7 @@ static struct phy_driver aquantia_driver[] = {
 	.phy_id		= PHY_ID_AQ2104,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Aquantia AQ2104",
-	.features	= PHY_AQUANTIA_FEATURES,
+	.features	= PHY_10GBIT_FULL_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.aneg_done	= genphy_c45_aneg_done,
 	.config_aneg    = aquantia_config_aneg,
@@ -139,7 +139,7 @@ static struct phy_driver aquantia_driver[] = {
 	.phy_id		= PHY_ID_AQR105,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Aquantia AQR105",
-	.features	= PHY_AQUANTIA_FEATURES,
+	.features	= PHY_10GBIT_FULL_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.aneg_done	= genphy_c45_aneg_done,
 	.config_aneg    = aquantia_config_aneg,
@@ -151,7 +151,7 @@ static struct phy_driver aquantia_driver[] = {
 	.phy_id		= PHY_ID_AQR106,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Aquantia AQR106",
-	.features	= PHY_AQUANTIA_FEATURES,
+	.features	= PHY_10GBIT_FULL_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.aneg_done	= genphy_c45_aneg_done,
 	.config_aneg    = aquantia_config_aneg,
@@ -163,7 +163,7 @@ static struct phy_driver aquantia_driver[] = {
 	.phy_id		= PHY_ID_AQR107,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Aquantia AQR107",
-	.features	= PHY_AQUANTIA_FEATURES,
+	.features	= PHY_10GBIT_FULL_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.aneg_done	= genphy_c45_aneg_done,
 	.config_aneg    = aquantia_config_aneg,
@@ -175,7 +175,7 @@ static struct phy_driver aquantia_driver[] = {
 	.phy_id		= PHY_ID_AQR405,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Aquantia AQR405",
-	.features	= PHY_AQUANTIA_FEATURES,
+	.features	= PHY_10GBIT_FULL_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.aneg_done	= genphy_c45_aneg_done,
 	.config_aneg    = aquantia_config_aneg,
diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c
index cf14613745c9..ff5acf01b877 100644
--- a/drivers/net/phy/bcm63xx.c
+++ b/drivers/net/phy/bcm63xx.c
@@ -42,6 +42,9 @@ static int bcm63xx_config_init(struct phy_device *phydev)
 {
 	int reg, err;
 
+	/* ASYM_PAUSE bit is marked RO in datasheet, so don't cheat */
+	linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported),
+
 	reg = phy_read(phydev, MII_BCM63XX_IR);
 	if (reg < 0)
 		return reg;
@@ -65,8 +68,7 @@ static struct phy_driver bcm63xx_driver[] = {
 	.phy_id		= 0x00406000,
 	.phy_id_mask	= 0xfffffc00,
 	.name		= "Broadcom BCM63XX (1)",
-	/* ASYM_PAUSE bit is marked RO in datasheet, so don't cheat */
-	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+	.features	= PHY_BASIC_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT | PHY_IS_INTERNAL,
 	.config_init	= bcm63xx_config_init,
 	.ack_interrupt	= bcm_phy_ack_intr,
@@ -75,8 +77,7 @@ static struct phy_driver bcm63xx_driver[] = {
 	/* same phy as above, with just a different OUI */
 	.phy_id		= 0x002bdc00,
 	.phy_id_mask	= 0xfffffc00,
-	.name		= "Broadcom BCM63XX (2)",
-	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+	.features	= PHY_BASIC_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT | PHY_IS_INTERNAL,
 	.config_init	= bcm63xx_config_init,
 	.ack_interrupt	= bcm_phy_ack_intr,
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index f7c69ca34056..de1e900f7253 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -2222,7 +2222,7 @@ static struct phy_driver marvell_drivers[] = {
 		.phy_id = MARVELL_PHY_ID_88E1510,
 		.phy_id_mask = MARVELL_PHY_ID_MASK,
 		.name = "Marvell 88E1510",
-		.features = PHY_GBIT_FEATURES | SUPPORTED_FIBRE,
+		.features = PHY_GBIT_FIBRE_FEATURES,
 		.flags = PHY_HAS_INTERRUPT,
 		.probe = &m88e1510_probe,
 		.config_init = &m88e1510_config_init,
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index f77a2d9e7f9d..7f4a43c65da6 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -535,16 +535,7 @@ static struct phy_driver mv3310_drivers[] = {
 		.phy_id		= 0x002b09aa,
 		.phy_id_mask	= MARVELL_PHY_ID_MASK,
 		.name		= "mv88x3310",
-		.features	= SUPPORTED_10baseT_Full |
-				  SUPPORTED_10baseT_Half |
-				  SUPPORTED_100baseT_Full |
-				  SUPPORTED_100baseT_Half |
-				  SUPPORTED_1000baseT_Full |
-				  SUPPORTED_Autoneg |
-				  SUPPORTED_TP |
-				  SUPPORTED_FIBRE |
-				  SUPPORTED_10000baseT_Full |
-				  SUPPORTED_Backplane,
+		.features	= PHY_10GBIT_FEATURES,
 		.soft_reset	= gen10g_no_soft_reset,
 		.config_init	= mv3310_config_init,
 		.probe		= mv3310_probe,
diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c
index b1917dd1978a..c600a8509d60 100644
--- a/drivers/net/phy/microchip_t1.c
+++ b/drivers/net/phy/microchip_t1.c
@@ -46,7 +46,7 @@ static struct phy_driver microchip_t1_phy_driver[] = {
 		.phy_id_mask    = 0xfffffff0,
 		.name           = "Microchip LAN87xx T1",
 
-		.features       = SUPPORTED_100baseT_Full,
+		.features       = PHY_BASIC_T1_FEATURES,
 		.flags          = PHY_HAS_INTERRUPT,
 
 		.config_init    = genphy_config_init,
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index af64a9320fb0..eed61ee1d394 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/bitmap.h>
 #include <linux/phy.h>
 #include <linux/phy_led_triggers.h>
 #include <linux/mdio.h>
@@ -42,6 +43,191 @@ MODULE_DESCRIPTION("PHY library");
 MODULE_AUTHOR("Andy Fleming");
 MODULE_LICENSE("GPL");
 
+#define BIT_IN_RANGE(bit, lower, upper)			\
+	((bit) < (lower) ? 0 : ((bit) > (upper) ? 0 :	\
+				 BIT((bit) - (lower))))
+
+#define BIT_IN_LONG_ARRAY(bit, index)				\
+	BIT_IN_RANGE(bit, (BITS_PER_LONG * (index)),		\
+		     (BITS_PER_LONG * ((index) + 1)) - 1)
+
+#define BIT_IN_LONG_ARRAY_0(bit) BIT_IN_LONG_ARRAY(bit, 0)
+#define BIT_IN_LONG_ARRAY_1(bit) BIT_IN_LONG_ARRAY(bit, 1)
+#define BIT_IN_LONG_ARRAY_2(bit) BIT_IN_LONG_ARRAY(bit, 2)
+
+const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_features) = {
+	[0] = (BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_Autoneg_BIT)	|
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_TP_BIT)		|
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_MII_BIT)		|
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	|
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	|
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	|
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Full_BIT)),
+#if BITS_PER_LONG == 32
+	[1] = (BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_Autoneg_BIT)	|
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_TP_BIT)		|
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_MII_BIT)		|
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	|
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	|
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	|
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Full_BIT)),
+#endif
+};
+EXPORT_SYMBOL_GPL(phy_basic_features);
+
+const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_t1_features) = {
+	[0] = (BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_TP_BIT)		|
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Full_BIT)),
+#if BITS_PER_LONG == 32
+	[1] = (BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_TP_BIT)		|
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Full_BIT)),
+#endif
+};
+EXPORT_SYMBOL_GPL(phy_basic_t1_features);
+
+const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_features) = {
+	[0] = (BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_1000baseT_Half_BIT) |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_1000baseT_Full_BIT)),
+#if BITS_PER_LONG == 32
+	[1] = (BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_1000baseT_Half_BIT) |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_1000baseT_Full_BIT)),
+#endif
+};
+EXPORT_SYMBOL_GPL(phy_gbit_features);
+
+const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_fibre_features) = {
+	[0] = (BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_FIBRE_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_1000baseT_Half_BIT) |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_1000baseT_Full_BIT)),
+#if BITS_PER_LONG == 32
+	[1] = (BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_FIBRE_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_1000baseT_Half_BIT) |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_1000baseT_Full_BIT)),
+#endif
+};
+EXPORT_SYMBOL_GPL(phy_gbit_fibre_features);
+
+const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features) = {
+	[0] = (BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_FIBRE_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_AUI_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_BNC_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_Backplane_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_1000baseT_Half_BIT) |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_1000baseT_Full_BIT)),
+#if BITS_PER_LONG == 32
+	[1] = (BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_FIBRE_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_AUI_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_BNC_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_Backplane_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_1000baseT_Half_BIT) |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_1000baseT_Full_BIT)),
+#endif
+};
+EXPORT_SYMBOL_GPL(phy_gbit_all_ports_features);
+
+const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) = {
+	[0] = (BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_FIBRE_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_AUI_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_BNC_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_Backplane_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_1000baseT_Half_BIT) |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10000baseT_Full_BIT)),
+#if BITS_PER_LONG == 32
+	[1] = (BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_FIBRE_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_Backplane_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Half_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_1000baseT_Half_BIT) |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10000baseT_Full_BIT)),
+#endif
+};
+EXPORT_SYMBOL_GPL(phy_10gbit_features);
+
+/* No half duplex support */
+const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) = {
+	[0] = (BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_FIBRE_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_AUI_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_BNC_BIT)		 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_Backplane_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
+	       BIT_IN_LONG_ARRAY_0(ETHTOOL_LINK_MODE_10000baseT_Full_BIT)),
+#if BITS_PER_LONG == 32
+	[1] = (BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_Autoneg_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_TP_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_MII_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_AUI_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_BNC_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_FIBRE_BIT)		 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_Backplane_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_100baseT_Full_BIT)	 |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
+	       BIT_IN_LONG_ARRAY_1(ETHTOOL_LINK_MODE_10000baseT_Full_BIT)),
+#endif
+};
+EXPORT_SYMBOL_GPL(phy_10gbit_full_features);
+
 void phy_device_free(struct phy_device *phydev)
 {
 	put_device(&phydev->mdio.dev);
@@ -1938,6 +2124,7 @@ static int phy_probe(struct device *dev)
 	struct phy_device *phydev = to_phy_device(dev);
 	struct device_driver *drv = phydev->mdio.dev.driver;
 	struct phy_driver *phydrv = to_phy_driver(drv);
+	u32 features;
 	int err = 0;
 
 	phydev->drv = phydrv;
@@ -1958,7 +2145,8 @@ static int phy_probe(struct device *dev)
 	 * a controller will attach, and may modify one
 	 * or both of these values
 	 */
-	phydev->supported = phydrv->features;
+	ethtool_convert_link_mode_to_legacy_u32(&features, phydrv->features);
+	phydev->supported = features;
 	of_set_phy_supported(phydev);
 	phydev->advertising = phydev->supported;
 
@@ -1978,10 +2166,14 @@ static int phy_probe(struct device *dev)
 	 * (e.g. hardware erratum) where the driver wants to set only one
 	 * of these bits.
 	 */
-	if (phydrv->features & (SUPPORTED_Pause | SUPPORTED_Asym_Pause)) {
+	if (test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydrv->features) ||
+	    test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydrv->features)) {
 		phydev->supported &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause);
-		phydev->supported |= phydrv->features &
-				     (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+		if (test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydrv->features))
+			phydev->supported |= SUPPORTED_Pause;
+		if (test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+			     phydrv->features))
+			phydev->supported |= SUPPORTED_Asym_Pause;
 	} else {
 		phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 	}
@@ -2094,9 +2286,7 @@ static struct phy_driver genphy_driver = {
 	.name		= "Generic PHY",
 	.soft_reset	= genphy_no_soft_reset,
 	.config_init	= genphy_config_init,
-	.features	= PHY_GBIT_FEATURES | SUPPORTED_MII |
-			  SUPPORTED_AUI | SUPPORTED_FIBRE |
-			  SUPPORTED_BNC,
+	.features	= PHY_GBIT_ALL_PORTS_FEATURES,
 	.aneg_done	= genphy_aneg_done,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 0ab9f89773fd..8343a1999e1b 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -42,13 +42,21 @@
 #define PHY_1000BT_FEATURES	(SUPPORTED_1000baseT_Half | \
 				 SUPPORTED_1000baseT_Full)
 
-#define PHY_BASIC_FEATURES	(PHY_10BT_FEATURES | \
-				 PHY_100BT_FEATURES | \
-				 PHY_DEFAULT_FEATURES)
-
-#define PHY_GBIT_FEATURES	(PHY_BASIC_FEATURES | \
-				 PHY_1000BT_FEATURES)
-
+extern const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_features);
+extern const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_t1_features);
+extern const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_features);
+extern const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_fibre_features);
+extern const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features);
+extern const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features);
+extern const __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features);
+
+#define PHY_BASIC_FEATURES ((unsigned long *)&phy_basic_features)
+#define PHY_BASIC_T1_FEATURES ((unsigned long *)&phy_basic_t1_features)
+#define PHY_GBIT_FEATURES ((unsigned long *)&phy_gbit_features)
+#define PHY_GBIT_FIBRE_FEATURES ((unsigned long *)&phy_gbit_fibre_features)
+#define PHY_GBIT_ALL_PORTS_FEATURES ((unsigned long *)&phy_gbit_all_ports_features)
+#define PHY_10GBIT_FEATURES ((unsigned long *)&phy_10gbit_features)
+#define PHY_10GBIT_FULL_FEATURES ((unsigned long *)&phy_10gbit_full_features)
 
 /*
  * Set phydev->irq to PHY_POLL if interrupts are not supported,
@@ -510,7 +518,7 @@ struct phy_driver {
 	u32 phy_id;
 	char *name;
 	u32 phy_id_mask;
-	u32 features;
+	const unsigned long * const features;
 	u32 flags;
 	const void *driver_data;
 
-- 
2.19.0.rc1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ