diff options
author | Sony Chacko <sony.chacko@qlogic.com> | 2013-05-23 21:04:32 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-24 23:04:54 -0700 |
commit | 099907fac61c47a67a02edb85d551e91959ecc5b (patch) | |
tree | 58ba065df593ecab44884d73492751dd3ab75503 | |
parent | 4690a7e48ac55cf84fcf214279baf133304d71e4 (diff) |
qlcnic: modify reset recovery path in diag mode
Provide diagnostics routines enough time to unwind before
proceeding with reset recovery.
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.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 35 |
3 files changed, 34 insertions, 8 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 8affec5e6eb8..4ff0625a0cef 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -1477,7 +1477,6 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *); /* Functions from qlcnic_ethtool.c */ - int qlcnic_check_loopback_buff(unsigned char *, u8 []); int qlcnic_do_lb_test(struct qlcnic_adapter *, u8); int qlcnic_loopback_test(struct net_device *, u8); @@ -1897,6 +1896,11 @@ static inline void qlcnic_release_diag_lock(struct qlcnic_adapter *adapter) clear_bit(__QLCNIC_DIAG_MODE, &adapter->state); } +static inline int qlcnic_check_diag_status(struct qlcnic_adapter *adapter) +{ + return test_bit(__QLCNIC_DIAG_MODE, &adapter->state); +} + extern const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops; extern const struct ethtool_ops qlcnic_ethtool_ops; extern const struct ethtool_ops qlcnic_ethtool_failed_ops; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index f5db67fc9f55..1bfe283a9412 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h @@ -314,6 +314,7 @@ struct qlc_83xx_idc { u8 vnic_state; u8 vnic_wait_limit; u8 quiesce_req; + u8 delay_reset; char **name; }; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 5e7fb1dfb97b..aa26250d7374 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -649,6 +649,7 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) ahw->idc.collect_dump = 0; ahw->reset_context = 0; adapter->tx_timeo_cnt = 0; + ahw->idc.delay_reset = 0; clear_bit(__QLCNIC_RESETTING, &adapter->state); } @@ -883,21 +884,41 @@ static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter) int ret = 0; if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) { - qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); set_bit(__QLCNIC_RESETTING, &adapter->state); clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) qlcnic_83xx_disable_vnic_mode(adapter, 1); - qlcnic_83xx_idc_detach_driver(adapter); + + if (qlcnic_check_diag_status(adapter)) { + dev_info(&adapter->pdev->dev, + "%s: Wait for diag completion\n", __func__); + adapter->ahw->idc.delay_reset = 1; + return 0; + } else { + qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); + qlcnic_83xx_idc_detach_driver(adapter); + } } - /* Check ACK from other functions */ - ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter); - if (ret) { + if (qlcnic_check_diag_status(adapter)) { dev_info(&adapter->pdev->dev, - "%s: Waiting for reset ACK\n", __func__); - return 0; + "%s: Wait for diag completion\n", __func__); + return -1; + } else { + if (adapter->ahw->idc.delay_reset) { + qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); + qlcnic_83xx_idc_detach_driver(adapter); + adapter->ahw->idc.delay_reset = 0; + } + + /* Check for ACK from other functions */ + ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter); + if (ret) { + dev_info(&adapter->pdev->dev, + "%s: Waiting for reset ACK\n", __func__); + return -1; + } } /* Transit to INIT state and restart the HW */ |