ixgbe: Correctly name and handle MSI-X other interrupt
authorAlexander Duyck <alexander.h.duyck@intel.com>
Fri, 15 Jul 2011 07:29:55 +0000 (07:29 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 16 Sep 2011 04:32:04 +0000 (21:32 -0700)
It was possible to inadvertently add additional interrupt causes to the
MSI-X other interrupt.  This occurred when things such as RX buffer overrun
events were being triggered at the same time as an event such as a Flow
Director table reinit request.  In order to avoid this we should be
explicitly programming only the interrupts that we want enabled.  In
addition I am renaming the ixgbe_msix_lsc function and interrupt to drop
any implied meaning of this being a link status only interrupt.

Unfortunately the patch is a bit ugly due to the fact that ixgbe_irq_enable
needed to be moved up before ixgbe_msix_other in order to have things
defined in the correct order.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

index 3f5a744f7099a2c0eb67be77c96f4d53f66c4a9f..bfdd42b7f9855bacc290fa87825f856150f2ae0a 100644 (file)
@@ -491,7 +491,6 @@ struct ixgbe_adapter {
        int node;
        u32 led_reg;
        u32 interrupt_event;
-       char lsc_int_name[IFNAMSIZ + 9];
 
        /* SR-IOV */
        DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
index 0ee7d094ff89ad4ca6fc10d133e4b420ca2f4712..6026ab0798e9a24ab270a1dbc2c5ea369489d3bc 100644 (file)
@@ -1828,7 +1828,98 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
        }
 }
 
-static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
+static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
+                                          u64 qmask)
+{
+       u32 mask;
+       struct ixgbe_hw *hw = &adapter->hw;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_82598EB:
+               mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
+               IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
+               break;
+       case ixgbe_mac_82599EB:
+       case ixgbe_mac_X540:
+               mask = (qmask & 0xFFFFFFFF);
+               if (mask)
+                       IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
+               mask = (qmask >> 32);
+               if (mask)
+                       IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
+               break;
+       default:
+               break;
+       }
+       /* skip the flush */
+}
+
+static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
+                                           u64 qmask)
+{
+       u32 mask;
+       struct ixgbe_hw *hw = &adapter->hw;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_82598EB:
+               mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
+               IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
+               break;
+       case ixgbe_mac_82599EB:
+       case ixgbe_mac_X540:
+               mask = (qmask & 0xFFFFFFFF);
+               if (mask)
+                       IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
+               mask = (qmask >> 32);
+               if (mask)
+                       IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
+               break;
+       default:
+               break;
+       }
+       /* skip the flush */
+}
+
+/**
+ * ixgbe_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
+                                   bool flush)
+{
+       u32 mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
+
+       /* don't reenable LSC while waiting for link */
+       if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)
+               mask &= ~IXGBE_EIMS_LSC;
+
+       if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
+               mask |= IXGBE_EIMS_GPI_SDP0;
+       if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
+               mask |= IXGBE_EIMS_GPI_SDP1;
+       switch (adapter->hw.mac.type) {
+       case ixgbe_mac_82599EB:
+       case ixgbe_mac_X540:
+               mask |= IXGBE_EIMS_ECC;
+               mask |= IXGBE_EIMS_GPI_SDP1;
+               mask |= IXGBE_EIMS_GPI_SDP2;
+               mask |= IXGBE_EIMS_MAILBOX;
+               break;
+       default:
+               break;
+       }
+       if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
+           !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT))
+               mask |= IXGBE_EIMS_FLOW_DIR;
+
+       IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
+       if (queues)
+               ixgbe_irq_enable_queues(adapter, ~0);
+       if (flush)
+               IXGBE_WRITE_FLUSH(&adapter->hw);
+}
+
+static irqreturn_t ixgbe_msix_other(int irq, void *data)
 {
        struct ixgbe_adapter *adapter = data;
        struct ixgbe_hw *hw = &adapter->hw;
@@ -1852,6 +1943,9 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
        switch (hw->mac.type) {
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+               if (eicr & IXGBE_EICR_ECC)
+                       e_info(link, "Received unrecoverable ECC Err, please "
+                              "reboot\n");
                /* Handle Flow Director Full threshold interrupt */
                if (eicr & IXGBE_EICR_FLOW_DIR) {
                        int reinit_count = 0;
@@ -1865,7 +1959,6 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
                        if (reinit_count) {
                                /* no more flow director interrupts until after init */
                                IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR);
-                               eicr &= ~IXGBE_EICR_FLOW_DIR;
                                adapter->flags2 |= IXGBE_FLAG2_FDIR_REQUIRES_REINIT;
                                ixgbe_service_event_schedule(adapter);
                        }
@@ -1888,64 +1981,11 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
 
        /* re-enable the original interrupt state, no lsc, no queues */
        if (!test_bit(__IXGBE_DOWN, &adapter->state))
-               IXGBE_WRITE_REG(hw, IXGBE_EIMS, eicr &
-                               ~(IXGBE_EIMS_LSC | IXGBE_EIMS_RTX_QUEUE));
+               ixgbe_irq_enable(adapter, false, false);
 
        return IRQ_HANDLED;
 }
 
-static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
-                                          u64 qmask)
-{
-       u32 mask;
-       struct ixgbe_hw *hw = &adapter->hw;
-
-       switch (hw->mac.type) {
-       case ixgbe_mac_82598EB:
-               mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
-               IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
-               break;
-       case ixgbe_mac_82599EB:
-       case ixgbe_mac_X540:
-               mask = (qmask & 0xFFFFFFFF);
-               if (mask)
-                       IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
-               mask = (qmask >> 32);
-               if (mask)
-                       IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
-               break;
-       default:
-               break;
-       }
-       /* skip the flush */
-}
-
-static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
-                                           u64 qmask)
-{
-       u32 mask;
-       struct ixgbe_hw *hw = &adapter->hw;
-
-       switch (hw->mac.type) {
-       case ixgbe_mac_82598EB:
-               mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
-               IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
-               break;
-       case ixgbe_mac_82599EB:
-       case ixgbe_mac_X540:
-               mask = (qmask & 0xFFFFFFFF);
-               if (mask)
-                       IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
-               mask = (qmask >> 32);
-               if (mask)
-                       IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
-               break;
-       default:
-               break;
-       }
-       /* skip the flush */
-}
-
 static irqreturn_t ixgbe_msix_clean_rings(int irq, void *data)
 {
        struct ixgbe_q_vector *q_vector = data;
@@ -2077,9 +2117,8 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
                }
        }
 
