diff options
author | Sony Chacko <sony.chacko@qlogic.com> | 2013-05-09 05:25:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-11 19:01:15 -0400 |
commit | 536faa61825c8e92f520264228388d69783370d3 (patch) | |
tree | 0f774d79e234546baceb955629bccf90f7090505 | |
parent | b938662d88264c1a92611ca1b82fdff5a4e87121 (diff) |
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: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 15 |
2 files changed, 23 insertions, 14 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index ab1d8d99cbd5..c67d1eb35e8f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | |||
@@ -435,10 +435,6 @@ static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter) | |||
435 | } | 435 | } |
436 | done: | 436 | done: |
437 | netif_device_attach(netdev); | 437 | netif_device_attach(netdev); |
438 | if (netif_running(netdev)) { | ||
439 | netif_carrier_on(netdev); | ||
440 | netif_wake_queue(netdev); | ||
441 | } | ||
442 | } | 438 | } |
443 | 439 | ||
444 | static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter, | 440 | 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 | 638 | ||
643 | static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) | 639 | static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) |
644 | { | 640 | { |
641 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
642 | |||
645 | qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1); | 643 | qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1); |
646 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
647 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | 644 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); |
648 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); | 645 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); |
649 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); | 646 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); |
650 | adapter->ahw->idc.quiesce_req = 0; | 647 | |
651 | adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; | 648 | ahw->idc.quiesce_req = 0; |
652 | adapter->ahw->idc.err_code = 0; | 649 | ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; |
653 | adapter->ahw->idc.collect_dump = 0; | 650 | ahw->idc.err_code = 0; |
651 | ahw->idc.collect_dump = 0; | ||
652 | ahw->reset_context = 0; | ||
653 | adapter->tx_timeo_cnt = 0; | ||
654 | |||
655 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
654 | } | 656 | } |
655 | 657 | ||
656 | /** | 658 | /** |
@@ -851,6 +853,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | |||
851 | /* Check for soft reset request */ | 853 | /* Check for soft reset request */ |
852 | if (ahw->reset_context && | 854 | if (ahw->reset_context && |
853 | !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) { | 855 | !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) { |
856 | adapter->ahw->reset_context = 0; | ||
854 | qlcnic_83xx_idc_tx_soft_reset(adapter); | 857 | qlcnic_83xx_idc_tx_soft_reset(adapter); |
855 | return ret; | 858 | return ret; |
856 | } | 859 | } |
@@ -914,6 +917,7 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter) | |||
914 | static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter) | 917 | static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter) |
915 | { | 918 | { |
916 | dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__); | 919 | dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__); |
920 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
917 | adapter->ahw->idc.err_code = -EIO; | 921 | adapter->ahw->idc.err_code = -EIO; |
918 | 922 | ||
919 | return 0; | 923 | return 0; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index d97446a3bf05..8fb836d4129f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -2502,12 +2502,17 @@ static void qlcnic_tx_timeout(struct net_device *netdev) | |||
2502 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) | 2502 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) |
2503 | return; | 2503 | return; |
2504 | 2504 | ||
2505 | dev_err(&netdev->dev, "transmit timeout, resetting.\n"); | 2505 | if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) { |
2506 | 2506 | netdev_info(netdev, "Tx timeout, reset the adapter.\n"); | |
2507 | if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) | 2507 | if (qlcnic_82xx_check(adapter)) |
2508 | adapter->need_fw_reset = 1; | 2508 | adapter->need_fw_reset = 1; |
2509 | else | 2509 | else if (qlcnic_83xx_check(adapter)) |
2510 | qlcnic_83xx_idc_request_reset(adapter, | ||
2511 | QLCNIC_FORCE_FW_DUMP_KEY); | ||
2512 | } else { | ||
2513 | netdev_info(netdev, "Tx timeout, reset adapter context.\n"); | ||
2510 | adapter->ahw->reset_context = 1; | 2514 | adapter->ahw->reset_context = 1; |
2515 | } | ||
2511 | } | 2516 | } |
2512 | 2517 | ||
2513 | static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) | 2518 | static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) |