forked from mirrors/linux
		
	usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_IN
Add parameter 'tag' to function usbtmc_ioctl_abort_bulk_in_tag() for future versions. Remove calculation of max_size (=wMaxPacketSize) and wrong condition (actual == max_size) in while loop. An abort operation should always flush the complete Bulk-IN until a short packet is received. Return error code ENOMSG when transfer (specified by given tag) is not in progress and device returns code USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS. Use USBTMC_BUFSIZE (4k) instead of USBTMC_SIZE_IOBUFFER (2k). Using USBTMC_SIZE_IOBUFFER is deprecated. Use common macro USB_CTRL_GET_TIMEOUT instead of USBTMC_TIMEOUT. Check only bit 0 (field bmAbortBulkIn) of the CHECK_ABORT_BULK_IN_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
							
								
									dfee02ac4b
								
							
						
					
					
						commit
						cbe743f133
					
				
					 1 changed files with 51 additions and 68 deletions
				
			
		| 
						 | 
					@ -270,18 +270,17 @@ static int usbtmc_release(struct inode *inode, struct file *file)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
 | 
					static int usbtmc_ioctl_abort_bulk_in_tag(struct usbtmc_device_data *data,
 | 
				
			||||||
 | 
										  u8 tag)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u8 *buffer;
 | 
						u8 *buffer;
 | 
				
			||||||
	struct device *dev;
 | 
						struct device *dev;
 | 
				
			||||||
	int rv;
 | 
						int rv;
 | 
				
			||||||
	int n;
 | 
						int n;
 | 
				
			||||||
	int actual;
 | 
						int actual;
 | 
				
			||||||
	struct usb_host_interface *current_setting;
 | 
					 | 
				
			||||||
	int max_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev = &data->intf->dev;
 | 
						dev = &data->intf->dev;
 | 
				
			||||||
	buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
 | 
						buffer = kmalloc(USBTMC_BUFSIZE, GFP_KERNEL);
 | 
				
			||||||
	if (!buffer)
 | 
						if (!buffer)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -289,21 +288,34 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
 | 
				
			||||||
			     usb_rcvctrlpipe(data->usb_dev, 0),
 | 
								     usb_rcvctrlpipe(data->usb_dev, 0),
 | 
				
			||||||
			     USBTMC_REQUEST_INITIATE_ABORT_BULK_IN,
 | 
								     USBTMC_REQUEST_INITIATE_ABORT_BULK_IN,
 | 
				
			||||||
			     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
 | 
								     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
 | 
				
			||||||
			     data->bTag_last_read, data->bulk_in,
 | 
								     tag, data->bulk_in,
 | 
				
			||||||
			     buffer, 2, USBTMC_TIMEOUT);
 | 
								     buffer, 2, USB_CTRL_GET_TIMEOUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rv < 0) {
 | 
						if (rv < 0) {
 | 
				
			||||||
		dev_err(dev, "usb_control_msg returned %d\n", rv);
 | 
							dev_err(dev, "usb_control_msg returned %d\n", rv);
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
 | 
						dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x with tag %02x\n",
 | 
				
			||||||
 | 
							buffer[0], buffer[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buffer[0] == USBTMC_STATUS_FAILED) {
 | 
						if (buffer[0] == USBTMC_STATUS_FAILED) {
 | 
				
			||||||
 | 
							/* No transfer in progress and the Bulk-OUT FIFO is empty. */
 | 
				
			||||||
		rv = 0;
 | 
							rv = 0;
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (buffer[0] == USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS) {
 | 
				
			||||||
 | 
							/* The device returns this status if either:
 | 
				
			||||||
 | 
							 * - There is a transfer in progress, but the specified bTag
 | 
				
			||||||
 | 
							 *   does not match.
 | 
				
			||||||
 | 
							 * - There is no transfer in progress, but the Bulk-OUT FIFO
 | 
				
			||||||
 | 
							 *   is not empty.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							rv = -ENOMSG;
 | 
				
			||||||
 | 
							goto exit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buffer[0] != USBTMC_STATUS_SUCCESS) {
 | 
						if (buffer[0] != USBTMC_STATUS_SUCCESS) {
 | 
				
			||||||
		dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n",
 | 
							dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n",
 | 
				
			||||||
			buffer[0]);
 | 
								buffer[0]);
 | 
				
			||||||
| 
						 | 
					@ -311,64 +323,52 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	max_size = 0;
 | 
					 | 
				
			||||||
	current_setting = data->intf->cur_altsetting;
 | 
					 | 
				
			||||||
	for (n = 0; n < current_setting->desc.bNumEndpoints; n++)
 | 
					 | 
				
			||||||
		if (current_setting->endpoint[n].desc.bEndpointAddress ==
 | 
					 | 
				
			||||||
			data->bulk_in)
 | 
					 | 
				
			||||||
			max_size = usb_endpoint_maxp(¤t_setting->endpoint[n].desc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (max_size == 0) {
 | 
					 | 
				
			||||||
		dev_err(dev, "Couldn't get wMaxPacketSize\n");
 | 
					 | 
				
			||||||
		rv = -EPERM;
 | 
					 | 
				
			||||||
		goto exit;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dev_dbg(&data->intf->dev, "wMaxPacketSize is %d\n", max_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	n = 0;
 | 
						n = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do {
 | 
					usbtmc_abort_bulk_in_status:
 | 
				
			||||||
		dev_dbg(dev, "Reading from bulk in EP\n");
 | 
						dev_dbg(dev, "Reading from bulk in EP\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rv = usb_bulk_msg(data->usb_dev,
 | 
						/* Data must be present. So use low timeout 300 ms */
 | 
				
			||||||
				  usb_rcvbulkpipe(data->usb_dev,
 | 
						rv = usb_bulk_msg(data->usb_dev,
 | 
				
			||||||
						  data->bulk_in),
 | 
								  usb_rcvbulkpipe(data->usb_dev,
 | 
				
			||||||
				  buffer, USBTMC_SIZE_IOBUFFER,
 | 
										  data->bulk_in),
 | 
				
			||||||
				  &actual, USBTMC_TIMEOUT);
 | 
								  buffer, USBTMC_BUFSIZE,
 | 
				
			||||||
 | 
								  &actual, 300);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		n++;
 | 
						print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE, 16, 1,
 | 
				
			||||||
 | 
								     buffer, actual, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (rv < 0) {
 | 
						n++;
 | 
				
			||||||
			dev_err(dev, "usb_bulk_msg returned %d\n", rv);
 | 
					
 | 
				
			||||||
 | 
						if (rv < 0) {
 | 
				
			||||||
 | 
							dev_err(dev, "usb_bulk_msg returned %d\n", rv);
 | 
				
			||||||
 | 
							if (rv != -ETIMEDOUT)
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
						}
 | 
				
			||||||
	} while ((actual == max_size) &&
 | 
					 | 
				
			||||||
		 (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (actual == max_size) {
 | 
						if (actual == USBTMC_BUFSIZE)
 | 
				
			||||||
 | 
							goto usbtmc_abort_bulk_in_status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (n >= USBTMC_MAX_READS_TO_CLEAR_BULK_IN) {
 | 
				
			||||||
		dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
 | 
							dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
 | 
				
			||||||
			USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
 | 
								USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
 | 
				
			||||||
		rv = -EPERM;
 | 
							rv = -EPERM;
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	n = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
usbtmc_abort_bulk_in_status:
 | 
					 | 
				
			||||||
	rv = usb_control_msg(data->usb_dev,
 | 
						rv = usb_control_msg(data->usb_dev,
 | 
				
			||||||
			     usb_rcvctrlpipe(data->usb_dev, 0),
 | 
								     usb_rcvctrlpipe(data->usb_dev, 0),
 | 
				
			||||||
			     USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS,
 | 
								     USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS,
 | 
				
			||||||
			     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
 | 
								     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
 | 
				
			||||||
			     0, data->bulk_in, buffer, 0x08,
 | 
								     0, data->bulk_in, buffer, 0x08,
 | 
				
			||||||
			     USBTMC_TIMEOUT);
 | 
								     USB_CTRL_GET_TIMEOUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rv < 0) {
 | 
						if (rv < 0) {
 | 
				
			||||||
		dev_err(dev, "usb_control_msg returned %d\n", rv);
 | 
							dev_err(dev, "usb_control_msg returned %d\n", rv);
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
 | 
						dev_dbg(dev, "CHECK_ABORT_BULK_IN returned %x\n", buffer[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buffer[0] == USBTMC_STATUS_SUCCESS) {
 | 
						if (buffer[0] == USBTMC_STATUS_SUCCESS) {
 | 
				
			||||||
		rv = 0;
 | 
							rv = 0;
 | 
				
			||||||
| 
						 | 
					@ -376,43 +376,26 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buffer[0] != USBTMC_STATUS_PENDING) {
 | 
						if (buffer[0] != USBTMC_STATUS_PENDING) {
 | 
				
			||||||
		dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
 | 
							dev_err(dev, "CHECK_ABORT_BULK_IN returned %x\n", buffer[0]);
 | 
				
			||||||
		rv = -EPERM;
 | 
							rv = -EPERM;
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buffer[1] == 1)
 | 
						if ((buffer[1] & 1) > 0) {
 | 
				
			||||||
		do {
 | 
							/* The device has 1 or more queued packets the Host can read */
 | 
				
			||||||
			dev_dbg(dev, "Reading from bulk in EP\n");
 | 
							goto usbtmc_abort_bulk_in_status;
 | 
				
			||||||
 | 
					 | 
				
			||||||
			rv = usb_bulk_msg(data->usb_dev,
 | 
					 | 
				
			||||||
					  usb_rcvbulkpipe(data->usb_dev,
 | 
					 | 
				
			||||||
							  data->bulk_in),
 | 
					 | 
				
			||||||
					  buffer, USBTMC_SIZE_IOBUFFER,
 | 
					 | 
				
			||||||
					  &actual, USBTMC_TIMEOUT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			n++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (rv < 0) {
 | 
					 | 
				
			||||||
				dev_err(dev, "usb_bulk_msg returned %d\n", rv);
 | 
					 | 
				
			||||||
				goto exit;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} while ((actual == max_size) &&
 | 
					 | 
				
			||||||
			 (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (actual == max_size) {
 | 
					 | 
				
			||||||
		dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
 | 
					 | 
				
			||||||
			USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
 | 
					 | 
				
			||||||
		rv = -EPERM;
 | 
					 | 
				
			||||||
		goto exit;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	goto usbtmc_abort_bulk_in_status;
 | 
						/* The Host must send CHECK_ABORT_BULK_IN_STATUS at a later time. */
 | 
				
			||||||
 | 
						rv = -EAGAIN;
 | 
				
			||||||
exit:
 | 
					exit:
 | 
				
			||||||
	kfree(buffer);
 | 
						kfree(buffer);
 | 
				
			||||||
	return rv;
 | 
						return rv;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return usbtmc_ioctl_abort_bulk_in_tag(data, data->bTag_last_read);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data)
 | 
					static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue