All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Hemminger <shemminger@osdl.org>
To: jgarzik@pobox.com
Cc: netdev@oss.sgi.com
Subject: [PATCH] (05/12) Probe2 -- ni5010
Date: Tue, 14 Oct 2003 16:01:25 -0700	[thread overview]
Message-ID: <200310142301.h9EN1Pr02971@mail.osdl.org> (raw)

from viro NE16-ni5010
	* switched ni5010 to dynamic allocation
	* ni5010: embedded ->priv
	* ni5010: fixed clobbering ->irq
	* ni5010: fixed IO before request_region()
Additional:
	* add free_netdev

diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	Mon Sep 29 09:44:30 2003
+++ b/drivers/net/Space.c	Mon Sep 29 09:44:30 2003
@@ -68,7 +68,7 @@
 extern int es_probe(struct net_device *);
 extern int lne390_probe(struct net_device *);
 extern int e2100_probe(struct net_device *);
-extern int ni5010_probe(struct net_device *);
+extern struct net_device *ni5010_probe(int unit);
 extern struct net_device *ni52_probe(int unit);
 extern struct net_device *ni65_probe(int unit);
 extern int sonic_probe(struct net_device *);
@@ -280,13 +280,13 @@
 #ifdef CONFIG_SK_G16
 	{SK_init, 0},
 #endif
-#ifdef CONFIG_NI5010
-	{ni5010_probe, 0},
-#endif
 	{NULL, 0},
 };
 
 static struct devprobe2 isa_probes2[] __initdata = {
+#ifdef CONFIG_NI5010
+	{ni5010_probe, 0},
+#endif
 #ifdef CONFIG_NI52
 	{ni52_probe, 0},
 #endif
diff -Nru a/drivers/net/ni5010.c b/drivers/net/ni5010.c
--- a/drivers/net/ni5010.c	Mon Sep 29 09:44:30 2003
+++ b/drivers/net/ni5010.c	Mon Sep 29 09:44:30 2003
@@ -82,7 +82,7 @@
 
 #ifndef FULL_IODETECT
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int ni5010_portlist[] __initdata =
+static unsigned int ports[] __initdata =
 	{ 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0 };
 #endif
 
@@ -95,13 +95,11 @@
 struct ni5010_local {
 	struct net_device_stats stats;
 	int o_pkt_size;
-	int i_pkt_size;
 	spinlock_t lock;
 };
 
 /* Index to functions, as function prototypes. */
 
-extern int 	ni5010_probe(struct net_device *dev);
 static int	ni5010_probe1(struct net_device *dev, int ioaddr);
 static int	ni5010_open(struct net_device *dev);
 static int	ni5010_send_packet(struct sk_buff *skb, struct net_device *dev);
@@ -120,38 +118,58 @@
 static void	dump_packet(void *buf, int len);
 static void 	ni5010_show_registers(struct net_device *dev);
 
+static int io;
+static int irq;
 
-int __init ni5010_probe(struct net_device *dev)
+struct net_device * __init ni5010_probe(int unit)
 {
+	struct net_device *dev = alloc_etherdev(sizeof(struct ni5010_local));
 	int *port;
-	int base_addr = dev->base_addr;
+	int err = 0;
 
-        PRINTK2((KERN_DEBUG "%s: Entering ni5010_probe\n", dev->name));
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
 
-	SET_MODULE_OWNER(dev);
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+		io = dev->base_addr;
+		irq = dev->irq;
+	}
 
-	if (base_addr > 0x1ff)		/* Check a single specified location. */
-		return ni5010_probe1(dev, base_addr);
-	else if (base_addr != 0)	/* Don't probe at all. */
-		return -ENXIO;
+	PRINTK2((KERN_DEBUG "%s: Entering ni5010_probe\n", dev->name));
 
+	SET_MODULE_OWNER(dev);
+
+	if (io > 0x1ff)	{	/* Check a single specified location. */
+		err = ni5010_probe1(dev, io);
+	} else if (io != 0) {	/* Don't probe at all. */
+		err = -ENXIO;
+	} else {
 #ifdef FULL_IODETECT
-		for (int ioaddr=0x200; ioaddr<0x400; ioaddr+=0x20) {
-			if (check_region(ioaddr, NI5010_IO_EXTENT))
-				continue;
-			if (ni5010_probe1(dev, ioaddr) == 0)
-				return 0;
-		}
+		for (io=0x200; io<0x400 && ni5010_probe1(dev, io) ; io+=0x20)
+			;
+		if (io == 0x400)
+			err = -ENODEV;
+
 #else
-		for (port = ni5010_portlist; *port; port++) {
-			int ioaddr = *port;
-			if (check_region(ioaddr, NI5010_IO_EXTENT))
-				continue;
-			if (ni5010_probe1(dev, ioaddr) == 0)
-				return 0;
-		}
+		for (port = ports; *port && ni5010_probe1(dev, *port); port++)
+			;
+		if (!*port)
+			err = -ENODEV;
 #endif	/* FULL_IODETECT */
-	return -ENODEV;
+	}
+	if (err)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	release_region(dev->base_addr, NI5010_IO_EXTENT);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
 }
 
 static inline int rd_port(int ioaddr)
