patch-2.3.99-pre6 linux/drivers/net/cs89x0.c

Next file: linux/drivers/net/de4x5.c
Previous file: linux/drivers/net/arcnet/com90io.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre5/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
@@ -48,10 +48,23 @@
                     : Don't call netif_wake_queue() in net_send_packet()
                     : Fixed an out-of-mem bug in dma_rx()
                     : Updated Documentation/cs89x0.txt
+
+  Andrew Morton     : andrewm@uow.edu.au / Kernel 2.3.99-pre1
+                    : Use skb_reserve to longword align IP header (two places)
+                    : Remove a delay loop from dma_rx()
+                    : Replace '100' with HZ
+                    : Clean up a couple of skb API abuses
+                    : Added 'cs89x0_dma=N' kernel boot option
+                    : Correctly initialise lp->lock in non-module compile
+
+  Andrew Morton     : andrewm@uow.edu.au / Kernel 2.3.99-pre4-1
+                    : MOD_INC/DEC race fix (see
+                    : http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html)
+
 */
 
 static char *version =
-"cs89x0.c: (kernel 2.3.48) Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n";
+"cs89x0.c: v2.3.99-pre1-2 Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n";
 
 /* ======================= end of configuration ======================= */
 
@@ -121,7 +134,7 @@
    { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
 
 #if DEBUGGING
-static unsigned int net_debug = 5;
+static unsigned int net_debug = DEBUGGING;
 #else
 #define net_debug 0	/* gcc will remove all the debug code for us */
 #endif
@@ -190,6 +203,21 @@
 /* Example routines you must write ;->. */
 #define tx_done(dev) 1
 
+/*
+ * Permit 'cs89x0_dma=N' in the kernel boot environment
+ */
+#if !defined(MODULE) && (ALLOW_DMA != 0)
+static int g_cs89x0_dma;
+
+static int __init dma_fn(char *str)
+{
+	g_cs89x0_dma = simple_strtol(str,NULL,0);
+	return 1;
+}
+
+__setup("cs89x0_dma=", dma_fn);
+#endif	/* !defined(MODULE) && (ALLOW_DMA != 0) */
+
 
 /* Check for a network adaptor of this type, and return '0' iff one exists.
    If dev->base_addr == 0, probe all likely locations.
@@ -318,7 +346,17 @@
 			retval = ENOMEM;
 			goto out;
 		}
-                memset(dev->priv, 0, sizeof(struct net_local));
+		lp = (struct net_local *)dev->priv;
+		memset(lp, 0, sizeof(*lp));
+		spin_lock_init(&lp->lock);
+#if !defined(MODULE) && (ALLOW_DMA != 0)
+		if (g_cs89x0_dma)
+		{
+			lp->use_dma = 1;
+			lp->dma = g_cs89x0_dma;
+			lp->dmasize = 16;	/* Could make this an option... */
+		}
+#endif
         }
 	lp = (struct net_local *)dev->priv;
 
@@ -612,12 +650,6 @@
 	int status, length;
 	unsigned char *bp = lp->rx_dma_ptr;
 
-	{
-		int i;
-		for (i = 0; i < 1000; i++)
-			;
-	}
-
 	status = bp[0] + (bp[1]<<8);
 	length = bp[2] + (bp[3]<<8);
 	bp += 4;
@@ -632,7 +664,7 @@
 	}
 
 	/* Malloc up new buffer. */
-	skb = alloc_skb(length, GFP_ATOMIC);
+	skb = dev_alloc_skb(length + 2);
 	if (skb == NULL) {
 		if (net_debug)	/* I don't think we want to do this to a stressed system */
 			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -645,8 +677,7 @@
 		lp->rx_dma_ptr = bp;
 		return;
 	}
-
-	skb->len = length;
+	skb_reserve(skb, 2);	/* longword align L3 header */
 	skb->dev = dev;
 
 	if (bp + length > lp->end_dma_buff) {
@@ -720,7 +751,7 @@
 	writereg(dev, PP_SelfCTL, selfcontrol);
 
 	/* Wait for the DC/DC converter to power up - 500ms */
-	while (jiffies - timenow < 100)
+	while (jiffies - timenow < HZ)
 		;
 
 }
@@ -914,6 +945,9 @@
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int result = 0;
 	int i;
+	int ret;
+
+	MOD_INC_USE_COUNT;
 
 	if (dev->irq < 2) {
 		/* Allow interrupts to be generated by the chip */
@@ -938,13 +972,15 @@
 			writereg(dev, PP_BusCTL, 0);	/* disable interrupts. */
 			if (net_debug)
 				printk("cs89x0: can't get an interrupt\n");
-			return -EAGAIN;
+			ret = -EAGAIN;
+			goto bad_out;
 		}
 	} else {
 		if (((1 << dev->irq) & lp->irq_map) == 0) {
 			printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                                dev->name, dev->irq, lp->irq_map);
-			return -EAGAIN;
+			ret = -EAGAIN;
+			goto bad_out;
 		}
 /* FIXME: Cirrus' release had this: */
 		writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
@@ -956,7 +992,8 @@
 		if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev)) {
 			if (net_debug)
 				printk("cs89x0: request_irq(%d) failed\n", dev->irq);
-			return -EAGAIN;
+			ret = -EAGAIN;
+			goto bad_out;
 		}
 	}
 
@@ -1032,7 +1069,8 @@
 #endif
                 writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
                 free_irq(dev->irq, dev);
-		return -EAGAIN;
+		ret = -EAGAIN;
+		goto bad_out;
 	}
 
         /* set the hardware to the configured choice */
@@ -1125,11 +1163,13 @@
 		 | dma_busctl(dev)
 #endif
                  );
-        MOD_INC_USE_COUNT;
         netif_start_queue(dev);
 	if (net_debug)
 		printk("cs89x0: net_open() succeeded\n");
 	return 0;
+bad_out:
+	MOD_DEC_USE_COUNT;
+	return ret;
 }
 
 static void net_timeout(struct net_device *dev)
@@ -1317,7 +1357,7 @@
 	}
 
 	/* Malloc up new buffer. */
-	skb = alloc_skb(length, GFP_ATOMIC);
+	skb = dev_alloc_skb(length + 2);
 	if (skb == NULL) {
 #if 0		/* Again, this seems a cruel thing to do */
 		printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -1325,10 +1365,10 @@
 		lp->stats.rx_dropped++;
 		return;
 	}
-	skb->len = length;
+	skb_reserve(skb, 2);	/* longword align L3 header */
 	skb->dev = dev;
 
-	insw(ioaddr + RX_FRAME_PORT, skb->data, length >> 1);
+	insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1);
 	if (length & 1)
 		skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT);
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)