|
@@ -86,6 +86,8 @@ struct usbtmc_device_data {
|
|
|
bool TermCharEnabled;
|
|
|
bool auto_abort;
|
|
|
|
|
|
+ bool zombie; /* fd of disconnected device */
|
|
|
+
|
|
|
struct usbtmc_dev_capabilities capabilities;
|
|
|
struct kref kref;
|
|
|
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,
|
|
|
return -ENOMEM;
|
|
|
|
|
|
mutex_lock(&data->io_mutex);
|
|
|
+ if (data->zombie) {
|
|
|
+ retval = -ENODEV;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
|
|
|
remaining = count;
|
|
|
done = 0;
|
|
@@ -496,6 +502,10 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
|
|
|
return -ENOMEM;
|
|
|
|
|
|
mutex_lock(&data->io_mutex);
|
|
|
+ if (data->zombie) {
|
|
|
+ retval = -ENODEV;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
|
|
|
remaining = count;
|
|
|
done = 0;
|
|
@@ -925,6 +935,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
|
|
|
|
data = file->private_data;
|
|
|
mutex_lock(&data->io_mutex);
|
|
|
+ if (data->zombie) {
|
|
|
+ retval = -ENODEV;
|
|
|
+ goto skip_io_on_zombie;
|
|
|
+ }
|
|
|
|
|
|
switch (cmd) {
|
|
|
case USBTMC_IOCTL_CLEAR_OUT_HALT:
|
|
@@ -952,6 +966,7 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+skip_io_on_zombie:
|
|
|
mutex_unlock(&data->io_mutex);
|
|
|
return retval;
|
|
|
}
|
|
@@ -995,6 +1010,7 @@ static int usbtmc_probe(struct usb_interface *intf,
|
|
|
usb_set_intfdata(intf, data);
|
|
|
kref_init(&data->kref);
|
|
|
mutex_init(&data->io_mutex);
|
|
|
+ data->zombie = 0;
|
|
|
|
|
|
/* Initialize USBTMC bTag and other fields */
|
|
|
data->bTag = 1;
|
|
@@ -1065,6 +1081,9 @@ static void usbtmc_disconnect(struct usb_interface *intf)
|
|
|
usb_deregister_dev(intf, &usbtmc_class);
|
|
|
sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
|
|
|
sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
|
|
|
+ mutex_lock(&data->io_mutex);
|
|
|
+ data->zombie = 1;
|
|
|
+ mutex_unlock(&data->io_mutex);
|
|
|
kref_put(&data->kref, usbtmc_delete);
|
|
|
}
|
|
|
|