diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tg3.c | 32 |
1 files changed, 15 insertions, 17 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index eea418124be1..a629706e2b37 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -488,7 +488,8 @@ static void tg3_disable_ints(struct tg3 *tp) | |||
488 | 488 | ||
489 | static inline void tg3_cond_int(struct tg3 *tp) | 489 | static inline void tg3_cond_int(struct tg3 *tp) |
490 | { | 490 | { |
491 | if (tp->hw_status->status & SD_STATUS_UPDATED) | 491 | if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) && |
492 | (tp->hw_status->status & SD_STATUS_UPDATED)) | ||
492 | tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT); | 493 | tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT); |
493 | } | 494 | } |
494 | 495 | ||
@@ -3220,18 +3221,17 @@ static int tg3_poll(struct net_device *netdev, int *budget) | |||
3220 | netdev->quota -= work_done; | 3221 | netdev->quota -= work_done; |
3221 | } | 3222 | } |
3222 | 3223 | ||
3223 | if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) | 3224 | if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { |
3224 | tp->last_tag = sblk->status_tag; | 3225 | tp->last_tag = sblk->status_tag; |
3225 | rmb(); | 3226 | rmb(); |
3226 | sblk->status &= ~SD_STATUS_UPDATED; | 3227 | } else |
3228 | sblk->status &= ~SD_STATUS_UPDATED; | ||
3227 | 3229 | ||
3228 | /* if no more work, tell net stack and NIC we're done */ | 3230 | /* if no more work, tell net stack and NIC we're done */ |
3229 | done = !tg3_has_work(tp); | 3231 | done = !tg3_has_work(tp); |
3230 | if (done) { | 3232 | if (done) { |
3231 | spin_lock(&tp->lock); | ||
3232 | netif_rx_complete(netdev); | 3233 | netif_rx_complete(netdev); |
3233 | tg3_restart_ints(tp); | 3234 | tg3_restart_ints(tp); |
3234 | spin_unlock(&tp->lock); | ||
3235 | } | 3235 | } |
3236 | 3236 | ||
3237 | return (done ? 0 : 1); | 3237 | return (done ? 0 : 1); |
@@ -3351,7 +3351,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r | |||
3351 | * Reading the PCI State register will confirm whether the | 3351 | * Reading the PCI State register will confirm whether the |
3352 | * interrupt is ours and will flush the status block. | 3352 | * interrupt is ours and will flush the status block. |
3353 | */ | 3353 | */ |
3354 | if ((sblk->status & SD_STATUS_UPDATED) || | 3354 | if ((sblk->status_tag != tp->last_tag) || |
3355 | !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { | 3355 | !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { |
3356 | /* | 3356 | /* |
3357 | * writing any value to intr-mbox-0 clears PCI INTA# and | 3357 | * writing any value to intr-mbox-0 clears PCI INTA# and |
@@ -3362,20 +3362,17 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r | |||
3362 | */ | 3362 | */ |
3363 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, | 3363 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, |
3364 | 0x00000001); | 3364 | 0x00000001); |
3365 | tp->last_tag = sblk->status_tag; | ||
3366 | rmb(); | ||
3367 | if (tg3_irq_sync(tp)) | 3365 | if (tg3_irq_sync(tp)) |
3368 | goto out; | 3366 | goto out; |
3369 | sblk->status &= ~SD_STATUS_UPDATED; | 3367 | if (netif_rx_schedule_prep(dev)) { |
3370 | if (likely(tg3_has_work(tp))) { | ||
3371 | prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); | 3368 | prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); |
3372 | netif_rx_schedule(dev); /* schedule NAPI poll */ | 3369 | /* Update last_tag to mark that this status has been |
3373 | } else { | 3370 | * seen. Because interrupt may be shared, we may be |
3374 | /* no work, shared interrupt perhaps? re-enable | 3371 | * racing with tg3_poll(), so only update last_tag |
3375 | * interrupts, and flush that PCI write | 3372 | * if tg3_poll() is not scheduled. |
3376 | */ | 3373 | */ |
3377 | tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, | 3374 | tp->last_tag = sblk->status_tag; |
3378 | tp->last_tag << 24); | 3375 | __netif_rx_schedule(dev); |
3379 | } | 3376 | } |
3380 | } else { /* shared interrupt */ | 3377 | } else { /* shared interrupt */ |
3381 | handled = 0; | 3378 | handled = 0; |
@@ -6238,6 +6235,7 @@ static int tg3_test_interrupt(struct tg3 *tp) | |||
6238 | if (err) | 6235 | if (err) |
6239 | return err; | 6236 | return err; |
6240 | 6237 | ||
6238 | tp->hw_status->status &= ~SD_STATUS_UPDATED; | ||
6241 | tg3_enable_ints(tp); | 6239 | tg3_enable_ints(tp); |
6242 | 6240 | ||
6243 | tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | | 6241 | tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | |