staging: comedi: usbduxfast: Move usb_driver (*probe) into comedi_driver
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Tue, 14 May 2013 20:30:09 +0000 (13:30 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 16 May 2013 23:24:20 +0000 (16:24 -0700)
Currently, the usb_driver (*probe) locates a free place in the static
usbduxfast array to use for the private data in this driver. It then
does some initial setup of the usb device and allocates the buffers
needed. The firmware for the device is then requested and uploaded
before calling comedi_usb_auto_config() to allow the comedi core to
complete the (*auto_attach) of the device.

Move the bulk of the (*probe) into the comedi_driver (*auto_attach).
This allows the private data to be kzalloc'ed. We can then remove the
static array along with the semaphore that protected it.

This also removes the 16 attached devices limitation.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/usbduxfast.c

index a83b2b5bcf189f3c1eb643e85ba939819d448449..9f6a0e930d94cd685b1980aa15888d594540c53f 100644 (file)
@@ -177,19 +177,6 @@ struct usbduxfast_private {
        struct semaphore sem;
 };
 
-/*
- * The pointer to the private usb-data of the driver
- * is also the private data for the comedi-device.
- * This has to be global as the usb subsystem needs
- * global variables. The other reason is that this
- * structure must be there _before_ any comedi
- * command is issued. The usb subsystem must be
- * initialised before comedi can access it.
- */
-static struct usbduxfast_private usbduxfastsub[NUMUSBDUXFAST];
-
-static DEFINE_SEMAPHORE(start_stop_sem);
-
 /*
  * bulk transfers to usbduxfast
  */
@@ -1293,24 +1280,20 @@ static void tidy_up(struct usbduxfast_private *devpriv)
        devpriv->ai_cmd_running = 0;
 }
 
