From: Andy Gospodarek <gospo@redhat.com> Date: Fri, 8 Oct 2010 20:14:48 -0400 Subject: [net] ixgbe: fix 82598 link issue and panic w/shared irq Message-id: <1286568888-28752-1-git-send-email-gospo@redhat.com> Patchwork-id: 28672 O-Subject: [PATCH RHEL5.6 v2] ixgbe: fix link issues and panic with shared interrupts for 82598 Bugzilla: 637331 RH-Acked-by: David S. Miller <davem@redhat.com> RH-Acked-by: Stefan Assmann <sassmann@redhat.com> RH-Acked-by: Dean Nelson <dnelson@redhat.com> Backport of upstream patch: commit 6af3b9ebfea38d0a057fbd7bdcecc61ac5662f02 Author: Emil Tantilov <emil.s.tantilov@intel.com> Date: Wed Sep 29 21:35:23 2010 +0000 ixgbe: fix link issues and panic with shared interrupts for 82598 Problem reported, fixed, and verified by Intel. This will resolve RHBZ 637331. diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d433fbe..be24f03 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2259,7 +2259,8 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) * ixgbe_irq_enable - Enable default interrupt generation settings * @adapter: board private structure **/ -static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) +static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, + bool flush) { u32 mask; @@ -2280,8 +2281,10 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) mask |= IXGBE_EIMS_FLOW_DIR; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); - ixgbe_irq_enable_queues(adapter, ~0); - IXGBE_WRITE_FLUSH(&adapter->hw); + if (queues) + ixgbe_irq_enable_queues(adapter, ~0); + if (flush) + IXGBE_WRITE_FLUSH(&adapter->hw); if (adapter->num_vfs > 32) { u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1; @@ -2304,7 +2307,7 @@ static irqreturn_t ixgbe_intr(int irq, void *data, struct pt_regs *regs) u32 eicr; /* - * Workaround for silicon errata. Mask the interrupts + * Workaround for silicon errata on 82598. Mask the interrupts * before the read of EICR. */ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); @@ -2313,10 +2316,15 @@ static irqreturn_t ixgbe_intr(int irq, void *data, struct pt_regs *regs) * therefore no explict interrupt disable is necessary */ eicr = IXGBE_READ_REG(hw, IXGBE_EICR); if (!eicr) { - /* shared interrupt alert! + /* + * shared interrupt alert! * make sure interrupts are enabled because the read will - * have disabled interrupts due to EIAM */ - ixgbe_irq_enable(adapter); + * have disabled interrupts due to EIAM + * finish the workaround of silicon errata on 82598. Unmask + * the interrupt that we masked before the EICR read. + */ + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + ixgbe_irq_enable(adapter, true, true); return IRQ_NONE; /* Not our interrupt */ } @@ -2340,6 +2348,14 @@ static irqreturn_t ixgbe_intr(int irq, void *data, struct pt_regs *regs) __netif_rx_schedule((q_vector->dummy_netdev)); } + /* + * re-enable link(maybe) and non-queue interrupts, no flush. + * ixgbe_poll will re-enable the queue interrupts + */ + + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + ixgbe_irq_enable(adapter, false, false); + return IRQ_HANDLED; } @@ -2905,7 +2921,7 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) vlan_group_set_device(adapter->vlgrp, vid, NULL); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_enable(adapter); + ixgbe_irq_enable(adapter, true, true); /* remove VID from filter table */ hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, false); @@ -3002,7 +3018,7 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, ixgbe_vlan_rx_add_vid(netdev, 0); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_enable(adapter); + ixgbe_irq_enable(adapter, true, true); } static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter) @@ -3534,7 +3550,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) /* clear any pending interrupts, may auto mask */ IXGBE_READ_REG(hw, IXGBE_EICR); - ixgbe_irq_enable(adapter); + ixgbe_irq_enable(adapter, true, true); /* * If this adapter has a fan, check to see if we had a failure