]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
cxgb3 - fix race in EEH
authorDivy Le Ray <divy@chelsio.com>
Thu, 25 Sep 2008 14:05:28 +0000 (14:05 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sat, 13 Dec 2008 23:29:30 +0000 (15:29 -0800)
commit 0ca41c0413a4d9ca58767d53d23accea9aa1cdef upstream.

A SGE queue set timer might access registers while in EEH recovery,
triggering an EEH error loop. Stop all timers early in EEH process.

Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Cc: Karsten Keil <kkeil@novell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/net/cxgb3/adapter.h
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/sge.c

index 271140433b09a68eaa7219873185e21cb3bd27b0..b1a694b5f7d359f3df77aa85f9ca996a033696ba 100644 (file)
@@ -285,6 +285,7 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_status,
 
 void t3_sge_start(struct adapter *adap);
 void t3_sge_stop(struct adapter *adap);
+void t3_stop_sge_timers(struct adapter *adap);
 void t3_free_sge_resources(struct adapter *adap);
 void t3_sge_err_intr_handler(struct adapter *adapter);
 irq_handler_t t3_intr_handler(struct adapter *adap, int polling);
index 5447f3e60f07cfca4af049d63cf0bf8cb836f4b1..d355c826b9b992633d8e3ad7be9a5d7c0f908d31 100644 (file)
@@ -479,6 +479,7 @@ static int setup_sge_qsets(struct adapter *adap)
                                                             irq_idx,
                                &adap->params.sge.qset[qset_idx], ntxq, dev);
                        if (err) {
+                               t3_stop_sge_timers(adap);
                                t3_free_sge_resources(adap);
                                return err;
                        }
@@ -2449,6 +2450,9 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev,
            test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
                offload_close(&adapter->tdev);
 
+       /* Stop SGE timers */
+       t3_stop_sge_timers(adapter);
+
        adapter->flags &= ~FULL_INIT_DONE;
 
        pci_disable_device(pdev);
@@ -2801,6 +2805,7 @@ static void __devexit remove_one(struct pci_dev *pdev)
                    if (test_bit(i, &adapter->registered_device_map))
                        unregister_netdev(adapter->port[i]);
 
+               t3_stop_sge_timers(adapter);
                t3_free_sge_resources(adapter);
                cxgb_disable_msi(adapter);
 
index 1b0861d73ab7d00ef103ab2d58de7975b134ab20..0c7355d5b2a96b7e84c7f150645c8084b9744cea 100644 (file)
@@ -603,9 +603,6 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
        int i;
        struct pci_dev *pdev = adapter->pdev;
 
-       if (q->tx_reclaim_timer.function)
-               del_timer_sync(&q->tx_reclaim_timer);
-
        for (i = 0; i < SGE_RXQ_PER_SET; ++i)
                if (q->fl[i].desc) {
                        spin_lock_irq(&adapter->sge.reg_lock);
@@ -3042,6 +3039,24 @@ err:
        return ret;
 }
 
+/**
+ *     t3_stop_sge_timers - stop SGE timer call backs
+ *     @adap: the adapter
+ *
+ *     Stops each SGE queue set's timer call back
+ */
+void t3_stop_sge_timers(struct adapter *adap)
+{
+       int i;
+
+       for (i = 0; i < SGE_QSETS; ++i) {
+               struct sge_qset *q = &adap->sge.qs[i];
+
+               if (q->tx_reclaim_timer.function)
+                       del_timer_sync(&q->tx_reclaim_timer);
+       }
+}
+
 /**
  *     t3_free_sge_resources - free SGE resources
  *     @adap: the adapter