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. Build bitmap equivalents of the u32 values at runtime, and have the drivers point to the appropriate bitmap. These bitmaps are shared, and we don't want a driver to modify them. So mark them __ro_after_init. Within phylib, the features bitmap is currently turned back into a u32. This will be removed once the whole of phylib, and the drivers are converted to use bitmaps. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
d0939c26c5
commit
719655a149
@@ -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,149 @@ MODULE_DESCRIPTION("PHY library");
|
||||
MODULE_AUTHOR("Andy Fleming");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_features) __ro_after_init;
|
||||
EXPORT_SYMBOL_GPL(phy_basic_features);
|
||||
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_t1_features) __ro_after_init;
|
||||
EXPORT_SYMBOL_GPL(phy_basic_t1_features);
|
||||
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_features) __ro_after_init;
|
||||
EXPORT_SYMBOL_GPL(phy_gbit_features);
|
||||
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_fibre_features) __ro_after_init;
|
||||
EXPORT_SYMBOL_GPL(phy_gbit_fibre_features);
|
||||
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features) __ro_after_init;
|
||||
EXPORT_SYMBOL_GPL(phy_gbit_all_ports_features);
|
||||
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
|
||||
EXPORT_SYMBOL_GPL(phy_10gbit_features);
|
||||
|
||||
static const int phy_basic_ports_array[] = {
|
||||
ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
ETHTOOL_LINK_MODE_TP_BIT,
|
||||
ETHTOOL_LINK_MODE_MII_BIT,
|
||||
};
|
||||
|
||||
static const int phy_fibre_port_array[] = {
|
||||
ETHTOOL_LINK_MODE_FIBRE_BIT,
|
||||
};
|
||||
|
||||
static const int phy_all_ports_features_array[] = {
|
||||
ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
ETHTOOL_LINK_MODE_TP_BIT,
|
||||
ETHTOOL_LINK_MODE_MII_BIT,
|
||||
ETHTOOL_LINK_MODE_FIBRE_BIT,
|
||||
ETHTOOL_LINK_MODE_AUI_BIT,
|
||||
ETHTOOL_LINK_MODE_BNC_BIT,
|
||||
ETHTOOL_LINK_MODE_Backplane_BIT,
|
||||
};
|
||||
|
||||
static const int phy_10_100_features_array[] = {
|
||||
ETHTOOL_LINK_MODE_10baseT_Half_BIT,
|
||||
ETHTOOL_LINK_MODE_10baseT_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100baseT_Half_BIT,
|
||||
ETHTOOL_LINK_MODE_100baseT_Full_BIT,
|
||||
};
|
||||
|
||||
static const int phy_basic_t1_features_array[] = {
|
||||
ETHTOOL_LINK_MODE_TP_BIT,
|
||||
ETHTOOL_LINK_MODE_100baseT_Full_BIT,
|
||||
};
|
||||
|
||||
static const int phy_gbit_features_array[] = {
|
||||
ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
|
||||
ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||
};
|
||||
|
||||
static const int phy_10gbit_features_array[] = {
|
||||
ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
|
||||
};
|
||||
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
|
||||
EXPORT_SYMBOL_GPL(phy_10gbit_full_features);
|
||||
|
||||
static const int phy_10gbit_full_features_array[] = {
|
||||
ETHTOOL_LINK_MODE_10baseT_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100baseT_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
|
||||
};
|
||||
|
||||
static void features_init(void)
|
||||
{
|
||||
/* 10/100 half/full*/
|
||||
linkmode_set_bit_array(phy_basic_ports_array,
|
||||
ARRAY_SIZE(phy_basic_ports_array),
|
||||
phy_basic_features);
|
||||
linkmode_set_bit_array(phy_10_100_features_array,
|
||||
ARRAY_SIZE(phy_10_100_features_array),
|
||||
phy_basic_features);
|
||||
|
||||
/* 100 full, TP */
|
||||
linkmode_set_bit_array(phy_basic_t1_features_array,
|
||||
ARRAY_SIZE(phy_basic_t1_features_array),
|
||||
phy_basic_t1_features);
|
||||
|
||||
/* 10/100 half/full + 1000 half/full */
|
||||
linkmode_set_bit_array(phy_basic_ports_array,
|
||||
ARRAY_SIZE(phy_basic_ports_array),
|
||||
phy_gbit_features);
|
||||
linkmode_set_bit_array(phy_10_100_features_array,
|
||||
ARRAY_SIZE(phy_10_100_features_array),
|
||||
phy_gbit_features);
|
||||
linkmode_set_bit_array(phy_gbit_features_array,
|
||||
ARRAY_SIZE(phy_gbit_features_array),
|
||||
phy_gbit_features);
|
||||
|
||||
/* 10/100 half/full + 1000 half/full + fibre*/
|
||||
linkmode_set_bit_array(phy_basic_ports_array,
|
||||
ARRAY_SIZE(phy_basic_ports_array),
|
||||
phy_gbit_fibre_features);
|
||||
linkmode_set_bit_array(phy_10_100_features_array,
|
||||
ARRAY_SIZE(phy_10_100_features_array),
|
||||
phy_gbit_fibre_features);
|
||||
linkmode_set_bit_array(phy_gbit_features_array,
|
||||
ARRAY_SIZE(phy_gbit_features_array),
|
||||
phy_gbit_fibre_features);
|
||||
linkmode_set_bit_array(phy_fibre_port_array,
|
||||
ARRAY_SIZE(phy_fibre_port_array),
|
||||
phy_gbit_fibre_features);
|
||||
|
||||
/* 10/100 half/full + 1000 half/full + TP/MII/FIBRE/AUI/BNC/Backplane*/
|
||||
linkmode_set_bit_array(phy_all_ports_features_array,
|
||||
ARRAY_SIZE(phy_all_ports_features_array),
|
||||
phy_gbit_all_ports_features);
|
||||
linkmode_set_bit_array(phy_10_100_features_array,
|
||||
ARRAY_SIZE(phy_10_100_features_array),
|
||||
phy_gbit_all_ports_features);
|
||||
linkmode_set_bit_array(phy_gbit_features_array,
|
||||
ARRAY_SIZE(phy_gbit_features_array),
|
||||
phy_gbit_all_ports_features);
|
||||
|
||||
/* 10/100 half/full + 1000 half/full + 10G full*/
|
||||
linkmode_set_bit_array(phy_all_ports_features_array,
|
||||
ARRAY_SIZE(phy_all_ports_features_array),
|
||||
phy_10gbit_features);
|
||||
linkmode_set_bit_array(phy_10_100_features_array,
|
||||
ARRAY_SIZE(phy_10_100_features_array),
|
||||
phy_10gbit_features);
|
||||
linkmode_set_bit_array(phy_gbit_features_array,
|
||||
ARRAY_SIZE(phy_gbit_features_array),
|
||||
phy_10gbit_features);
|
||||
linkmode_set_bit_array(phy_10gbit_features_array,
|
||||
ARRAY_SIZE(phy_10gbit_features_array),
|
||||
phy_10gbit_features);
|
||||
|
||||
/* 10/100/1000/10G full */
|
||||
linkmode_set_bit_array(phy_all_ports_features_array,
|
||||
ARRAY_SIZE(phy_all_ports_features_array),
|
||||
phy_10gbit_full_features);
|
||||
linkmode_set_bit_array(phy_10gbit_full_features_array,
|
||||
ARRAY_SIZE(phy_10gbit_full_features_array),
|
||||
phy_10gbit_full_features);
|
||||
}
|
||||
|
||||
void phy_device_free(struct phy_device *phydev)
|
||||
{
|
||||
put_device(&phydev->mdio.dev);
|
||||
@@ -1936,6 +2080,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;
|
||||
@@ -1956,7 +2101,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;
|
||||
|
||||
@@ -1976,10 +2122,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;
|
||||
}
|
||||
@@ -2092,9 +2242,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,
|
||||
@@ -2109,6 +2257,8 @@ static int __init phy_init(void)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
features_init();
|
||||
|
||||
rc = phy_driver_register(&genphy_10g_driver, THIS_MODULE);
|
||||
if (rc)
|
||||
goto err_10g;
|
||||
|
Reference in New Issue
Block a user