Commit bab2bce7 authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by Jeff Garzik

ixgb: add explicit state checking

In order to remove the irq_sem code we need to implement strict
adapter state checking to prevent accidental double up or downs
or resets. This code is largely copied from e1000/e1000e.
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: default avatarAuke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent c3033b01
...@@ -195,6 +195,15 @@ struct ixgb_adapter { ...@@ -195,6 +195,15 @@ struct ixgb_adapter {
struct ixgb_hw_stats stats; struct ixgb_hw_stats stats;
uint32_t alloc_rx_buff_failed; uint32_t alloc_rx_buff_failed;
boolean_t have_msi; boolean_t have_msi;
unsigned long flags;
};
enum ixgb_state_t {
/* TBD
__IXGB_TESTING,
__IXGB_RESETTING,
*/
__IXGB_DOWN
}; };
/* Exported from other modules */ /* Exported from other modules */
......
...@@ -283,13 +283,15 @@ ixgb_up(struct ixgb_adapter *adapter) ...@@ -283,13 +283,15 @@ ixgb_up(struct ixgb_adapter *adapter)
} }
} }
mod_timer(&adapter->watchdog_timer, jiffies); clear_bit(__IXGB_DOWN, &adapter->flags);
#ifdef CONFIG_IXGB_NAPI #ifdef CONFIG_IXGB_NAPI
napi_enable(&adapter->napi); napi_enable(&adapter->napi);
#endif #endif
ixgb_irq_enable(adapter); ixgb_irq_enable(adapter);
mod_timer(&adapter->watchdog_timer, jiffies);
return 0; return 0;
} }
...@@ -298,11 +300,14 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog) ...@@ -298,11 +300,14 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
{ {
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
/* prevent the interrupt handler from restarting watchdog */
set_bit(__IXGB_DOWN, &adapter->flags);
#ifdef CONFIG_IXGB_NAPI #ifdef CONFIG_IXGB_NAPI
napi_disable(&adapter->napi); napi_disable(&adapter->napi);
atomic_set(&adapter->irq_sem, 0); atomic_set(&adapter->irq_sem, 0);
#endif #endif
/* waiting for NAPI to complete can re-enable interrupts */
ixgb_irq_disable(adapter); ixgb_irq_disable(adapter);
free_irq(adapter->pdev->irq, netdev); free_irq(adapter->pdev->irq, netdev);
...@@ -592,6 +597,7 @@ ixgb_sw_init(struct ixgb_adapter *adapter) ...@@ -592,6 +597,7 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
atomic_set(&adapter->irq_sem, 1); atomic_set(&adapter->irq_sem, 1);
spin_lock_init(&adapter->tx_lock); spin_lock_init(&adapter->tx_lock);
set_bit(__IXGB_DOWN, &adapter->flags);
return 0; return 0;
} }
...@@ -1464,14 +1470,18 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1464,14 +1470,18 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
int vlan_id = 0; int vlan_id = 0;
int tso; int tso;
if (test_bit(__IXGB_DOWN, &adapter->flags)) {
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
if(skb->len <= 0) { if(skb->len <= 0) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return 0; return 0;
} }
#ifdef NETIF_F_LLTX #ifdef NETIF_F_LLTX
local_irq_save(flags); if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
if (!spin_trylock(&adapter->tx_lock)) {
/* Collision - tell upper layer to requeue */ /* Collision - tell upper layer to requeue */
local_irq_restore(flags); local_irq_restore(flags);
return NETDEV_TX_LOCKED; return NETDEV_TX_LOCKED;
...@@ -1753,9 +1763,9 @@ ixgb_intr(int irq, void *data) ...@@ -1753,9 +1763,9 @@ ixgb_intr(int irq, void *data)
if(unlikely(!icr)) if(unlikely(!icr))
return IRQ_NONE; /* Not our interrupt */ return IRQ_NONE; /* Not our interrupt */
if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) { if (unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)))
mod_timer(&adapter->watchdog_timer, jiffies); if (!test_bit(__IXGB_DOWN, &adapter->flags))
} mod_timer(&adapter->watchdog_timer, jiffies);
#ifdef CONFIG_IXGB_NAPI #ifdef CONFIG_IXGB_NAPI
if (netif_rx_schedule_prep(netdev, &adapter->napi)) { if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
...@@ -2195,7 +2205,9 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ...@@ -2195,7 +2205,9 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
IXGB_WRITE_REG(&adapter->hw, RCTL, rctl); IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
} }
ixgb_irq_enable(adapter); /* don't enable interrupts unless we are UP */
if (adapter->netdev->flags & IFF_UP)
ixgb_irq_enable(adapter);
} }
static void static void
...@@ -2222,9 +2234,11 @@ ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) ...@@ -2222,9 +2234,11 @@ ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
vlan_group_set_device(adapter->vlgrp, vid, NULL); vlan_group_set_device(adapter->vlgrp, vid, NULL);
ixgb_irq_enable(adapter); /* don't enable interrupts unless we are UP */
if (adapter->netdev->flags & IFF_UP)
ixgb_irq_enable(adapter);
/* remove VID from filter table*/ /* remove VID from filter table */
index = (vid >> 5) & 0x7F; index = (vid >> 5) & 0x7F;
vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index); vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment