Skip to content

Commit

Permalink
Merge branch 'u32-to-linkmode-fixes'
Browse files Browse the repository at this point in the history
Andrew Lunn says:

====================
u32 to linkmode fixes

This patchset fixes issues found in the last patchset which converted
the phydev advertise etc, from a u32 to a linux bitmap. Most of the
issues are the result of clearing bits which should not of been
cleared. To make the API clearer, the idea from Heiner Kallweit was
used, with _mod_ to indicate the function modifies just the bits it
needs to, or _to_ to clear all bits and just set bit that need to be
set.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Dec 6, 2018
2 parents b255e50 + 9db299c commit 7127f2f
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 47 deletions.
24 changes: 12 additions & 12 deletions drivers/net/phy/marvell.c
Original file line number Diff line number Diff line change
Expand Up @@ -1047,21 +1047,21 @@ static int m88e1145_config_init(struct phy_device *phydev)
}

/**
* fiber_lpa_to_linkmode_lpa_t
* fiber_lpa_mod_linkmode_lpa_t
* @advertising: the linkmode advertisement settings
* @lpa: value of the MII_LPA register for fiber link
*
* A small helper function that translates MII_LPA
* bits to linkmode LP advertisement settings.
* A small helper function that translates MII_LPA bits to linkmode LP
* advertisement settings. Other bits in advertising are left
* unchanged.
*/
static void fiber_lpa_to_linkmode_lpa_t(unsigned long *advertising, u32 lpa)
static void fiber_lpa_mod_linkmode_lpa_t(unsigned long *advertising, u32 lpa)
{
if (lpa & LPA_FIBER_1000HALF)
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
advertising);
if (lpa & LPA_FIBER_1000FULL)
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
advertising);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
advertising, lpa & LPA_FIBER_1000HALF);

linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
advertising, lpa & LPA_FIBER_1000FULL);
}

/**
Expand Down Expand Up @@ -1138,15 +1138,15 @@ static int marvell_read_status_page_an(struct phy_device *phydev,

if (!fiber) {
mii_lpa_to_linkmode_lpa_t(phydev->lp_advertising, lpa);
mii_stat1000_to_linkmode_lpa_t(phydev->lp_advertising, lpagb);
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, lpagb);

if (phydev->duplex == DUPLEX_FULL) {
phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
}
} else {
/* The fiber link is only 1000M capable */
fiber_lpa_to_linkmode_lpa_t(phydev->lp_advertising, lpa);
fiber_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa);

if (phydev->duplex == DUPLEX_FULL) {
if (!(lpa & LPA_PAUSE_FIBER)) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/phy/marvell10g.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ static int mv3310_read_status(struct phy_device *phydev)
if (val < 0)
return val;

mii_stat1000_to_linkmode_lpa_t(phydev->lp_advertising, val);
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);

if (phydev->autoneg == AUTONEG_ENABLE)
phy_resolve_aneg_linkmode(phydev);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/phy/phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,8 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
}
break;
case MII_ADVERTISE:
mii_adv_to_linkmode_adv_t(phydev->advertising,
val);
mii_adv_mod_linkmode_adv_t(phydev->advertising,
val);
change_autoneg = true;
break;
default:
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/phy/phy_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -1739,16 +1739,16 @@ int genphy_read_status(struct phy_device *phydev)
return -ENOLINK;
}

mii_stat1000_to_linkmode_lpa_t(phydev->lp_advertising,
lpagb);
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
lpagb);
common_adv_gb = lpagb & adv << 2;
}

lpa = phy_read(phydev, MII_LPA);
if (lpa < 0)
return lpa;

mii_lpa_to_linkmode_lpa_t(phydev->lp_advertising, lpa);
mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa);

adv = phy_read(phydev, MII_ADVERTISE);
if (adv < 0)
Expand Down
9 changes: 9 additions & 0 deletions include/linux/linkmode.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ static inline void linkmode_clear_bit(int nr, volatile unsigned long *addr)
__clear_bit(nr, addr);
}

static inline void linkmode_mod_bit(int nr, volatile unsigned long *addr,
int set)
{
if (set)
linkmode_set_bit(nr, addr);
else
linkmode_clear_bit(nr, addr);
}

static inline void linkmode_change_bit(int nr, volatile unsigned long *addr)
{
__change_bit(nr, addr);
Expand Down
93 changes: 64 additions & 29 deletions include/linux/mii.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,22 +288,22 @@ static inline u32 mii_stat1000_to_ethtool_lpa_t(u32 lpa)
}

/**
* mii_stat1000_to_linkmode_lpa_t
* mii_stat1000_mod_linkmode_lpa_t
* @advertising: target the linkmode advertisement settings
* @adv: value of the MII_STAT1000 register
*
* A small helper function that translates MII_STAT1000 bits, when in
* 1000Base-T mode, to linkmode advertisement settings.
* 1000Base-T mode, to linkmode advertisement settings. Other bits in
* advertising are not changes.
*/
static inline void mii_stat1000_to_linkmode_lpa_t(unsigned long *advertising,
u32 lpa)
static inline void mii_stat1000_mod_linkmode_lpa_t(unsigned long *advertising,
u32 lpa)
{
if (lpa & LPA_1000HALF)
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
advertising);
if (lpa & LPA_1000FULL)
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
advertising);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
advertising, lpa & LPA_1000HALF);

linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
advertising, lpa & LPA_1000FULL);
}

/**
Expand Down Expand Up @@ -372,52 +372,87 @@ static inline u32 mii_lpa_to_ethtool_lpa_x(u32 lpa)
return result | mii_adv_to_ethtool_adv_x(lpa);
}

/**
* mii_adv_mod_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. Leaves other bits unchanged.
*/
static inline void mii_adv_mod_linkmode_adv_t(unsigned long *advertising,
u32 adv)
{
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
advertising, adv & ADVERTISE_10HALF);

linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
advertising, adv & ADVERTISE_10FULL);

linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
advertising, adv & ADVERTISE_100HALF);

linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
advertising, adv & ADVERTISE_100FULL);

linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising,
adv & ADVERTISE_PAUSE_CAP);

linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
advertising, adv & ADVERTISE_PAUSE_ASYM);
}

/**
* 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.
* to linkmode advertisement settings. Clears the old value
* of advertising.
*/
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);
mii_adv_mod_linkmode_adv_t(advertising, adv);
}

/**
* mii_lpa_to_linkmode_lpa_t
* @adv: value of the MII_LPA register
*
* A small helper function that translates MII_LPA bits, when in
* 1000Base-T mode, to linkmode LP advertisement settings.
* 1000Base-T mode, to linkmode LP advertisement settings. Clears the
* old value of advertising
*/
static inline void mii_lpa_to_linkmode_lpa_t(unsigned long *lp_advertising,
u32 lpa)
{
mii_adv_to_linkmode_adv_t(lp_advertising, lpa);

if (lpa & LPA_LPACK)
linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
lp_advertising);

mii_adv_to_linkmode_adv_t(lp_advertising, lpa);
}

/**
* mii_lpa_mod_linkmode_lpa_t
* @adv: value of the MII_LPA register
*
* A small helper function that translates MII_LPA bits, when in
* 1000Base-T mode, to linkmode LP advertisement settings. Leaves
* other bits unchanged.
*/
static inline void mii_lpa_mod_linkmode_lpa_t(unsigned long *lp_advertising,
u32 lpa)
{
mii_adv_mod_linkmode_adv_t(lp_advertising, lpa);

linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
lp_advertising, lpa & LPA_LPACK);
}

/**
Expand Down

0 comments on commit 7127f2f

Please sign in to comment.