e1000e: Fix irq_synchronize in MSI-X case
authorJeff Kirsher <jeffrey.t.kirsher@intel.com>
Mon, 2 Aug 2010 14:27:23 +0000 (14:27 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 3 Aug 2010 04:20:21 +0000 (21:20 -0700)
Based on original patch/work from Jean Delvare <jdelvare@suse.de>
Synchronize all IRQs when in MSI-X IRQ mode.

Jean's original patch hard coded the sync with the 3 possible vectors,
this patch incorporates more flexibility for the future and aligns
with how igb stores the number of vectors into the adapter structure.

CC: Jean Delvare <jdelvare@suse.de>
Cc: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Acked-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/e1000e/e1000.h
drivers/net/e1000e/netdev.c

index 9ee133f..f9a31c8 100644 (file)
@@ -348,6 +348,7 @@ struct e1000_adapter {
        u32 test_icr;
 
        u32 msg_enable;
+       unsigned int num_vectors;
        struct msix_entry *msix_entries;
        int int_mode;
        u32 eiac_mask;
index 464c9a2..9e9164a 100644 (file)
@@ -1785,25 +1785,25 @@ void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter)
 void e1000e_set_interrupt_capability(struct e1000_adapter *adapter)
 {
        int err;
-       int numvecs, i;
-
+       int i;
 
        switch (adapter->int_mode) {
        case E1000E_INT_MODE_MSIX:
                if (adapter->flags & FLAG_HAS_MSIX) {
-                       numvecs = 3; /* RxQ0, TxQ0 and other */
-                       adapter->msix_entries = kcalloc(numvecs,
+                       adapter->num_vectors = 3; /* RxQ0, TxQ0 and other */
+                       adapter->msix_entries = kcalloc(adapter->num_vectors,
                                                      sizeof(struct msix_entry),
                                                      GFP_KERNEL);
                        if (adapter->msix_entries) {
-                               for (i = 0; i < numvecs; i++)
+                               for (i = 0; i < adapter->num_vectors; i++)
                                        adapter->msix_entries[i].entry = i;
 
                                err = pci_enable_msix(adapter->pdev,
                                                      adapter->msix_entries,
-                                                     numvecs);
-                               if (err == 0)
+                                                     adapter->num_vectors);
+                               if (err == 0) {
                                        return;
+                               }
                        }
                        /* MSI-X failed, so fall through and try MSI */
                        e_err("Failed to initialize MSI-X interrupts.  "
@@ -1825,6 +1825,9 @@ void e1000e_set_interrupt_capability(struct e1000_adapter *adapter)
                /* Don't do anything; this is the system default */
                break;
        }
+
+       /* store the number of vectors being used */
+       adapter->num_vectors = 1;
 }
 
 /**
@@ -1946,7 +1949,14 @@ static void e1000_irq_disable(struct e1000_adapter *adapter)
        if (adapter->msix_entries)
                ew32(EIAC_82574, 0);
        e1e_flush();
-       synchronize_irq(adapter->pdev->irq);
+
+       if (adapter->msix_entries) {
+               int i;
+               for (i = 0; i < adapter->num_vectors; i++)
+                       synchronize_irq(adapter->msix_entries[i].vector);
+       } else {
+               synchronize_irq(adapter->pdev->irq);
+       }
 }
 
 /**