Re: ] Sandisk Ultra Fit USB 3.0 thumb drive overheating way more than same USB does in Windows

2018-08-03 Thread Greg KH
On Fri, Aug 03, 2018 at 04:15:22PM +0100, Mustafa A wrote:
> The drive (128GB USB 3.0)
> https://www.sandisk.co.uk/home/usb-flash/ultra-fit-usb overheats to
> the point where the metal part would burn someone if they held it for
> more than a second.
> 
> The overheating only happens on this brand of USB drives, other USB
> 3.0 drives have been fine.
> The overheating only happens with Linux 4.15.0-29 (the default Kubuntu
> 18.04 kernel), it's fine when transferring files in Windows (tried
> with 8.1).
> The overheating happens even when files aren't transferring, even when
> the drive is idle.
> 
> The other hardware used is a HP g6-2205sa laptop (Intel i3-3110M CPU)

I have seen this with some devices before, they just have bad thermal
properties.  Make sure the device is actually going to sleep when idle,
use powertop to make it happen, that seems to work for me and is
probably what Windows does.

Otherwise, no, there's nothing that Linux can do here, as a test, try to
plug the device into a system like a BIOS/UEFI that does not do any
power management and watch it also heat up.

I recommend getting a new device, that's what I did :)

thanks,

greg k-h
--
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


Re: g_mass_storage performance on partition vs. file

2018-08-03 Thread Alan Stern
On Fri, 3 Aug 2018, Martin Hicks wrote:

> 
> Hi,
> 
> I've run into a huge performance gap between running a g_mass_storage
> gadget with the backing file pointing to a raw partition (/dev/mmcblk1)
> vs. creating a file on an ext4 filesystem and exporting that.
> 
> With the partition I see write rates around 5MB/s, and with 
> /proc/sys/vm/block_dump
> enabled I can see that all writes are 512-byte single-sector writes.
> 
> Using a file within ext4fs, I get around 20MB and block_dump shows large IOs
> (mostly 2048 sector).
> 
> Is there any way to get raw-partition to better use caching and not write back
> every sector individually?

g_mass_storage does no buffering internally; the benefit you get with
ext4 comes from buffering within the filesystem.

I have no idea how much or what kind of buffering the block-layer 
drivers do for raw partition accesses.  You're better off asking the 
people responsible for the block layer about that.

Alan Stern

--
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


] Sandisk Ultra Fit USB 3.0 thumb drive overheating way more than same USB does in Windows

2018-08-03 Thread Mustafa A
The drive (128GB USB 3.0)
https://www.sandisk.co.uk/home/usb-flash/ultra-fit-usb overheats to
the point where the metal part would burn someone if they held it for
more than a second.

The overheating only happens on this brand of USB drives, other USB
3.0 drives have been fine.
The overheating only happens with Linux 4.15.0-29 (the default Kubuntu
18.04 kernel), it's fine when transferring files in Windows (tried
with 8.1).
The overheating happens even when files aren't transferring, even when
the drive is idle.

The other hardware used is a HP g6-2205sa laptop (Intel i3-3110M CPU)


g_mass_storage performance on partition vs. file

2018-08-03 Thread Martin Hicks


Hi,

I've run into a huge performance gap between running a g_mass_storage
gadget with the backing file pointing to a raw partition (/dev/mmcblk1)
vs. creating a file on an ext4 filesystem and exporting that.

With the partition I see write rates around 5MB/s, and with 
/proc/sys/vm/block_dump
enabled I can see that all writes are 512-byte single-sector writes.

Using a file within ext4fs, I get around 20MB and block_dump shows large IOs
(mostly 2048 sector).

Is there any way to get raw-partition to better use caching and not write back
every sector individually?

Thanks,
mh

-- 
Martin Hicks P.Eng.|  m...@bork.org
Bork Consulting Inc.   |  +1 (613) 266-2296
--
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


Re: [PATCH] Fix memory issue in non-DMA mode for MUSB gadget

2018-08-03 Thread Bin Liu
Hi,

Please don't top-posting.

On Fri, Aug 03, 2018 at 06:25:50AM +, Alexey Spirkov wrote:
> Hi, Bin,
> 
> Thanks for note, but what do you think - is 'dma_mapping_error'
> checking still needed before call of unmap_dma_buffer? If yes than
> I'll check DMA usage in this check instead of is_buffer_map.

No, unmap_dma_buffer() can be called unconditionally here because
unmap_dma_buffer() already calls is_buffer_mapped() internally.

So my comment below is to remove the 'if' condition check you modified.

Regards,
-Bin.

> 
> Best regards,
> Alexey Spirkov
> 
> -Original Message-
> From: Bin Liu  
> Sent: Thursday, August 2, 2018 7:15 PM
> To: Alexey Spirkov 
> Cc: Greg Kroah-Hartman ; 
> linux-usb@vger.kernel.org; and...@ncrmnt.org
> Subject: Re: [PATCH] Fix memory issue in non-DMA mode for MUSB gadget
> 
> Hi,
> 
> On Thu, Jul 26, 2018 at 12:52:57PM +, Alexey Spirkov wrote:
> > dma_mapping_error function unable to works in PowerPC arch when MUSB 
> > do not use DMA (illegal memory access). Proposed patch replace its 
> > usage to usual define for checking DMA mapping.
> > 
> > Signed-off-by: Alexey Spirkov 
> > ---
> >  drivers/usb/musb/musb_gadget.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/usb/musb/musb_gadget.c 
> > b/drivers/usb/musb/musb_gadget.c index eae8b1b..3bc7c25 100644
> > --- a/drivers/usb/musb/musb_gadget.c
> > +++ b/drivers/usb/musb/musb_gadget.c
> > @@ -140,7 +140,7 @@ __acquires(ep->musb->lock)
> > ep->busy = 1;
> > spin_unlock(>lock);
> >  
> > -   if (!dma_mapping_error(>g.dev, request->dma))
> > +   if (req && is_buffer_mapped(req))
> 
> unmap_dma_buffer() checks for is_buffer_mapped(), so this line can be dropped.
> 
> > unmap_dma_buffer(req, musb);
> >  
> > trace_musb_req_gb(req);
> 
> Regards,
> -Bin.
--
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


RE: [PATCH v2] usb: musb: gadget: Fix big-endian arch issue

2018-08-03 Thread Alexey Spirkov
Hi Andy,

Before my change: 

CHECK   drivers/usb/musb/musb_gadget_ep0.c
drivers/usb/musb/musb_gadget_ep0.c:85:26: warning: cast from restricted __le16
drivers/usb/musb/musb_gadget_ep0.c:220:58: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:227:48: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:237:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:251:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:310:56: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:313:60: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:303:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:303:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:303:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:303:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:303:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:303:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:402:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:415:52: warning: restricted __le16 degrades 
to integer
drivers/usb/musb/musb_gadget_ep0.c:540:22: warning: expression using 
sizeof(void)

After my change:

CHECK   drivers/usb/musb/musb_gadget_ep0.c
drivers/usb/musb/musb_gadget_ep0.c:539:22: warning: expression using 
sizeof(void)

PS: Thanks for hint about endian issues check!

Best regards,
Alexey Spirkov

-Original Message-
From: Andy Shevchenko  
Sent: Friday, August 3, 2018 12:17 PM
To: Alexey Spirkov 
Cc: Bin Liu ; Greg Kroah-Hartman ; 
linux-usb@vger.kernel.org; and...@ncrmnt.org
Subject: Re: [PATCH v2] usb: musb: gadget: Fix big-endian arch issue

On Fri, Aug 3, 2018 at 12:03 PM, Alexey Spirkov  wrote:
> Existing code is not applicable to big-endian machines ctrlrequest 
> fields received in USB endian - i.e. in little-endian and should be 
> converted to cpu endianness before usage.

> -   epnum = (u8) ctrlrequest->wIndex;
> +   epnum = (u8) le16_to_cpu(ctrlrequest->wIndex);

> +   u16 reqval = le16_to_cpu(ctrlrequest->wValue);
> +   u16 reqidx = le16_to_cpu(ctrlrequest->wIndex);

I'm wondering, if you run make with C=1 CF=-D__CHECK_ENDIAN__ before and after 
your change.


--
With Best Regards,
Andy Shevchenko


[PATCH v5 18/22] usb: usbtmc: Update ioctl-number.txt

2018-08-03 Thread Guido Kiener
Reserve a suitable range of ioctl numbers for USBTMC driver.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 Documentation/ioctl/ioctl-number.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 480c8609dc58..810dd6c30296 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -200,7 +200,7 @@ Code  Seq#(hex) Include FileComments
 'X'01  linux/pktcdvd.h conflict!
 'Y'all linux/cyclades.h
 'Z'14-15   drivers/message/fusion/mptctl.h
-'['00-07   linux/usb/tmc.h USB Test and Measurement Devices
+'['00-3F   linux/usb/tmc.h USB Test and Measurement Devices

 'a'all linux/atm*.h, linux/sonet.h ATM on linux

-- 
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


[PATCH v5 21/22] usb: usbtmc: Fix split quoted string in debug message

