Skip to content

Commit

Permalink
mv643xx_eth: fix for disabled autoneg
Browse files Browse the repository at this point in the history
When autoneg has been disabled in the PHY (Marvell 88E1118 here), auto
negotiation between MAC and PHY seem non-functional anymore. The only
way I found to workaround this is to manually configure the MAC with the
settings sent to the PHY earlier.

Signed-off-by: Phil Sutter <phil.sutter@viprinet.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Phil Sutter authored and David S. Miller committed Mar 7, 2013
1 parent 80028ea commit 260055b
Showing 1 changed file with 51 additions and 4 deletions.
55 changes: 51 additions & 4 deletions drivers/net/ethernet/marvell/mv643xx_eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,45 @@ static void txq_set_fixed_prio_mode(struct tx_queue *txq)


/* mii management interface *************************************************/
static void mv643xx_adjust_pscr(struct mv643xx_eth_private *mp)
{
u32 pscr = rdlp(mp, PORT_SERIAL_CONTROL);
u32 autoneg_disable = FORCE_LINK_PASS |
DISABLE_AUTO_NEG_SPEED_GMII |
DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
DISABLE_AUTO_NEG_FOR_DUPLEX;

if (mp->phy->autoneg == AUTONEG_ENABLE) {
/* enable auto negotiation */
pscr &= ~autoneg_disable;
goto out_write;
}

pscr |= autoneg_disable;

if (mp->phy->speed == SPEED_1000) {
/* force gigabit, half duplex not supported */
pscr |= SET_GMII_SPEED_TO_1000;
pscr |= SET_FULL_DUPLEX_MODE;
goto out_write;
}

pscr &= ~SET_GMII_SPEED_TO_1000;

if (mp->phy->speed == SPEED_100)
pscr |= SET_MII_SPEED_TO_100;
else
pscr &= ~SET_MII_SPEED_TO_100;

if (mp->phy->duplex == DUPLEX_FULL)
pscr |= SET_FULL_DUPLEX_MODE;
else
pscr &= ~SET_FULL_DUPLEX_MODE;

out_write:
wrlp(mp, PORT_SERIAL_CONTROL, pscr);
}

static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id)
{
struct mv643xx_eth_shared_private *msp = dev_id;
Expand Down Expand Up @@ -1499,6 +1538,7 @@ static int
mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
int ret;

if (mp->phy == NULL)
return -EINVAL;
Expand All @@ -1508,7 +1548,10 @@ mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
*/
cmd->advertising &= ~ADVERTISED_1000baseT_Half;

return phy_ethtool_sset(mp->phy, cmd);
ret = phy_ethtool_sset(mp->phy, cmd);
if (!ret)
mv643xx_adjust_pscr(mp);
return ret;
}

static void mv643xx_eth_get_drvinfo(struct net_device *dev,
Expand Down Expand Up @@ -2442,11 +2485,15 @@ static int mv643xx_eth_stop(struct net_device *dev)
static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
int ret;

if (mp->phy != NULL)
return phy_mii_ioctl(mp->phy, ifr, cmd);
if (mp->phy == NULL)
return -ENOTSUPP;

return -EOPNOTSUPP;
ret = phy_mii_ioctl(mp->phy, ifr, cmd);
if (!ret)
mv643xx_adjust_pscr(mp);
return ret;
}

static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
Expand Down

0 comments on commit 260055b

Please sign in to comment.