[PATCH] irda 2.6.0-test6

From
Stephen Hemminger <hidden>
Date
2003-09-30 00:06:06
Here is a patch for all the pieces that are missing in 2.6.0-test6,
it contains all the pieces that didn't get picked up from my earlier
patches. 
	
	irport:
		* 'ret' set but only used in test.
		* use alloc_netdev and dev->priv
		* error unwind fixup
	sa1100: 
		* need to call free_netdev (no destructor anymore)
	smsc_ircc:
		* use alloc_netdev and dev->priv

	irda_device:
		* no destructor, let devices use device
		  before freeing.
	
This should fix the rmmod issues for irda in 2.6.0-test6
and matches what Jean tested.

diff -urN -X dontdiff linux-2.5/drivers/net/irda/irport.c linux-2.5-net/drivers/net/irda/irport.c
--- linux-2.5/drivers/net/irda/irport.c	2003-06-05 10:04:37.000000000 -0700
+++ linux-2.5-net/drivers/net/irda/irport.c	2003-09-19 23:09:40.000000000 -0700
@@ -78,7 +78,6 @@
 static inline int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
 static inline void irport_receive(struct irport_cb *self);
 
-static int  irport_net_init(struct net_device *dev);
 static int  irport_net_ioctl(struct net_device *dev, struct ifreq *rq, 
 			     int cmd);
 static inline int  irport_is_receiving(struct irport_cb *self);
