Merge branch 'Continue-towards-using-linkmode-in-phylib'

Andrew Lunn says:

====================
Continue towards using linkmode in phylib

These patches contain some further cleanup and helpers, and the first
real patch towards using linkmode bitmaps in phylink.

The macro magic in the RFC version has been replaced with run time
initialisation.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2018-10-01 22:55:36 -07:00
commit 26cf48a668
21 changed files with 419 additions and 134 deletions

View File

@ -658,11 +658,7 @@ static void mt7530_adjust_link(struct dsa_switch *ds, int port,
if (phydev->asym_pause)
rmt_adv |= LPA_PAUSE_ASYM;
if (phydev->advertising & ADVERTISED_Pause)
lcl_adv |= ADVERTISE_PAUSE_CAP;
if (phydev->advertising & ADVERTISED_Asym_Pause)
lcl_adv |= ADVERTISE_PAUSE_ASYM;
lcl_adv = ethtool_adv_to_lcl_adv_t(phydev->advertising);
flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
if (flowctrl & FLOW_CTRL_TX)

View File

@ -878,8 +878,9 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata)
phy_write(phy_data->phydev, 0x04, 0x0d01);
phy_write(phy_data->phydev, 0x00, 0x9140);
phy_data->phydev->supported = PHY_GBIT_FEATURES;
phy_data->phydev->advertising = phy_data->phydev->supported;
phy_data->phydev->supported = PHY_10BT_FEATURES |
PHY_100BT_FEATURES |
PHY_1000BT_FEATURES;
phy_support_asym_pause(phy_data->phydev);
netif_dbg(pdata, drv, pdata->netdev,
@ -950,8 +951,9 @@ static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata)
reg = phy_read(phy_data->phydev, 0x00);
phy_write(phy_data->phydev, 0x00, reg & ~0x00800);
phy_data->phydev->supported = PHY_GBIT_FEATURES;
phy_data->phydev->advertising = phy_data->phydev->supported;
phy_data->phydev->supported = (PHY_10BT_FEATURES |
PHY_100BT_FEATURES |
PHY_1000BT_FEATURES);
phy_support_asym_pause(phy_data->phydev);
netif_dbg(pdata, drv, pdata->netdev,
@ -1495,10 +1497,7 @@ static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata)
if (!phy_data->phydev)
return;
if (phy_data->phydev->advertising & ADVERTISED_Pause)
lcl_adv |= ADVERTISE_PAUSE_CAP;
if (phy_data->phydev->advertising & ADVERTISED_Asym_Pause)
lcl_adv |= ADVERTISE_PAUSE_ASYM;
lcl_adv = ethtool_adv_to_lcl_adv_t(phy_data->phydev->advertising);
if (phy_data->phydev->pause) {
XGBE_SET_LP_ADV(lks, Pause);

View File

@ -393,11 +393,7 @@ void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause,
*/
/* get local capabilities */
lcl_adv = 0;
if (phy_dev->advertising & ADVERTISED_Pause)
lcl_adv |= ADVERTISE_PAUSE_CAP;
if (phy_dev->advertising & ADVERTISED_Asym_Pause)
lcl_adv |= ADVERTISE_PAUSE_ASYM;
lcl_adv = ethtool_adv_to_lcl_adv_t(phy_dev->advertising);
/* get link partner capabilities */
rmt_adv = 0;

View File

@ -3656,12 +3656,7 @@ static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv)
if (phydev->asym_pause)
rmt_adv |= LPA_PAUSE_ASYM;
lcl_adv = 0;
if (phydev->advertising & ADVERTISED_Pause)
lcl_adv |= ADVERTISE_PAUSE_CAP;
if (phydev->advertising & ADVERTISED_Asym_Pause)
lcl_adv |= ADVERTISE_PAUSE_ASYM;
lcl_adv = ethtool_adv_to_lcl_adv_t(phydev->advertising);
flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
if (flowctrl & FLOW_CTRL_TX)
val |= MACCFG1_TX_FLOW;

