diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2011-06-13 09:38:55 -0400 |
---|---|---|
committer | David S. Miller <davem@conan.davemloft.net> | 2011-06-15 11:11:55 -0400 |
commit | 0e6cf6a9e3cf911577b1dde0dc724f634e4ca119 (patch) | |
tree | 8a974393bd1fba47688223f771d3035657d306c4 | |
parent | b96368e9365a4db7429da87cfd25bb54b24954f8 (diff) |
tg3: Workaround tagged status update bug
On rare occasions, writing the tag to the interrupt mailbox does not
reenable interrupts. This patch fixes the problem by reissuing the
mailbox update.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
Signed-off-by: David S. Miller <davem@conan.davemloft.net>
-rw-r--r-- | drivers/net/tg3.c | 38 | ||||
-rw-r--r-- | drivers/net/tg3.h | 3 |
2 files changed, 40 insertions, 1 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index aa1d1defc820..46352da36a81 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -7754,6 +7754,9 @@ static void tg3_rings_reset(struct tg3 *tp) | |||
7754 | 7754 | ||
7755 | /* Disable interrupts */ | 7755 | /* Disable interrupts */ |
7756 | tw32_mailbox_f(tp->napi[0].int_mbox, 1); | 7756 | tw32_mailbox_f(tp->napi[0].int_mbox, 1); |
7757 | tp->napi[0].chk_msi_cnt = 0; | ||
7758 | tp->napi[0].last_rx_cons = 0; | ||
7759 | tp->napi[0].last_tx_cons = 0; | ||
7757 | 7760 | ||
7758 | /* Zero mailbox registers. */ | 7761 | /* Zero mailbox registers. */ |
7759 | if (tg3_flag(tp, SUPPORT_MSIX)) { | 7762 | if (tg3_flag(tp, SUPPORT_MSIX)) { |
@@ -7764,6 +7767,9 @@ static void tg3_rings_reset(struct tg3 *tp) | |||
7764 | tw32_mailbox(tp->napi[i].prodmbox, 0); | 7767 | tw32_mailbox(tp->napi[i].prodmbox, 0); |
7765 | tw32_rx_mbox(tp->napi[i].consmbox, 0); | 7768 | tw32_rx_mbox(tp->napi[i].consmbox, 0); |
7766 | tw32_mailbox_f(tp->napi[i].int_mbox, 1); | 7769 | tw32_mailbox_f(tp->napi[i].int_mbox, 1); |
7770 | tp->napi[0].chk_msi_cnt = 0; | ||
7771 | tp->napi[i].last_rx_cons = 0; | ||
7772 | tp->napi[i].last_tx_cons = 0; | ||
7767 | } | 7773 | } |
7768 | if (!tg3_flag(tp, ENABLE_TSS)) | 7774 | if (!tg3_flag(tp, ENABLE_TSS)) |
7769 | tw32_mailbox(tp->napi[0].prodmbox, 0); | 7775 | tw32_mailbox(tp->napi[0].prodmbox, 0); |
@@ -8819,6 +8825,30 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) | |||
8819 | TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT); | 8825 | TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT); |
8820 | } | 8826 | } |
8821 | 8827 | ||
8828 | static void tg3_chk_missed_msi(struct tg3 *tp) | ||
8829 | { | ||
8830 | u32 i; | ||
8831 | |||
8832 | for (i = 0; i < tp->irq_cnt; i++) { | ||
8833 | struct tg3_napi *tnapi = &tp->napi[i]; | ||
8834 | |||
8835 | if (tg3_has_work(tnapi)) { | ||
8836 | if (tnapi->last_rx_cons == tnapi->rx_rcb_ptr && | ||
8837 | tnapi->last_tx_cons == tnapi->tx_cons) { | ||
8838 | if (tnapi->chk_msi_cnt < 1) { | ||
8839 | tnapi->chk_msi_cnt++; | ||
8840 | return; | ||
8841 | } | ||
8842 | tw32_mailbox(tnapi->int_mbox, | ||
8843 | tnapi->last_tag << 24); | ||
8844 | } | ||
8845 | } | ||
8846 | tnapi->chk_msi_cnt = 0; | ||
8847 | tnapi->last_rx_cons = tnapi->rx_rcb_ptr; | ||
8848 | tnapi->last_tx_cons = tnapi->tx_cons; | ||
8849 | } | ||
8850 | } | ||
8851 | |||
8822 | static void tg3_timer(unsigned long __opaque) | 8852 | static void tg3_timer(unsigned long __opaque) |
8823 | { | 8853 | { |
8824 | struct tg3 *tp = (struct tg3 *) __opaque; | 8854 | struct tg3 *tp = (struct tg3 *) __opaque; |
@@ -8828,6 +8858,10 @@ static void tg3_timer(unsigned long __opaque) | |||
8828 | 8858 | ||
8829 | spin_lock(&tp->lock); | 8859 | spin_lock(&tp->lock); |
8830 | 8860 | ||
8861 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || | ||
8862 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) | ||
8863 | tg3_chk_missed_msi(tp); | ||
8864 | |||
8831 | if (!tg3_flag(tp, TAGGED_STATUS)) { | 8865 | if (!tg3_flag(tp, TAGGED_STATUS)) { |
8832 | /* All of this garbage is because when using non-tagged | 8866 | /* All of this garbage is because when using non-tagged |
8833 | * IRQ status the mailbox/status_block protocol the chip | 8867 | * IRQ status the mailbox/status_block protocol the chip |
@@ -9303,7 +9337,9 @@ static int tg3_open(struct net_device *dev) | |||
9303 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 9337 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); |
9304 | tg3_free_rings(tp); | 9338 | tg3_free_rings(tp); |
9305 | } else { | 9339 | } else { |
9306 | if (tg3_flag(tp, TAGGED_STATUS)) | 9340 | if (tg3_flag(tp, TAGGED_STATUS) && |
9341 | GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && | ||
9342 | GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) | ||
9307 | tp->timer_offset = HZ; | 9343 | tp->timer_offset = HZ; |
9308 | else | 9344 | else |
9309 | tp->timer_offset = HZ / 10; | 9345 | tp->timer_offset = HZ / 10; |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 5b3d2f34da7a..3c113c1e9d35 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2800,6 +2800,7 @@ struct tg3_napi { | |||
2800 | struct tg3 *tp; | 2800 | struct tg3 *tp; |
2801 | struct tg3_hw_status *hw_status; | 2801 | struct tg3_hw_status *hw_status; |
2802 | 2802 | ||
2803 | u32 chk_msi_cnt; | ||
2803 | u32 last_tag; | 2804 | u32 last_tag; |
2804 | u32 last_irq_tag; | 2805 | u32 last_irq_tag; |
2805 | u32 int_mbox; | 2806 | u32 int_mbox; |
@@ -2807,6 +2808,7 @@ struct tg3_napi { | |||
2807 | 2808 | ||
2808 | u32 consmbox ____cacheline_aligned; | 2809 | u32 consmbox ____cacheline_aligned; |
2809 | u32 rx_rcb_ptr; | 2810 | u32 rx_rcb_ptr; |
2811 | u32 last_rx_cons; | ||
2810 | u16 *rx_rcb_prod_idx; | 2812 | u16 *rx_rcb_prod_idx; |
2811 | struct tg3_rx_prodring_set prodring; | 2813 | struct tg3_rx_prodring_set prodring; |
2812 | struct tg3_rx_buffer_desc *rx_rcb; | 2814 | struct tg3_rx_buffer_desc *rx_rcb; |
@@ -2814,6 +2816,7 @@ struct tg3_napi { | |||
2814 | u32 tx_prod ____cacheline_aligned; | 2816 | u32 tx_prod ____cacheline_aligned; |
2815 | u32 tx_cons; | 2817 | u32 tx_cons; |
2816 | u32 tx_pending; | 2818 | u32 tx_pending; |
2819 | u32 last_tx_cons; | ||
2817 | u32 prodmbox; | 2820 | u32 prodmbox; |
2818 | struct tg3_tx_buffer_desc *tx_ring; | 2821 | struct tg3_tx_buffer_desc *tx_ring; |
2819 | struct ring_info *tx_buffers; | 2822 | struct ring_info *tx_buffers; |