@@ -188,9 +206,17 @@
 static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
 {
 	static unsigned version_printed;
+	struct ni5010_local *lp;
 	int i;
 	unsigned int data = 0;
 	int boguscount = 40;
+	int err = -ENODEV;
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+
+	if (!request_region(ioaddr, NI5010_IO_EXTENT, boardname))
+		return -EBUSY;
 
 	/*
 	 * This is no "official" probe method, I've rather tested which
@@ -205,36 +231,40 @@
 	 *
 	 *   - Andreas
 	 */
-	
+
  	PRINTK2((KERN_DEBUG "%s: entering ni5010_probe1(%#3x)\n", 
  		dev->name, ioaddr));
 
-	if (inb(ioaddr+0) == 0xff) return -ENODEV;
+	if (inb(ioaddr+0) == 0xff)
+		goto out;
 
 	while ( (rd_port(ioaddr) & rd_port(ioaddr) & rd_port(ioaddr) &
 		 rd_port(ioaddr) & rd_port(ioaddr) & rd_port(ioaddr)) != 0xff)
 	{
-		if (boguscount-- == 0) return -ENODEV;
+		if (boguscount-- == 0)
+			goto out;
 	}
 
 	PRINTK2((KERN_DEBUG "%s: I/O #1 passed!\n", dev->name));
 
 	for (i=0; i<32; i++)
 		if ( (data = rd_port(ioaddr)) != 0xff) break;
-	if (data==0xff) return -ENODEV;
+	if (data==0xff)
+		goto out;
 
 	PRINTK2((KERN_DEBUG "%s: I/O #2 passed!\n", dev->name));
 
-	if (		(data == SA_ADDR0) &&
-	     (rd_port(ioaddr) == SA_ADDR1) &&
-	     (rd_port(ioaddr) == SA_ADDR2) ) {
-		for (i=0; i<4; i++) rd_port(ioaddr);
-		if ( (rd_port(ioaddr) != NI5010_MAGICVAL1) ||
-		     (rd_port(ioaddr) != NI5010_MAGICVAL2) ) {
-		     	return -ENODEV;
-		}
-	} else return -ENODEV;
-	
+	if ((data != SA_ADDR0) || (rd_port(ioaddr) != SA_ADDR1) ||
+	    (rd_port(ioaddr) != SA_ADDR2))
+		goto out;
+
+	for (i=0; i<4; i++)
+		rd_port(ioaddr);
+
+	if ( (rd_port(ioaddr) != NI5010_MAGICVAL1) ||
+	     (rd_port(ioaddr) != NI5010_MAGICVAL2) )
+		goto out;
+
 	PRINTK2((KERN_DEBUG "%s: I/O #3 passed!\n", dev->name));
 
 	if (NI5010_DEBUG && version_printed++ == 0)
@@ -267,8 +297,9 @@
 		PRINTK2((KERN_DEBUG "%s: I/O #6 passed!\n", dev->name));
 
 		if (dev->irq == 0) {
+			err = -EAGAIN;
 			printk(KERN_WARNING "%s: no IRQ found!\n", dev->name);
-			return -EAGAIN;
+			goto out;
 		}
 		PRINTK2((KERN_DEBUG "%s: I/O #7 passed!\n", dev->name));
 	} else if (dev->irq == 2) {
@@ -278,19 +309,9 @@
 	PRINTK2((KERN_DEBUG "%s: I/O #9 passed!\n", dev->name));
 
 	/* DMA is not supported (yet?), so no use detecting it */
+	lp = (struct ni5010_local*)dev->priv;
 
-	if (dev->priv == NULL) {
-		struct ni5010_local* lp;
-
-		dev->priv = kmalloc(sizeof(struct ni5010_local), GFP_KERNEL|GFP_DMA);
-		if (dev->priv == NULL) {
-			printk(KERN_WARNING "%s: Failed to allocate private memory\n", dev->name);
-			return -ENOMEM;
-		}
-
-		lp = (struct ni5010_local*)dev->priv;
-		spin_lock_init(&lp->lock);
-	}
+	spin_lock_init(&lp->lock);
 
 	PRINTK2((KERN_DEBUG "%s: I/O #10 passed!\n", dev->name));
 
@@ -315,9 +336,6 @@
 	}
         printk("// bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE);
 	memset(dev->priv, 0, sizeof(struct ni5010_local));
-
-	/* Grab the region so we can find another board if autoIRQ fails. */
-	request_region(ioaddr, NI5010_IO_EXTENT, boardname);
 	
 	dev->open		= ni5010_open;
 	dev->stop		= ni5010_close;
@@ -327,9 +345,6 @@
 	dev->tx_timeout		= ni5010_timeout;
 	dev->watchdog_timeo	= HZ/20;
 
-	/* Fill in the fields of the device structure with ethernet values. */
-	ether_setup(dev);
-	
 	dev->flags &= ~IFF_MULTICAST;	/* Multicast doesn't work */
 
 	/* Shut up the ni5010 */
@@ -345,6 +360,9 @@
 	printk(KERN_INFO "Join the NI5010 driver development team!\n");
 	printk(KERN_INFO "Mail to a.mohr@mailto.de or jvbest@wi.leidenuniv.nl\n");
 	return 0;
+out:
+	release_region(dev->base_addr, NI5010_IO_EXTENT);
+	return err;
 }
 
 /* 
@@ -513,6 +531,7 @@
 	int ioaddr = dev->base_addr;
 	unsigned char rcv_stat;
 	struct sk_buff *skb;
+	int i_pkt_size;
 	
 	PRINTK2((KERN_DEBUG "%s: entering ni5010_rx()\n", dev->name)); 
 	
@@ -532,17 +551,17 @@
 	
         outb(0xff, EDLC_RCLR);  /* Clear the interrupt */
 