View File

@ -5006,11 +5006,7 @@ int hclge_cfg_flowctrl(struct hclge_dev *hdev)
if (!phydev->link || !phydev->autoneg)
return 0;
if (phydev->advertising & ADVERTISED_Pause)
local_advertising = ADVERTISE_PAUSE_CAP;
if (phydev->advertising & ADVERTISED_Asym_Pause)
local_advertising |= ADVERTISE_PAUSE_ASYM;
local_advertising = ethtool_adv_to_lcl_adv_t(phydev->advertising);
if (phydev->pause)
remote_advertising = LPA_PAUSE_CAP;

View File

@ -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)

View File

@ -243,11 +243,7 @@ static void mtk_phy_link_adjust(struct net_device *dev)
if (dev->phydev->asym_pause)
rmt_adv |= LPA_PAUSE_ASYM;
if (dev->phydev->advertising & ADVERTISED_Pause)
lcl_adv |= ADVERTISE_PAUSE_CAP;
if (dev->phydev->advertising & ADVERTISED_Asym_Pause)
lcl_adv |= ADVERTISE_PAUSE_ASYM;
lcl_adv = ethtool_adv_to_lcl_adv_t(dev->phydev->advertising);
flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
if (flowctrl & FLOW_CTRL_TX)

View File

@ -1116,11 +1116,8 @@ static void ave_phy_adjust_link(struct net_device *ndev)
rmt_adv |= LPA_PAUSE_CAP;
if (phydev->asym_pause)
rmt_adv |= LPA_PAUSE_ASYM;
if (phydev->advertising & ADVERTISED_Pause)
lcl_adv |= ADVERTISE_PAUSE_CAP;
if (phydev->advertising & ADVERTISED_Asym_Pause)
lcl_adv |= ADVERTISE_PAUSE_ASYM;
lcl_adv = ethtool_adv_to_lcl_adv_t(phydev->advertising);
cap = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
if (cap & FLOW_CTRL_TX)
txcr |= AVE_TXCR_FLOCTR;

View File

@ -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,

View File

@ -357,7 +357,7 @@ static int at803x_aneg_done(struct phy_device *phydev)
/* check if the SGMII link is OK. */
if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) {
pr_warn("803x_aneg_done: SGMII link is not ok\n");
phydev_warn(phydev, "803x_aneg_done: SGMII link is not ok\n");
aneg_done = 0;
}
/* switch back to copper page */

View File

@ -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 */
phydev->supported |= SUPPORTED_Pause;
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,

View File

@ -553,16 +553,17 @@ static void enable_status_frames(struct phy_device *phydev, bool on)
mutex_unlock(&clock->extreg_lock);
if (!phydev->attached_dev) {
pr_warn("expected to find an attached netdevice\n");
phydev_warn(phydev,
"expected to find an attached netdevice\n");
return;
}
if (on) {
if (dev_mc_add(phydev->attached_dev, status_frame_dst))
pr_warn("failed to add mc address\n");
phydev_warn(phydev, "failed to add mc address\n");
} else {
if (dev_mc_del(phydev->attached_dev, status_frame_dst))
pr_warn("failed to delete mc address\n");
phydev_warn(phydev, "failed to delete mc address\n");
}
}
@ -686,9 +687,9 @@ static void recalibrate(struct dp83640_clock *clock)
* read out and correct offsets
*/
val = ext_read(master, PAGE4, PTP_STS);
pr_info("master PTP_STS 0x%04hx\n", val);
phydev_info(master, "master PTP_STS 0x%04hx\n", val);
val = ext_read(master, PAGE4, PTP_ESTS);
pr_info("master PTP_ESTS 0x%04hx\n", val);
phydev_info(master, "master PTP_ESTS 0x%04hx\n", val);
event_ts.ns_lo = ext_read(master, PAGE4, PTP_EDATA);
event_ts.ns_hi = ext_read(master, PAGE4, PTP_EDATA);
event_ts.sec_lo = ext_read(master, PAGE4, PTP_EDATA);
@ -698,15 +699,16 @@ static void recalibrate(struct dp83640_clock *clock)
list_for_each(this, &clock->phylist) {
tmp = list_entry(this, struct dp83640_private, list);
val = ext_read(tmp->phydev, PAGE4, PTP_STS);
pr_info("slave PTP_STS 0x%04hx\n", val);
phydev_info(tmp->phydev, "slave PTP_STS 0x%04hx\n", val);
val = ext_read(tmp->phydev, PAGE4, PTP_ESTS);
pr_info("slave PTP_ESTS 0x%04hx\n", val);
phydev_info(tmp->phydev, "slave PTP_ESTS 0x%04hx\n", val);
event_ts.ns_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
event_ts.ns_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
event_ts.sec_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
event_ts.sec_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA);
diff = now - (s64) phy2txts(&event_ts);
pr_info("slave offset %lld nanoseconds\n", diff);
phydev_info(tmp->phydev, "slave offset %lld nanoseconds\n",
diff);
diff += ADJTIME_FIX;
ts = ns_to_timespec64(diff);
tdr_write(0, tmp->phydev, &ts, PTP_STEP_CLK);

