diff options
author | Amit Kumar Salecha <amit.salecha@qlogic.com> | 2010-06-22 07:19:03 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-24 00:16:31 +0400 |
commit | 68bf1c68a4b3d9ad0a98f3310f2f79dca075a035 (patch) | |
tree | 8e29abda3a579c252076eab1b79718d0702a008e /drivers | |
parent | 52486a3ac86eabe5a2f283eb9682a69c14347213 (diff) | |
download | linux-68bf1c68a4b3d9ad0a98f3310f2f79dca075a035.tar.xz |
qlcnic: offload tx timeout recovery
Offload tx timeout recovery to fw recovery func(check_health).
In check_health, first check health of device, if it its ok, then
do tx timeout recovery otherwise device recovery.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/qlcnic/qlcnic.h | 3 | ||||
-rw-r--r-- | drivers/net/qlcnic/qlcnic_main.c | 65 |
2 files changed, 32 insertions, 36 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 5c7d474e560b..6ec34a7fba65 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -934,6 +934,7 @@ struct qlcnic_adapter { u8 rx_csum; u8 portnum; u8 physical_port; + u8 reset_context; u8 mc_enabled; u8 max_mc_count; @@ -1001,8 +1002,6 @@ struct qlcnic_adapter { struct delayed_work fw_work; - struct work_struct tx_timeout_task; - struct qlcnic_nic_intr_coalesce coal; unsigned long state; diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index c4602fa866d4..3b71dfcd6d44 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -75,7 +75,6 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev); static int qlcnic_open(struct net_device *netdev); static int qlcnic_close(struct net_device *netdev); static void qlcnic_tx_timeout(struct net_device *netdev); -static void qlcnic_tx_timeout_task(struct work_struct *work); static void qlcnic_attach_work(struct work_struct *work); static void qlcnic_fwinit_work(struct work_struct *work); static void qlcnic_fw_poll_work(struct work_struct *work); @@ -911,6 +910,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) qlcnic_linkevent_request(adapter, 1); + adapter->reset_context = 0; set_bit(__QLCNIC_DEV_UP, &adapter->state); return 0; } @@ -1110,6 +1110,27 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) return 0; } +/* Reset context in hardware only */ +static int +qlcnic_reset_hw_context(struct qlcnic_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + + if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + return -EBUSY; + + netif_device_detach(netdev); + + qlcnic_down(adapter, netdev); + + qlcnic_up(adapter, netdev); + + netif_device_attach(netdev); + + clear_bit(__QLCNIC_RESETTING, &adapter->state); + return 0; +} + int qlcnic_reset_context(struct qlcnic_adapter *adapter) { @@ -1178,8 +1199,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, netdev->irq = adapter->msix_entries[0].vector; - INIT_WORK(&adapter->tx_timeout_task, qlcnic_tx_timeout_task); - if (qlcnic_read_mac_addr(adapter)) dev_warn(&pdev->dev, "failed to read mac addr\n"); @@ -1350,8 +1369,6 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev) unregister_netdev(netdev); - cancel_work_sync(&adapter->tx_timeout_task); - qlcnic_detach(adapter); if (adapter->npars != NULL) @@ -1390,8 +1407,6 @@ static int __qlcnic_shutdown(struct pci_dev *pdev) if (netif_running(netdev)) qlcnic_down(adapter, netdev); - cancel_work_sync(&adapter->tx_timeout_task); - qlcnic_clr_all_drv_state(adapter); clear_bit(__QLCNIC_RESETTING, &adapter->state); @@ -1854,35 +1869,11 @@ static void qlcnic_tx_timeout(struct net_device *netdev) return; dev_err(&netdev->dev, "transmit timeout, resetting.\n"); - schedule_work(&adapter->tx_timeout_task); -} - -static void qlcnic_tx_timeout_task(struct work_struct *work) -{ - struct qlcnic_adapter *adapter = - container_of(work, struct qlcnic_adapter, tx_timeout_task); - - if (!netif_running(adapter->netdev)) - return; - - if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) - return; if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) - goto request_reset; - - clear_bit(__QLCNIC_RESETTING, &adapter->state); - if (!qlcnic_reset_context(adapter)) { - adapter->netdev->trans_start = jiffies; - return; - - /* context reset failed, fall through for fw reset */ - } - -request_reset: - adapter->need_fw_reset = 1; - clear_bit(__QLCNIC_RESETTING, &adapter->state); - QLCDB(adapter, DRV, "Resetting adapter\n"); + adapter->need_fw_reset = 1; + else + adapter->reset_context = 1; } static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) @@ -2540,6 +2531,12 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) adapter->fw_fail_cnt = 0; if (adapter->need_fw_reset) goto detach; + + if (adapter->reset_context) { + qlcnic_reset_hw_context(adapter); + adapter->netdev->trans_start = jiffies; + } + return 0; } |