aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMike McCormack <mikem@ring3k.org>2010-02-12 01:58:06 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-12 19:21:04 -0500
commit8a0c9228f110218f443d9ef8f9ab629251959733 (patch)
tree2aee6ed0512901e8a060d91bffdb10faa53e1765 /drivers
parentf2b31cb3ae491f9e82443cf25cc5a9ebdbc63619 (diff)
sky2: Avoid down and up during sky2_reset
Rewrite sky2_reset to work with interrupts disabled and avoid freeing and reallocing memory. The old code used sky2_down and sky2_up to implement sky2_reset, which meant interrupts could not be disabled, and the transmit and receive ring buffers would be free'd and reallocated. To avoid the interrupt handler waking the transmit queue while we're doing a reset, it's better to have interrupts and NAPI polls disabled. Note: Modified Mike's patch to do IRQ disable in sky2_down before calling sky2_hw_down - Stephen Signed-off-by: Mike McCormack <mikem@ring3k.org> Acked-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sky2.c68
1 files changed, 47 insertions, 21 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 61a0451957b0..4147530cee02 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1880,10 +1880,6 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
1880 1880
1881 sky2->tx_cons = idx; 1881 sky2->tx_cons = idx;
1882 smp_mb(); 1882 smp_mb();
1883
1884 /* Wake unless it's detached, and called e.g. from sky2_down() */
1885 if (tx_avail(sky2) > MAX_SKB_TX_LE + 4 && netif_device_present(dev))
1886 netif_wake_queue(dev);
1887} 1883}
1888 1884
1889static void sky2_tx_reset(struct sky2_hw *hw, unsigned port) 1885static void sky2_tx_reset(struct sky2_hw *hw, unsigned port)
@@ -1912,7 +1908,6 @@ static void sky2_hw_down(struct sky2_port *sky2)
1912{ 1908{
1913 struct sky2_hw *hw = sky2->hw; 1909 struct sky2_hw *hw = sky2->hw;
1914 unsigned port = sky2->port; 1910 unsigned port = sky2->port;
1915 u32 imask;
1916 u16 ctrl; 1911 u16 ctrl;
1917 1912
1918 /* Force flow control off */ 1913 /* Force flow control off */
@@ -1946,15 +1941,6 @@ static void sky2_hw_down(struct sky2_port *sky2)
1946 1941
1947 sky2_rx_stop(sky2); 1942 sky2_rx_stop(sky2);
1948 1943
1949 /* Disable port IRQ */
1950 imask = sky2_read32(hw, B0_IMSK);
1951 imask &= ~portirq_msk[port];
1952 sky2_write32(hw, B0_IMSK, imask);
1953 sky2_read32(hw, B0_IMSK);
1954
1955 synchronize_irq(hw->pdev->irq);
1956 napi_synchronize(&hw->napi);
1957
1958 spin_lock_bh(&sky2->phy_lock); 1944 spin_lock_bh(&sky2->phy_lock);
1959 sky2_phy_power_down(hw, port); 1945 sky2_phy_power_down(hw, port);
1960 spin_unlock_bh(&sky2->phy_lock); 1946 spin_unlock_bh(&sky2->phy_lock);
@@ -1969,6 +1955,7 @@ static void sky2_hw_down(struct sky2_port *sky2)
1969static int sky2_down(struct net_device *dev) 1955static int sky2_down(struct net_device *dev)
1970{ 1956{
1971 struct sky2_port *sky2 = netdev_priv(dev); 1957 struct sky2_port *sky2 = netdev_priv(dev);
1958 struct sky2_hw *hw = sky2->hw;
1972 1959
1973 /* Never really got started! */ 1960 /* Never really got started! */
1974 if (!sky2->tx_le) 1961 if (!sky2->tx_le)
@@ -1977,6 +1964,14 @@ static int sky2_down(struct net_device *dev)
1977 if (netif_msg_ifdown(sky2)) 1964 if (netif_msg_ifdown(sky2))
1978 printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); 1965 printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
1979 1966
1967 /* Disable port IRQ */
1968 sky2_write32(hw, B0_IMSK,
1969 sky2_read32(hw, B0_IMSK) & ~portirq_msk[sky2->port]);
1970 sky2_read32(hw, B0_IMSK);
1971
1972 synchronize_irq(hw->pdev->irq);
1973 napi_synchronize(&hw->napi);
1974
1980 sky2_hw_down(sky2); 1975 sky2_hw_down(sky2);
1981 1976
1982 sky2_free_buffers(sky2); 1977 sky2_free_buffers(sky2);
@@ -2475,8 +2470,13 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
2475{ 2470{
2476 struct sky2_port *sky2 = netdev_priv(dev); 2471 struct sky2_port *sky2 = netdev_priv(dev);
2477 2472
2478 if (netif_running(dev)) 2473 if (netif_running(dev)) {
2479 sky2_tx_complete(sky2, last); 2474 sky2_tx_complete(sky2, last);
2475
2476 /* Wake unless it's detached, and called e.g. from sky2_down() */
2477 if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
2478 netif_wake_queue(dev);
2479 }
2480} 2480}
2481 2481
2482static inline void sky2_skb_rx(const struct sky2_port *sky2, 2482static inline void sky2_skb_rx(const struct sky2_port *sky2,
@@ -3277,20 +3277,46 @@ static int sky2_reattach(struct net_device *dev)
3277static void sky2_restart(struct work_struct *work) 3277static void sky2_restart(struct work_struct *work)
3278{ 3278{
3279 struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work); 3279 struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work);
3280 u32 imask;
3280 int i; 3281 int i;
3281 3282
3282 rtnl_lock(); 3283 rtnl_lock();
3283 for (i = 0; i < hw->ports; i++)
3284 sky2_detach(hw->dev[i]);
3285 3284
3286 napi_disable(&hw->napi); 3285 napi_disable(&hw->napi);
3286 synchronize_irq(hw->pdev->irq);
3287 imask = sky2_read32(hw, B0_IMSK);
3287 sky2_write32(hw, B0_IMSK, 0); 3288 sky2_write32(hw, B0_IMSK, 0);
3289
3290 for (i = 0; i < hw->ports; i++) {
3291 struct net_device *dev = hw->dev[i];
3292 struct sky2_port *sky2 = netdev_priv(dev);
3293
3294 if (!netif_running(dev))
3295 continue;
3296
3297 netif_carrier_off(dev);
3298 netif_tx_disable(dev);
3299 sky2_hw_down(sky2);
3300 }
3301
3288 sky2_reset(hw); 3302 sky2_reset(hw);
3289 sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
3290 napi_enable(&hw->napi);
3291 3303
3292 for (i = 0; i < hw->ports; i++) 3304 for (i = 0; i < hw->ports; i++) {
3293 sky2_reattach(hw->dev[i]); 3305 struct net_device *dev = hw->dev[i];
3306 struct sky2_port *sky2 = netdev_priv(dev);
3307
3308 if (!netif_running(dev))
3309 continue;
3310
3311 sky2_hw_up(sky2);
3312 netif_wake_queue(dev);
3313 }
3314
3315 sky2_write32(hw, B0_IMSK, imask);
3316 sky2_read32(hw, B0_IMSK);
3317
3318 sky2_read32(hw, B0_Y2_SP_LISR);
3319 napi_enable(&hw->napi);
3294 3320
3295 rtnl_unlock(); 3321 rtnl_unlock();
3296} 3322}