mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	usb: usbtmc: Fix ioctl USBTMC_IOCTL_CLEAR
Remove calculation of max_size (=wMaxPacketSize) and wrong condition (actual == max_size) in while loop. A device clear should always flush the complete Bulk-IN FIFO. Insert a sleep of 50 ms between subsequent CHECK_CLEAR_STATUS control requests to avoid stressing the instrument with repeated requests. Some instruments need time to cleanup internal I/O buffers. Polling and nonbraked requests slow down the response time of devices. Use USBTMC_BUFSIZE (4k) instead of USBTMC_SIZE_IOBUFFER (2k). Using USBTMC_SIZE_IOBUFFER is deprecated. Check only bit 0 (field bmClear) of the CHECK_CLEAR_STATUS response, since other bits are reserved and can change in future versions. Signed-off-by: Guido Kiener <guido.kiener@rohde-schwarz.com> Reviewed-by: Steve Bayless <steve_bayless@keysight.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									d7604ff0dc
								
							
						
					
					
						commit
						dfee02ac4b
					
				
					 1 changed files with 18 additions and 28 deletions
				
			
		| 
						 | 
				
			
			@ -1632,20 +1632,17 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
 | 
			
		|||
 | 
			
		||||
static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
 | 
			
		||||
{
 | 
			
		||||
	struct usb_host_interface *current_setting;
 | 
			
		||||
	struct usb_endpoint_descriptor *desc;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	u8 *buffer;
 | 
			
		||||
	int rv;
 | 
			
		||||
	int n;
 | 
			
		||||
	int actual = 0;
 | 
			
		||||
	int max_size;
 | 
			
		||||
 | 
			
		||||
	dev = &data->intf->dev;
 | 
			
		||||
 | 
			
		||||
	dev_dbg(dev, "Sending INITIATE_CLEAR request\n");
 | 
			
		||||
 | 
			
		||||
	buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
 | 
			
		||||
	buffer = kmalloc(USBTMC_BUFSIZE, GFP_KERNEL);
 | 
			
		||||
	if (!buffer)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1653,7 +1650,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
 | 
			
		|||
			     usb_rcvctrlpipe(data->usb_dev, 0),
 | 
			
		||||
			     USBTMC_REQUEST_INITIATE_CLEAR,
 | 
			
		||||
			     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 | 
			
		||||
			     0, 0, buffer, 1, USBTMC_TIMEOUT);
 | 
			
		||||
			     0, 0, buffer, 1, USB_CTRL_GET_TIMEOUT);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
		dev_err(dev, "usb_control_msg returned %d\n", rv);
 | 
			
		||||
		goto exit;
 | 
			
		||||
| 
						 | 
				
			
			@ -1667,22 +1664,6 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
 | 
			
		|||
		goto exit;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	max_size = 0;
 | 
			
		||||
	current_setting = data->intf->cur_altsetting;
 | 
			
		||||
	for (n = 0; n < current_setting->desc.bNumEndpoints; n++) {
 | 
			
		||||
		desc = ¤t_setting->endpoint[n].desc;
 | 
			
		||||
		if (desc->bEndpointAddress == data->bulk_in)
 | 
			
		||||
			max_size = usb_endpoint_maxp(desc);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (max_size == 0) {
 | 
			
		||||
		dev_err(dev, "Couldn't get wMaxPacketSize\n");
 | 
			
		||||
		rv = -EPERM;
 | 
			
		||||
		goto exit;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev_dbg(dev, "wMaxPacketSize is %d\n", max_size);
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
 | 
			
		||||
usbtmc_clear_check_status:
 | 
			
		||||
| 
						 | 
				
			
			@ -1693,7 +1674,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
 | 
			
		|||
			     usb_rcvctrlpipe(data->usb_dev, 0),
 | 
			
		||||
			     USBTMC_REQUEST_CHECK_CLEAR_STATUS,
 | 
			
		||||
			     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 | 
			
		||||
			     0, 0, buffer, 2, USBTMC_TIMEOUT);
 | 
			
		||||
			     0, 0, buffer, 2, USB_CTRL_GET_TIMEOUT);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
		dev_err(dev, "usb_control_msg returned %d\n", rv);
 | 
			
		||||
		goto exit;
 | 
			
		||||
| 
						 | 
				
			
			@ -1710,15 +1691,19 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
 | 
			
		|||
		goto exit;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (buffer[1] == 1)
 | 
			
		||||
	if ((buffer[1] & 1) != 0) {
 | 
			
		||||
		do {
 | 
			
		||||
			dev_dbg(dev, "Reading from bulk in EP\n");
 | 
			
		||||
 | 
			
		||||
			rv = usb_bulk_msg(data->usb_dev,
 | 
			
		||||
					  usb_rcvbulkpipe(data->usb_dev,
 | 
			
		||||
							  data->bulk_in),
 | 
			
		||||
					  buffer, USBTMC_SIZE_IOBUFFER,
 | 
			
		||||
					  &actual, USBTMC_TIMEOUT);
 | 
			
		||||
					  buffer, USBTMC_BUFSIZE,
 | 
			
		||||
					  &actual, USB_CTRL_GET_TIMEOUT);
 | 
			
		||||
 | 
			
		||||
			print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE,
 | 
			
		||||
					     16, 1, buffer, actual, true);
 | 
			
		||||
 | 
			
		||||
			n++;
 | 
			
		||||
 | 
			
		||||
			if (rv < 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1726,10 +1711,15 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
 | 
			
		|||
					rv);
 | 
			
		||||
				goto exit;
 | 
			
		||||
			}
 | 
			
		||||
		} while ((actual == max_size) &&
 | 
			
		||||
		} while ((actual == USBTMC_BUFSIZE) &&
 | 
			
		||||
			  (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
 | 
			
		||||
	} else {
 | 
			
		||||
		/* do not stress device with subsequent requests */
 | 
			
		||||
		msleep(50);
 | 
			
		||||
		n++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (actual == max_size) {
 | 
			
		||||
	if (n >= USBTMC_MAX_READS_TO_CLEAR_BULK_IN) {
 | 
			
		||||
		dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
 | 
			
		||||
			USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
 | 
			
		||||
		rv = -EPERM;
 | 
			
		||||
| 
						 | 
				
			
			@ -1743,7 +1733,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
 | 
			
		|||
	rv = usb_clear_halt(data->usb_dev,
 | 
			
		||||
			    usb_sndbulkpipe(data->usb_dev, data->bulk_out));
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
		dev_err(dev, "usb_control_msg returned %d\n", rv);
 | 
			
		||||
		dev_err(dev, "usb_clear_halt returned %d\n", rv);
 | 
			
		||||
		goto exit;
 | 
			
		||||
	}
 | 
			
		||||
	rv = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue