Commit 57cf09ae authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: vmk80xx: push usb (*probe) into comedi (*auto_attach)

Make the usb_driver (*probe) simply call comedi_usb_auto_config()
and move all the (*probe) code into the (*auto_attach) function.

This allows getting rid of the static private data array since we
no longer do part of the initialization in the (*probe) and then
finish it in the (*auto_attach). We can simply kzalloc the private
data instead. The comedi core will then handle the kfree of the
data when the driver is detached.

We can also get rid of the static 'glb_mutex' since this mutex was
only used to protect the static private data array.

Change the parameters for a couple of the helper functions used
during the auto attach. Now that the comedi_device is available
we can simply pass that pointer and get the specific pointers
needed by the helper functions from it.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 55ab4f64
...@@ -212,10 +212,6 @@ struct vmk80xx_private { ...@@ -212,10 +212,6 @@ struct vmk80xx_private {
unsigned long flags; unsigned long flags;
}; };
static struct vmk80xx_private vmb[VMK80XX_MAX_BOARDS];
static DEFINE_MUTEX(glb_mutex);
static void vmk80xx_tx_callback(struct urb *urb) static void vmk80xx_tx_callback(struct urb *urb)
{ {
struct vmk80xx_private *devpriv = urb->context; struct vmk80xx_private *devpriv = urb->context;
...@@ -1131,9 +1127,10 @@ static int vmk80xx_pwm_winsn(struct comedi_device *dev, ...@@ -1131,9 +1127,10 @@ static int vmk80xx_pwm_winsn(struct comedi_device *dev,
return n; return n;
} }
static int vmk80xx_find_usb_endpoints(struct vmk80xx_private *devpriv, static int vmk80xx_find_usb_endpoints(struct comedi_device *dev)
struct usb_interface *intf)
{ {
struct vmk80xx_private *devpriv = dev->private;
struct usb_interface *intf = devpriv->intf;
struct usb_host_interface *iface_desc = intf->cur_altsetting; struct usb_host_interface *iface_desc = intf->cur_altsetting;
struct usb_endpoint_descriptor *ep_desc; struct usb_endpoint_descriptor *ep_desc;
int i; int i;
...@@ -1165,8 +1162,9 @@ static int vmk80xx_find_usb_endpoints(struct vmk80xx_private *devpriv, ...@@ -1165,8 +1162,9 @@ static int vmk80xx_find_usb_endpoints(struct vmk80xx_private *devpriv,
return 0; 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_t size;
size = le16_to_cpu(devpriv->ep_rx->wMaxPacketSize); size = le16_to_cpu(devpriv->ep_rx->wMaxPacketSize);
...@@ -1184,21 +1182,16 @@ static int vmk80xx_alloc_usb_buffers(struct vmk80xx_private *devpriv) ...@@ -1184,21 +1182,16 @@ static int vmk80xx_alloc_usb_buffers(struct vmk80xx_private *devpriv)
return 0; return 0;
} }
static int vmk80xx_attach_common(struct comedi_device *dev, static int vmk80xx_attach_common(struct comedi_device *dev)
struct vmk80xx_private *devpriv)
{ {
const struct vmk80xx_board *boardinfo; const struct vmk80xx_board *boardinfo = comedi_board(dev);
int n_subd; struct vmk80xx_private *devpriv = dev->private;
struct comedi_subdevice *s; struct comedi_subdevice *s;
int n_subd;
int ret; int ret;
down(&devpriv->limit_sem); down(&devpriv->limit_sem);
boardinfo = devpriv->board;
dev->board_ptr = boardinfo;
dev->board_name = boardinfo->name;
dev->private = devpriv;
if (boardinfo->model == VMK8055_MODEL) if (boardinfo->model == VMK8055_MODEL)
n_subd = 5; n_subd = 5;
else else
...@@ -1283,94 +1276,33 @@ static int vmk80xx_attach_common(struct comedi_device *dev, ...@@ -1283,94 +1276,33 @@ static int vmk80xx_attach_common(struct comedi_device *dev,
} }
static int vmk80xx_auto_attach(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); 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; const struct vmk80xx_board *boardinfo;
struct vmk80xx_private *devpriv; struct vmk80xx_private *devpriv;
int ret; int ret;
int i;
mutex_lock(&glb_mutex);
for (i = 0; i < VMK80XX_MAX_BOARDS; i++) boardinfo = &vmk80xx_boardinfo[context];
if (!vmb[i].intf) dev->board_ptr = boardinfo;
break; dev->board_name = boardinfo->name;
if (i == VMK80XX_MAX_BOARDS) { devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
ret = -EMFILE; if (!devpriv)
goto fail; 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) if (ret)
goto error; return ret;
ret = vmk80xx_alloc_usb_buffers(devpriv); ret = vmk80xx_alloc_usb_buffers(dev);
if (ret) if (ret)
goto error; return ret;
devpriv->usb = interface_to_usbdev(intf);
devpriv->intf = intf;
sema_init(&devpriv->limit_sem, 8); sema_init(&devpriv->limit_sem, 8);
init_waitqueue_head(&devpriv->read_wait); init_waitqueue_head(&devpriv->read_wait);
...@@ -1381,9 +1313,6 @@ static int vmk80xx_usb_probe(struct usb_interface *intf, ...@@ -1381,9 +1313,6 @@ static int vmk80xx_usb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, devpriv); usb_set_intfdata(intf, devpriv);
boardinfo = &vmk80xx_boardinfo[id->driver_info];
devpriv->board = boardinfo;
if (boardinfo->model == VMK8061_MODEL) { if (boardinfo->model == VMK8061_MODEL) {
vmk80xx_read_eeprom(devpriv, IC3_VERSION); vmk80xx_read_eeprom(devpriv, IC3_VERSION);
dev_info(&intf->dev, "%s\n", devpriv->fw.ic3_vers); dev_info(&intf->dev, "%s\n", devpriv->fw.ic3_vers);
...@@ -1399,22 +1328,40 @@ static int vmk80xx_usb_probe(struct usb_interface *intf, ...@@ -1399,22 +1328,40 @@ static int vmk80xx_usb_probe(struct usb_interface *intf,
if (boardinfo->model == VMK8055_MODEL) if (boardinfo->model == VMK8055_MODEL)
vmk80xx_reset_device(devpriv); 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: down(&devpriv->limit_sem);
/*
* Since 'devpriv' points to an element of the static vmb array usb_set_intfdata(devpriv->intf, NULL);
* we can't kfree it. Instead memset it to all '0' so subsequent
* usb probes don't find any garbage in it. usb_kill_anchored_urbs(&devpriv->rx_anchor);
*/ usb_kill_anchored_urbs(&devpriv->tx_anchor);
memset(devpriv, 0x00, sizeof(*devpriv));
fail: kfree(devpriv->usb_rx_buf);
mutex_unlock(&glb_mutex); kfree(devpriv->usb_tx_buf);
return ret;
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[] = { static const struct usb_device_id vmk80xx_usb_id_table[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment