diff options
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 53 |
1 files changed, 28 insertions, 25 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 92b0e4975135..903d0ced7ddb 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -426,9 +426,30 @@ static void tg3_enable_ints(struct tg3 *tp) | |||
426 | tg3_cond_int(tp); | 426 | tg3_cond_int(tp); |
427 | } | 427 | } |
428 | 428 | ||
429 | static inline unsigned int tg3_has_work(struct tg3 *tp) | ||
430 | { | ||
431 | struct tg3_hw_status *sblk = tp->hw_status; | ||
432 | unsigned int work_exists = 0; | ||
433 | |||
434 | /* check for phy events */ | ||
435 | if (!(tp->tg3_flags & | ||
436 | (TG3_FLAG_USE_LINKCHG_REG | | ||
437 | TG3_FLAG_POLL_SERDES))) { | ||
438 | if (sblk->status & SD_STATUS_LINK_CHG) | ||
439 | work_exists = 1; | ||
440 | } | ||
441 | /* check for RX/TX work to do */ | ||
442 | if (sblk->idx[0].tx_consumer != tp->tx_cons || | ||
443 | sblk->idx[0].rx_producer != tp->rx_rcb_ptr) | ||
444 | work_exists = 1; | ||
445 | |||
446 | return work_exists; | ||
447 | } | ||
448 | |||
429 | /* tg3_restart_ints | 449 | /* tg3_restart_ints |
430 | * similar to tg3_enable_ints, but it can return without flushing the | 450 | * similar to tg3_enable_ints, but it accurately determines whether there |
431 | * PIO write which reenables interrupts | 451 | * is new work pending and can return without flushing the PIO write |
452 | * which reenables interrupts | ||
432 | */ | 453 | */ |
433 | static void tg3_restart_ints(struct tg3 *tp) | 454 | static void tg3_restart_ints(struct tg3 *tp) |
434 | { | 455 | { |
@@ -437,7 +458,9 @@ static void tg3_restart_ints(struct tg3 *tp) | |||
437 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000); | 458 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000); |
438 | mmiowb(); | 459 | mmiowb(); |
439 | 460 | ||
440 | tg3_cond_int(tp); | 461 | if (tg3_has_work(tp)) |
462 | tw32(HOSTCC_MODE, tp->coalesce_mode | | ||
463 | (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); | ||
441 | } | 464 | } |
442 | 465 | ||
443 | static inline void tg3_netif_stop(struct tg3 *tp) | 466 | static inline void tg3_netif_stop(struct tg3 *tp) |
@@ -2891,26 +2914,6 @@ static int tg3_poll(struct net_device *netdev, int *budget) | |||
2891 | return (done ? 0 : 1); | 2914 | return (done ? 0 : 1); |
2892 | } | 2915 | } |
2893 | 2916 | ||
2894 | static inline unsigned int tg3_has_work(struct net_device *dev, struct tg3 *tp) | ||
2895 | { | ||
2896 | struct tg3_hw_status *sblk = tp->hw_status; | ||
2897 | unsigned int work_exists = 0; | ||
2898 | |||
2899 | /* check for phy events */ | ||
2900 | if (!(tp->tg3_flags & | ||
2901 | (TG3_FLAG_USE_LINKCHG_REG | | ||
2902 | TG3_FLAG_POLL_SERDES))) { | ||
2903 | if (sblk->status & SD_STATUS_LINK_CHG) | ||
2904 | work_exists = 1; | ||
2905 | } | ||
2906 | /* check for RX/TX work to do */ | ||
2907 | if (sblk->idx[0].tx_consumer != tp->tx_cons || | ||
2908 | sblk->idx[0].rx_producer != tp->rx_rcb_ptr) | ||
2909 | work_exists = 1; | ||
2910 | |||
2911 | return work_exists; | ||
2912 | } | ||
2913 | |||
2914 | /* MSI ISR - No need to check for interrupt sharing and no need to | 2917 | /* MSI ISR - No need to check for interrupt sharing and no need to |
2915 | * flush status block and interrupt mailbox. PCI ordering rules | 2918 | * flush status block and interrupt mailbox. PCI ordering rules |
2916 | * guarantee that MSI will arrive after the status block. | 2919 | * guarantee that MSI will arrive after the status block. |
@@ -2934,7 +2937,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) | |||
2934 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); | 2937 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); |
2935 | sblk->status &= ~SD_STATUS_UPDATED; | 2938 | sblk->status &= ~SD_STATUS_UPDATED; |
2936 | 2939 | ||
2937 | if (likely(tg3_has_work(dev, tp))) | 2940 | if (likely(tg3_has_work(tp))) |
2938 | netif_rx_schedule(dev); /* schedule NAPI poll */ | 2941 | netif_rx_schedule(dev); /* schedule NAPI poll */ |
2939 | else { | 2942 | else { |
2940 | /* no work, re-enable interrupts | 2943 | /* no work, re-enable interrupts |
@@ -2981,7 +2984,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
2981 | tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); | 2984 | tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); |
2982 | sblk->status &= ~SD_STATUS_UPDATED; | 2985 | sblk->status &= ~SD_STATUS_UPDATED; |
2983 | 2986 | ||
2984 | if (likely(tg3_has_work(dev, tp))) | 2987 | if (likely(tg3_has_work(tp))) |
2985 | netif_rx_schedule(dev); /* schedule NAPI poll */ | 2988 | netif_rx_schedule(dev); /* schedule NAPI poll */ |
2986 | else { | 2989 | else { |
2987 | /* no work, shared interrupt perhaps? re-enable | 2990 | /* no work, shared interrupt perhaps? re-enable |