aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2011-06-13 09:38:55 -0400
committerDavid S. Miller <davem@conan.davemloft.net>2011-06-15 11:11:55 -0400
commit0e6cf6a9e3cf911577b1dde0dc724f634e4ca119 (patch)
tree8a974393bd1fba47688223f771d3035657d306c4
parentb96368e9365a4db7429da87cfd25bb54b24954f8 (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.c38
-rw-r--r--drivers/net/tg3.h3
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
8828static 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
8822static void tg3_timer(unsigned long __opaque) 8852static 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;