diff options
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 201be425643a..e4fa02c79278 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -4656,6 +4656,7 @@ static int tg3_poll(struct napi_struct *napi, int budget) | |||
4656 | * so we must read it before checking for more work. | 4656 | * so we must read it before checking for more work. |
4657 | */ | 4657 | */ |
4658 | tp->last_tag = sblk->status_tag; | 4658 | tp->last_tag = sblk->status_tag; |
4659 | tp->last_irq_tag = tp->last_tag; | ||
4659 | rmb(); | 4660 | rmb(); |
4660 | } else | 4661 | } else |
4661 | sblk->status &= ~SD_STATUS_UPDATED; | 4662 | sblk->status &= ~SD_STATUS_UPDATED; |
@@ -4811,7 +4812,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) | |||
4811 | * Reading the PCI State register will confirm whether the | 4812 | * Reading the PCI State register will confirm whether the |
4812 | * interrupt is ours and will flush the status block. | 4813 | * interrupt is ours and will flush the status block. |
4813 | */ | 4814 | */ |
4814 | if (unlikely(sblk->status_tag == tp->last_tag)) { | 4815 | if (unlikely(sblk->status_tag == tp->last_irq_tag)) { |
4815 | if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || | 4816 | if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || |
4816 | (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { | 4817 | (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { |
4817 | handled = 0; | 4818 | handled = 0; |
@@ -4831,18 +4832,22 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) | |||
4831 | * excessive spurious interrupts can be worse in some cases. | 4832 | * excessive spurious interrupts can be worse in some cases. |
4832 | */ | 4833 | */ |
4833 | tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); | 4834 | tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); |
4835 | |||
4836 | /* | ||
4837 | * In a shared interrupt configuration, sometimes other devices' | ||
4838 | * interrupts will scream. We record the current status tag here | ||
4839 | * so that the above check can report that the screaming interrupts | ||
4840 | * are unhandled. Eventually they will be silenced. | ||
4841 | */ | ||
4842 | tp->last_irq_tag = sblk->status_tag; | ||
4843 | |||
4834 | if (tg3_irq_sync(tp)) | 4844 | if (tg3_irq_sync(tp)) |
4835 | goto out; | 4845 | goto out; |
4836 | if (napi_schedule_prep(&tp->napi)) { | 4846 | |
4837 | prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); | 4847 | prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); |
4838 | /* Update last_tag to mark that this status has been | 4848 | |
4839 | * seen. Because interrupt may be shared, we may be | 4849 | napi_schedule(&tp->napi); |
4840 | * racing with tg3_poll(), so only update last_tag | 4850 | |
4841 | * if tg3_poll() is not scheduled. | ||
4842 | */ | ||
4843 | tp->last_tag = sblk->status_tag; | ||
4844 | __napi_schedule(&tp->napi); | ||
4845 | } | ||
4846 | out: | 4851 | out: |
4847 | return IRQ_RETVAL(handled); | 4852 | return IRQ_RETVAL(handled); |
4848 | } | 4853 | } |
@@ -6156,6 +6161,7 @@ static int tg3_chip_reset(struct tg3 *tp) | |||
6156 | tp->hw_status->status_tag = 0; | 6161 | tp->hw_status->status_tag = 0; |
6157 | } | 6162 | } |
6158 | tp->last_tag = 0; | 6163 | tp->last_tag = 0; |
6164 | tp->last_irq_tag = 0; | ||
6159 | smp_mb(); | 6165 | smp_mb(); |
6160 | synchronize_irq(tp->pdev->irq); | 6166 | synchronize_irq(tp->pdev->irq); |
6161 | 6167 | ||
@@ -7138,7 +7144,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
7138 | udelay(100); | 7144 | udelay(100); |
7139 | 7145 | ||
7140 | tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); | 7146 | tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); |
7141 | tp->last_tag = 0; | ||
7142 | 7147 | ||
7143 | if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { | 7148 | if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { |
7144 | tw32_f(DMAC_MODE, DMAC_MODE_ENABLE); | 7149 | tw32_f(DMAC_MODE, DMAC_MODE_ENABLE); |