View File

@ -638,7 +638,7 @@ static void marvell_config_led(struct phy_device *phydev)
err = phy_write_paged(phydev, MII_MARVELL_LED_PAGE, MII_PHY_LED_CTRL,
def_config);
if (err < 0)
pr_warn("Fail to config marvell phy LED.\n");
phydev_warn(phydev, "Fail to config marvell phy LED.\n");
}
static int marvell_config_init(struct phy_device *phydev)
@ -2201,7 +2201,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,

View File

@ -337,9 +337,9 @@ static int mv3310_config_init(struct phy_device *phydev)
}
if (!ethtool_convert_link_mode_to_legacy_u32(&mask, supported))
dev_warn(&phydev->mdio.dev,
"PHY supports (%*pb) more modes than phylib supports, some modes not supported.\n",
__ETHTOOL_LINK_MODE_MASK_NBITS, supported);
phydev_warn(phydev,
"PHY supports (%*pb) more modes than phylib supports, some modes not supported.\n",
__ETHTOOL_LINK_MODE_MASK_NBITS, supported);
phydev->supported &= mask;
phydev->advertising &= phydev->supported;
@ -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,

View File

@ -88,7 +88,7 @@ static int lan88xx_TR_reg_set(struct phy_device *phydev, u16 regaddr,
/* Save current page */
save_page = phy_save_page(phydev);
if (save_page < 0) {
pr_warn("Failed to get current page\n");
phydev_warn(phydev, "Failed to get current page\n");
goto err;
}
@ -98,14 +98,14 @@ static int lan88xx_TR_reg_set(struct phy_device *phydev, u16 regaddr,
ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_LOW_DATA,
(data & 0xFFFF));
if (ret < 0) {
pr_warn("Failed to write TR low data\n");
phydev_warn(phydev, "Failed to write TR low data\n");
goto err;
}
ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_HIGH_DATA,
(data & 0x00FF0000) >> 16);
if (ret < 0) {
pr_warn("Failed to write TR high data\n");
phydev_warn(phydev, "Failed to write TR high data\n");
goto err;
}
@ -115,14 +115,15 @@ static int lan88xx_TR_reg_set(struct phy_device *phydev, u16 regaddr,
ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_CR, buf);
if (ret < 0) {
pr_warn("Failed to write data in reg\n");
phydev_warn(phydev, "Failed to write data in reg\n");
goto err;
}
usleep_range(1000, 2000);/* Wait for Data to be written */
val = __phy_read(phydev, LAN88XX_EXT_PAGE_TR_CR);
if (!(val & 0x8000))
pr_warn("TR Register[0x%X] configuration failed\n", regaddr);
phydev_warn(phydev, "TR Register[0x%X] configuration failed\n",
regaddr);
err:
return phy_restore_page(phydev, save_page, ret);
}
@ -137,7 +138,7 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x0F82, 0x12B00A);
if (err < 0)
pr_warn("Failed to Set Register[0x0F82]\n");
phydev_warn(phydev, "Failed to Set Register[0x0F82]\n");
/* Get access to Channel b'10, Node b'1101, Register 0x06.
* Write 24-bit value 0xD2C46F to register. Setting SSTrKf1000Slv,
@ -145,7 +146,7 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x168C, 0xD2C46F);
if (err < 0)
pr_warn("Failed to Set Register[0x168C]\n");
phydev_warn(phydev, "Failed to Set Register[0x168C]\n");
/* Get access to Channel b'10, Node b'1111, Register 0x11.
* Write 24-bit value 0x620 to register. Setting rem_upd_done_thresh
@ -153,7 +154,7 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x17A2, 0x620);
if (err < 0)
pr_warn("Failed to Set Register[0x17A2]\n");
phydev_warn(phydev, "Failed to Set Register[0x17A2]\n");
/* Get access to Channel b'10, Node b'1101, Register 0x10.
* Write 24-bit value 0xEEFFDD to register. Setting
@ -162,7 +163,7 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x16A0, 0xEEFFDD);
if (err < 0)
pr_warn("Failed to Set Register[0x16A0]\n");
phydev_warn(phydev, "Failed to Set Register[0x16A0]\n");
/* Get access to Channel b'10, Node b'1101, Register 0x13.
* Write 24-bit value 0x071448 to register. Setting
@ -170,7 +171,7 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x16A6, 0x071448);
if (err < 0)
pr_warn("Failed to Set Register[0x16A6]\n");
phydev_warn(phydev, "Failed to Set Register[0x16A6]\n");
/* Get access to Channel b'10, Node b'1101, Register 0x12.
* Write 24-bit value 0x13132F to register. Setting
@ -178,7 +179,7 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x16A4, 0x13132F);
if (err < 0)
pr_warn("Failed to Set Register[0x16A4]\n");
phydev_warn(phydev, "Failed to Set Register[0x16A4]\n");
/* Get access to Channel b'10, Node b'1101, Register 0x14.
* Write 24-bit value 0x0 to register. Setting eee_3level_delay,
@ -186,7 +187,7 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x16A8, 0x0);
if (err < 0)
pr_warn("Failed to Set Register[0x16A8]\n");
phydev_warn(phydev, "Failed to Set Register[0x16A8]\n");
/* Get access to Channel b'01, Node b'1111, Register 0x34.
* Write 24-bit value 0x91B06C to register. Setting
@ -195,7 +196,7 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x0FE8, 0x91B06C);
if (err < 0)
pr_warn("Failed to Set Register[0x0FE8]\n");
phydev_warn(phydev, "Failed to Set Register[0x0FE8]\n");
/* Get access to Channel b'01, Node b'1111, Register 0x3E.
* Write 24-bit value 0xC0A028 to register. Setting
@ -204,7 +205,7 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x0FFC, 0xC0A028);
if (err < 0)
pr_warn("Failed to Set Register[0x0FFC]\n");
phydev_warn(phydev, "Failed to Set Register[0x0FFC]\n");
/* Get access to Channel b'01, Node b'1111, Register 0x35.
* Write 24-bit value 0x041600 to register. Setting
@ -213,14 +214,14 @@ static void lan88xx_config_TR_regs(struct phy_device *phydev)
*/
err = lan88xx_TR_reg_set(phydev, 0x0FEA, 0x041600);
if (err < 0)
pr_warn("Failed to Set Register[0x0FEA]\n");
phydev_warn(phydev, "Failed to Set Register[0x0FEA]\n");
/* Get access to Channel b'10, Node b'1101, Register 0x03.
* Write 24-bit value 0x000004 to register. Setting TrFreeze bits.
*/
err = lan88xx_TR_reg_set(phydev, 0x1686, 0x000004);
if (err < 0)
pr_warn("Failed to Set Register[0x1686]\n");
phydev_warn(phydev, "Failed to Set Register[0x1686]\n");
}
static int lan88xx_probe(struct phy_device *phydev)

