diff options
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 113 |
1 files changed, 66 insertions, 47 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ab87bb1893a5..26dcd1c36b30 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -3568,32 +3568,34 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id) | |||
3568 | * Reading the PCI State register will confirm whether the | 3568 | * Reading the PCI State register will confirm whether the |
3569 | * interrupt is ours and will flush the status block. | 3569 | * interrupt is ours and will flush the status block. |
3570 | */ | 3570 | */ |
3571 | if ((sblk->status & SD_STATUS_UPDATED) || | 3571 | if (unlikely(!(sblk->status & SD_STATUS_UPDATED))) { |
3572 | !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { | 3572 | if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || |
3573 | /* | 3573 | (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { |
3574 | * Writing any value to intr-mbox-0 clears PCI INTA# and | 3574 | handled = 0; |
3575 | * chip-internal interrupt pending events. | ||
3576 | * Writing non-zero to intr-mbox-0 additional tells the | ||
3577 | * NIC to stop sending us irqs, engaging "in-intr-handler" | ||
3578 | * event coalescing. | ||
3579 | */ | ||
3580 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, | ||
3581 | 0x00000001); | ||
3582 | if (tg3_irq_sync(tp)) | ||
3583 | goto out; | 3575 | goto out; |
3584 | sblk->status &= ~SD_STATUS_UPDATED; | ||
3585 | if (likely(tg3_has_work(tp))) { | ||
3586 | prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); | ||
3587 | netif_rx_schedule(dev); /* schedule NAPI poll */ | ||
3588 | } else { | ||
3589 | /* No work, shared interrupt perhaps? re-enable | ||
3590 | * interrupts, and flush that PCI write | ||
3591 | */ | ||
3592 | tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, | ||
3593 | 0x00000000); | ||
3594 | } | 3576 | } |
3595 | } else { /* shared interrupt */ | 3577 | } |
3596 | handled = 0; | 3578 | |
3579 | /* | ||
3580 | * Writing any value to intr-mbox-0 clears PCI INTA# and | ||
3581 | * chip-internal interrupt pending events. | ||
3582 | * Writing non-zero to intr-mbox-0 additional tells the | ||
3583 | * NIC to stop sending us irqs, engaging "in-intr-handler" | ||
3584 | * event coalescing. | ||
3585 | */ | ||
3586 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); | ||
3587 | if (tg3_irq_sync(tp)) | ||
3588 | goto out; | ||
3589 | sblk->status &= ~SD_STATUS_UPDATED; | ||
3590 | if (likely(tg3_has_work(tp))) { | ||
3591 | prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); | ||
3592 | netif_rx_schedule(dev); /* schedule NAPI poll */ | ||
3593 | } else { | ||
3594 | /* No work, shared interrupt perhaps? re-enable | ||
3595 | * interrupts, and flush that PCI write | ||
3596 | */ | ||
3597 | tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, | ||
3598 | 0x00000000); | ||
3597 | } | 3599 | } |
3598 | out: | 3600 | out: |
3599 | return IRQ_RETVAL(handled); | 3601 | return IRQ_RETVAL(handled); |
@@ -3611,31 +3613,33 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) | |||
3611 | * Reading the PCI State register will confirm whether the | 3613 | * Reading the PCI State register will confirm whether the |
3612 | * interrupt is ours and will flush the status block. | 3614 | * interrupt is ours and will flush the status block. |
3613 | */ | 3615 | */ |
3614 | if ((sblk->status_tag != tp->last_tag) || | 3616 | if (unlikely(sblk->status_tag == tp->last_tag)) { |
3615 | !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { | 3617 | if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || |
3616 | /* | 3618 | (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { |
3617 | * writing any value to intr-mbox-0 clears PCI INTA# and | 3619 | handled = 0; |
3618 | * chip-internal interrupt pending events. | ||
3619 | * writing non-zero to intr-mbox-0 additional tells the | ||
3620 | * NIC to stop sending us irqs, engaging "in-intr-handler" | ||
3621 | * event coalescing. | ||
3622 | */ | ||
3623 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, | ||
3624 | 0x00000001); | ||
3625 | if (tg3_irq_sync(tp)) | ||
3626 | goto out; | 3620 | goto out; |
3627 | if (netif_rx_schedule_prep(dev)) { | ||
3628 | prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); | ||
3629 | /* Update last_tag to mark that this status has been | ||
3630 | * seen. Because interrupt may be shared, we may be | ||
3631 | * racing with tg3_poll(), so only update last_tag | ||
3632 | * if tg3_poll() is not scheduled. | ||
3633 | */ | ||
3634 | tp->last_tag = sblk->status_tag; | ||
3635 | __netif_rx_schedule(dev); | ||
3636 | } | 3621 | } |
3637 | } else { /* shared interrupt */ | 3622 | } |
3638 | handled = 0; | 3623 | |
3624 | /* | ||
3625 | * writing any value to intr-mbox-0 clears PCI INTA# and | ||
3626 | * chip-internal interrupt pending events. | ||
3627 | * writing non-zero to intr-mbox-0 additional tells the | ||
3628 | * NIC to stop sending us irqs, engaging "in-intr-handler" | ||
3629 | * event coalescing. | ||
3630 | */ | ||
3631 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); | ||
3632 | if (tg3_irq_sync(tp)) | ||
3633 | goto out; | ||
3634 | if (netif_rx_schedule_prep(dev)) { | ||
3635 | prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); | ||
3636 | /* Update last_tag to mark that this status has been | ||
3637 | * seen. Because interrupt may be shared, we may be | ||
3638 | * racing with tg3_poll(), so only update last_tag | ||
3639 | * if tg3_poll() is not scheduled. | ||
3640 | */ | ||
3641 | tp->last_tag = sblk->status_tag; | ||
3642 | __netif_rx_schedule(dev); | ||
3639 | } | 3643 | } |
3640 | out: | 3644 | out: |
3641 | return IRQ_RETVAL(handled); | 3645 | return IRQ_RETVAL(handled); |
@@ -4823,6 +4827,19 @@ static int tg3_chip_reset(struct tg3 *tp) | |||
4823 | if (write_op == tg3_write_flush_reg32) | 4827 | if (write_op == tg3_write_flush_reg32) |
4824 | tp->write32 = tg3_write32; | 4828 | tp->write32 = tg3_write32; |
4825 | 4829 | ||
4830 | /* Prevent the irq handler from reading or writing PCI registers | ||
4831 | * during chip reset when the memory enable bit in the PCI command | ||
4832 | * register may be cleared. The chip does not generate interrupt | ||
4833 | * at this time, but the irq handler may still be called due to irq | ||
4834 | * sharing or irqpoll. | ||
4835 | */ | ||
4836 | tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING; | ||
4837 | tp->hw_status->status = 0; | ||
4838 | tp->hw_status->status_tag = 0; | ||
4839 | tp->last_tag = 0; | ||
4840 | smp_mb(); | ||
4841 | synchronize_irq(tp->pdev->irq); | ||
4842 | |||
4826 | /* do the reset */ | 4843 | /* do the reset */ |
4827 | val = GRC_MISC_CFG_CORECLK_RESET; | 4844 | val = GRC_MISC_CFG_CORECLK_RESET; |
4828 | 4845 | ||
@@ -4904,6 +4921,8 @@ static int tg3_chip_reset(struct tg3 *tp) | |||
4904 | 4921 | ||
4905 | pci_restore_state(tp->pdev); | 4922 | pci_restore_state(tp->pdev); |
4906 | 4923 | ||
4924 | tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING; | ||
4925 | |||
4907 | /* Make sure PCI-X relaxed ordering bit is clear. */ | 4926 | /* Make sure PCI-X relaxed ordering bit is clear. */ |
4908 | pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); | 4927 | pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); |
4909 | val &= ~PCIX_CAPS_RELAXED_ORDERING; | 4928 | val &= ~PCIX_CAPS_RELAXED_ORDERING; |