-       sprintf(adapter->lsc_int_name, "%s:lsc", netdev->name);
        err = request_irq(adapter->msix_entries[vector].vector,
-                         ixgbe_msix_lsc, 0, adapter->lsc_int_name, adapter);
+                         ixgbe_msix_other, 0, netdev->name, adapter);
        if (err) {
                e_err(probe, "request_irq for msix_lsc failed: %d\n", err);
                goto free_queue_irqs;
@@ -2102,42 +2141,6 @@ free_queue_irqs:
        return err;
 }
 
-/**
- * ixgbe_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
-                                   bool flush)
-{
-       u32 mask;
-
-       mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
-       if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
-               mask |= IXGBE_EIMS_GPI_SDP0;
-       if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
-               mask |= IXGBE_EIMS_GPI_SDP1;
-       switch (adapter->hw.mac.type) {
-       case ixgbe_mac_82599EB:
-       case ixgbe_mac_X540:
-               mask |= IXGBE_EIMS_ECC;
-               mask |= IXGBE_EIMS_GPI_SDP1;
-               mask |= IXGBE_EIMS_GPI_SDP2;
-               if (adapter->num_vfs)
-                       mask |= IXGBE_EIMS_MAILBOX;
-               break;
-       default:
-               break;
-       }
-       if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
-               mask |= IXGBE_EIMS_FLOW_DIR;
-
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
-       if (queues)
-               ixgbe_irq_enable_queues(adapter, ~0);
-       if (flush)
-               IXGBE_WRITE_FLUSH(&adapter->hw);
-}
-
 /**
  * ixgbe_intr - legacy mode Interrupt Handler
  * @irq: interrupt number