2018-08-03 Thread Guido Kiener
Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 785eee3a6b89..6aef3447adcc 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -2507,8 +2507,8 @@ static int usbtmc_probe(struct usb_interface *intf,
 
retcode = usb_register_dev(intf, _class);
if (retcode) {
-   dev_err(>dev, "Not able to get a minor"
-   " (base %u, slice default): %d\n", USBTMC_MINOR_BASE,
+   dev_err(>dev, "Not able to get a minor (base %u, slice 
default): %d\n",
+   USBTMC_MINOR_BASE,
retcode);
goto error_register;
}
-- 
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


[PATCH v5 22/22] usb: usbtmc: Remove sysfs group TermChar and auto_abort

2018-08-03 Thread Guido Kiener
As all the properties of the usbtmc driver can now be
controlled on a per file descriptor basis by ioctl functions
the sysfs interface is of limited use.
We are not aware about applications that are using the sysfs
parameter TermChar, TermCharEnabled or auto_abort.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 .../ABI/stable/sysfs-driver-usb-usbtmc| 35 
 drivers/usb/class/usbtmc.c| 84 +--
 2 files changed, 3 insertions(+), 116 deletions(-)

diff --git a/Documentation/ABI/stable/sysfs-driver-usb-usbtmc 
b/Documentation/ABI/stable/sysfs-driver-usb-usbtmc
index e960cd027e1e..a9e123ba32cd 100644
--- a/Documentation/ABI/stable/sysfs-driver-usb-usbtmc
+++ b/Documentation/ABI/stable/sysfs-driver-usb-usbtmc
@@ -25,38 +25,3 @@ Description:
4.2.2.
 
The files are read only.
-
-
-What:  /sys/bus/usb/drivers/usbtmc/*/TermChar
-Date:  August 2008
-Contact:   Greg Kroah-Hartman 
-Description:
-   This file is the TermChar value to be sent to the USB TMC
-   device as described by the document, "Universal Serial Bus Test
-   and Measurement Class Specification
-   (USBTMC) Revision 1.0" as published by the USB-IF.
-
-   Note that the TermCharEnabled file determines if this value is
-   sent to the device or not.
-
-
-What:  /sys/bus/usb/drivers/usbtmc/*/TermCharEnabled
-Date:  August 2008
-Contact:   Greg Kroah-Hartman 
-Description:
-   This file determines if the TermChar is to be sent to the
-   device on every transaction or not.  For more details about
-   this, please see the document, "Universal Serial Bus Test and
-   Measurement Class Specification (USBTMC) Revision 1.0" as
-   published by the USB-IF.
-
-
-What:  /sys/bus/usb/drivers/usbtmc/*/auto_abort
-Date:  August 2008
-Contact:   Greg Kroah-Hartman 
-Description:
-   This file determines if the transaction of the USB TMC
-   device is to be automatically aborted if there is any error.
-   For more details about this, please see the document,
-   "Universal Serial Bus Test and Measurement Class Specification
-   (USBTMC) Revision 1.0" as published by the USB-IF.
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 6aef3447adcc..f8391d41b13d 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -102,11 +102,6 @@ struct usbtmc_device_data {
/* coalesced usb488_caps from usbtmc_dev_capabilities */
__u8 usb488_caps;
 
-   /* attributes from the USB TMC spec for this device */
-   u8 TermChar;
-   bool TermCharEnabled;
-   bool auto_abort;
-
bool zombie; /* fd of disconnected device */
 
struct usbtmc_dev_capabilities  capabilities;
@@ -204,11 +199,10 @@ static int usbtmc_open(struct inode *inode, struct file 
*filp)
 
atomic_set(_data->closing, 0);
 
-   /* copy default values from device settings */
file_data->timeout = USBTMC_TIMEOUT;
-   file_data->term_char = data->TermChar;
-   file_data->term_char_enabled = data->TermCharEnabled;
-   file_data->auto_abort = data->auto_abort;
+   file_data->term_char = '\n';
+   file_data->term_char_enabled = 0;
+   file_data->auto_abort = 0;
file_data->eom_val = 1;
 
INIT_LIST_HEAD(_data->file_elem);
@@ -1859,72 +1853,6 @@ static const struct attribute_group capability_attr_grp 
= {
.attrs = capability_attrs,
 };
 
-static ssize_t TermChar_show(struct device *dev,
-struct device_attribute *attr, char *buf)
-{
-   struct usb_interface *intf = to_usb_interface(dev);
-   struct usbtmc_device_data *data = usb_get_intfdata(intf);
-
-   return sprintf(buf, "%c\n", data->TermChar);
-}
-
-static ssize_t TermChar_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
-   struct usb_interface *intf = to_usb_interface(dev);
-   struct usbtmc_device_data *data = usb_get_intfdata(intf);
-
-   if (count < 1)
-   return -EINVAL;
-   data->TermChar = buf[0];
-   return count;
-}
-static DEVICE_ATTR_RW(TermChar);
-
-#define data_attribute(name)   \
-static ssize_t name##_show(struct device *dev, \
-  struct device_attribute *attr, char *buf)\
-{  \
-   struct usb_interface *intf = to_usb_interface(dev); \
-   struct usbtmc_device_data *data = usb_get_intfdata(intf);   \
-   \
-   return sprintf(buf, "%d\n", 

[PATCH v5 20/22] usb: usbtmc: Remove redundant macro USBTMC_SIZE_IOBUFFER

2018-08-03 Thread Guido Kiener
Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 81144c0c4772..785eee3a6b89 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -30,12 +30,6 @@
 #define USBTMC_HEADER_SIZE 12
 #define USBTMC_MINOR_BASE  176
 
-/*
- * Size of driver internal IO buffer. Must be multiple of 4 and at least as
- * large as wMaxPacketSize (which is usually 512 bytes).
- */
-#define USBTMC_SIZE_IOBUFFER   2048
-
 /* Minimum USB timeout (in milliseconds) */
 #define USBTMC_MIN_TIMEOUT 100
 /* Default USB timeout (in milliseconds) */
-- 
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


[PATCH v5 19/22] usb: usbtmc: Remove redundant code

2018-08-03 Thread Guido Kiener
Remove redundant code and fix debug messages.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c | 25 -
 1 file changed, 8 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index fb49a737ea61..81144c0c4772 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -1753,12 +1753,9 @@ static int usbtmc_ioctl_clear_out_halt(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(>usb_dev->dev, "usb_control_msg returned %d\n",
-   rv);
-   return rv;
-   }
-   return 0;
+   if (rv < 0)
+   dev_err(>usb_dev->dev, "%s returned %d\n", __func__, rv);
+   return rv;
 }
 
 static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data)
@@ -1768,12 +1765,9 @@ static int usbtmc_ioctl_clear_in_halt(struct 
usbtmc_device_data *data)
rv = usb_clear_halt(data->usb_dev,
usb_rcvbulkpipe(data->usb_dev, data->bulk_in));
 
-   if (rv < 0) {
-   dev_err(>usb_dev->dev, "usb_control_msg returned %d\n",
-   rv);
-   return rv;
-   }
-   return 0;
+   if (rv < 0)
+   dev_err(>usb_dev->dev, "%s returned %d\n", __func__, rv);
+   return rv;
 }
 
 static int usbtmc_ioctl_cancel_io(struct usbtmc_file_data *file_data)
@@ -2197,11 +2191,8 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
break;
 
case USBTMC488_IOCTL_GET_CAPS:
-   retval = copy_to_user((void __user *)arg,
-   >usb488_caps,
-   sizeof(data->usb488_caps));
-   if (retval)
-   retval = -EFAULT;
+   retval = put_user(data->usb488_caps,
+ (unsigned char __user *)arg);
break;
 
case USBTMC488_IOCTL_READ_STB:
-- 
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


[PATCH v5 16/22] usb: usbtmc: Replace USBTMC_TIMEOUT macros for control messages

2018-08-03 Thread Guido Kiener
Use common timeout macro USB_CTRL_GET_TIMEOUT (=5s) for all
usb_control_msg() function calls.

The macro USBTMC_TIMEOUT should only be used as default value for
Bulk IN/OUT transfers.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 4609dc0db8a8..91fb2fbf1aeb 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -529,7 +529,7 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data 
*file_data,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
data->iin_bTag,
data->ifnum,
-   buffer, 0x03, USBTMC_TIMEOUT);
+   buffer, 0x03, USB_CTRL_GET_TIMEOUT);
if (rv < 0) {
dev_err(dev, "stb usb_control_msg returned %d\n", rv);
goto exit;
@@ -663,7 +663,7 @@ static int usbtmc488_ioctl_simple(struct usbtmc_device_data 
*data,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wValue,
data->ifnum,
-   buffer, 0x01, USBTMC_TIMEOUT);
+   buffer, 0x01, USB_CTRL_GET_TIMEOUT);
if (rv < 0) {
dev_err(dev, "simple usb_control_msg failed %d\n", rv);
goto exit;
@@ -1810,7 +1810,7 @@ static int get_capabilities(struct usbtmc_device_data 
*data)
rv = usb_control_msg(data->usb_dev, usb_rcvctrlpipe(data->usb_dev, 0),
 USBTMC_REQUEST_GET_CAPABILITIES,
 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-0, 0, buffer, 0x18, USBTMC_TIMEOUT);
+0, 0, buffer, 0x18, USB_CTRL_GET_TIMEOUT);
if (rv < 0) {
dev_err(dev, "usb_control_msg returned %d\n", rv);
goto err_out;
@@ -1949,7 +1949,7 @@ static int usbtmc_ioctl_indicator_pulse(struct 
usbtmc_device_data *data)
 usb_rcvctrlpipe(data->usb_dev, 0),
 USBTMC_REQUEST_INDICATOR_PULSE,
 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-0, 0, buffer, 0x01, USBTMC_TIMEOUT);
+0, 0, buffer, 0x01, USB_CTRL_GET_TIMEOUT);
 