-	lp->i_pkt_size = inw(IE_RCNT);
-	if (lp->i_pkt_size > ETH_FRAME_LEN || lp->i_pkt_size < 10 ) {
+	i_pkt_size = inw(IE_RCNT);
+	if (i_pkt_size > ETH_FRAME_LEN || i_pkt_size < 10 ) {
 		PRINTK((KERN_DEBUG "%s: Packet size error, packet size = %#4.4x\n", 
-			dev->name, lp->i_pkt_size));
+			dev->name, i_pkt_size));
 		lp->stats.rx_errors++;
 		lp->stats.rx_length_errors++;
 		return;
 	}
 
 	/* Malloc up new buffer. */
-	skb = dev_alloc_skb(lp->i_pkt_size + 3);
+	skb = dev_alloc_skb(i_pkt_size + 3);
 	if (skb == NULL) {
 		printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
 		lp->stats.rx_dropped++;
@@ -555,7 +574,7 @@
 	/* Read packet into buffer */
         outb(MM_MUX, IE_MMODE); /* Rcv buffer to system bus */
 	outw(0, IE_GP);	/* Seek to beginning of packet */
-	insb(IE_RBUF, skb_put(skb, lp->i_pkt_size), lp->i_pkt_size); 
+	insb(IE_RBUF, skb_put(skb, i_pkt_size), i_pkt_size); 
 	
 	if (NI5010_DEBUG >= 4) 
 		dump_packet(skb->data, skb->len); 
@@ -564,10 +583,10 @@
 	netif_rx(skb);
 	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
-	lp->stats.rx_bytes += lp->i_pkt_size;
+	lp->stats.rx_bytes += i_pkt_size;
 
 	PRINTK2((KERN_DEBUG "%s: Received packet, size=%#4.4x\n", 
-		dev->name, lp->i_pkt_size));
+		dev->name, i_pkt_size));
 	
 }
 
