summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH Hartley Sweeten <hsweeten@visionengravers.com>2013-02-05 17:22:27 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-02-05 18:07:10 -0800
commitdb7dabf707f1eb3c4288ca8bedd4b2aa6701ca7b (patch)
treedc1c8a5a867ae7d278107d84195d92ea8e5cf2e3
parent1cc8f8854c86b77637b1300b22e553028c6f2668 (diff)
staging: comedi: vmk80xx: make sure private data is clean when detached
Currently the private data used in this driver is stored in a static array. During the usb (*probe) and empty location is found in this array for use by the usb device. Some initialization of the private data is then done before comedi_usb_auto_config() is called to allow the comedi core to attach its comedi_device to the usb device. The (*probe) can fail for various reasons. If it does, make sure that the private data is clean before returning an error. The usb (*disconnect) simply calls comedi_usb_auto_unconfig() to allow the comedi core to disconnect its comedi_device from the usb device. Since the private data points to the static array it cannot be kfree'ed during the detach. Instead make sure it clean before leaving the detach. 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>
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index ec9ff0d2a4c0..e82319b28992 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -1323,8 +1323,6 @@ static void vmk80xx_detach(struct comedi_device *dev)
dev->private = NULL;
- devpriv->attached = 0;
- devpriv->probed = 0;
usb_set_intfdata(devpriv->intf, NULL);
usb_kill_anchored_urbs(&devpriv->rx_anchor);
@@ -1334,6 +1332,14 @@ static void vmk80xx_detach(struct comedi_device *dev)
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);
}
@@ -1359,25 +1365,19 @@ static int vmk80xx_usb_probe(struct usb_interface *intf,
break;
if (i == VMK80XX_MAX_BOARDS) {
- mutex_unlock(&glb_mutex);
- return -EMFILE;
+ ret = -EMFILE;
+ goto fail;
}
devpriv = &vmb[i];
- memset(devpriv, 0x00, sizeof(*devpriv));
-
ret = vmk80xx_find_usb_endpoints(devpriv, intf);
- if (ret) {
- mutex_unlock(&glb_mutex);
- return ret;
- }
+ if (ret)
+ goto error;
ret = vmk80xx_alloc_usb_buffers(devpriv);
- if (ret) {
- mutex_unlock(&glb_mutex);
- return ret;
- }
+ if (ret)
+ goto error;
devpriv->usb = interface_to_usbdev(intf);
devpriv->intf = intf;
@@ -1416,6 +1416,17 @@ static int vmk80xx_usb_probe(struct usb_interface *intf,
comedi_usb_auto_config(intf, &vmk80xx_driver);
return 0;
+
+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;
}
static const struct usb_device_id vmk80xx_usb_id_table[] = {