Commit 0e6cf6a9 authored by Matt Carlson's avatar Matt Carlson Committed by David S. Miller

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: default avatarMatt Carlson <mcarlson@broadcom.com>
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Reviewed-by: default avatarBenjamin Li <benli@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@conan.davemloft.net>
parent b96368e9
...@@ -7754,6 +7754,9 @@ static void tg3_rings_reset(struct tg3 *tp) ...@@ -7754,6 +7754,9 @@ static void tg3_rings_reset(struct tg3 *tp)
/* Disable interrupts */ /* Disable interrupts */
tw32_mailbox_f(tp->napi[0].int_mbox, 1); tw32_mailbox_f(tp->napi[0].int_mbox, 1);
tp->napi[0].chk_msi_cnt = 0;
tp->napi[0].last_rx_cons = 0;
tp->napi[0].last_tx_cons = 0;
/* Zero mailbox registers. */ /* Zero mailbox registers. */
if (tg3_flag(tp, SUPPORT_MSIX)) { if (tg3_flag(tp, SUPPORT_MSIX)) {
...@@ -7764,6 +7767,9 @@ static void tg3_rings_reset(struct tg3 *tp) ...@@ -7764,6 +7767,9 @@ static void tg3_rings_reset(struct tg3 *tp)
tw32_mailbox(tp->napi[i].prodmbox, 0); tw32_mailbox(tp->napi[i].prodmbox, 0);
tw32_rx_mbox(tp->napi[i].consmbox, 0); tw32_rx_mbox(tp->napi[i].consmbox, 0);
tw32_mailbox_f(tp->napi[i].int_mbox, 1); tw32_mailbox_f(tp->napi[i].int_mbox, 1);
tp->napi[0].chk_msi_cnt = 0;
tp->napi[i].last_rx_cons = 0;
tp->napi[i].last_tx_cons = 0;
} }
if (!tg3_flag(tp, ENABLE_TSS)) if (!tg3_flag(tp, ENABLE_TSS))
tw32_mailbox(tp->napi[0].prodmbox, 0); tw32_mailbox(tp->napi[0].prodmbox, 0);
...@@ -8819,6 +8825,30 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) ...@@ -8819,6 +8825,30 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT); TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT);
} }
static void tg3_chk_missed_msi(struct tg3 *tp)
{
u32 i;
for (i = 0; i < tp->irq_cnt; i++) {
struct tg3_napi *tnapi = &tp->napi[i];
if (tg3_has_work(tnapi)) {
if (tnapi->last_rx_cons == tnapi->rx_rcb_ptr &&
tnapi->last_tx_cons == tnapi->tx_cons) {
if (tnapi->chk_msi_cnt < 1) {
tnapi->chk_msi_cnt++;
return;
}
tw32_mailbox(tnapi->int_mbox,
tnapi->last_tag << 24);
}
}
tnapi->chk_msi_cnt = 0;
tnapi->last_rx_cons = tnapi->rx_rcb_ptr;
tnapi->last_tx_cons = tnapi->tx_cons;
}
}
static void tg3_timer(unsigned long __opaque) static void tg3_timer(unsigned long __opaque)
{ {
struct tg3 *tp = (struct tg3 *) __opaque; struct tg3 *tp = (struct tg3 *) __opaque;
...@@ -8828,6 +8858,10 @@ static void tg3_timer(unsigned long __opaque) ...@@ -8828,6 +8858,10 @@ static void tg3_timer(unsigned long __opaque)
spin_lock(&tp->lock); spin_lock(&tp->lock);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
tg3_chk_missed_msi(tp);
if (!tg3_flag(tp, TAGGED_STATUS)) { if (!tg3_flag(tp, TAGGED_STATUS)) {
/* All of this garbage is because when using non-tagged /* All of this garbage is because when using non-tagged
* IRQ status the mailbox/status_block protocol the chip * IRQ status the mailbox/status_block protocol the chip
...@@ -9303,7 +9337,9 @@ static int tg3_open(struct net_device *dev) ...@@ -9303,7 +9337,9 @@ static int tg3_open(struct net_device *dev)
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp); tg3_free_rings(tp);
} else { } else {
if (tg3_flag(tp, TAGGED_STATUS)) if (tg3_flag(tp, TAGGED_STATUS) &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765)
tp->timer_offset = HZ; tp->timer_offset = HZ;
else else
tp->timer_offset = HZ / 10; tp->timer_offset = HZ / 10;
......
...@@ -2800,6 +2800,7 @@ struct tg3_napi { ...@@ -2800,6 +2800,7 @@ struct tg3_napi {
struct tg3 *tp; struct tg3 *tp;
struct tg3_hw_status *hw_status; struct tg3_hw_status *hw_status;
u32 chk_msi_cnt;
u32 last_tag; u32 last_tag;
u32 last_irq_tag; u32 last_irq_tag;
u32 int_mbox; u32 int_mbox;
...@@ -2807,6 +2808,7 @@ struct tg3_napi { ...@@ -2807,6 +2808,7 @@ struct tg3_napi {
u32 consmbox ____cacheline_aligned; u32 consmbox ____cacheline_aligned;
u32 rx_rcb_ptr; u32 rx_rcb_ptr;
u32 last_rx_cons;
u16 *rx_rcb_prod_idx; u16 *rx_rcb_prod_idx;
struct tg3_rx_prodring_set prodring; struct tg3_rx_prodring_set prodring;
struct tg3_rx_buffer_desc *rx_rcb; struct tg3_rx_buffer_desc *rx_rcb;
...@@ -2814,6 +2816,7 @@ struct tg3_napi { ...@@ -2814,6 +2816,7 @@ struct tg3_napi {
u32 tx_prod ____cacheline_aligned; u32 tx_prod ____cacheline_aligned;
u32 tx_cons; u32 tx_cons;
u32 tx_pending; u32 tx_pending;
u32 last_tx_cons;
u32 prodmbox; u32 prodmbox;
struct tg3_tx_buffer_desc *tx_ring; struct tg3_tx_buffer_desc *tx_ring;
struct ring_info *tx_buffers; struct ring_info *tx_buffers;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment