diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2011-01-06 13:40:36 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-09 18:52:58 -0500 |
commit | 2aca31e765f756408ebc8408378afa5795d1ae49 (patch) | |
tree | 9e7f59ae4d5c32012725c8792f7f095a2fa4e934 | |
parent | 9bcb8018cf7af1f00f35cad4b121897cac077269 (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.c | 26 |
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 | ||
3428 | static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | 3425 | static 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); |