diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/comedi/drivers/vmk80xx.c | 163 |
1 files changed, 55 insertions, 108 deletions
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index c20202c5cb77..6ed70eef149c 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -212,10 +212,6 @@ struct vmk80xx_private { unsigned long flags; }; -static struct vmk80xx_private vmb[VMK80XX_MAX_BOARDS]; - -static DEFINE_MUTEX(glb_mutex); - static void vmk80xx_tx_callback(struct urb *urb) { struct vmk80xx_private *devpriv = urb->context; @@ -1131,9 +1127,10 @@ static int vmk80xx_pwm_winsn(struct comedi_device *dev, return n; } -static int vmk80xx_find_usb_endpoints(struct vmk80xx_private *devpriv, - struct usb_interface *intf) +static int vmk80xx_find_usb_endpoints(struct comedi_device *dev) { + struct vmk80xx_private *devpriv = dev->private; + struct usb_interface *intf = devpriv->intf; struct usb_host_interface *iface_desc = intf->cur_altsetting; struct usb_endpoint_descriptor *ep_desc; int i; @@ -1165,8 +1162,9 @@ static int vmk80xx_find_usb_endpoints(struct vmk80xx_private *devpriv, return 0; } -static int vmk80xx_alloc_usb_buffers(struct vmk80xx_private *devpriv) +static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev) { + struct vmk80xx_private *devpriv = dev->private; size_t size; size = le16_to_cpu(devpriv->ep_rx->wMaxPacketSize); @@ -1184,21 +1182,16 @@ static int vmk80xx_alloc_usb_buffers(struct vmk80xx_private *devpriv) return 0; } -static int vmk80xx_attach_common(struct comedi_device *dev, - struct vmk80xx_private *devpriv) +static int vmk80xx_attach_common(struct comedi_device *dev) { - const struct vmk80xx_board *boardinfo; - int n_subd; + const struct vmk80xx_board *boardinfo = comedi_board(dev); + struct vmk80xx_private *devpriv = dev->private; struct comedi_subdevice *s; + int n_subd; int ret; down(&devpriv->limit_sem); - boardinfo = devpriv->board; - dev->board_ptr = boardinfo; - dev->board_name = boardinfo->name; - dev->private = devpriv; - if (boardinfo->model == VMK8055_MODEL) n_subd = 5; else @@ -1283,94 +1276,33 @@ static int vmk80xx_attach_common(struct comedi_device *dev, } static int vmk80xx_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct usb_interface *intf = comedi_to_usb_interface(dev); - int i; - int ret; - - mutex_lock(&glb_mutex); - for (i = 0; i < VMK80XX_MAX_BOARDS; i++) - if (vmb[i].intf == intf) - break; - if (i == VMK80XX_MAX_BOARDS) - ret = -ENODEV; - else - ret = vmk80xx_attach_common(dev, &vmb[i]); - mutex_unlock(&glb_mutex); - return ret; -} - -static void vmk80xx_detach(struct comedi_device *dev) -{ - struct vmk80xx_private *devpriv = dev->private; - - if (!devpriv) - return; - - mutex_lock(&glb_mutex); - down(&devpriv->limit_sem); - - dev->private = NULL; - - usb_set_intfdata(devpriv->intf, NULL); - - usb_kill_anchored_urbs(&devpriv->rx_anchor); - usb_kill_anchored_urbs(&devpriv->tx_anchor); - - kfree(devpriv->usb_rx_buf); - kfree(devpriv->usb_tx_buf); - - up(&devpriv->limit_sem); - - /* - * Since 'devpriv' points to an element of the static vmb array - * we can't kfree it. Instead memset it to all '0' so subsequent - * usb probes don't find any garbage in it. - */ - memset(devpriv, 0x00, sizeof(*devpriv)); - - mutex_unlock(&glb_mutex); -} - -static struct comedi_driver vmk80xx_driver = { - .module = THIS_MODULE, - .driver_name = "vmk80xx", - .auto_attach = vmk80xx_auto_attach, - .detach = vmk80xx_detach, -}; - -static int vmk80xx_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ const struct vmk80xx_board *boardinfo; struct vmk80xx_private *devpriv; int ret; - int i; - - mutex_lock(&glb_mutex); - for (i = 0; i < VMK80XX_MAX_BOARDS; i++) - if (!vmb[i].intf) - break; + boardinfo = &vmk80xx_boardinfo[context]; + dev->board_ptr = boardinfo; + dev->board_name = boardinfo->name; - if (i == VMK80XX_MAX_BOARDS) { - ret = -EMFILE; - goto fail; - } + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + if (!devpriv) + return -ENOMEM; + dev->private = devpriv; - devpriv = &vmb[i]; + devpriv->usb = interface_to_usbdev(intf); + devpriv->intf = intf; + devpriv->board = boardinfo; - ret = vmk80xx_find_usb_endpoints(devpriv, intf); + ret = vmk80xx_find_usb_endpoints(dev); if (ret) - goto error; + return ret; - ret = vmk80xx_alloc_usb_buffers(devpriv); + ret = vmk80xx_alloc_usb_buffers(dev); if (ret) - goto error; - - devpriv->usb = interface_to_usbdev(intf); - devpriv->intf = intf; + return ret; sema_init(&devpriv->limit_sem, 8); init_waitqueue_head(&devpriv->read_wait); @@ -1381,9 +1313,6 @@ static int vmk80xx_usb_probe(struct usb_interface *intf, usb_set_intfdata(intf, devpriv); - boardinfo = &vmk80xx_boardinfo[id->driver_info]; - devpriv->board = boardinfo; - if (boardinfo->model == VMK8061_MODEL) { vmk80xx_read_eeprom(devpriv, IC3_VERSION); dev_info(&intf->dev, "%s\n", devpriv->fw.ic3_vers); @@ -1399,22 +1328,40 @@ static int vmk80xx_usb_probe(struct usb_interface *intf, if (boardinfo->model == VMK8055_MODEL) vmk80xx_reset_device(devpriv); - mutex_unlock(&glb_mutex); + return vmk80xx_attach_common(dev); +} - comedi_usb_auto_config(intf, &vmk80xx_driver, id->driver_info); +static void vmk80xx_detach(struct comedi_device *dev) +{ + struct vmk80xx_private *devpriv = dev->private; - return 0; + if (!devpriv) + return; -error: - /* - * Since 'devpriv' points to an element of the static vmb array - * we can't kfree it. Instead memset it to all '0' so subsequent - * usb probes don't find any garbage in it. - */ - memset(devpriv, 0x00, sizeof(*devpriv)); -fail: - mutex_unlock(&glb_mutex); - return ret; + down(&devpriv->limit_sem); + + usb_set_intfdata(devpriv->intf, NULL); + + usb_kill_anchored_urbs(&devpriv->rx_anchor); + usb_kill_anchored_urbs(&devpriv->tx_anchor); + + kfree(devpriv->usb_rx_buf); + kfree(devpriv->usb_tx_buf); + + up(&devpriv->limit_sem); +} + +static struct comedi_driver vmk80xx_driver = { + .module = THIS_MODULE, + .driver_name = "vmk80xx", + .auto_attach = vmk80xx_auto_attach, + .detach = vmk80xx_detach, +}; + +static int vmk80xx_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return comedi_usb_auto_config(intf, &vmk80xx_driver, id->driver_info); } static const struct usb_device_id vmk80xx_usb_id_table[] = { |