View File

@ -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,

View File

@ -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);
@ -920,13 +1064,13 @@ void phy_attached_print(struct phy_device *phydev, const char *fmt, ...)
if (!fmt) {
dev_info(&phydev->mdio.dev, ATTACHED_FMT "\n",
phydev_info(phydev, ATTACHED_FMT "\n",
drv_name, phydev_name(phydev),
irq_str);
} else {
va_list ap;
dev_info(&phydev->mdio.dev, ATTACHED_FMT,
phydev_info(phydev, ATTACHED_FMT,
drv_name, phydev_name(phydev),
irq_str);
@ -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;

View File

@ -68,33 +68,6 @@ struct phylink {
struct sfp_bus *sfp_bus;
};
static inline void linkmode_zero(unsigned long *dst)
{
bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline void linkmode_copy(unsigned long *dst, const unsigned long *src)
{
bitmap_copy(dst, src, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline void linkmode_and(unsigned long *dst, const unsigned long *a,
const unsigned long *b)
{
bitmap_and(dst, a, b, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline void linkmode_or(unsigned long *dst, const unsigned long *a,
const unsigned long *b)
{
bitmap_or(dst, a, b, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline bool linkmode_empty(const unsigned long *src)
{
return bitmap_empty(src, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
/**
* phylink_set_port_modes() - set the port type modes in the ethtool mask
* @mask: ethtool link mode mask

76
include/linux/linkmode.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef __LINKMODE_H
#define __LINKMODE_H
#include <linux/bitmap.h>
#include <linux/ethtool.h>
#include <uapi/linux/ethtool.h>
static inline void linkmode_zero(unsigned long *dst)
{
bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline void linkmode_copy(unsigned long *dst, const unsigned long *src)
{
bitmap_copy(dst, src, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline void linkmode_and(unsigned long *dst, const unsigned long *a,
const unsigned long *b)
{
bitmap_and(dst, a, b, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline void linkmode_or(unsigned long *dst, const unsigned long *a,
const unsigned long *b)
{
bitmap_or(dst, a, b, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline bool linkmode_empty(const unsigned long *src)
{
return bitmap_empty(src, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline int linkmode_andnot(unsigned long *dst, const unsigned long *src1,
const unsigned long *src2)
{
return bitmap_andnot(dst, src1, src2, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
static inline void linkmode_set_bit(int nr, volatile unsigned long *addr)
{
__set_bit(nr, addr);
}
static inline void linkmode_set_bit_array(const int *array, int array_size,
unsigned long *addr)
{
int i;
for (i = 0; i < array_size; i++)
linkmode_set_bit(array[i], addr);
}
static inline void linkmode_clear_bit(int nr, volatile unsigned long *addr)
{
__clear_bit(nr, addr);
}
static inline void linkmode_change_bit(int nr, volatile unsigned long *addr)
{
__change_bit(nr, addr);
}
static inline int linkmode_test_bit(int nr, volatile unsigned long *addr)
{
return test_bit(nr, addr);
}
static inline int linkmode_equal(const unsigned long *src1,
const unsigned long *src2)
{
return bitmap_equal(src1, src2, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
#endif /* __LINKMODE_H */

View File

@ -10,6 +10,7 @@
#include <linux/if.h>
#include <linux/linkmode.h>
#include <uapi/linux/mii.h>
struct ethtool_cmd;
@ -131,6 +132,34 @@ static inline u32 ethtool_adv_to_mii_adv_t(u32 ethadv)
return result;
}
/**
* linkmode_adv_to_mii_adv_t
* @advertising: the linkmode advertisement settings
*
* A small helper function that translates linkmode advertisement
* settings to phy autonegotiation advertisements for the
* MII_ADVERTISE register.
*/
static inline u32 linkmode_adv_to_mii_adv_t(unsigned long *advertising)
{
u32 result = 0;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, advertising))
result |= ADVERTISE_10HALF;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, advertising))
result |= ADVERTISE_10FULL;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, advertising))
result |= ADVERTISE_100HALF;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, advertising))
result |= ADVERTISE_100FULL;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising))
result |= ADVERTISE_PAUSE_CAP;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising))
result |= ADVERTISE_PAUSE_ASYM;
return result;
}
/**
* mii_adv_to_ethtool_adv_t
* @adv: value of the MII_ADVERTISE register
@ -178,6 +207,28 @@ static inline u32 ethtool_adv_to_mii_ctrl1000_t(u32 ethadv)
return result;
}
/**
* linkmode_adv_to_mii_ctrl1000_t
* advertising: the linkmode advertisement settings
*
* A small helper function that translates linkmode advertisement
* settings to phy autonegotiation advertisements for the
* MII_CTRL1000 register when in 1000T mode.
*/
static inline u32 linkmode_adv_to_mii_ctrl1000_t(unsigned long *advertising)
{
u32 result = 0;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
advertising))
result |= ADVERTISE_1000HALF;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
advertising))
result |= ADVERTISE_1000FULL;
return result;
}
/**
* mii_ctrl1000_to_ethtool_adv_t
* @adv: value of the MII_CTRL1000 register
@ -302,6 +353,56 @@ static inline u32 mii_lpa_to_ethtool_lpa_x(u32 lpa)
return result | mii_adv_to_ethtool_adv_x(lpa);
}
/**
* mii_adv_to_linkmode_adv_t
* @advertising:pointer to destination link mode.
* @adv: value of the MII_ADVERTISE register
*
* A small helper function that translates MII_ADVERTISE bits
* to linkmode advertisement settings.
*/
static inline void mii_adv_to_linkmode_adv_t(unsigned long *advertising,
u32 adv)
{
linkmode_zero(advertising);
if (adv & ADVERTISE_10HALF)
linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
advertising);
if (adv & ADVERTISE_10FULL)
linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
advertising);
if (adv & ADVERTISE_100HALF)
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
advertising);
if (adv & ADVERTISE_100FULL)
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
advertising);
if (adv & ADVERTISE_PAUSE_CAP)
linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising);
if (adv & ADVERTISE_PAUSE_ASYM)
linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising);
}
/**
* ethtool_adv_to_lcl_adv_t
* @advertising:pointer to ethtool advertising
*
* A small helper function that translates ethtool advertising to LVL
* pause capabilities.
*/
static inline u32 ethtool_adv_to_lcl_adv_t(u32 advertising)
{
u32 lcl_adv = 0;
if (advertising & ADVERTISED_Pause)
lcl_adv |= ADVERTISE_PAUSE_CAP;
if (advertising & ADVERTISED_Asym_Pause)
lcl_adv |= ADVERTISE_PAUSE_ASYM;
return lcl_adv;
}
/**
* mii_advertise_flowctrl - get flow control advertisement flags
* @cap: Flow control capabilities (FLOW_CTRL_RX, FLOW_CTRL_TX or both)

View File

@ -19,6 +19,7 @@
#include <linux/compiler.h>
#include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <linux/linkmode.h>
#include <linux/mdio.h>
#include <linux/mii.h>
#include <linux/module.h>
@ -41,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 __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_features) __ro_after_init;
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_t1_features) __ro_after_init;
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_features) __ro_after_init;
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_fibre_features) __ro_after_init;
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features) __ro_after_init;
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
#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,
@ -509,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;
@ -967,6 +976,12 @@ static inline void phy_device_reset(struct phy_device *phydev, int value)
#define phydev_err(_phydev, format, args...) \
dev_err(&_phydev->mdio.dev, format, ##args)
#define phydev_info(_phydev, format, args...) \
dev_info(&_phydev->mdio.dev, format, ##args)
#define phydev_warn(_phydev, format, args...) \
dev_warn(&_phydev->mdio.dev, format, ##args)
#define phydev_dbg(_phydev, format, args...) \
dev_dbg(&_phydev->mdio.dev, format, ##args)