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 {  	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);  }  | 
