[patch] skbuffs leak in lance.c

From: Ivan Kokshaysky (ink@jurassic.park.msu.ru)
Date: Thu Feb 24 2000 - 10:12:52 EST


One of our boxes was crashing weekly (+-2 days) since it was upgraded
to 2.2.x due to this bug...
When device on the other end of the wire is powered off (most of the time
in my case) we have tx timeouts and driver tries to restart the chip
and re-initialize ring buffers. But it allocates a new set of rx skbs
without freeing an old one, quikly eating all available memory.

Ivan.

--- linux-2.2.15-pre/drivers/net/lance.c.orig Tue Jan 4 21:12:17 2000
+++ linux-2.2.15-pre/drivers/net/lance.c Tue Feb 22 19:05:39 2000
@@ -780,11 +780,19 @@
 */
 
 static void
-lance_purge_tx_ring(struct device *dev)
+lance_purge_ring(struct device *dev)
 {
         struct lance_private *lp = (struct lance_private *)dev->priv;
         int i;
 
+ /* Free all the skbuffs in the Rx and Tx queues. */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ struct sk_buff *skb = lp->rx_skbuff[i];
+ lp->rx_skbuff[i] = 0;
+ lp->rx_ring[i].base = 0; /* Not owned by LANCE chip. */
+ if (skb)
+ dev_kfree_skb(skb);
+ }
         for (i = 0; i < TX_RING_SIZE; i++) {
                 if (lp->tx_skbuff[i]) {
                         dev_kfree_skb(lp->tx_skbuff[i]);
@@ -845,7 +853,7 @@
 
         if (must_reinit ||
                 (chip_table[lp->chip_version].flags & LANCE_MUST_REINIT_RING)) {
- lance_purge_tx_ring(dev);
+ lance_purge_ring(dev);
                 lance_init_ring(dev, GFP_ATOMIC);
         }
         outw(0x0000, dev->base_addr + LANCE_ADDR);
@@ -870,7 +878,7 @@
                 outw(0x0004, ioaddr+LANCE_DATA);
                 lp->stats.tx_errors++;
 #ifndef final_version
- {
+ if (lance_debug > 3) {
                         int i;
                         printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
                                    lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
@@ -891,7 +899,7 @@
                 dev->tbusy=0;
                 dev->trans_start = jiffies;
 
- return 0;
+ return 1;
         }
 
         if (lance_debug > 3) {
@@ -1206,19 +1214,7 @@
         }
         free_irq(dev->irq, dev);
 
- /* Free all the skbuffs in the Rx and Tx queues. */
- for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = lp->rx_skbuff[i];
- lp->rx_skbuff[i] = 0;
- lp->rx_ring[i].base = 0; /* Not owned by LANCE chip. */
- if (skb)
- dev_kfree_skb(skb);
- }
- for (i = 0; i < TX_RING_SIZE; i++) {
- if (lp->tx_skbuff[i])
- dev_kfree_skb(lp->tx_skbuff[i]);
- lp->tx_skbuff[i] = 0;
- }
+ lance_purge_ring(dev);
 
         MOD_DEC_USE_COUNT;
         return 0;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Feb 29 2000 - 21:00:10 EST