if (rv < 0) {
dev_err(dev, "usb_control_msg returned %d\n", rv);
-- 
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


[PATCH v5 00/22] usb: usbtmc: Changes needed for compatible IVI/VISA library

2018-08-03 Thread Guido Kiener
The working group "VISA for Linux" of the IVI Foundation
www.ivifoundation.org specifies common rules, shared libraries and
drivers to implement the specification of "VPP-4.3: The VISA Library"
on Linux to be compatible with implementations on other operating systems.

The USBTMC protocol is part of the "VISA Library" that is used by many
popular T applications.

Initial implementations for Linux based on libusb has been created.
However using one common USBTMC driver results in more benefits:

- Multiple applications can share access to the same instruments.
- The driver handles SRQ conflicts.
- Simplifies definition of udev rules for USBTMC devices.
- Simplifies development of applications using T instruments.

The following collaborative patches meet the requirements of the IVI
Foundation to implement the library based on the usbtmc driver.

Improvements in the data transfer rate of over 130 MByte/s for
usb 3.x connections have been measured.


V5: Added this version history. No change to patches.

V4: Removed redundant #ifdef CONFIG_COMPAT.

V3: Replaced data pointer of type void* in structs 
usbtmc_ctrlrequest and usbtmc_message with data pointer of
type __u64 to avoid double implementation of ioctls with
different structure sizes for 32 and 64 bit applications.

Following patch is added to usb-next branch:
usb: usbtmc: Add support for 32 bit compat applications

V2: Split patch series into smaller patches.
Add compatible ioctls and structs to support 32 bit applications.
Incorporates feedback from reviewers.

Following patches are added to usb-next branch:
usb: usbtmc: Add ioctl for termination character
usb: usbtmc: Add ioctl for EOM bit
usb: usbtmc: Add ioctl for trigger
usb: usbtmc: Add ioctls to set/get usb timeout
usb: usbtmc: use consistent timeout error
usb: usbtmc: Support Read Status Byte with SRQ per file

V1: usb: usbtmc: Remove rigol_quirk (accepted)
https://patchwork.kernel.org/patch/10407097/

Guido Kiener, Dave Penkler, Steve Bayless (22):
  usb: usbtmc: Add ioctl for generic requests on control
  usb: usbtmc: Add ioctl for vendor specific write
  usb: usbtmc: Add ioctl USBTMC_IOCTL_WRITE_RESULT
  usb: usbtmc: Add ioctl for vendor specific read
  usb: usbtmc: Add ioctl USBTMC_IOCTL_CANCEL_IO
  usb: usbtmc: Add ioctl USBTMC_IOCTL_CLEANUP_IO
  usb: usbtmc: Fix suspend/resume
  usb: usbtmc: Add ioctl USBTMC488_IOCTL_WAIT_SRQ
  usb: usbtmc: add ioctl USBTMC_IOCTL_MSG_IN_ATTR
  usb: usbtmc: Add ioctl USBTMC_IOCTL_AUTO_ABORT
  usb: usbtmc: Optimize usbtmc_write
  usb: usbtmc: Optimize usbtmc_read
  usb: usbtmc: Fix ioctl USBTMC_IOCTL_CLEAR
  usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_IN
  usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_OUT
  usb: usbtmc: Replace USBTMC_TIMEOUT macros for control messages
  usb: usbtmc: Add ioctl USBTMC_IOCTL_API_VERSION
  usb: usbtmc: Update ioctl-number.txt
  usb: usbtmc: Remove redundant code
  usb: usbtmc: Remove redundant macro USBTMC_SIZE_IOBUFFER
  usb: usbtmc: Fix split quoted string in debug message
  usb: usbtmc: Remove sysfs group TermChar and auto_abort


 .../ABI/stable/sysfs-driver-usb-usbtmc|   35 -
 Documentation/ioctl/ioctl-number.txt  |2 +-
 drivers/usb/class/usbtmc.c| 1652 +
 include/uapi/linux/usb/tmc.h  |   41 +
 4 files changed, 1291 insertions(+), 439 deletions(-)

-- 
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


[PATCH v5 08/22] usb: usbtmc: Add ioctl USBTMC488_IOCTL_WAIT_SRQ

2018-08-03 Thread Guido Kiener
Wait until an SRQ (service request) is received on the interrupt pipe
or until the given period of time is expired. In contrast to the
poll() function this ioctl does not return when other (a)synchronous
I/O operations fail with EPOLLERR.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 57 
 include/uapi/linux/usb/tmc.h |  1 +
 2 files changed, 58 insertions(+)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 9953b62b7db4..15421aa71eef 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -130,6 +130,7 @@ struct usbtmc_file_data {
u32timeout;
u8 srq_byte;
atomic_t   srq_asserted;
+   atomic_t   closing;
 
u8 eom_val;
u8 term_char;
@@ -201,6 +202,8 @@ static int usbtmc_open(struct inode *inode, struct file 
*filp)
mutex_lock(>io_mutex);
file_data->data = data;
 
+   atomic_set(_data->closing, 0);
+
/* copy default values from device settings */
file_data->timeout = USBTMC_TIMEOUT;
file_data->term_char = data->TermChar;
@@ -231,6 +234,7 @@ static int usbtmc_flush(struct file *file, fl_owner_t id)
if (file_data == NULL)
return -ENODEV;
 
+   atomic_set(_data->closing, 1);
data = file_data->data;
 
/* wait for io to stop */
@@ -584,6 +588,54 @@ static int usbtmc488_ioctl_read_stb(struct 
usbtmc_file_data *file_data,
return rv;
 }
 
+static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data,
+   __u32 __user *arg)
+{
+   struct usbtmc_device_data *data = file_data->data;
+   struct device *dev = >intf->dev;
+   int rv;
+   u32 timeout;
+   unsigned long expire;
+
+   if (!data->iin_ep_present) {
+   dev_dbg(dev, "no interrupt endpoint present\n");
+   return -EFAULT;
+   }
+
+   if (get_user(timeout, arg))
+   return -EFAULT;
+
+   expire = msecs_to_jiffies(timeout);
+
+   mutex_unlock(>io_mutex);
+
+   rv = wait_event_interruptible_timeout(
+   data->waitq,
+   atomic_read(_data->srq_asserted) != 0 ||
+   atomic_read(_data->closing),
+   expire);
+
+   mutex_lock(>io_mutex);
+
+   /* Note! disconnect or close could be called in the meantime */
+   if (atomic_read(_data->closing) || data->zombie)
+   rv = -ENODEV;
+
+   if (rv < 0) {
+   /* dev can be invalid now! */
+   pr_debug("%s - wait interrupted %d\n", __func__, rv);
+   return rv;
+   }
+
+   if (rv == 0) {
+   dev_dbg(dev, "%s - wait timed out\n", __func__);
+   return -ETIMEDOUT;
+   }
+
+   dev_dbg(dev, "%s - srq asserted\n", __func__);
+   return 0;
+}
+
 static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data,
void __user *arg, unsigned int cmd)
 {
@@ -2150,6 +2202,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
retval = usbtmc488_ioctl_trigger(file_data);
break;
 
+   case USBTMC488_IOCTL_WAIT_SRQ:
+   retval = usbtmc488_ioctl_wait_srq(file_data,
+ (__u32 __user *)arg);
+   break;
+
case USBTMC_IOCTL_CANCEL_IO:
retval = usbtmc_ioctl_cancel_io(file_data);
break;
diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h
index d638c198c7a8..56c76a9680e5 100644
--- a/include/uapi/linux/usb/tmc.h
+++ b/include/uapi/linux/usb/tmc.h
@@ -96,6 +96,7 @@ struct usbtmc_message {
 #define USBTMC488_IOCTL_GOTO_LOCAL _IO(USBTMC_IOC_NR, 20)
 #define USBTMC488_IOCTL_LOCAL_LOCKOUT  _IO(USBTMC_IOC_NR, 21)
 #define USBTMC488_IOCTL_TRIGGER_IO(USBTMC_IOC_NR, 22)
+#define USBTMC488_IOCTL_WAIT_SRQ   _IOW(USBTMC_IOC_NR, 23, __u32)
 
 /* Cancel and cleanup asynchronous calls */
 #define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35)
-- 
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


[PATCH v5 04/22] usb: usbtmc: Add ioctl for vendor specific read

2018-08-03 Thread Guido Kiener
The USBTMC_IOCTL_READ call provides for generic synchronous and
asynchronous reads on bulk IN to implement vendor specific library
routines.

Depending on transfer_size the function submits one or more urbs (up
to 16) each with a size of up to 4kB.

The flag USBTMC_FLAG_IGNORE_TRAILER can be used when the transmission
size is already known. Then the function does not truncate the
transfer_size to a multiple of 4 kB, but does reserve extra space
to receive the final short or zero length packet. Note that the
instrument is allowed to send up to wMaxPacketSize - 1 bytes at the
end of a message to avoid sending a zero length packet.

With flag USBTMC_FLAG_ASYNC the ioctl is non blocking. When no
received data is available, the read function submits as many urbs as
needed to receive transfer_size bytes. However the number of flying
urbs (=4kB) is limited to 16 even with subsequent calls of this ioctl.

Returns -EAGAIN when non blocking and no data is received.
Signals EPOLLIN | EPOLLRDNORM when asynchronous urbs are ready to
be read.

In non blocking mode the usbtmc_message.message pointer may be NULL
and the ioctl just submits urbs to initiate receiving data. However if
data is already available due to a previous non blocking call the ioctl
will return -EINVAL when the message pointer is NULL.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 336 ++-
 include/uapi/linux/usb/tmc.h |   2 +
 2 files changed, 337 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 32aef9e53bc5..5edb548d9122 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -85,6 +85,9 @@ struct usbtmc_device_data {
u8 bTag_last_write; /* needed for abort */
u8 bTag_last_read;  /* needed for abort */
 
+   /* packet size of IN bulk */
+   u16wMaxPacketSize;
+
/* data for interrupt in endpoint handling */
u8 bNotify1;
u8 bNotify2;
@@ -140,6 +143,13 @@ struct usbtmc_file_data {
struct semaphore limit_write_sem;
u32 out_transfer_size;
int out_status;
+
+   /* data for generic_read */
+   u32 in_transfer_size;
+   int in_status;
+   int in_urbs_used;
+   struct usb_anchor in_anchor;
+   wait_queue_head_t wait_bulk_in;
 };
 
 /* Forward declarations */
@@ -181,6 +191,8 @@ static int usbtmc_open(struct inode *inode, struct file 
*filp)
spin_lock_init(_data->err_lock);
sema_init(_data->limit_write_sem, MAX_URBS_IN_FLIGHT);
init_usb_anchor(_data->submitted);
+   init_usb_anchor(_data->in_anchor);
+   init_waitqueue_head(_data->wait_bulk_in);
 
data = usb_get_intfdata(intf);
/* Protect reference to data from file structure until release */
@@ -227,6 +239,9 @@ static int usbtmc_flush(struct file *file, fl_owner_t id)
usbtmc_draw_down(file_data);
 
spin_lock_irq(_data->err_lock);
+   file_data->in_status = 0;
+   file_data->in_transfer_size = 0;
+   file_data->in_urbs_used = 0;
file_data->out_status = 0;
file_data->out_transfer_size = 0;
spin_unlock_irq(_data->err_lock);
@@ -690,6 +705,307 @@ static struct urb *usbtmc_create_urb(void)
return urb;
 }
 
+static void usbtmc_read_bulk_cb(struct urb *urb)
+{
+   struct usbtmc_file_data *file_data = urb->context;
+   int status = urb->status;
+   unsigned long flags;
+
+   /* sync/async unlink faults aren't errors */
+   if (status) {
+   if (!(/* status == -ENOENT || */
+   status == -ECONNRESET ||
+   status == -EREMOTEIO || /* Short packet */
+   status == -ESHUTDOWN))
+   dev_err(_data->data->intf->dev,
+   "%s - nonzero read bulk status received: %d\n",
+   __func__, status);
+
+   spin_lock_irqsave(_data->err_lock, flags);
+   if (!file_data->in_status)
+   file_data->in_status = status;
+   spin_unlock_irqrestore(_data->err_lock, flags);
+   }
+
+   spin_lock_irqsave(_data->err_lock, flags);
+   file_data->in_transfer_size += urb->actual_length;
+   dev_dbg(_data->data->intf->dev,
+   "%s - total size: %u current: %d status: %d\n",
+   __func__, file_data->in_transfer_size,
+   urb->actual_length, status);
+   spin_unlock_irqrestore(_data->err_lock, flags);
+   usb_anchor_urb(urb, _data->in_anchor);
+
+   wake_up_interruptible(_data->wait_bulk_in);
+   wake_up_interruptible(_data->data->waitq);
+}
+
+static inline bool usbtmc_do_transfer(struct usbtmc_file_data *file_data)
+{
+   bool data_or_error;
+
+   spin_lock_irq(_data->err_lock);
+   data_or_error = !usb_anchor_empty(_data->in_anchor)
+   || 

[PATCH v5 10/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_AUTO_ABORT

2018-08-03 Thread Guido Kiener
Add ioctl USBTMC_IOCTL_AUTO_ABORT to configure auto_abort for
each specific file handle.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 23 ---
 include/uapi/linux/usb/tmc.h |  1 +
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 1e7a1dcfcec7..42989c7902a8 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -136,6 +136,7 @@ struct usbtmc_file_data {
u8 eom_val;
u8 term_char;
bool   term_char_enabled;
+   bool   auto_abort;
 
spinlock_t err_lock; /* lock for errors */
 
@@ -209,6 +210,7 @@ static int usbtmc_open(struct inode *inode, struct file 
*filp)
file_data->timeout = USBTMC_TIMEOUT;
file_data->term_char = data->TermChar;
file_data->term_char_enabled = data->TermCharEnabled;
+   file_data->auto_abort = data->auto_abort;
file_data->eom_val = 1;
 
INIT_LIST_HEAD(_data->file_elem);
@@ -1384,7 +1386,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user 
*buf,
retval = send_request_dev_dep_msg_in(file_data, count);
 
if (retval < 0) {
-   if (data->auto_abort)
+   if (file_data->auto_abort)
usbtmc_ioctl_abort_bulk_out(data);
goto exit;
}
@@ -1409,7 +1411,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user 
*buf,
 
if (retval < 0) {
dev_dbg(dev, "Unable to read data, error %d\n", retval);
-   if (data->auto_abort)
+   if (file_data->auto_abort)
usbtmc_ioctl_abort_bulk_in(data);
goto exit;
}
@@ -1419,21 +1421,21 @@ static ssize_t usbtmc_read(struct file *filp, char 
__user *buf,
/* Sanity checks for the header */
if (actual < USBTMC_HEADER_SIZE) {
dev_err(dev, "Device sent too small first 
packet: %u < %u\n", actual, USBTMC_HEADER_SIZE);
-   if (data->auto_abort)
+   if (file_data->auto_abort)
usbtmc_ioctl_abort_bulk_in(data);
goto exit;
}
 
if (buffer[0] != 2) {
dev_err(dev, "Device sent reply with wrong 
MsgID: %u != 2\n", buffer[0]);
-   if (data->auto_abort)
+   if (file_data->auto_abort)
usbtmc_ioctl_abort_bulk_in(data);
goto exit;
}
 
if (buffer[1] != data->bTag_last_write) {
dev_err(dev, "Device sent reply with wrong 
bTag: %u != %u\n", buffer[1], data->bTag_last_write);
-   if (data->auto_abort)
+   if (file_data->auto_abort)
usbtmc_ioctl_abort_bulk_in(data);
goto exit;
}
@@ -1448,7 +1450,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user 
*buf,
 
if (n_characters > this_part) {
dev_err(dev, "Device wants to return more data 
than requested: %u > %zu\n", n_characters, count);
-   if (data->auto_abort)
+   if (file_data->auto_abort)
usbtmc_ioctl_abort_bulk_in(data);
goto exit;
}
@@ -1590,7 +1592,7 @@ static ssize_t usbtmc_write(struct file *filp, const char 
__user *buf,
if (retval < 0) {
dev_err(>intf->dev,
"Unable to send data, error %d\n", retval);
-   if (data->auto_abort)
+   if (file_data->auto_abort)
usbtmc_ioctl_abort_bulk_out(data);
goto exit;
}
@@ -2099,6 +2101,7 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
struct usbtmc_file_data *file_data;
struct usbtmc_device_data *data;
int retval = -EBADRQC;
+   __u8 tmp_byte;
 
file_data = file->private_data;
data = file_data->data;
@@ -2215,6 +2218,12 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
  (__u8 __user *)arg);
break;
 
+   case USBTMC_IOCTL_AUTO_ABORT:
+   retval = get_user(tmp_byte, (unsigned char __user *)arg);
+   if (retval == 0)
+   

[PATCH v5 09/22] usb: usbtmc: add ioctl USBTMC_IOCTL_MSG_IN_ATTR

2018-08-03 Thread Guido Kiener
add ioctl USBTMC_IOCTL_MSG_IN_ATTR that returns the specific
bmTransferAttributes field of the last DEV_DEP_MSG_IN Bulk-IN
header. This header is received by the read() function. The
meaning of the (u8) bitmap bmTransferAttributes is:

Bit 0 = EOM flag is set when the last transfer of a USBTMC
message is received.

Bit 1 = is set when the last byte is a termchar (e.g. '\n').
Note that this bit is always zero when the device does not support
the termchar feature or when termchar detection is not enabled
(see ioctl USBTMC_IOCTL_CONFIG_TERMCHAR).

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 8 
 include/uapi/linux/usb/tmc.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 15421aa71eef..1e7a1dcfcec7 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -131,6 +131,7 @@ struct usbtmc_file_data {
u8 srq_byte;
atomic_t   srq_asserted;
atomic_t   closing;
+   u8 bmTransferAttributes; /* member of DEV_DEP_MSG_IN */
 
u8 eom_val;
u8 term_char;
@@ -1443,6 +1444,8 @@ static ssize_t usbtmc_read(struct file *filp, char __user 
*buf,
   (buffer[6] << 16) +
   (buffer[7] << 24);
 
+   file_data->bmTransferAttributes = buffer[8];
+
if (n_characters > this_part) {
dev_err(dev, "Device wants to return more data 
than requested: %u > %zu\n", n_characters, count);
if (data->auto_abort)
@@ -2207,6 +2210,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
  (__u32 __user *)arg);
break;
 
+   case USBTMC_IOCTL_MSG_IN_ATTR:
+   retval = put_user(file_data->bmTransferAttributes,
+ (__u8 __user *)arg);
+   break;
+
case USBTMC_IOCTL_CANCEL_IO:
retval = usbtmc_ioctl_cancel_io(file_data);
break;
diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h
index 56c76a9680e5..d2ed6a20de6b 100644
--- a/include/uapi/linux/usb/tmc.h
+++ b/include/uapi/linux/usb/tmc.h
@@ -98,6 +98,8 @@ struct usbtmc_message {
 #define USBTMC488_IOCTL_TRIGGER_IO(USBTMC_IOC_NR, 22)
 #define USBTMC488_IOCTL_WAIT_SRQ   _IOW(USBTMC_IOC_NR, 23, __u32)
 
+#define USBTMC_IOCTL_MSG_IN_ATTR   _IOR(USBTMC_IOC_NR, 24, __u8)
+
 /* Cancel and cleanup asynchronous calls */
 #define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35)
 #define USBTMC_IOCTL_CLEANUP_IO_IO(USBTMC_IOC_NR, 36)
-- 
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


[PATCH v5 11/22] usb: usbtmc: Optimize usbtmc_write

2018-08-03 Thread Guido Kiener
Use new usbtmc_generic_write function to maximize bandwidth
during long data transfer.
The maximum output transfer size is limited to INT_MAX (=2GB).

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c | 176 +++--
 1 file changed, 109 insertions(+), 67 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 42989c7902a8..6d5f514b3081 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -1517,94 +1517,136 @@ static ssize_t usbtmc_write(struct file *filp, const 
char __user *buf,
 {
struct usbtmc_file_data *file_data;
struct usbtmc_device_data *data;
+   struct urb *urb = NULL;
+   ssize_t retval = 0;
u8 *buffer;
-   int retval;
-   int actual;
-   unsigned long int n_bytes;
-   int remaining;
-   int done;
-   int this_part;
+   u32 remaining, done;
+   u32 transfersize, aligned, buflen;
 
file_data = filp->private_data;
data = file_data->data;
 
-   buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
-   if (!buffer)
-   return -ENOMEM;
-
mutex_lock(>io_mutex);
+
if (data->zombie) {
retval = -ENODEV;
goto exit;
}
 
-   remaining = count;
done = 0;
 
-   while (remaining > 0) {
-   if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE) {
-   this_part = USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE;
-   buffer[8] = 0;
-   } else {
-   this_part = remaining;
-   buffer[8] = file_data->eom_val;
-   }
-
-   /* Setup IO buffer for DEV_DEP_MSG_OUT message */
-   buffer[0] = 1;
-   buffer[1] = data->bTag;
-   buffer[2] = ~data->bTag;
-   buffer[3] = 0; /* Reserved */
-   buffer[4] = this_part >> 0;
-   buffer[5] = this_part >> 8;
-   buffer[6] = this_part >> 16;
-   buffer[7] = this_part >> 24;
-   /* buffer[8] is set above... */
-   buffer[9] = 0; /* Reserved */
-   buffer[10] = 0; /* Reserved */
-   buffer[11] = 0; /* Reserved */
-
-   if (copy_from_user([USBTMC_HEADER_SIZE], buf + done, 
this_part)) {
-   retval = -EFAULT;
-   goto exit;
-   }
-
-   n_bytes = roundup(USBTMC_HEADER_SIZE + this_part, 4);
-   memset(buffer + USBTMC_HEADER_SIZE + this_part, 0, n_bytes - 
(USBTMC_HEADER_SIZE + this_part));
-
-   do {
-   retval = usb_bulk_msg(data->usb_dev,
- usb_sndbulkpipe(data->usb_dev,
- data->bulk_out),
- buffer, n_bytes,
- , file_data->timeout);
-   if (retval != 0)
-   break;
-   n_bytes -= actual;
-   } while (n_bytes);
-
-   data->bTag_last_write = data->bTag;
+   spin_lock_irq(_data->err_lock);
+   file_data->out_transfer_size = 0;
+   file_data->out_status = 0;
+   spin_unlock_irq(_data->err_lock);
+
+   if (!count)
+   goto exit;
+
+   if (down_trylock(_data->limit_write_sem)) {
+   /* previous calls were async */
+   retval = -EBUSY;
+   goto exit;
+   }
+
+   urb = usbtmc_create_urb();
+   if (!urb) {
+   retval = -ENOMEM;
+   up(_data->limit_write_sem);
+   goto exit;
+   }
+
+   buffer = urb->transfer_buffer;
+   buflen = urb->transfer_buffer_length;
+
+   if (count > INT_MAX) {
+   transfersize = INT_MAX;
+   buffer[8] = 0;
+   } else {
+   transfersize = count;
+   buffer[8] = file_data->eom_val;
+   }
+
+   /* Setup IO buffer for DEV_DEP_MSG_OUT message */
+   buffer[0] = 1;
+   buffer[1] = data->bTag;
+   buffer[2] = ~data->bTag;
+   buffer[3] = 0; /* Reserved */
+   buffer[4] = transfersize >> 0;
+   buffer[5] = transfersize >> 8;
+   buffer[6] = transfersize >> 16;
+   buffer[7] = transfersize >> 24;
+   /* buffer[8] is set above... */
+   buffer[9] = 0; /* Reserved */
+   buffer[10] = 0; /* Reserved */
+   buffer[11] = 0; /* Reserved */
+
+   remaining = transfersize;
+
+   if (transfersize + USBTMC_HEADER_SIZE > buflen) {
+   transfersize = buflen - USBTMC_HEADER_SIZE;
+   aligned = buflen;
+   } else {
+   aligned = (transfersize + (USBTMC_HEADER_SIZE + 3)) & ~3;
+   }
+
+   if (copy_from_user([USBTMC_HEADER_SIZE], buf, transfersize)) {
+   

[PATCH v5 03/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_WRITE_RESULT

2018-08-03 Thread Guido Kiener
ioctl USBTMC_IOCTL_WRITE_RESULT copies current out_transfer_size
to given __u32 pointer and returns current out_status of the last
(asnynchronous) USBTMC_IOCTL_WRITE call.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 25 +
 include/uapi/linux/usb/tmc.h |  1 +
 2 files changed, 26 insertions(+)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index b30935d8af6b..32aef9e53bc5 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -901,6 +901,26 @@ static ssize_t usbtmc_ioctl_generic_write(struct 
usbtmc_file_data *file_data,
return retval;
 }
 
+/*
+ * Get the generic write result
+ */
+static ssize_t usbtmc_ioctl_write_result(struct usbtmc_file_data *file_data,
+   void __user *arg)
+{
+   u32 transferred;
+   int retval;
+
+   spin_lock_irq(_data->err_lock);
+   transferred = file_data->out_transfer_size;
+   retval = file_data->out_status;
+   spin_unlock_irq(_data->err_lock);
+
+   if (put_user(transferred, (__u32 __user *)arg))
+   return -EFAULT;
+
+   return retval;
+}
+
 /*
  * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-OUT endpoint.
  * @transfer_size: number of bytes to request from the device.
@@ -1756,6 +1776,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
(void __user *)arg);
break;
 
+   case USBTMC_IOCTL_WRITE_RESULT:
+   retval = usbtmc_ioctl_write_result(file_data,
+  (void __user *)arg);
+   break;
+
case USBTMC488_IOCTL_GET_CAPS:
retval = copy_to_user((void __user *)arg,
>usb488_caps,
diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h
index 56faeb3b5f0f..4a47b11e4a7e 100644
--- a/include/uapi/linux/usb/tmc.h
+++ b/include/uapi/linux/usb/tmc.h
@@ -86,6 +86,7 @@ struct usbtmc_message {
 #define USBTMC_IOCTL_EOM_ENABLE_IOW(USBTMC_IOC_NR, 11, __u8)
 #define USBTMC_IOCTL_CONFIG_TERMCHAR   _IOW(USBTMC_IOC_NR, 12, struct 
usbtmc_termchar)
 #define USBTMC_IOCTL_WRITE _IOWR(USBTMC_IOC_NR, 13, struct 
usbtmc_message)
+#define USBTMC_IOCTL_WRITE_RESULT  _IOWR(USBTMC_IOC_NR, 15, __u32)
 
 #define USBTMC488_IOCTL_GET_CAPS   _IOR(USBTMC_IOC_NR, 17, unsigned char)
 #define USBTMC488_IOCTL_READ_STB   _IOR(USBTMC_IOC_NR, 18, unsigned char)
-- 
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


[PATCH v5 13/22] usb: usbtmc: Fix ioctl USBTMC_IOCTL_CLEAR

2018-08-03 Thread Guido Kiener
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 
Reviewed-by: Steve Bayless 
---
 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 11225c6d6c69..1903d98f5a18 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -1640,20 +1640,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 = >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;
 
@@ -1661,7 +1658,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;
@@ -1675,22 +1672,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 = _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:
@@ -1701,7 +1682,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;
@@ -1718,15 +1699,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,
- , USBTMC_TIMEOUT);
+ buffer, USBTMC_BUFSIZE,
+ , USB_CTRL_GET_TIMEOUT);
+
+   print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE,
+16, 1, buffer, actual, true);
+
n++;
 
if (rv < 0) {
@@ -1734,10 +1719,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 == 

[PATCH v5 12/22] usb: usbtmc: Optimize usbtmc_read

2018-08-03 Thread Guido Kiener
Use new usbtmc_generic_read function to maximize bandwidth
during long data transfer. Also fix reading of zero length
packet (ZLP) or trailing short packet.
The maximum input transfer size is limited to INT_MAX (=2GB).
Also remove redundant return in send_request_dev_dep_msg_in().

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c | 222 ++---
 1 file changed, 105 insertions(+), 117 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 6d5f514b3081..11225c6d6c69 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -1301,7 +1301,7 @@ static ssize_t usbtmc_ioctl_write_result(struct 
usbtmc_file_data *file_data,
  * Also updates bTag_last_write.
  */
 static int send_request_dev_dep_msg_in(struct usbtmc_file_data *file_data,
-  size_t transfer_size)
+  u32 transfer_size)
 {
struct usbtmc_device_data *data = file_data->data;
int retval;
@@ -1344,12 +1344,11 @@ static int send_request_dev_dep_msg_in(struct 
usbtmc_file_data *file_data,
data->bTag++;
 
kfree(buffer);
-   if (retval < 0) {
-   dev_err(>intf->dev, "usb_bulk_msg in 
send_request_dev_dep_msg_in() returned %d\n", retval);
-   return retval;
-   }
+   if (retval < 0)
+   dev_err(>intf->dev, "%s returned %d\n",
+   __func__, retval);
 
-   return 0;
+   return retval;
 }
 
 static ssize_t usbtmc_read(struct file *filp, char __user *buf,
@@ -1358,20 +1357,20 @@ static ssize_t usbtmc_read(struct file *filp, char 
__user *buf,
struct usbtmc_file_data *file_data;
struct usbtmc_device_data *data;
struct device *dev;
+   const u32 bufsize = USBTMC_BUFSIZE;
u32 n_characters;
u8 *buffer;
int actual;
-   size_t done;
-   size_t remaining;
+   u32 done = 0;
+   u32 remaining;
int retval;
-   size_t this_part;
 
/* Get pointer to private data structure */
file_data = filp->private_data;
data = file_data->data;
dev = >intf->dev;
 
-   buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
+   buffer = kmalloc(bufsize, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
 
@@ -1381,7 +1380,10 @@ static ssize_t usbtmc_read(struct file *filp, char 
__user *buf,
goto exit;
}
 
-   dev_dbg(dev, "usb_bulk_msg_in: count(%zu)\n", count);
+   if (count > INT_MAX)
+   count = INT_MAX;
+
+   dev_dbg(dev, "%s(count:%zu)\n", __func__, count);
 
retval = send_request_dev_dep_msg_in(file_data, count);
 
@@ -1393,114 +1395,100 @@ static ssize_t usbtmc_read(struct file *filp, char 
__user *buf,
 
/* Loop until we have fetched everything we requested */
remaining = count;
-   this_part = remaining;
-   done = 0;
-
-   while (remaining > 0) {
-   /* Send bulk URB */
-   retval = usb_bulk_msg(data->usb_dev,
- usb_rcvbulkpipe(data->usb_dev,
- data->bulk_in),
- buffer, USBTMC_SIZE_IOBUFFER, ,
- file_data->timeout);
-
-   dev_dbg(dev, "usb_bulk_msg: retval(%u), done(%zu), 
remaining(%zu), actual(%d)\n", retval, done, remaining, actual);
-
-   /* Store bTag (in case we need to abort) */
-   data->bTag_last_read = data->bTag;
-
-   if (retval < 0) {
-   dev_dbg(dev, "Unable to read data, error %d\n", retval);
-   if (file_data->auto_abort)
-   usbtmc_ioctl_abort_bulk_in(data);
+
+   /* Send bulk URB */
+   retval = usb_bulk_msg(data->usb_dev,
+ usb_rcvbulkpipe(data->usb_dev,
+ data->bulk_in),
+ buffer, bufsize, ,
+ file_data->timeout);
+
+   dev_dbg(dev, "%s: bulk_msg retval(%u), actual(%d)\n",
+   __func__, retval, actual);
+
+   /* Store bTag (in case we need to abort) */
+   data->bTag_last_read = data->bTag;
+
+   if (retval < 0) {
+   if (file_data->auto_abort)
+   usbtmc_ioctl_abort_bulk_in(data);
+   goto exit;
+   }
+
+   /* Sanity checks for the header */
+   if (actual < USBTMC_HEADER_SIZE) {
+   dev_err(dev, "Device sent too small first packet: %u < %u\n",
+   actual, USBTMC_HEADER_SIZE);
+   if (file_data->auto_abort)
+   usbtmc_ioctl_abort_bulk_in(data);
+   goto exit;
+   }
+
+   if (buffer[0] != 2) {
+   dev_err(dev, "Device sent reply with wrong 

[PATCH v5 17/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_API_VERSION

2018-08-03 Thread Guido Kiener
Add ioctl USBTMC_IOCTL_API_VERSION to get current API version
of usbtmc driver.

This is to allow an instrument library to determine whether
the driver API is compatible with the implementation.

The API may change in future versions. Therefore the macro
USBTMC_API_VERSION should be incremented when changing tmc.h
with new flags, ioctls or when changing a significant behavior
of the driver.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 9 +
 include/uapi/linux/usb/tmc.h | 1 +
 2 files changed, 10 insertions(+)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 91fb2fbf1aeb..fb49a737ea61 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -22,6 +22,10 @@
 #include 
 #include 
 
+/* Increment API VERSION when changing tmc.h with new flags or ioctls
+ * or when changing a significant behavior of the driver.
+ */
+#define USBTMC_API_VERSION (2)
 
 #define USBTMC_HEADER_SIZE 12
 #define USBTMC_MINOR_BASE  176
@@ -2187,6 +2191,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
   (void __user *)arg);
break;
 
+   case USBTMC_IOCTL_API_VERSION:
+   retval = put_user(USBTMC_API_VERSION,
+ (__u32 __user *)arg);
+   break;
+
case USBTMC488_IOCTL_GET_CAPS:
retval = copy_to_user((void __user *)arg,
>usb488_caps,
diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h
index 2435694d3ba5..1d3373922e5e 100644
--- a/include/uapi/linux/usb/tmc.h
+++ b/include/uapi/linux/usb/tmc.h
@@ -89,6 +89,7 @@ struct usbtmc_message {
 #define USBTMC_IOCTL_WRITE _IOWR(USBTMC_IOC_NR, 13, struct 
usbtmc_message)
 #define USBTMC_IOCTL_READ  _IOWR(USBTMC_IOC_NR, 14, struct 
usbtmc_message)
 #define USBTMC_IOCTL_WRITE_RESULT  _IOWR(USBTMC_IOC_NR, 15, __u32)
+#define USBTMC_IOCTL_API_VERSION   _IOR(USBTMC_IOC_NR, 16, __u32)
 
 #define USBTMC488_IOCTL_GET_CAPS   _IOR(USBTMC_IOC_NR, 17, unsigned char)
 #define USBTMC488_IOCTL_READ_STB   _IOR(USBTMC_IOC_NR, 18, unsigned char)
-- 
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


[PATCH v5 06/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_CLEANUP_IO

2018-08-03 Thread Guido Kiener
The ioctl USBTMC_IOCTL_CLEANUP_IO kills all submitted urbs to OUT
and IN bulk, and clears all received data from IN bulk. Internal
transfer counters and error states are reset.

An application should use this ioctl after an asnychronous transfer
was canceled and/or error handling has finished.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 19 +++
 include/uapi/linux/usb/tmc.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index e78176ef0e42..b8a4140bd161 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -1714,6 +1714,21 @@ static int usbtmc_ioctl_cancel_io(struct 
usbtmc_file_data *file_data)
return 0;
 }
 
+static int usbtmc_ioctl_cleanup_io(struct usbtmc_file_data *file_data)
+{
+   usb_kill_anchored_urbs(_data->submitted);
+   usb_scuttle_anchored_urbs(_data->in_anchor);
+   spin_lock_irq(_data->err_lock);
+   file_data->in_status = 0;
+   file_data->in_transfer_size = 0;
+   file_data->out_status = 0;
+   file_data->out_transfer_size = 0;
+   spin_unlock_irq(_data->err_lock);
+
+   file_data->in_urbs_used = 0;
+   return 0;
+}
+
 static int get_capabilities(struct usbtmc_device_data *data)
 {
struct device *dev = >usb_dev->dev;
@@ -2138,6 +2153,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
case USBTMC_IOCTL_CANCEL_IO:
retval = usbtmc_ioctl_cancel_io(file_data);
break;
+
+   case USBTMC_IOCTL_CLEANUP_IO:
+   retval = usbtmc_ioctl_cleanup_io(file_data);
+   break;
}
 
 skip_io_on_zombie:
diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h
index 934991624a28..d638c198c7a8 100644
--- a/include/uapi/linux/usb/tmc.h
+++ b/include/uapi/linux/usb/tmc.h
@@ -99,6 +99,7 @@ struct usbtmc_message {
 
 /* Cancel and cleanup asynchronous calls */
 #define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35)
+#define USBTMC_IOCTL_CLEANUP_IO_IO(USBTMC_IOC_NR, 36)
 
 /* Driver encoded usb488 capabilities */
 #define USBTMC488_CAPABILITY_TRIGGER 1
-- 
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


[PATCH v5 14/22] usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_IN

2018-08-03 Thread Guido Kiener
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 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c | 139 -
 1 file changed, 61 insertions(+), 78 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 1903d98f5a18..c197d8c629f2 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -278,18 +278,17 @@ static int usbtmc_release(struct inode *inode, struct 
file *file)
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;
struct device *dev;
int rv;
int n;
int actual;
-   struct usb_host_interface *current_setting;
-   int max_size;
 
dev = >intf->dev;
-   buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
+   buffer = kmalloc(USBTMC_BUFSIZE, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
 
@@ -297,21 +296,34 @@ static int usbtmc_ioctl_abort_bulk_in(struct 
usbtmc_device_data *data)
 usb_rcvctrlpipe(data->usb_dev, 0),
 USBTMC_REQUEST_INITIATE_ABORT_BULK_IN,
 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
-data->bTag_last_read, data->bulk_in,
-buffer, 2, USBTMC_TIMEOUT);
+tag, data->bulk_in,
+buffer, 2, USB_CTRL_GET_TIMEOUT);
 
if (rv < 0) {
dev_err(dev, "usb_control_msg returned %d\n", rv);
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) {
+   /* No transfer in progress and the Bulk-OUT FIFO is empty. */
rv = 0;
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) {
dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n",
buffer[0]);
@@ -319,64 +331,52 @@ static int usbtmc_ioctl_abort_bulk_in(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++)
-   if (current_setting->endpoint[n].desc.bEndpointAddress ==
-   data->bulk_in)
-   max_size = 
usb_endpoint_maxp(_setting->endpoint[n].desc);
-
-   if (max_size == 0) {
-   dev_err(dev, "Couldn't get wMaxPacketSize\n");
-   rv = -EPERM;
-   goto exit;
-   }
-
-   dev_dbg(>intf->dev, "wMaxPacketSize is %d\n", max_size);
-
-   n = 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,
- , 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);
- 

[PATCH v5 02/22] usb: usbtmc: Add ioctl for vendor specific write

2018-08-03 Thread Guido Kiener
The new ioctl USBTMC_IOCTL_WRITE sends a generic message to bulk OUT.
This ioctl is used for vendor specific or asynchronous I/O as well.

The message is split into chunks of 4k (page size).
Message size is aligned to 32 bit boundaries.

With flag USBTMC_FLAG_ASYNC the ioctl is non blocking.
With flag USBTMC_FLAG_APPEND additional urbs are queued and
out_status/out_transfer_size is not reset. EPOLLOUT | EPOLLWRNORM
is signaled when all submitted urbs are completed.

Flush flying urbs when file handle is closed or device is
suspended or reset.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 376 ++-
 include/uapi/linux/usb/tmc.h |  14 ++
 2 files changed, 388 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index f5603c835336..b30935d8af6b 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -37,6 +37,8 @@
 /* Default USB timeout (in milliseconds) */
 #define USBTMC_TIMEOUT 5000
 
+/* Max number of urbs used in write transfers */
+#define MAX_URBS_IN_FLIGHT 16
 /* I/O buffer size used in generic read/write functions */
 #define USBTMC_BUFSIZE (4096)
 
@@ -125,13 +127,24 @@ struct usbtmc_file_data {
u32timeout;
u8 srq_byte;
atomic_t   srq_asserted;
+
u8 eom_val;
u8 term_char;
bool   term_char_enabled;
+
+   spinlock_t err_lock; /* lock for errors */
+
+   struct usb_anchor submitted;
+
+   /* data for generic_write */
+   struct semaphore limit_write_sem;
+   u32 out_transfer_size;
+   int out_status;
 };
 
 /* Forward declarations */
 static struct usb_driver usbtmc_driver;
+static void usbtmc_draw_down(struct usbtmc_file_data *file_data);
 
 static void __user *u64_to_uptr(u64 value)
 {
@@ -165,6 +178,10 @@ static int usbtmc_open(struct inode *inode, struct file 
*filp)
if (!file_data)
return -ENOMEM;
 
+   spin_lock_init(_data->err_lock);
+   sema_init(_data->limit_write_sem, MAX_URBS_IN_FLIGHT);
+   init_usb_anchor(_data->submitted);
+
data = usb_get_intfdata(intf);
/* Protect reference to data from file structure until release */
kref_get(>kref);
@@ -190,6 +207,36 @@ static int usbtmc_open(struct inode *inode, struct file 
*filp)
return 0;
 }
 
+/*
+ * usbtmc_flush - called before file handle is closed
+ */
+static int usbtmc_flush(struct file *file, fl_owner_t id)
+{
+   struct usbtmc_file_data *file_data;
+   struct usbtmc_device_data *data;
+
+   file_data = file->private_data;
+   if (file_data == NULL)
+   return -ENODEV;
+
+   data = file_data->data;
+
+   /* wait for io to stop */
+   mutex_lock(>io_mutex);
+
+   usbtmc_draw_down(file_data);
+
+   spin_lock_irq(_data->err_lock);
+   file_data->out_status = 0;
+   file_data->out_transfer_size = 0;
+   spin_unlock_irq(_data->err_lock);
+
+   wake_up_interruptible_all(>waitq);
+   mutex_unlock(>io_mutex);
+
+   return 0;
+}
+
 static int usbtmc_release(struct inode *inode, struct file *file)
 {
struct usbtmc_file_data *file_data = file->private_data;
@@ -622,6 +669,238 @@ static int usbtmc488_ioctl_trigger(struct 
usbtmc_file_data *file_data)
return 0;
 }
 
+static struct urb *usbtmc_create_urb(void)
+{
+   const size_t bufsize = USBTMC_BUFSIZE;
+   u8 *dmabuf = NULL;
+   struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
+
+   if (!urb)
+   return NULL;
+
+   dmabuf = kmalloc(bufsize, GFP_KERNEL);
+   if (!dmabuf) {
+   usb_free_urb(urb);
+   return NULL;
+   }
+
+   urb->transfer_buffer = dmabuf;
+   urb->transfer_buffer_length = bufsize;
+   urb->transfer_flags |= URB_FREE_BUFFER;
+   return urb;
+}
+
+static void usbtmc_write_bulk_cb(struct urb *urb)
+{
+   struct usbtmc_file_data *file_data = urb->context;
+   int wakeup = 0;
+   unsigned long flags;
+
+   spin_lock_irqsave(_data->err_lock, flags);
+   file_data->out_transfer_size += urb->actual_length;
+
+   /* sync/async unlink faults aren't errors */
+   if (urb->status) {
+   if (!(urb->status == -ENOENT ||
+   urb->status == -ECONNRESET ||
+   urb->status == -ESHUTDOWN))
+   dev_err(_data->data->intf->dev,
+   "%s - nonzero write bulk status received: %d\n",
+   __func__, urb->status);
+
+   if (!file_data->out_status) {
+   file_data->out_status = urb->status;
+   wakeup = 1;
+   }
+   }
+   spin_unlock_irqrestore(_data->err_lock, flags);
+
+   dev_dbg(_data->data->intf->dev,
+   "%s - write bulk total size: %u\n",
+   

[PATCH v5 01/22] usb: usbtmc: Add ioctl for generic requests on control

2018-08-03 Thread Guido Kiener
Add USBTMC_IOCTL_CTRL_REQUEST to send arbitrary requests on the
control pipe.  Used by specific applications of IVI Foundation,
Inc. to implement VISA API functions: viUsbControlIn/Out.

The maximum length of control request is set to 4k.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 77 
 include/uapi/linux/usb/tmc.h | 15 +++
 2 files changed, 92 insertions(+)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 83ffa5a14c3d..f5603c835336 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany
  * Copyright (C) 2008 Novell, Inc.
  * Copyright (C) 2008 Greg Kroah-Hartman 
+ * Copyright (C) 2018 IVI Foundation, Inc.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -36,6 +37,9 @@
 /* Default USB timeout (in milliseconds) */
 #define USBTMC_TIMEOUT 5000
 
+/* I/O buffer size used in generic read/write functions */
+#define USBTMC_BUFSIZE (4096)
+
 /*
  * Maximum number of read cycles to empty bulk in endpoint during CLEAR and
  * ABORT_BULK_IN requests. Ends the loop if (for whatever reason) a short
@@ -129,6 +133,14 @@ struct usbtmc_file_data {
 /* Forward declarations */
 static struct usb_driver usbtmc_driver;
 
+static void __user *u64_to_uptr(u64 value)
+{
+   if (in_compat_syscall())
+   return compat_ptr(value);
+   else
+   return (void __user *)(unsigned long)value;
+}
+
 static void usbtmc_delete(struct kref *kref)
 {
struct usbtmc_device_data *data = to_usbtmc_data(kref);
@@ -1250,6 +1262,67 @@ static int usbtmc_ioctl_indicator_pulse(struct 
usbtmc_device_data *data)
return rv;
 }
 
+static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+   void __user *arg)
+{
+   struct device *dev = >intf->dev;
+   struct usbtmc_ctrlrequest request;
+   u8 *buffer = NULL;
+   int rv;
+   unsigned long res;
+
+   res = copy_from_user(, arg, sizeof(struct usbtmc_ctrlrequest));
+   if (res)
+   return -EFAULT;
+
+   buffer = kmalloc(request.req.wLength, GFP_KERNEL);
+   if (!buffer)
+   return -ENOMEM;
+
+   if (request.req.wLength > USBTMC_BUFSIZE)
+   return -EMSGSIZE;
+
+   if (request.req.wLength) {
+   buffer = kmalloc(request.req.wLength, GFP_KERNEL);
+   if (!buffer)
+   return -ENOMEM;
+
+   if ((request.req.bRequestType & USB_DIR_IN) == 0) {
+   /* Send control data to device */
+   res = copy_from_user(buffer, u64_to_uptr(request.data),
+request.req.wLength);
+   if (res) {
+   rv = -EFAULT;
+   goto exit;
+   }
+   }
+   }
+
+   rv = usb_control_msg(data->usb_dev,
+   usb_rcvctrlpipe(data->usb_dev, 0),
+   request.req.bRequest,
+   request.req.bRequestType,
+   request.req.wValue,
+   request.req.wIndex,
+   buffer, request.req.wLength, USB_CTRL_GET_TIMEOUT);
+
+   if (rv < 0) {
+   dev_err(dev, "%s failed %d\n", __func__, rv);
+   goto exit;
+   }
+
+   if (rv && (request.req.bRequestType & USB_DIR_IN)) {
+   /* Read control data from device */
+   res = copy_to_user(u64_to_uptr(request.data), buffer, rv);
+   if (res)
+   rv = -EFAULT;
+   }
+
+ exit:
+   kfree(buffer);
+   return rv;
+}
+
 /*
  * Get the usb timeout value
  */
@@ -1366,6 +1439,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
retval = usbtmc_ioctl_abort_bulk_in(data);
break;
 
+   case USBTMC_IOCTL_CTRL_REQUEST:
+   retval = usbtmc_ioctl_request(data, (void __user *)arg);
+   break;
+
case USBTMC_IOCTL_GET_TIMEOUT:
retval = usbtmc_ioctl_get_timeout(file_data,
  (void __user *)arg);
diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h
index 729af2f861a4..95533118ac34 100644
--- a/include/uapi/linux/usb/tmc.h
+++ b/include/uapi/linux/usb/tmc.h
@@ -4,6 +4,7 @@
  * Copyright (C) 2008 Novell, Inc.
  * Copyright (C) 2008 Greg Kroah-Hartman 
  * Copyright (C) 2015 Dave Penkler 
+ * Copyright (C) 2018 IVI Foundation, Inc.
  *
  * This file holds USB constants defined by the USB Device Class
  * and USB488 Subclass Definitions for Test and Measurement devices
@@ -40,6 +41,19 @@
 #define USBTMC488_REQUEST_GOTO_LOCAL   161
 #define USBTMC488_REQUEST_LOCAL_LOCKOUT162
 

[PATCH v5 07/22] usb: usbtmc: Fix suspend/resume

2018-08-03 Thread Guido Kiener
Submitted urbs are not allowed when system is suspended.
Thus the submitted urb waiting at interrupt pipe is killed
during suspend callback and submitted again when system resumes.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index b8a4140bd161..9953b62b7db4 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -2314,7 +2314,9 @@ static void usbtmc_free_int(struct usbtmc_device_data 
*data)
return;
usb_kill_urb(data->iin_urb);
kfree(data->iin_buffer);
+   data->iin_buffer = NULL;
usb_free_urb(data->iin_urb);
+   data->iin_urb = NULL;
kref_put(>kref, usbtmc_delete);
 }
 
@@ -2496,13 +2498,25 @@ static int usbtmc_suspend(struct usb_interface *intf, 
pm_message_t message)
   file_elem);
usbtmc_draw_down(file_data);
}
+
+   if (data->iin_ep_present && data->iin_urb)
+   usb_kill_urb(data->iin_urb);
+
mutex_unlock(>io_mutex);
return 0;
 }
 
 static int usbtmc_resume(struct usb_interface *intf)
 {
-   return 0;
+   struct usbtmc_device_data *data = usb_get_intfdata(intf);
+   int retcode = 0;
+
+   if (data->iin_ep_present && data->iin_urb)
+   retcode = usb_submit_urb(data->iin_urb, GFP_KERNEL);
+   if (retcode)
+   dev_err(>dev, "Failed to submit iin_urb\n");
+
+   return retcode;
 }
 
 static int usbtmc_pre_reset(struct usb_interface *intf)
-- 
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


[PATCH v5 15/22] usb: usbtmc: Fix ioctl USBTMC_IOCTL_ABORT_BULK_OUT

2018-08-03 Thread Guido Kiener
Add parameter 'tag' to function usbtmc_ioctl_abort_bulk_out_tag()
for future versions.

Use USBTMC_BUFSIZE (4k) instead of USBTMC_SIZE_IOBUFFER (2k).
Using USBTMC_SIZE_IOBUFFER is deprecated.

Insert a sleep of 50 ms between subsequent
CHECK_ABORT_BULK_OUT_STATUS control requests to avoid stressing
the instrument with repeated requests.

Use common macro USB_CTRL_GET_TIMEOUT instead of USBTMC_TIMEOUT.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index c197d8c629f2..4609dc0db8a8 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -406,7 +406,8 @@ 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_tag(struct usbtmc_device_data *data,
+  u8 tag)
 {
struct device *dev;
u8 *buffer;
@@ -423,8 +424,8 @@ static int usbtmc_ioctl_abort_bulk_out(struct 
usbtmc_device_data *data)
 usb_rcvctrlpipe(data->usb_dev, 0),
 USBTMC_REQUEST_INITIATE_ABORT_BULK_OUT,
 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
-data->bTag_last_write, data->bulk_out,
-buffer, 2, USBTMC_TIMEOUT);
+tag, data->bulk_out,
+buffer, 2, USB_CTRL_GET_TIMEOUT);
 
if (rv < 0) {
dev_err(dev, "usb_control_msg returned %d\n", rv);
@@ -443,12 +444,14 @@ static int usbtmc_ioctl_abort_bulk_out(struct 
usbtmc_device_data *data)
n = 0;
 
 usbtmc_abort_bulk_out_check_status:
+   /* do not stress device with subsequent requests */
+   msleep(50);
rv = usb_control_msg(data->usb_dev,
 usb_rcvctrlpipe(data->usb_dev, 0),
 USBTMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS,
 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
 0, data->bulk_out, buffer, 0x08,
-USBTMC_TIMEOUT);
+USB_CTRL_GET_TIMEOUT);
n++;
if (rv < 0) {
dev_err(dev, "usb_control_msg returned %d\n", rv);
@@ -482,6 +485,11 @@ static int usbtmc_ioctl_abort_bulk_out(struct 
usbtmc_device_data *data)
return rv;
 }
 
+static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data)
+{
+   return usbtmc_ioctl_abort_bulk_out_tag(data, data->bTag_last_write);
+}
+
 static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data,
void __user *arg)
 {
-- 
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


[PATCH v5 05/22] usb: usbtmc: Add ioctl USBTMC_IOCTL_CANCEL_IO

2018-08-03 Thread Guido Kiener
ioctl USBTMC_IOCTL_CANCEL_IO stops and kills all flying urbs of
last USBTMC_IOCTL_READ and USBTMC_IOCTL_WRITE function calls.
A subsequent call to USBTMC_IOCTL_READ or
USBTMC_IOCTL_WRITE_RESULT returns -ECANCELED with
information about current transferred data.

Signed-off-by: Guido Kiener 
Reviewed-by: Steve Bayless 
---
 drivers/usb/class/usbtmc.c   | 4 
 include/uapi/linux/usb/tmc.h | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 5edb548d9122..e78176ef0e42 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -2134,6 +2134,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
case USBTMC488_IOCTL_TRIGGER:
retval = usbtmc488_ioctl_trigger(file_data);
break;
+
+   case USBTMC_IOCTL_CANCEL_IO:
+   retval = usbtmc_ioctl_cancel_io(file_data);
+   break;
}
 
 skip_io_on_zombie:
diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h
index c75354dfd592..934991624a28 100644
--- a/include/uapi/linux/usb/tmc.h
+++ b/include/uapi/linux/usb/tmc.h
@@ -97,6 +97,9 @@ struct usbtmc_message {
 #define USBTMC488_IOCTL_LOCAL_LOCKOUT  _IO(USBTMC_IOC_NR, 21)
 #define USBTMC488_IOCTL_TRIGGER_IO(USBTMC_IOC_NR, 22)
 
+/* Cancel and cleanup asynchronous calls */
+#define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35)
+
 /* Driver encoded usb488 capabilities */
 #define USBTMC488_CAPABILITY_TRIGGER 1
 #define USBTMC488_CAPABILITY_SIMPLE  2
-- 
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


Re: [PATCH v2] usb: musb: gadget: Fix big-endian arch issue

2018-08-03 Thread Andy Shevchenko
On Fri, Aug 3, 2018 at 12:03 PM, Alexey Spirkov  wrote:
> Existing code is not applicable to big-endian machines
> ctrlrequest fields received in USB endian - i.e. in little-endian
> and should be converted to cpu endianness before usage.

> -   epnum = (u8) ctrlrequest->wIndex;
> +   epnum = (u8) le16_to_cpu(ctrlrequest->wIndex);

> +   u16 reqval = le16_to_cpu(ctrlrequest->wValue);
> +   u16 reqidx = le16_to_cpu(ctrlrequest->wIndex);

I'm wondering, if you run make with C=1 CF=-D__CHECK_ENDIAN__ before
and after your change.


-- 
With Best Regards,
Andy Shevchenko
--
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


[PATCH v2] usb: musb: gadget: Fix big-endian arch issue

2018-08-03 Thread Alexey Spirkov
Existing code is not applicable to big-endian machines
ctrlrequest fields received in USB endian - i.e. in little-endian
and should be converted to cpu endianness before usage.

Signed-off-by: Alexey Spirkov 
---
 drivers/usb/musb/musb_gadget_ep0.c | 29 ++---
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/musb/musb_gadget_ep0.c 
b/drivers/usb/musb/musb_gadget_ep0.c
index 91a5027..90abacb 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -82,7 +82,7 @@ static int service_tx_status_request(
u16 tmp;
void __iomem*regs;

-   epnum = (u8) ctrlrequest->wIndex;
+   epnum = (u8) le16_to_cpu(ctrlrequest->wIndex);
if (!epnum) {
result[0] = 0;
break;
@@ -209,6 +209,8 @@ __acquires(musb->lock)
int handled = -EINVAL;
void __iomem *mbase = musb->mregs;
const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK;
+   u16 reqval = le16_to_cpu(ctrlrequest->wValue);
+   u16 reqidx = le16_to_cpu(ctrlrequest->wIndex);

/* the gadget driver handles everything except what we MUST handle */
if ((ctrlrequest->bRequestType & USB_TYPE_MASK)
@@ -217,15 +219,14 @@ __acquires(musb->lock)
case USB_REQ_SET_ADDRESS:
/* change it after the status stage */
musb->set_address = true;
-   musb->address = (u8) (ctrlrequest->wValue & 0x7f);
+   musb->address = (u8) (reqval & 0x7f);
handled = 1;
break;

case USB_REQ_CLEAR_FEATURE:
switch (recip) {
case USB_RECIP_DEVICE:
-   if (ctrlrequest->wValue
-   != USB_DEVICE_REMOTE_WAKEUP)
+   if (reqval != USB_DEVICE_REMOTE_WAKEUP)
break;
musb->may_wakeup = 0;
handled = 1;
@@ -233,8 +234,7 @@ __acquires(musb->lock)
case USB_RECIP_INTERFACE:
break;
case USB_RECIP_ENDPOINT:{
-   const u8epnum =
-   ctrlrequest->wIndex & 0x0f;
+   const u8epnum = reqidx & 0x0f;
struct musb_ep  *musb_ep;
struct musb_hw_ep   *ep;
struct musb_request *request;
@@ -243,12 +243,12 @@ __acquires(musb->lock)
u16 csr;

if (epnum == 0 || epnum >= MUSB_C_NUM_EPS ||
-   ctrlrequest->wValue != USB_ENDPOINT_HALT)
+   reqval != USB_ENDPOINT_HALT)
break;

ep = musb->endpoints + epnum;
regs = ep->regs;
-   is_in = ctrlrequest->wIndex & USB_DIR_IN;
+   is_in = reqidx & USB_DIR_IN;
if (is_in)
musb_ep = >ep_in;
else
@@ -300,17 +300,17 @@ __acquires(musb->lock)
switch (recip) {
case USB_RECIP_DEVICE:
handled = 1;
-   switch (ctrlrequest->wValue) {
+   switch (reqval) {
case USB_DEVICE_REMOTE_WAKEUP:
musb->may_wakeup = 1;
break;
case USB_DEVICE_TEST_MODE:
if (musb->g.speed != USB_SPEED_HIGH)
goto stall;
-   if (ctrlrequest->wIndex & 0xff)
+   if (reqidx & 0xff)
goto stall;

-   switch (ctrlrequest->wIndex >> 8) {
+   switch (reqidx >> 8) {
case 1:
pr_debug("TEST_J\n");
/* TEST_J */
@@ -398,8 +398,7 @@ __acquires(musb->lock)
break;

case USB_RECIP_ENDPOINT:{
-   const u8epnum =
-   ctrlrequest->wIndex & 0x0f;
+   

Re: [PATCH 2/3] usb: dwc3: gadget: Don't skip updating remaining data

2018-08-03 Thread Felipe Balbi

Hi,

Thinh Nguyen  writes:
> On 8/2/2018 12:46 AM, Felipe Balbi wrote:
>> Hi,
>>
>> Thinh Nguyen  writes:
>>
>> 
>>
 These patches will not fix the issue.

>>> What do you think of this fix?
>>>
>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>> index f452ab708ffc..338f7ab8a8b4 100644
>>> --- a/drivers/usb/dwc3/gadget.c
>>> +++ b/drivers/usb/dwc3/gadget.c
>>> @@ -2277,8 +2277,10 @@ static int
>>> dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
>>>  * with one TRB pending in the ring. We need to manually clear
>>> HWO bit
>>>  * from that TRB.
>>>  */
>>> -   if ((req->zero || req->unaligned) && (trb->ctrl & 
>>> DWC3_TRB_CTRL_HWO)) {
>>> -   trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
>>> +   if ((req->zero || req->unaligned) && !chain) {
>>> +   if (trb->ctrl & DWC3_TRB_CTRL_HWO)
>>> +   trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
>>> +
>>> return 1;
>>> }
>> This is a rathher minimal fix. I like it. So this together with the one
>> I wrote for the TRB type, right? Can you send this one as a proper patch
>> and add the correct Cc stable and Fixes tags?
>>
> Yes. Can you create an official patch for that TRB type issue you found?

Just sent it out, you're on Cc

-- 
balbi


signature.asc
Description: PGP signature


[PATCH] usb: dwc3: gadget: fix ISOC TRB type on unaligned transfers

2018-08-03 Thread Felipe Balbi
When chaining ISOC TRBs together, only the first ISOC TRB should be of
type ISOC_FIRST, all others should be of type ISOC. This patch fixes
that.

Fixes: c6267a51639b ("usb: dwc3: gadget: align transfers to wMaxPacketSize")
Cc:  # v4.11+
Signed-off-by: Felipe Balbi 
---
 drivers/usb/dwc3/gadget.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 032ea7d709ba..2ca52a056e49 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1073,7 +1073,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
/* Now prepare one extra TRB to align transfer size */
trb = >trb_pool[dep->trb_enqueue];
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr,
-   maxp - rem, false, 0,
+   maxp - rem, false, 1,
req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);
@@ -1117,7 +1117,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep 
*dep,
/* Now prepare one extra TRB to align transfer size */
trb = >trb_pool[dep->trb_enqueue];
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem,
-   false, 0, req->request.stream_id,
+   false, 1, req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);
} else if (req->request.zero && req->request.length &&
@@ -1133,7 +1133,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep 
*dep,
/* Now prepare one extra TRB to handle ZLP */
trb = >trb_pool[dep->trb_enqueue];
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
-   false, 0, req->request.stream_id,
+   false, 1, req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);
} else {
-- 
2.16.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


RE: [PATCH] Fix memory issue in non-DMA mode for MUSB gadget

2018-08-03 Thread Alexey Spirkov
Hi, Bin,

Thanks for note, but what do you think - is 'dma_mapping_error' checking still 
needed before call 
of unmap_dma_buffer? If yes than I'll check DMA usage in this check instead of 
is_buffer_map.

Best regards,
Alexey Spirkov

-Original Message-
From: Bin Liu  
Sent: Thursday, August 2, 2018 7:15 PM
To: Alexey Spirkov 
Cc: Greg Kroah-Hartman ; linux-usb@vger.kernel.org; 
and...@ncrmnt.org
Subject: Re: [PATCH] Fix memory issue in non-DMA mode for MUSB gadget

Hi,

On Thu, Jul 26, 2018 at 12:52:57PM +, Alexey Spirkov wrote:
> dma_mapping_error function unable to works in PowerPC arch when MUSB 
> do not use DMA (illegal memory access). Proposed patch replace its 
> usage to usual define for checking DMA mapping.
> 
> Signed-off-by: Alexey Spirkov 
> ---
>  drivers/usb/musb/musb_gadget.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/musb/musb_gadget.c 
> b/drivers/usb/musb/musb_gadget.c index eae8b1b..3bc7c25 100644
> --- a/drivers/usb/musb/musb_gadget.c
> +++ b/drivers/usb/musb/musb_gadget.c
> @@ -140,7 +140,7 @@ __acquires(ep->musb->lock)
>   ep->busy = 1;
>   spin_unlock(>lock);
>  
> - if (!dma_mapping_error(>g.dev, request->dma))
> + if (req && is_buffer_mapped(req))

unmap_dma_buffer() checks for is_buffer_mapped(), so this line can be dropped.

>   unmap_dma_buffer(req, musb);
>  
>   trace_musb_req_gb(req);

Regards,
-Bin.
--
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