diff options
author | Xiaoming.Zhang <Xiaoming.Zhang@resilience.com> | 2008-09-25 16:28:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-10-08 19:00:57 -0400 |
commit | 9ac1353f3832716eb25268c0cd06c93080a83c7b (patch) | |
tree | 247ea1589fc35e2f3166969deb3652b40c4dc339 /drivers/net/skge.c | |
parent | 0ca41c0413a4d9ca58767d53d23accea9aa1cdef (diff) |
[10/21] driver/net/skge.c: restart the interface when it's options or
pauseparam is set
On Wednesday 24 September 2008 07:47, Stephen Hemminger wrote:
> On Mon, 22 Sep 2008 14:52:17 -0700
>
> akpm@linux-foundation.org wrote:
> > From: "Xiaoming.Zhang" <Xiaoming.Zhang@resilience.com>
> >
> > We have an issue of the skge driver: The card won't work when it's
> > options are changed. Here's the hardware info:
> >
> > # lspci -v
> > 05:04.0 Ethernet controller: Marvell Technology Group Ltd. 88E8001
> > Gigabit Ethernet Controller (rev 13) Subsystem: Marvell Technology Group
> > Ltd. Marvell RDK-8001 Flags: bus master, 66MHz, medium devsel, latency
> > 32, IRQ 16 Memory at d042c000 (32-bit, non-prefetchable) [size=16K] I/O
> > ports at d000 [size=256]
> > [virtual] Expansion ROM at 20400000 [disabled] [size=128K]
> > Capabilities: [48] Power Management version 2
> > Capabilities: [50] Vital Product Data
> >
> > The happens in both Linux-2.6.26(skge version 1.23) and RHEL5.2(skge
> > version 1.6).
> >
> > For example, at first it is set to "speed 1000 duplex full auto-neg on"
> > and it works, then run
> >
> > ethtool -s <ethx> autoneg off
> > or ethtool -s <ethx> speed 100 duplex full autoneg off
> >
> > Then it will stop working. After that if we restart the interface:
> >
> > ifconifg <ethx> down
> > ifconfig <ethx> up
> >
> > It will work again. And `ethtool -A' has the same issue.
> >
> > So we think after setting the options, the interface should be restarted.
> >
> > Signed-off-by: Zhang Xiaoming <xiaoming.zhang@resilience.com>
> > Cc: Stephen Hemminger <shemminger@vyatta.com>
> > Cc: Jeff Garzik <jeff@garzik.org>
> > Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
> > ---
> >
> > drivers/net/skge.c | 12 ++++++++----
> > 1 file changed, 8 insertions(+), 4 deletions(-)
> >
> > diff -puN
> > drivers/net/skge.c~driver-net-skgec-restart-the-interface-when-its-option
> >s-or-pauseparam-is-set drivers/net/skge.c ---
> > a/drivers/net/skge.c~driver-net-skgec-restart-the-interface-when-its-opti
> >ons-or-pauseparam-is-set +++ a/drivers/net/skge.c
> > @@ -353,8 +353,10 @@ static int skge_set_settings(struct net_
> > skge->autoneg = ecmd->autoneg;
> > skge->advertising = ecmd->advertising;
> >
> > - if (netif_running(dev))
> > - skge_phy_reset(skge);
> > + if (netif_running(dev)) {
> > + skge_down(dev);
> > + skge_up(dev);
> > + }
> >
> > return (0);
> > }
> > @@ -595,8 +597,10 @@ static int skge_set_pauseparam(struct ne
> > skge->flow_control = FLOW_MODE_NONE;
> > }
> >
> > - if (netif_running(dev))
> > - skge_phy_reset(skge);
> > + if (netif_running(dev)) {
> > + skge_down(dev);
> > + skge_up(dev);
> > + }
> >
> > return 0;
> > }
>
> Since skge_up can fail because of out of memory, this code needs to
> check the return value. And then if it fails the "limbo state" needs
> to be handled in skge_down.
How about like this? It is tested.
Thank you.
Signed-off-by: Zhang Xiaoming <xiaoming.zhang@resilience.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r-- | drivers/net/skge.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 2e26dced13a1..3bca52c142fe 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -319,6 +319,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
319 | struct skge_port *skge = netdev_priv(dev); | 319 | struct skge_port *skge = netdev_priv(dev); |
320 | const struct skge_hw *hw = skge->hw; | 320 | const struct skge_hw *hw = skge->hw; |
321 | u32 supported = skge_supported_modes(hw); | 321 | u32 supported = skge_supported_modes(hw); |
322 | int err = 0; | ||
322 | 323 | ||
323 | if (ecmd->autoneg == AUTONEG_ENABLE) { | 324 | if (ecmd->autoneg == AUTONEG_ENABLE) { |
324 | ecmd->advertising = supported; | 325 | ecmd->advertising = supported; |
@@ -367,8 +368,14 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
367 | skge->autoneg = ecmd->autoneg; | 368 | skge->autoneg = ecmd->autoneg; |
368 | skge->advertising = ecmd->advertising; | 369 | skge->advertising = ecmd->advertising; |
369 | 370 | ||
370 | if (netif_running(dev)) | 371 | if (netif_running(dev)) { |
371 | skge_phy_reset(skge); | 372 | skge_down(dev); |
373 | err = skge_up(dev); | ||
374 | if (err) { | ||
375 | dev_close(dev); | ||
376 | return err; | ||
377 | } | ||
378 | } | ||
372 | 379 | ||
373 | return (0); | 380 | return (0); |
374 | } | 381 | } |
@@ -593,6 +600,7 @@ static int skge_set_pauseparam(struct net_device *dev, | |||
593 | { | 600 | { |
594 | struct skge_port *skge = netdev_priv(dev); | 601 | struct skge_port *skge = netdev_priv(dev); |
595 | struct ethtool_pauseparam old; | 602 | struct ethtool_pauseparam old; |
603 | int err = 0; | ||
596 | 604 | ||
597 | skge_get_pauseparam(dev, &old); | 605 | skge_get_pauseparam(dev, &old); |
598 | 606 | ||
@@ -609,8 +617,14 @@ static int skge_set_pauseparam(struct net_device *dev, | |||
609 | skge->flow_control = FLOW_MODE_NONE; | 617 | skge->flow_control = FLOW_MODE_NONE; |
610 | } | 618 | } |
611 | 619 | ||
612 | if (netif_running(dev)) | 620 | if (netif_running(dev)) { |
613 | skge_phy_reset(skge); | 621 | skge_down(dev); |
622 | err = skge_up(dev); | ||
623 | if (err) { | ||
624 | dev_close(dev); | ||
625 | return err; | ||
626 | } | ||
627 | } | ||
614 | 628 | ||
615 | return 0; | 629 | return 0; |
616 | } | 630 | } |