@@ -136,30 +135,29 @@
 {
 	struct net_device *dev;
 	struct irport_cb *self;
-	void *ret;
-	int err;
 
 	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
 
 	/* Lock the port that we need */
-	ret = request_region(iobase, IO_EXTENT, driver_name);
-	if (!ret) {
+	if (!request_region(iobase, IO_EXTENT, driver_name)) {
 		IRDA_DEBUG(0, "%s(), can't get iobase of 0x%03x\n",
 			   __FUNCTION__, iobase);
-		return NULL;
+		goto err_out1;
 	}
 
 	/*
 	 *  Allocate new instance of the driver
 	 */
-	self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL);
-	if (!self) {
+	dev = alloc_netdev(sizeof(struct irport_cb), "irda%d",
+			   irda_device_setup);
+	if (!dev) {
 		ERROR("%s(), can't allocate memory for "
 		      "control block!\n", __FUNCTION__);
-		release_region(iobase, IO_EXTENT);
-		return NULL;
+		goto err_out2;
 	}
-	memset(self, 0, sizeof(struct irport_cb));
+
+	self = dev->priv;
+	self->netdev = dev;
 	spin_lock_init(&self->lock);
 
 	/* Need to store self somewhere */
@@ -189,8 +187,9 @@
 	self->rx_buff.truesize = IRDA_SKB_MAX_MTU;
 	self->rx_buff.skb = __dev_alloc_skb(self->rx_buff.truesize,
 					    GFP_KERNEL);
-	if (self->rx_buff.skb == NULL)
-		return NULL;
+	if (self->rx_buff.skb == NULL) 
+		goto err_out3;
+
 	skb_reserve(self->rx_buff.skb, 1);
 	self->rx_buff.head = self->rx_buff.skb->data;
 	/* No need to memset the buffer, unless you are really pedantic */
@@ -207,31 +206,24 @@
 	if (self->tx_buff.truesize > 0) {
 		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
 						      GFP_KERNEL);
-		if (self->tx_buff.head == NULL) {
-			kfree_skb(self->rx_buff.skb);
-			self->rx_buff.skb = NULL;
-			self->rx_buff.head = NULL;
-			return NULL;
-		}
+		if (self->tx_buff.head == NULL) 
+			goto err_out4;
 		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 	}	
 	self->tx_buff.data = self->tx_buff.head;
 
-	if (!(dev = dev_alloc("irda%d", &err))) {
-		ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
-		return NULL;
-	}
-	self->netdev = dev;
-	/* Keep track of module usage */
-	SET_MODULE_OWNER(dev);
-
 	/* May be overridden by piggyback drivers */
- 	dev->priv = (void *) self;
 	self->interrupt    = irport_interrupt;
 	self->change_speed = irport_change_speed;
 
+	/* Make ifconfig display some details */
+	dev->base_addr = iobase;
+	dev->irq = irq;
+	
 	/* Override the network functions we need to use */
-	dev->init            = irport_net_init;
+
+	SET_MODULE_OWNER(dev);
+
 	dev->hard_start_xmit = irport_hard_xmit;
 	dev->tx_timeout	     = irport_timeout;
 	dev->watchdog_timeo  = HZ;  /* Allow time enough for speed change */
@@ -240,25 +232,31 @@
 	dev->get_stats	     = irport_net_get_stats;
 	dev->do_ioctl        = irport_net_ioctl;
 
-	/* Make ifconfig display some details */
-	dev->base_addr = iobase;
-	dev->irq = irq;
-
-	rtnl_lock();
-	err = register_netdevice(dev);
-	rtnl_unlock();
-	if (err) {
+	if (register_netdev(dev)) {
 		ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
-		return NULL;
+		goto err_out5;
 	}
 	MESSAGE("IrDA: Registered device %s (irport io=0x%X irq=%d)\n",
 		dev->name, iobase, irq);
 
 	return self;
+ err_out5:
+	kfree(self->tx_buff.head);
+ err_out4:
+	kfree_skb(self->rx_buff.skb);
+ err_out3:
+	free_netdev(dev);
+	dev_self[i] = NULL;
+ err_out2:
+	release_region(iobase, IO_EXTENT);
+ err_out1:
+	return NULL;
 }
 
 int irport_close(struct irport_cb *self)
 {
+	struct net_device *dev = self->netdev;
+
 	ASSERT(self != NULL, return -1;);
 
 	/* We are not using any dongle anymore! */
@@ -267,8 +265,7 @@
 	self->dongle = NULL;
 	
 	/* Remove netdevice */
-	if (self->netdev)
-		unregister_netdev(self->netdev);
+	unregister_netdev(dev);
 
 	/* Release the IO-port that this driver is using */
 	IRDA_DEBUG(0 , "%s(), Releasing Region %03x\n", 
@@ -284,7 +281,7 @@
 	
 	/* Remove ourselves */
 	dev_self[self->index] = NULL;
-	kfree(self);
+	free_netdev(dev);
 	
 	return 0;
 }
@@ -886,15 +883,6 @@
 	return IRQ_RETVAL(handled);
 }
 
-static int irport_net_init(struct net_device *dev)
-{
-	/* Set up to be a normal IrDA network device driver */
-	irda_device_setup(dev);
-
-	/* Insert overrides below this line! */
-
-	return 0;
-}
 
 /*
  * Function irport_net_open (dev)
diff -urN -X dontdiff linux-2.5/drivers/net/irda/sa1100_ir.c linux-2.5-net/drivers/net/irda/sa1100_ir.c
--- linux-2.5/drivers/net/irda/sa1100_ir.c	2003-06-05 10:04:37.000000000 -0700
+++ linux-2.5-net/drivers/net/irda/sa1100_ir.c	2003-09-17 15:49:30.000000000 -0700
@@ -1132,12 +1132,8 @@
 	release_mem_region(__PREG(Ser2HSCR0), 0x1c);
 	release_mem_region(__PREG(Ser2UTCR0), 0x24);
 
-	/*
-	 * We now know that the netdevice is no longer in use, and all
-	 * references to our driver have been removed.  The only structure
-	 * which may still be present is the netdevice, which will get
-	 * cleaned up by net/core/dev.c
-	 */
+	if(dev)
+		free_netdev(dev);
 }
 
 static int __init sa1100ir_setup(char *line)
diff -urN -X dontdiff linux-2.5/drivers/net/irda/smsc-ircc2.c linux-2.5-net/drivers/net/irda/smsc-ircc2.c
--- linux-2.5/drivers/net/irda/smsc-ircc2.c	2003-06-05 10:04:37.000000000 -0700
+++ linux-2.5-net/drivers/net/irda/smsc-ircc2.c	2003-09-18 10:39:48.000000000 -0700
@@ -140,10 +140,10 @@
 
 static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq);
 static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base);
-static int smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq);
+static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq);
 static int smsc_ircc_setup_buffers(struct smsc_ircc_cb *self);
 static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self);
-static int smsc_ircc_setup_netdev(struct smsc_ircc_cb *self);
+static void smsc_ircc_netdev_setup(struct net_device *dev);
 static void smsc_ircc_init_chip(struct smsc_ircc_cb *self);
 static int __exit smsc_ircc_close(struct smsc_ircc_cb *self);
 static int  smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase); 
