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.kie...@rohde-schwarz.com>
Reviewed-by: Steve Bayless <steve_bayl...@keysight.com>
---
 drivers/usb/class/usbtmc.c | 46 +++++++++++++++-----------------------
 1 file changed, 18 insertions(+), 28 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index fa8b17947792..dda5391d01e5 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -1700,20 +1700,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;
 
@@ -1721,7 +1718,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;
@@ -1735,22 +1732,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 = &current_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:
@@ -1761,7 +1742,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;
@@ -1778,15 +1759,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) {
@@ -1794,10 +1779,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;
@@ -1811,7 +1801,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;
-- 
2.17.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to