Commit 536faa61 authored by Sony Chacko's avatar Sony Chacko Committed by David S. Miller

qlcnic: Fix reset recovery after transmit timeout

o When transmit timeout happens, recovery attempt should start with
  adapter soft reset. If soft reset fails to resume traffic, firmware
  dump will be collected and driver will perform a hard reset of the
  adapter. Reset recovery on 83xx was failing after a hard reset.
  This patch fixes that issue.
Signed-off-by: default avatarSony Chacko <sony.chacko@qlogic.com>
Signed-off-by: default avatarShahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b938662d
...@@ -435,10 +435,6 @@ static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter) ...@@ -435,10 +435,6 @@ static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter)
} }
done: done:
netif_device_attach(netdev); netif_device_attach(netdev);
if (netif_running(netdev)) {
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
} }
static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter, static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter,
...@@ -642,15 +638,21 @@ static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) ...@@ -642,15 +638,21 @@ static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1); qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
adapter->ahw->idc.quiesce_req = 0;
adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; ahw->idc.quiesce_req = 0;
adapter->ahw->idc.err_code = 0; ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
adapter->ahw->idc.collect_dump = 0; ahw->idc.err_code = 0;
ahw->idc.collect_dump = 0;
ahw->reset_context = 0;
adapter->tx_timeo_cnt = 0;
clear_bit(__QLCNIC_RESETTING, &adapter->state);
} }
/** /**
...@@ -851,6 +853,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) ...@@ -851,6 +853,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
/* Check for soft reset request */ /* Check for soft reset request */
if (ahw->reset_context && if (ahw->reset_context &&
!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) { !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
adapter->ahw->reset_context = 0;
qlcnic_83xx_idc_tx_soft_reset(adapter); qlcnic_83xx_idc_tx_soft_reset(adapter);
return ret; return ret;
} }
...@@ -914,6 +917,7 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter) ...@@ -914,6 +917,7 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)
static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter) static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
{ {
dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__); dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
adapter->ahw->idc.err_code = -EIO; adapter->ahw->idc.err_code = -EIO;
return 0; return 0;
......
...@@ -2502,12 +2502,17 @@ static void qlcnic_tx_timeout(struct net_device *netdev) ...@@ -2502,12 +2502,17 @@ static void qlcnic_tx_timeout(struct net_device *netdev)
if (test_bit(__QLCNIC_RESETTING, &adapter->state)) if (test_bit(__QLCNIC_RESETTING, &adapter->state))
return; return;
dev_err(&netdev->dev, "transmit timeout, resetting.\n"); if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) {
netdev_info(netdev, "Tx timeout, reset the adapter.\n");
if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) if (qlcnic_82xx_check(adapter))
adapter->need_fw_reset = 1; adapter->need_fw_reset = 1;
else else if (qlcnic_83xx_check(adapter))
qlcnic_83xx_idc_request_reset(adapter,
QLCNIC_FORCE_FW_DUMP_KEY);
} else {
netdev_info(netdev, "Tx timeout, reset adapter context.\n");
adapter->ahw->reset_context = 1; adapter->ahw->reset_context = 1;
}
} }
static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
......
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