Skip to content

Commit

Permalink
r8169: support control of advertising.
Browse files Browse the repository at this point in the history
This allows "ethtool advertise" to control the speed and duplex
features the device offers the switch.

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
  • Loading branch information
Oliver Neukum authored and Francois Romieu committed Mar 5, 2011
1 parent 5a5e444 commit 54405cd
Showing 1 changed file with 37 additions and 17 deletions.
54 changes: 37 additions & 17 deletions drivers/net/r8169.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ struct rtl8169_private {
void (*up)(struct rtl8169_private *);
} pll_power_ops;

int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
int (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(struct rtl8169_private *tp);
void (*hw_start)(struct net_device *);
Expand Down Expand Up @@ -1108,7 +1108,7 @@ static int rtl8169_get_regs_len(struct net_device *dev)
}

static int rtl8169_set_speed_tbi(struct net_device *dev,
u8 autoneg, u16 speed, u8 duplex)
u8 autoneg, u16 speed, u8 duplex, u32 ignored)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
Expand All @@ -1131,19 +1131,30 @@ static int rtl8169_set_speed_tbi(struct net_device *dev,
}

static int rtl8169_set_speed_xmii(struct net_device *dev,
u8 autoneg, u16 speed, u8 duplex)
u8 autoneg, u16 speed, u8 duplex, u32 adv)
{
struct rtl8169_private *tp = netdev_priv(dev);
int giga_ctrl, bmcr;
int rc = -EINVAL;

rtl_writephy(tp, 0x1f, 0x0000);

if (autoneg == AUTONEG_ENABLE) {
int auto_nego;

auto_nego = rtl_readphy(tp, MII_ADVERTISE);
auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100FULL);
auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100FULL);

if (adv & ADVERTISED_10baseT_Half)
auto_nego |= ADVERTISE_10HALF;
if (adv & ADVERTISED_10baseT_Full)
auto_nego |= ADVERTISE_10FULL;
if (adv & ADVERTISED_100baseT_Half)
auto_nego |= ADVERTISE_100HALF;
if (adv & ADVERTISED_100baseT_Full)
auto_nego |= ADVERTISE_100FULL;

auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;

giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
Expand All @@ -1160,10 +1171,15 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
(tp->mac_version != RTL_GIGA_MAC_VER_16) &&
(tp->mac_version != RTL_GIGA_MAC_VER_29) &&
(tp->mac_version != RTL_GIGA_MAC_VER_30)) {
giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
} else {
if (adv & ADVERTISED_1000baseT_Half)
giga_ctrl |= ADVERTISE_1000HALF;
if (adv & ADVERTISED_1000baseT_Full)
giga_ctrl |= ADVERTISE_1000FULL;
} else if (adv & (ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full)) {
netif_info(tp, link, dev,
"PHY does not support 1000Mbps\n");
goto out;
}

bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Expand All @@ -1178,7 +1194,7 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
else if (speed == SPEED_100)
bmcr = BMCR_SPEED100;
else
return -EINVAL;
goto out;

if (duplex == DUPLEX_FULL)
bmcr |= BMCR_FULLDPLX;
Expand All @@ -1199,16 +1215,18 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
}
}

return 0;
rc = 0;
out:
return rc;
}

static int rtl8169_set_speed(struct net_device *dev,
u8 autoneg, u16 speed, u8 duplex)
u8 autoneg, u16 speed, u8 duplex, u32 advertising)
{
struct rtl8169_private *tp = netdev_priv(dev);
int ret;

ret = tp->set_speed(dev, autoneg, speed, duplex);
ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);

if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))
mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Expand All @@ -1223,7 +1241,8 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
int ret;

spin_lock_irqsave(&tp->lock, flags);
ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex);
ret = rtl8169_set_speed(dev,
cmd->autoneg, cmd->speed, cmd->duplex, cmd->advertising);
spin_unlock_irqrestore(&tp->lock, flags);

return ret;
Expand Down Expand Up @@ -2669,11 +2688,12 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)

rtl8169_phy_reset(dev, tp);

/*
* rtl8169_set_speed_xmii takes good care of the Fast Ethernet
* only 8101. Don't panic.
*/
rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
tp->mii.supports_gmii ?
ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full : 0);

if (RTL_R8(PHYstatus) & TBI_Enable)
netif_info(tp, link, dev, "TBI auto-negotiating\n");
Expand Down

0 comments on commit 54405cd

Please sign in to comment.