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 */
|