-static int usbduxfast_attach_common(struct comedi_device *dev,
-                                   struct usbduxfast_private *devpriv)
+static int usbduxfast_attach_common(struct comedi_device *dev)
 {
+       struct usbduxfast_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        int ret;
 
        down(&devpriv->sem);
 
-       devpriv->comedidev = dev;
-
        ret = comedi_alloc_subdevices(dev, 1);
        if (ret) {
                up(&devpriv->sem);
                return ret;
        }
 
-       dev->private = devpriv;
-
        /* Analog Input subdevice */
        s = &dev->subdevices[SUBDEV_AD];
        dev->read_subdev = s;
@@ -1332,53 +1315,6 @@ static int usbduxfast_attach_common(struct comedi_device *dev,
        return 0;
 }
 
-static int usbduxfast_auto_attach(struct comedi_device *dev,
-                                 unsigned long context_unused)
-{
-       struct usb_interface *intf = comedi_to_usb_interface(dev);
-       struct usbduxfast_private *devpriv;
-       int ret;
-
-       dev->private = NULL;
-       down(&start_stop_sem);
-       devpriv = usb_get_intfdata(intf);
-       if (!devpriv || !devpriv->probed) {
-               dev_err(dev->class_dev,
-                       "usbduxfast: error: auto_attach failed, not connected\n");
-               ret = -ENODEV;
-       } else if (devpriv->attached) {
-               dev_err(dev->class_dev,
-                      "usbduxfast: error: auto_attach failed, already attached\n");
-               ret = -ENODEV;
-       } else
-               ret = usbduxfast_attach_common(dev, devpriv);
-       up(&start_stop_sem);
-       return ret;
-}
-
-static void usbduxfast_detach(struct comedi_device *dev)
-{
-       struct usbduxfast_private *devpriv = dev->private;
-
-       if (devpriv) {
-               down(&devpriv->sem);
-               down(&start_stop_sem);
-               dev->private = NULL;
-               devpriv->attached = 0;
-               devpriv->comedidev = NULL;
-               tidy_up(devpriv);
-               up(&start_stop_sem);
-               up(&devpriv->sem);
-       }
-}
-
-static struct comedi_driver usbduxfast_driver = {
-       .driver_name    = "usbduxfast",
-       .module         = THIS_MODULE,
-       .auto_attach    = usbduxfast_auto_attach,
-       .detach         = usbduxfast_detach,
-};
-
 static int usbduxfast_request_firmware(struct usb_interface *intf)
 {
        struct usb_device *usb = interface_to_usbdev(intf);
@@ -1396,12 +1332,12 @@ static int usbduxfast_request_firmware(struct usb_interface *intf)
        return ret;
 }
 
-static int usbduxfast_usb_probe(struct usb_interface *intf,
-                               const struct usb_device_id *id)
+static int usbduxfast_auto_attach(struct comedi_device *dev,
+                                 unsigned long context_unused)
 {
+       struct usb_interface *intf = comedi_to_usb_interface(dev);
        struct usb_device *usb = interface_to_usbdev(intf);
-       struct usbduxfast_private *devpriv = NULL;
-       int i;
+       struct usbduxfast_private *devpriv;
        int ret;
 
        if (usb->speed != USB_SPEED_HIGH) {
@@ -1410,24 +1346,13 @@ static int usbduxfast_usb_probe(struct usb_interface *intf,
                return -ENODEV;
        }
 
-       down(&start_stop_sem);
-       /* look for a free place in the usbduxfast array */
-       for (i = 0; i < NUMUSBDUXFAST; i++) {
-               if (!usbduxfastsub[i].probed) {
-                       devpriv = &usbduxfastsub[i];
-                       break;
-               }
-       }
-
-       /* no more space */
-       if (!devpriv) {
-               dev_err(&intf->dev,
-                       "Too many usbduxfast-devices connected.\n");
-               up(&start_stop_sem);
-               return -EMFILE;
-       }
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
 
        sema_init(&devpriv->sem, 1);
+       devpriv->comedidev = dev;
        devpriv->usb = usb;
        devpriv->intf = intf;
        devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber;
@@ -1436,23 +1361,20 @@ static int usbduxfast_usb_probe(struct usb_interface *intf,
        devpriv->dux_commands = kmalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
        if (!devpriv->dux_commands) {
                tidy_up(devpriv);
-               up(&start_stop_sem);
                return -ENOMEM;
        }
 
        devpriv->insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
        if (!devpriv->insnBuffer) {
                tidy_up(devpriv);
-               up(&start_stop_sem);
                return -ENOMEM;
        }
 
-       i = usb_set_interface(devpriv->usb, devpriv->ifnum, 1);
-       if (i < 0) {
+       ret = usb_set_interface(devpriv->usb, devpriv->ifnum, 1);
+       if (ret < 0) {
                dev_err(&intf->dev,
                        "could not switch to alternate setting 1\n");
                tidy_up(devpriv);
-               up(&start_stop_sem);
                return -ENODEV;
        }
 
@@ -1460,19 +1382,16 @@ static int usbduxfast_usb_probe(struct usb_interface *intf,
        if (!devpriv->urbIn) {
                dev_err(&intf->dev, "Could not alloc. urb\n");
                tidy_up(devpriv);
-               up(&start_stop_sem);
                return -ENOMEM;
        }
 
        devpriv->transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
        if (!devpriv->transfer_buffer) {
                tidy_up(devpriv);
-               up(&start_stop_sem);
                return -ENOMEM;
        }
 
        devpriv->probed = 1;
-       up(&start_stop_sem);
 
        /*
         * Request, and upload, the firmware so we can
@@ -1484,6 +1403,32 @@ static int usbduxfast_usb_probe(struct usb_interface *intf,
                return ret;
        }
 
+       return usbduxfast_attach_common(dev);
+}
+
+static void usbduxfast_detach(struct comedi_device *dev)
+{
+       struct usbduxfast_private *devpriv = dev->private;
+
+       if (devpriv) {
+               down(&devpriv->sem);
+               devpriv->attached = 0;
+               devpriv->comedidev = NULL;
+               tidy_up(devpriv);
+               up(&devpriv->sem);
+       }
+}
+
+static struct comedi_driver usbduxfast_driver = {
+       .driver_name    = "usbduxfast",
+       .module         = THIS_MODULE,
+       .auto_attach    = usbduxfast_auto_attach,
+       .detach         = usbduxfast_detach,
+};
+
+static int usbduxfast_usb_probe(struct usb_interface *intf,
+                               const struct usb_device_id *id)
+{
        return comedi_usb_auto_config(intf, &usbduxfast_driver, 0);
 }