mirror of https://gitee.com/openkylin/linux.git
ixgbe: only process one ixgbe_watchdog_task at a time.
Processing multiple ixgbe_watchdog_task calls may cause the link_up variable and IXGBE_FLAG_NEED_LINK_UPDATE flag to be set incorrectly. In the worse case this is causing the netif_carrier_off to be called inappropriately which results in an interface that can't be brought up. Although schedule_work() will only schedule the task if it is not already on the work queue the WORK_STRUCT_PENDING bits are cleared just before calling the work function. This allows WORK_STRUCT_PENDING to be cleared, the work function to start and meanwhile schedule another task. This patch adds a mutex to the watchdog task. This bug is actualized by changing DCB settings or doing extended cable pull or reset tests. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9c119ba54c
commit
10eec95569
|
@ -341,15 +341,14 @@ struct ixgbe_adapter {
|
|||
#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19)
|
||||
#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20)
|
||||
#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22)
|
||||
#define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23)
|
||||
#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 24)
|
||||
#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 25)
|
||||
#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 26)
|
||||
#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 27)
|
||||
#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 28)
|
||||
#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 29)
|
||||
#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 30)
|
||||
#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 31)
|
||||
#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 23)
|
||||
#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 24)
|
||||
#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 25)
|
||||
#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 26)
|
||||
#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 27)
|
||||
#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 28)
|
||||
#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 29)
|
||||
#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 30)
|
||||
|
||||
u32 flags2;
|
||||
#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1)
|
||||
|
|
|
@ -4996,6 +4996,8 @@ static void ixgbe_fdir_reinit_task(struct work_struct *work)
|
|||
netif_tx_start_all_queues(adapter->netdev);
|
||||
}
|
||||
|
||||
static DEFINE_MUTEX(ixgbe_watchdog_lock);
|
||||
|
||||
/**
|
||||
* ixgbe_watchdog_task - worker thread to bring link up
|
||||
* @work: pointer to work_struct containing our data
|
||||
|
@ -5007,13 +5009,16 @@ static void ixgbe_watchdog_task(struct work_struct *work)
|
|||
watchdog_task);
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct ixgbe_hw *hw = &adapter->hw;
|
||||
u32 link_speed = adapter->link_speed;
|
||||
bool link_up = adapter->link_up;
|
||||
u32 link_speed;
|
||||
bool link_up;
|
||||
int i;
|
||||
struct ixgbe_ring *tx_ring;
|
||||
int some_tx_pending = 0;
|
||||
|
||||
adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK;
|
||||
mutex_lock(&ixgbe_watchdog_lock);
|
||||
|
||||
link_up = adapter->link_up;
|
||||
link_speed = adapter->link_speed;
|
||||
|
||||
if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
|
||||
hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
|
||||
|
@ -5102,7 +5107,7 @@ static void ixgbe_watchdog_task(struct work_struct *work)
|
|||
}
|
||||
|
||||
ixgbe_update_stats(adapter);
|
||||
adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK;
|
||||
mutex_unlock(&ixgbe_watchdog_lock);
|
||||
}
|
||||
|
||||
static int ixgbe_tso(struct ixgbe_adapter *adapter,
|
||||
|
|
Loading…
Reference in New Issue