diff options
Diffstat (limited to 'drivers/usb/class/usbtmc.c')
-rw-r--r-- | drivers/usb/class/usbtmc.c | 19 |
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 | ||
969 | skip_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 | ||