aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2009-07-02 05:36:30 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:28 -0400
commit86286883fc8218c81cc1deb04cd1b4a8464bba6f (patch)
tree3db8bad50d4e3b1e16227914e057b7376ef3ad31 /drivers/usb
parent75b48f09e577cbb91d9f2a36bede9a2507929714 (diff)
USB: usbtmc can do IO to device after disconnect
usbtmc will happily complete read/write requests even after disconnect has returned. The fix is to introduce a flag. Signed-off-by: Oliver Neukum <oliver@neukum.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/class/usbtmc.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index b09a527f7341..0c9df97f6775 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -86,6 +86,8 @@ struct usbtmc_device_data {
86 bool TermCharEnabled; 86 bool TermCharEnabled;
87 bool auto_abort; 87 bool auto_abort;
88 88
89 bool zombie; /* fd of disconnected device */
90
89 struct usbtmc_dev_capabilities capabilities; 91 struct usbtmc_dev_capabilities capabilities;
90 struct kref kref; 92 struct kref kref;
91 struct mutex io_mutex; /* only one i/o function running at a time */ 93 struct mutex io_mutex; /* only one i/o function running at a time */
@@ -384,6 +386,10 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
384 return -ENOMEM; 386 return -ENOMEM;
385 387
386 mutex_lock(&data->io_mutex); 388 mutex_lock(&data->io_mutex);
389 if (data->zombie) {
390 retval = -ENODEV;
391 goto exit;
392 }
387 393
388 remaining = count; 394 remaining = count;
389 done = 0; 395 done = 0;
@@ -496,6 +502,10 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
496 return -ENOMEM; 502 return -ENOMEM;
497 503
498 mutex_lock(&data->io_mutex); 504 mutex_lock(&data->io_mutex);
505 if (data->zombie) {
506 retval = -ENODEV;
507 goto exit;
508 }
499 509
500 remaining = count; 510 remaining = count;
501 done = 0; 511 done = 0;
@@ -925,6 +935,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
925 935
926 data = file->private_data; 936 data = file->private_data;
927 mutex_lock(&data->io_mutex); 937 mutex_lock(&data->io_mutex);
938 if (data->zombie) {
939 retval = -ENODEV;
940 goto skip_io_on_zombie;
941 }
928 942
929 switch (cmd) { 943 switch (cmd) {
930 case USBTMC_IOCTL_CLEAR_OUT_HALT: 944 case USBTMC_IOCTL_CLEAR_OUT_HALT:
@@ -952,6 +966,7 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
952 break; 966 break;
953 } 967 }
954 968
969skip_io_on_zombie:
955 mutex_unlock(&data->io_mutex); 970 mutex_unlock(&data->io_mutex);
956 return retval; 971 return retval;
957} 972}
@@ -995,6 +1010,7 @@ static int usbtmc_probe(struct usb_interface *intf,
995 usb_set_intfdata(intf, data); 1010 usb_set_intfdata(intf, data);
996 kref_init(&data->kref); 1011 kref_init(&data->kref);
997 mutex_init(&data->io_mutex); 1012 mutex_init(&data->io_mutex);
1013 data->zombie = 0;
998 1014
999 /* Initialize USBTMC bTag and other fields */ 1015 /* Initialize USBTMC bTag and other fields */
1000 data->bTag = 1; 1016 data->bTag = 1;
@@ -1065,6 +1081,9 @@ static void usbtmc_disconnect(struct usb_interface *intf)
1065 usb_deregister_dev(intf, &usbtmc_class); 1081 usb_deregister_dev(intf, &usbtmc_class);
1066 sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); 1082 sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
1067 sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); 1083 sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
1084 mutex_lock(&data->io_mutex);
1085 data->zombie = 1;
1086 mutex_unlock(&data->io_mutex);
1068 kref_put(&data->kref, usbtmc_delete); 1087 kref_put(&data->kref, usbtmc_delete);
1069} 1088}
1070 1089