netdev
[Top] [All Lists]

[PATCH] irda 2.6.0-test6

Subject: [PATCH] irda 2.6.0-test6
From: Stephen Hemminger <shemminger@xxxxxxxx>
Date: Mon, 29 Sep 2003 17:06:06 -0700
Cc: irda-users@xxxxxxxxxxxxxxxxxxxxx, "David S. Miller" <davem@xxxxxxxxxx>, netdev@xxxxxxxxxxx
In-reply-to: <20030929175938.GA11698@bougret.hpl.hp.com>
Organization: Open Source Development Lab
References: <20030929175938.GA11698@bougret.hpl.hp.com>
Sender: netdev-bounce@xxxxxxxxxxx
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 */
 


<Prev in Thread] Current Thread [Next in Thread>