Renaming the "reset_task" to a more general purpose name,
"sp_rtnl_task", as it is already used for another purpose
other than reset which is parity recovery, and since I
plan to add a third operation for this task, updating the
priority to traffic class and traffic class to transmission
queues mappings after dcbx negotiation takes place.
Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
struct per_queue_stats queue_stats[1];
};
struct per_queue_stats queue_stats[1];
};
+/* Public slow path states */
+enum {
+ BNX2X_SP_RTNL_TX_TIMEOUT,
+};
+
+
struct bnx2x {
/* Fields used in the tx and intr/napi performance paths
* are grouped together in the beginning of the structure
struct bnx2x {
/* Fields used in the tx and intr/napi performance paths
* are grouped together in the beginning of the structure
int mrrs;
struct delayed_work sp_task;
int mrrs;
struct delayed_work sp_task;
- struct delayed_work reset_task;
+ struct delayed_work sp_rtnl_task;
struct delayed_work period_task;
struct timer_list timer;
struct delayed_work period_task;
struct timer_list timer;
+ /* operation indication for the sp_rtnl task */
+ unsigned long sp_rtnl_state;
+
/* DCBX Negotation results */
struct dcbx_features dcbx_local_feat;
u32 dcbx_error;
/* DCBX Negotation results */
struct dcbx_features dcbx_local_feat;
u32 dcbx_error;
if (!bp->panic)
bnx2x_panic();
#endif
if (!bp->panic)
bnx2x_panic();
#endif
+
+ smp_mb__before_clear_bit();
+ set_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state);
+ smp_mb__after_clear_bit();
+
/* This allows the netif to be shutdown gracefully before resetting */
/* This allows the netif to be shutdown gracefully before resetting */
- schedule_delayed_work(&bp->reset_task, 0);
+ schedule_delayed_work(&bp->sp_rtnl_task, 0);
}
int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
}
int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
if (bnx2x_chk_parity_attn(bp, &global, true)) {
#ifndef BNX2X_STOP_ON_ERROR
bp->recovery_state = BNX2X_RECOVERY_INIT;
if (bnx2x_chk_parity_attn(bp, &global, true)) {
#ifndef BNX2X_STOP_ON_ERROR
bp->recovery_state = BNX2X_RECOVERY_INIT;
- schedule_delayed_work(&bp->reset_task, 0);
+ schedule_delayed_work(&bp->sp_rtnl_task, 0);
/* Disable HW interrupts */
bnx2x_int_disable(bp);
/* In case of parity errors don't handle attentions so that
/* Disable HW interrupts */
bnx2x_int_disable(bp);
/* In case of parity errors don't handle attentions so that
/* Wait until all other functions get
* down.
*/
/* Wait until all other functions get
* down.
*/
- schedule_delayed_work(&bp->reset_task,
+ schedule_delayed_work(&bp->sp_rtnl_task,
- schedule_delayed_work(&bp->reset_task,
+ schedule_delayed_work(&bp->sp_rtnl_task,
*/
if (bnx2x_reset_is_global(bp)) {
schedule_delayed_work(
*/
if (bnx2x_reset_is_global(bp)) {
schedule_delayed_work(
- &bp->reset_task, HZ/10);
+ &bp->sp_rtnl_task,
+ HZ/10);
/* bnx2x_nic_unload() flushes the bnx2x_wq, thus reset task is
* scheduled on a general queue in order to prevent a dead lock.
*/
/* bnx2x_nic_unload() flushes the bnx2x_wq, thus reset task is
* scheduled on a general queue in order to prevent a dead lock.
*/
-static void bnx2x_reset_task(struct work_struct *work)
+static void bnx2x_sp_rtnl_task(struct work_struct *work)
- struct bnx2x *bp = container_of(work, struct bnx2x, reset_task.work);
-
-#ifdef BNX2X_STOP_ON_ERROR
- BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
- " so reset not done to allow debug dump,\n"
- KERN_ERR " you will need to reboot when done\n");
- return;
-#endif
+ struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work);
rtnl_lock();
if (!netif_running(bp->dev))
rtnl_lock();
if (!netif_running(bp->dev))
+ goto sp_rtnl_exit;
+
+ /* if stop on error is defined no recovery flows should be executed */
+#ifdef BNX2X_STOP_ON_ERROR
+ BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined "
+ "so reset not done to allow debug dump,\n"
+ "you will need to reboot when done\n");
+ goto sp_rtnl_exit;
+#endif
- if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE))
+ if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) {
+ /*
+ * Clear TX_TIMEOUT bit as we are going to reset the function
+ * anyway.
+ */
+ smp_mb__before_clear_bit();
+ clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state);
+ smp_mb__after_clear_bit();
bnx2x_parity_recover(bp);
bnx2x_parity_recover(bp);
+ } else if (test_and_clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT,
+ &bp->sp_rtnl_state)){
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_NORMAL);
}
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_NORMAL);
}
#endif
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
#endif
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
- INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task);
+ INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
rc = bnx2x_get_hwinfo(bp);
if (rc)
INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
rc = bnx2x_get_hwinfo(bp);
if (rc)
bnx2x_set_power_state(bp, PCI_D3hot);
/* Make sure RESET task is not scheduled before continuing */
bnx2x_set_power_state(bp, PCI_D3hot);
/* Make sure RESET task is not scheduled before continuing */
- cancel_delayed_work_sync(&bp->reset_task);
+ cancel_delayed_work_sync(&bp->sp_rtnl_task);
if (bp->regview)
iounmap(bp->regview);
if (bp->regview)
iounmap(bp->regview);