diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index a83b2b5bcf189f3c1eb643e85ba939819d448449..9f6a0e930d94cd685b1980aa15888d594540c53f 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -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); }