Skip to content

Commit

Permalink
tg3: Workaround tagged status update bug
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Matt Carlson authored and David S. Miller committed Jun 15, 2011
1 parent b96368e commit 0e6cf6a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
38 changes: 37 additions & 1 deletion drivers/net/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -7754,6 +7754,9 @@ static void tg3_rings_reset(struct tg3 *tp)

/* Disable interrupts */
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. */
if (tg3_flag(tp, SUPPORT_MSIX)) {
Expand All @@ -7764,6 +7767,9 @@ static void tg3_rings_reset(struct tg3 *tp)
tw32_mailbox(tp->napi[i].prodmbox, 0);
tw32_rx_mbox(tp->napi[i].consmbox, 0);
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))
tw32_mailbox(tp->napi[0].prodmbox, 0);
Expand Down Expand Up @@ -8819,6 +8825,30 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
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)
{
struct tg3 *tp = (struct tg3 *) __opaque;
Expand All @@ -8828,6 +8858,10 @@ static void tg3_timer(unsigned long __opaque)

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)) {
/* All of this garbage is because when using non-tagged
* IRQ status the mailbox/status_block protocol the chip
Expand Down Expand Up @@ -9303,7 +9337,9 @@ static int tg3_open(struct net_device *dev)
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
} 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;
else
tp->timer_offset = HZ / 10;
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/tg3.h
Original file line number Diff line number Diff line change
Expand Up @@ -2800,20 +2800,23 @@ struct tg3_napi {
struct tg3 *tp;
struct tg3_hw_status *hw_status;

u32 chk_msi_cnt;
u32 last_tag;
u32 last_irq_tag;
u32 int_mbox;
u32 coal_now;

u32 consmbox ____cacheline_aligned;
u32 rx_rcb_ptr;
u32 last_rx_cons;
u16 *rx_rcb_prod_idx;
struct tg3_rx_prodring_set prodring;
struct tg3_rx_buffer_desc *rx_rcb;

u32 tx_prod ____cacheline_aligned;
u32 tx_cons;
u32 tx_pending;
u32 last_tx_cons;
u32 prodmbox;
struct tg3_tx_buffer_desc *tx_ring;
struct ring_info *tx_buffers;
Expand Down

0 comments on commit 0e6cf6a

Please sign in to comment.