@@ -697,10 +716,10 @@
 	
 	if (NI5010_DEBUG > 3) dump_packet(buf, length);
 
-        buf_offs = NI5010_BUFSIZE - length - pad;
-        lp->o_pkt_size = length + pad;
+	buf_offs = NI5010_BUFSIZE - length - pad;
 
 	spin_lock_irqsave(&lp->lock, flags);
+	lp->o_pkt_size = length + pad;
 
 	outb(0, EDLC_RMASK);	/* Mask all receive interrupts */
 	outb(0, IE_MMODE);	/* Put Xmit buffer on system bus */
@@ -745,9 +764,7 @@
 }
 
 #ifdef MODULE
-static struct net_device dev_ni5010;
-static int io;
-static int irq;
+static struct net_device *dev_ni5010;
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
@@ -756,8 +773,6 @@
 
 int init_module(void)
 {
-	int result;
-	
 	PRINTK2((KERN_DEBUG "%s: entering init_module\n", boardname));
 	/*
 	if(io <= 0 || irq == 0){
@@ -771,29 +786,18 @@
 	}
 
 	PRINTK2((KERN_DEBUG "%s: init_module irq=%#2x, io=%#3x\n", boardname, irq, io));
-        dev_ni5010.irq=irq;
-        dev_ni5010.base_addr=io;
-	dev_ni5010.init=ni5010_probe;
-        if ((result = register_netdev(&dev_ni5010)) != 0) {
-        	PRINTK((KERN_WARNING "%s: register_netdev returned %d.\n", 
-        		boardname, result));
-                return -EIO;
-        }
+	dev_ni5010 = ni5010_probe(-1);
+	if (IS_ERR(dev_ni5010))
+		return PTR_ERR(dev_ni5010);
         return 0;
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
 	PRINTK2((KERN_DEBUG "%s: entering cleanup_module\n", boardname));
-
-        unregister_netdev(&dev_ni5010);
-
-	release_region(dev_ni5010.base_addr, NI5010_IO_EXTENT);
-	if (dev_ni5010.priv != NULL){
-	        kfree(dev_ni5010.priv);
-	        dev_ni5010.priv = NULL;
-	}
+	unregister_netdev(dev_ni5010);
+	release_region(dev_ni5010->base_addr, NI5010_IO_EXTENT);
+	free_netdev(dev_ni5010);
 }
 #endif /* MODULE */
 MODULE_LICENSE("GPL");

             reply	other threads:[~2003-10-14 23:01 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-10-14 23:01 Stephen Hemminger [this message]
  -- strict thread matches above, loose matches on Subject: below --
2003-10-14 22:34 [PATCH] (05/12) Probe2 -- ni5010 Stephen Hemminger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200310142301.h9EN1Pr02971@mail.osdl.org \
    --to=shemminger@osdl.org \
    --cc=jgarzik@pobox.com \
    --cc=netdev@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.