be more careful about subdevice allocation/free
authorFrank Mori Hess <fmhess@speakeasy.net>
Mon, 12 Jan 2004 00:28:40 +0000 (00:28 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Mon, 12 Jan 2004 00:28:40 +0000 (00:28 +0000)
comedi/comedi_fops.c
comedi/drivers.c

index da333e947912c81527da53dd848f174a73ba37eb..f419650ba1923b75e48062c0299d1af1462cb453 100644 (file)
@@ -1662,17 +1662,19 @@ static int comedi_close_v22(struct inode *inode,struct file *file)
        comedi_subdevice *s = NULL;
        int i;
 
-       for(i=0;i<dev->n_subdevices;i++){
-               s=dev->subdevices+i;
+       if(dev->subdevices)
+       {
+               for(i=0;i<dev->n_subdevices;i++){
+                       s=dev->subdevices+i;
 
-               if(s->busy==file){
-                       do_cancel(dev,s);
-               }
-               if(s->lock==file){
-                       s->lock=NULL;
+                       if(s->busy==file){
+                               do_cancel(dev,s);
+                       }
+                       if(s->lock==file){
+                               s->lock=NULL;
+                       }
                }
        }
-
        if(dev->attached && dev->use_count==1 && dev->close){
                dev->close(dev);
        }
index af8a75907eb3a5157c2b55dc57b962ffff6748d2..1ccf1e25ec3216a31f43c74aa3c284865193888b 100644 (file)
@@ -56,11 +56,35 @@ int comedi_modprobe(int minor)
        return -EINVAL;
 }
 
-int comedi_device_detach(comedi_device *dev)
+static void cleanup_device_allocations(comedi_device *dev)
 {
        int i;
        comedi_subdevice *s;
 
+       if(dev->subdevices)
+       {
+               for(i = 0; i < dev->n_subdevices; i++)
+               {
+                       s = dev->subdevices + i;
+                       if(s->async)
+                       {
+                               comedi_buf_alloc(dev, s, 0);
+                               if(s->buf_change) s->buf_change(dev, s, 0);
+                               kfree(s->async);
+                       }
+               }
+               kfree(dev->subdevices);
+               dev->subdevices = NULL;
+       }
+       if(dev->private)
+       {
+               kfree(dev->private);
+               dev->private = NULL;
+       }
+}
+
+int comedi_device_detach(comedi_device *dev)
+{
        if(!dev->attached)
                return 0;
 
@@ -69,24 +93,13 @@ int comedi_device_detach(comedi_device *dev)
 
        dev->attached=0;
 
-       for(i=0;i<dev->n_subdevices;i++){
-               s=dev->subdevices+i;
-               if(s->async){
-                       comedi_buf_alloc(dev, s, 0);
-                       if(s->buf_change) s->buf_change(dev,s,0);
-                       kfree(s->async);
-               }
-       }
-
        if(dev->driver){
                dev->driver->detach(dev);
        }else{
                printk("BUG: dev->driver=NULL in comedi_device_detach()\n");
        }
 
-       if(dev->subdevices)kfree(dev->subdevices);
-       if(dev->private)kfree(dev->private);
-
+       cleanup_device_allocations(dev);
        return 0;
 }
 
@@ -130,8 +143,7 @@ int comedi_device_attach(comedi_device *dev,comedi_devconfig *it)
                ret=driv->attach(dev,it);
                if(ret<0){
                        driv->detach(dev);
-                       if(dev->subdevices)kfree(dev->subdevices);
-                       if(dev->private)kfree(dev->private);
+                       cleanup_device_allocations(dev);
                        module_put( driv->module );
                        return ret;
                }
@@ -158,9 +170,7 @@ attached:
        if(ret < 0)
        {
                driv->detach(dev);
-               if(dev->subdevices)kfree(dev->subdevices);
-               if(dev->private)kfree(dev->private);
-
+               cleanup_device_allocations(dev);
                return ret;
        }