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

[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
...@@ -4258,7 +4258,7 @@ static void tg3_free_rings(struct tg3 *tp) ...@@ -4258,7 +4258,7 @@ static void tg3_free_rings(struct tg3 *tp)
* end up in the driver. tp->{tx,}lock are held and thus * end up in the driver. tp->{tx,}lock are held and thus
* we may not sleep. * we may not sleep.
*/ */
static void tg3_init_rings(struct tg3 *tp) static int tg3_init_rings(struct tg3 *tp)
{ {
u32 i; u32 i;
...@@ -4307,18 +4307,38 @@ static void tg3_init_rings(struct tg3 *tp) ...@@ -4307,18 +4307,38 @@ static void tg3_init_rings(struct tg3 *tp)
/* Now allocate fresh SKBs for each rx ring. */ /* Now allocate fresh SKBs for each rx ring. */
for (i = 0; i < tp->rx_pending; i++) { for (i = 0; i < tp->rx_pending; i++) {
if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD, if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD, -1, i) < 0) {
-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; break;
}
} }
if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) {
for (i = 0; i < tp->rx_jumbo_pending; i++) { for (i = 0; i < tp->rx_jumbo_pending; i++) {
if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_JUMBO, 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; break;
}
} }
} }
return 0;
} }
/* /*
...@@ -5969,7 +5989,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ...@@ -5969,7 +5989,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
* can only do this after the hardware has been * can only do this after the hardware has been
* successfully reset. * successfully reset.
*/ */
tg3_init_rings(tp); err = tg3_init_rings(tp);
if (err)
return err;
/* This value is determined during the probe time DMA /* This value is determined during the probe time DMA
* engine test, tg3_test_dma. * engine test, tg3_test_dma.
......
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