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

Commit 32d8c572 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller
Browse files

[TG3]: Handle tg3_init_rings() failures



Handle dev_alloc_skb() failures when initializing the RX rings.
Without proper handling, the driver will crash when using a partial
ring.

Thanks to Stephane Doyon <sdoyon@max-t.com> for reporting the bug and
providing the initial patch.

Howie Xu <howie@vmware.com> also reported the same issue.

Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b9ec6c1b
Loading
Loading
Loading
Loading
+27 −5
Original line number Diff line number Diff line
@@ -4258,7 +4258,7 @@ static void tg3_free_rings(struct tg3 *tp)
 * end up in the driver.  tp->{tx,}lock are held and thus
 * we may not sleep.
 */
static void tg3_init_rings(struct tg3 *tp)
static int tg3_init_rings(struct tg3 *tp)
{
	u32 i;

@@ -4307,19 +4307,39 @@ static void tg3_init_rings(struct tg3 *tp)

	/* Now allocate fresh SKBs for each rx ring. */
	for (i = 0; i < tp->rx_pending; i++) {
		if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD,
				     -1, i) < 0)
		if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD, -1, i) < 0) {
			printk(KERN_WARNING PFX
			       "%s: Using a smaller RX standard ring, "
			       "only %d out of %d buffers were allocated "
			       "successfully.\n",
			       tp->dev->name, i, tp->rx_pending);
			if (i == 0)
				return -ENOMEM;
			tp->rx_pending = i;
			break;
		}
	}

	if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) {
		for (i = 0; i < tp->rx_jumbo_pending; i++) {
			if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_JUMBO,
					     -1, i) < 0)
					     -1, i) < 0) {
				printk(KERN_WARNING PFX
				       "%s: Using a smaller RX jumbo ring, "
				       "only %d out of %d buffers were "
				       "allocated successfully.\n",
				       tp->dev->name, i, tp->rx_jumbo_pending);
				if (i == 0) {
					tg3_free_rings(tp);
					return -ENOMEM;
				}
				tp->rx_jumbo_pending = i;
				break;
			}
		}
	}
	return 0;
}

/*
 * Must not be invoked with interrupt sources disabled and
@@ -5969,7 +5989,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
	 * can only do this after the hardware has been
	 * successfully reset.
	 */
	tg3_init_rings(tp);
	err = tg3_init_rings(tp);
	if (err)
		return err;

	/* This value is determined during the probe time DMA
	 * engine test, tg3_test_dma.