Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+37 −1
Original line number Diff line number Diff line
@@ -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)) {
@@ -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);
@@ -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;
@@ -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
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -2800,6 +2800,7 @@ 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;
@@ -2807,6 +2808,7 @@ struct tg3_napi {

	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;
@@ -2814,6 +2816,7 @@ struct tg3_napi {
	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;