diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-10-16 12:15:50 -0700 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-10-16 21:10:28 -0400 |
commit | 60b24b51799cc23313eed85fb874b70a6d02e2b7 (patch) | |
tree | 7ee3aef13967c65923a24962ece0e8af66a227a2 /drivers | |
parent | 7fb7ac241162dc51ec0f7644d4a97b2855213c32 (diff) | |
download | linux-60b24b51799cc23313eed85fb874b70a6d02e2b7.tar.gz linux-60b24b51799cc23313eed85fb874b70a6d02e2b7.tar.bz2 linux-60b24b51799cc23313eed85fb874b70a6d02e2b7.zip |
skge: changing MTU while running causes problems
Rather than bring network down/up when changing MTU,
only need to impact receiver.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/skge.c | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index e593585f8bf7..d5c10fd93bf4 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2544,6 +2544,15 @@ static int skge_up(struct net_device *dev) return err; } +/* stop receiver */ +static void skge_rx_stop(struct skge_hw *hw, int port) +{ + skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP); + skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL), + RB_RST_SET|RB_DIS_OP_MD); + skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET); +} + static int skge_down(struct net_device *dev) { struct skge_port *skge = netdev_priv(dev); @@ -2595,11 +2604,8 @@ static int skge_down(struct net_device *dev) /* Reset the RAM Buffer async Tx queue */ skge_write8(hw, RB_ADDR(port == 0 ? Q_XA1 : Q_XA2, RB_CTRL), RB_RST_SET); - /* stop receiver */ - skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP); - skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL), - RB_RST_SET|RB_DIS_OP_MD); - skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET); + + skge_rx_stop(hw, port); if (hw->chip_id == CHIP_ID_GENESIS) { skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); @@ -2782,7 +2788,11 @@ static void skge_tx_timeout(struct net_device *dev) static int skge_change_mtu(struct net_device *dev, int new_mtu) { + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int port = skge->port; int err; + u16 ctl, reg; if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; @@ -2792,13 +2802,40 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu) return 0; } - skge_down(dev); + skge_write32(hw, B0_IMSK, 0); + dev->trans_start = jiffies; /* prevent tx timeout */ + netif_stop_queue(dev); + napi_disable(&skge->napi); + + ctl = gma_read16(hw, port, GM_GP_CTRL); + gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); + + skge_rx_clean(skge); + skge_rx_stop(hw, port); dev->mtu = new_mtu; - err = skge_up(dev); + reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); + if (new_mtu > 1500) + reg |= GM_SMOD_JUMBO_ENA; + gma_write16(hw, port, GM_SERIAL_MODE, reg); + + skge_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD); + + err = skge_rx_fill(dev); + wmb(); + if (!err) + skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); + skge_write32(hw, B0_IMSK, hw->intr_mask); + if (err) dev_close(dev); + else { + gma_write16(hw, port, GM_GP_CTRL, ctl); + + napi_enable(&skge->napi); + netif_wake_queue(dev); + } return err; } |