@@ -366,38 +366,48 @@
 static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
 {
 	struct smsc_ircc_cb *self;
+	struct net_device *dev;
 	int err;
 	
 	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
-	err= smsc_ircc_present(fir_base, sir_base);
-	if(err) return -ENODEV;
+	err = smsc_ircc_present(fir_base, sir_base);
+	if(err) 
+		goto out;
 		
-	if (dev_count>DIM(dev_self)) {
+	if (dev_count > DIM(dev_self)) {
 	        WARNING("%s(), too many devices!\n", __FUNCTION__);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out1;
 	}
 
 	/*
 	 *  Allocate new instance of the driver
 	 */
-	self = kmalloc(sizeof(struct smsc_ircc_cb), GFP_KERNEL);
-	if (self == NULL) {
-		ERROR("%s, Can't allocate memory for control block!\n",
-                      driver_name);
-		return -ENOMEM;
+	dev = alloc_netdev(sizeof(*self), "irda%d", 
+			   smsc_ircc_netdev_setup);
+	if (!dev) {
+		WARNING("%s() can't allocate net device\n", __FUNCTION__);
+		err = -ENOMEM;
+		goto out1;
 	}
-	memset(self, 0, sizeof(struct smsc_ircc_cb));
+
+	self = dev->priv;
+	self->netdev = dev;
+
+	/* Make ifconfig display some details */
+	dev->base_addr = self->io.fir_base = fir_base;
+	dev->irq = self->io.irq = irq;
 
 	/* Need to store self somewhere */
 	dev_self[dev_count++] = self;
 	spin_lock_init(&self->lock);
 
 	err = smsc_ircc_setup_buffers(self);
-	if(err) return err;
+	if(err)
+		goto out2;
 	   
-	err= smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
-	if(err) return err;
+	smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
 
 	smsc_ircc_setup_qos(self);
 
@@ -405,17 +415,32 @@
 		
 	smsc_ircc_init_chip(self);
 	
-	if(ircc_transceiver > 0 && ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS) self->transceiver = ircc_transceiver;
-	else smsc_ircc_probe_transceiver(self);
+	if(ircc_transceiver > 0  && 
+	   ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS)
+		self->transceiver = ircc_transceiver;
+	else
+		smsc_ircc_probe_transceiver(self);
 
-	err = smsc_ircc_setup_netdev(self);
-	if(err) return err;
+	err = register_netdev(self->netdev);
+	if(err)
+		goto out2;
 
 	self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, smsc_ircc_pmproc);
 	if (self->pmdev)
 		self->pmdev->data = self;
 
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
+
 	return 0;
+ out2:
+	kfree(self->tx_buff.head);
+	kfree(self->rx_buff.head);
+	free_netdev(self->netdev);
+ out1:
+	release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
+	release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
+ out:
+	return err;
 }
 
 /*
@@ -428,18 +453,19 @@
 {
 	unsigned char low, high, chip, config, dma, irq, version;
 
-	if (check_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT) < 0) {
+	if (!request_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT,
+			    driver_name)) {
 		WARNING("%s: can't get fir_base of 0x%03x\n",
 			__FUNCTION__, fir_base);
-		return -ENODEV;
+		goto out1;
 	}
-#if POSSIBLE_USED_BY_SERIAL_DRIVER
-	if (check_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT) < 0) {
+
+	if (!request_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT,
+			    driver_name)) {
 		WARNING("%s: can't get sir_base of 0x%03x\n",
 			__FUNCTION__, sir_base);
-		return -ENODEV;
+		goto out2;
 	}
-#endif
 
 	register_bank(fir_base, 3);
 
@@ -454,13 +480,19 @@
 	if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { 
 	        WARNING("%s(), addr 0x%04x - no device found!\n",
 			__FUNCTION__, fir_base);
-		return -ENODEV;
+		goto out3;
 	}
 	MESSAGE("SMsC IrDA Controller found\n IrCC version %d.%d, "
 		"firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
 		chip & 0x0f, version, fir_base, sir_base, dma, irq);
 
 	return 0;
+ out3:
+	release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
+ out2:
+	release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
+ out1:
+	return -ENODEV;
 }
 
 /*
@@ -510,10 +542,11 @@
  *    Setup I/O
  *
  */
-static int smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, 
+			       unsigned int fir_base, unsigned int sir_base, 
+			       u8 dma, u8 irq)
 {
 	unsigned char config, chip_dma, chip_irq;
-	void *ret;
 
 	register_bank(fir_base, 3);
 	config  = inb(fir_base+IRCC_INTERFACE);
@@ -545,27 +578,6 @@
 	else
 		self->io.dma = chip_dma;
 
-	ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name);
-	if (!ret) { 
-		WARNING("%s(), can't get iobase of 0x%03x\n",
-			__FUNCTION__, self->io.fir_base);
-		kfree(self->tx_buff.head);
-		kfree(self->rx_buff.head);
-		kfree(self);
-		return -ENODEV;
-	}
-	ret = request_region(self->io.sir_base, self->io.sir_ext, driver_name);
-	if (!ret) { 
-		WARNING("%s(), can't get iobase of 0x%03x\n",
-			__FUNCTION__, self->io.sir_base);
-		release_region(self->io.fir_base, self->io.fir_ext);
-		kfree(self->tx_buff.head);
-		kfree(self->rx_buff.head);
-		kfree(self);
-		return -ENODEV;
-	}
-
-	return 0;
 }
 
 /*
@@ -634,57 +646,19 @@
 	outb(0x00, iobase+IRCC_MASTER);
 }
 
-/*
- * Function smsc_ircc_setup_netdev(self)
- *
- *    Alloc and setup network device
- *
- */
-static int smsc_ircc_setup_netdev(struct smsc_ircc_cb *self)
+static void smsc_ircc_netdev_setup(struct net_device *dev)
 {
-	struct net_device *dev;
-	int err;
-	/* Alloc netdev */
-
-	if (!(dev = dev_alloc("irda%d", &err))) {
-		ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
-		kfree(self->tx_buff.head);
-		kfree(self->rx_buff.head);
-		kfree(self);
-		return -ENOMEM;
-	}
-
-	dev->priv = (void *) self;
-	self->netdev = dev;
-
 	dev->init            = smsc_ircc_net_init;
 	dev->hard_start_xmit = smsc_ircc_hard_xmit_sir;
-	#if SMSC_IRCC2_C_NET_TIMEOUT
+#if SMSC_IRCC2_C_NET_TIMEOUT
 	dev->tx_timeout	     = smsc_ircc_timeout;
 	dev->watchdog_timeo  = HZ*2;  /* Allow enough time for speed change */
-	#endif
+#endif
 	dev->open            = smsc_ircc_net_open;
 	dev->stop            = smsc_ircc_net_close;
 	dev->do_ioctl        = smsc_ircc_net_ioctl;
 	dev->get_stats	     = smsc_ircc_net_get_stats;
 	
-	/* Make ifconfig display some details */
-	dev->base_addr = self->io.fir_base;
-	dev->irq = self->io.irq;
-
-	rtnl_lock();
-	err = register_netdevice(dev);
-	rtnl_unlock();
-	if (err) {
-		ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
-		kfree(self->tx_buff.head);
-		kfree(self->rx_buff.head);
-		kfree(self);
-		return -ENODEV;
-	}
-	MESSAGE("IrDA: Registered device %s\n", dev->name);
-
-	return 0;
 }
 
 /*
@@ -1734,22 +1708,22 @@
 {
 	int iobase;
 	unsigned long flags;
+	struct net_device *dev;
 
 	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
 	ASSERT(self != NULL, return -1;);
 
+	dev = self->netdev;
+	ASSERT(dev != NULL, return -1;);
+
 	iobase = self->io.fir_base;
 
 	if (self->pmdev)
 		pm_unregister(self->pmdev);
 
 	/* Remove netdevice */
-	if (self->netdev) {
-		rtnl_lock();
-		unregister_netdevice(self->netdev);
-		rtnl_unlock();
-	}
+	unregister_netdev(dev);
 
 	/* Make sure the irq handler is not exectuting */
 	spin_lock_irqsave(&self->lock, flags);
@@ -1784,7 +1758,7 @@
 	if (self->rx_buff.head)
 		kfree(self->rx_buff.head);
 
-	kfree(self);
+	free_netdev(dev);
 
 	return 0;
 }
diff -urN -X dontdiff linux-2.5/net/irda/irda_device.c linux-2.5-net/net/irda/irda_device.c
--- linux-2.5/net/irda/irda_device.c	2003-09-08 09:17:23.000000000 -0700
+++ linux-2.5-net/net/irda/irda_device.c	2003-09-19 22:29:17.000000000 -0700
@@ -378,8 +378,6 @@
         dev->hard_header_len = 0;
         dev->addr_len        = 0;
 
-	dev->destructor      = free_netdev;
-
         dev->type            = ARPHRD_IRDA;
         dev->tx_queue_len    = 8; /* Window size + 1 s-frame */
 
Thread (2 messages) 2 messages, 2 authors, last reply 2003-09-30
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help