aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2011-01-06 13:40:36 -0500
committerDavid S. Miller <davem@davemloft.net>2011-01-09 18:52:58 -0500
commit2aca31e765f756408ebc8408378afa5795d1ae49 (patch)
tree9e7f59ae4d5c32012725c8792f7f095a2fa4e934
parent9bcb8018cf7af1f00f35cad4b121897cac077269 (diff)
sky2: fix limited auto negotiation
The sky2 driver would always try all possible supported speeds even if the user only asked for a limited set of speed/duplex combinations. Reported-by: Mohsen Hariri <m.hariri@gmail.com> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/sky2.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 39996bf3b247..b56109294758 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -3411,18 +3411,15 @@ static u32 sky2_supported_modes(const struct sky2_hw *hw)
3411 u32 modes = SUPPORTED_10baseT_Half 3411 u32 modes = SUPPORTED_10baseT_Half
3412 | SUPPORTED_10baseT_Full 3412 | SUPPORTED_10baseT_Full
3413 | SUPPORTED_100baseT_Half 3413 | SUPPORTED_100baseT_Half
3414 | SUPPORTED_100baseT_Full 3414 | SUPPORTED_100baseT_Full;
3415 | SUPPORTED_Autoneg | SUPPORTED_TP;
3416 3415
3417 if (hw->flags & SKY2_HW_GIGABIT) 3416 if (hw->flags & SKY2_HW_GIGABIT)
3418 modes |= SUPPORTED_1000baseT_Half 3417 modes |= SUPPORTED_1000baseT_Half
3419 | SUPPORTED_1000baseT_Full; 3418 | SUPPORTED_1000baseT_Full;
3420 return modes; 3419 return modes;
3421 } else 3420 } else
3422 return SUPPORTED_1000baseT_Half 3421 return SUPPORTED_1000baseT_Half
3423 | SUPPORTED_1000baseT_Full 3422 | SUPPORTED_1000baseT_Full;
3424 | SUPPORTED_Autoneg
3425 | SUPPORTED_FIBRE;
3426} 3423}
3427 3424
3428static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) 3425static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -3436,9 +3433,11 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
3436 if (sky2_is_copper(hw)) { 3433 if (sky2_is_copper(hw)) {
3437 ecmd->port = PORT_TP; 3434 ecmd->port = PORT_TP;
3438 ecmd->speed = sky2->speed; 3435 ecmd->speed = sky2->speed;
3436 ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_TP;
3439 } else { 3437 } else {
3440 ecmd->speed = SPEED_1000; 3438 ecmd->speed = SPEED_1000;
3441 ecmd->port = PORT_FIBRE; 3439 ecmd->port = PORT_FIBRE;
3440 ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_FIBRE;
3442 } 3441 }
3443 3442
3444 ecmd->advertising = sky2->advertising; 3443 ecmd->advertising = sky2->advertising;
@@ -3455,8 +3454,19 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
3455 u32 supported = sky2_supported_modes(hw); 3454 u32 supported = sky2_supported_modes(hw);
3456 3455
3457 if (ecmd->autoneg == AUTONEG_ENABLE) { 3456 if (ecmd->autoneg == AUTONEG_ENABLE) {
3457 if (ecmd->advertising & ~supported)
3458 return -EINVAL;
3459
3460 if (sky2_is_copper(hw))
3461 sky2->advertising = ecmd->advertising |
3462 ADVERTISED_TP |
3463 ADVERTISED_Autoneg;
3464 else
3465 sky2->advertising = ecmd->advertising |
3466 ADVERTISED_FIBRE |
3467 ADVERTISED_Autoneg;
3468
3458 sky2->flags |= SKY2_FLAG_AUTO_SPEED; 3469 sky2->flags |= SKY2_FLAG_AUTO_SPEED;
3459 ecmd->advertising = supported;
3460 sky2->duplex = -1; 3470 sky2->duplex = -1;
3461 sky2->speed = -1; 3471 sky2->speed = -1;
3462 } else { 3472 } else {
@@ -3500,8 +3510,6 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
3500 sky2->flags &= ~SKY2_FLAG_AUTO_SPEED; 3510 sky2->flags &= ~SKY2_FLAG_AUTO_SPEED;
3501 } 3511 }
3502 3512
3503 sky2->advertising = ecmd->advertising;
3504
3505 if (netif_running(dev)) { 3513 if (netif_running(dev)) {
3506 sky2_phy_reinit(sky2); 3514 sky2_phy_reinit(sky2);
3507 sky2_set_multicast(dev); 3515 sky2_set_multicast(dev);