[2.6.28,1/1] cxgb3 - fix race in EEH
authorDivy Le Ray <divy@chelsio.com>
Thu, 25 Sep 2008 14:05:28 +0000 (14:05 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 8 Oct 2008 22:57:17 +0000 (15:57 -0700)
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>
drivers/net/cxgb3/adapter.h
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/sge.c

index 4f5cc6987ec18a4ad479ef70ac3626c9e867e1cb..e9da285972331a8f4001f17ca8ebc3fed54b445e 100644 (file)
@@ -284,6 +284,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 89efd04be4e0d340bfae3a68f144281ae68cafaf..7346a8e26da139812efd957c39c85e23f2d230fc 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);
@@ -3008,6 +3005,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