Re: 3.2.63-longterm: unloading vhci-hcd tries to free already-free IRQ 0

2014-10-09 Thread Thomas Pugliese


On Thu, 9 Oct 2014, Thomas Bork wrote:

 Hi @all,
 
 loading and unloading vhci-hcd in 3.2.63-longterm produces a warning in syslog
 (Trying to free already-free IRQ 0). I know vhci-hcd is staging but
 backporting as much as possible changes of usbip from 3.16.4 (without the
 switch to udev) changed nothing to this warning.
 
 I tested kernel 3.16.4. This one don't show this behavior.
 
 So:
 I'm not good enough to find the right fix for this in the commits in 3.16.4.
 Maybe anybody has an idea? I cannot switch to 3.16.4 right now.
 
 

Hi Tom, 
I actually ran into this same issue a while back when porting WUSB updates 
back to older kernels.  The commit that fixes the warning is 
cd70469d084fde198dc07c1a31b8463562228a5a from Linus' tree.  If that 
doesn't apply cleanly, you could also change the second parameter passed 
to usb_add_hcd in vhci_hcd_probe from 0 to -1.  Hope this helps.

Regards,
Tom
--
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 1/3] uwb: line length cleanup

2014-09-16 Thread Thomas Pugliese
Fix line length in uwb-internal.h

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/uwb-internal.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h
index 9a103b1..6d1bed1 100644
--- a/drivers/uwb/uwb-internal.h
+++ b/drivers/uwb/uwb-internal.h
@@ -172,7 +172,8 @@ struct uwb_rsv_alloc_info {
int interval;
 };
 
-int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv, struct uwb_mas_bm 
*available, 
+int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv,
+struct uwb_mas_bm *available,
 struct uwb_mas_bm *result);
 void uwb_rsv_handle_drp_avail_change(struct uwb_rc *rc);
 /*
-- 
1.8.3.2

--
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 3/3] uwb: remove UWB build dependency on PCI

2014-09-16 Thread Thomas Pugliese
UWB does not require PCI to be enabled so remove build dependency.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/uwb/Kconfig b/drivers/uwb/Kconfig
index 2431eed..c204094 100644
--- a/drivers/uwb/Kconfig
+++ b/drivers/uwb/Kconfig
@@ -4,7 +4,6 @@
 
 menuconfig UWB
tristate Ultra Wideband devices
-   depends on PCI
default n
help
  UWB is a high-bandwidth, low-power, point-to-point radio
-- 
1.8.3.2

--
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 2/3] uwb: update uwb device prints to be more useful

2014-09-16 Thread Thomas Pugliese
Print info about the radio controller device instead of the its parent
when UWB devices connect and disconnect.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/lc-dev.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c
index d0303f0..ba76810 100644
--- a/drivers/uwb/lc-dev.c
+++ b/drivers/uwb/lc-dev.c
@@ -365,8 +365,8 @@ int __uwb_dev_offair(struct uwb_dev *uwb_dev, struct uwb_rc 
*rc)
uwb_dev_addr_print(devbuf, sizeof(devbuf), uwb_dev-dev_addr);
dev_info(dev, uwb device (mac %s dev %s) disconnected from %s %s\n,
 macbuf, devbuf,
-rc ? rc-uwb_dev.dev.parent-bus-name : n/a,
-rc ? dev_name(rc-uwb_dev.dev.parent) : );
+uwb_dev-dev.bus-name,
+rc ? dev_name((rc-uwb_dev.dev)) : );
uwb_dev_rm(uwb_dev);
list_del(uwb_dev-bce-node);
uwb_bce_put(uwb_dev-bce);
@@ -445,8 +445,8 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e 
*bce)
}
 
dev_info(dev, uwb device (mac %s dev %s) connected to %s %s\n,
-macbuf, devbuf, rc-uwb_dev.dev.parent-bus-name,
-dev_name(rc-uwb_dev.dev.parent));
+macbuf, devbuf, uwb_dev-dev.bus-name,
+dev_name((rc-uwb_dev.dev)));
uwb_notify(rc, uwb_dev, UWB_NOTIF_ONAIR);
return;
 
-- 
1.8.3.2

--
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 0/3] uwb: minor cleanups

2014-09-16 Thread Thomas Pugliese
Some UWB cleanups for 3.18

Thomas Pugliese (3):
  uwb: line length cleanup
  uwb: update uwb device prints to be more useful
  uwb: remove UWB build dependency on PCI

 drivers/uwb/Kconfig| 1 -
 drivers/uwb/lc-dev.c   | 8 
 drivers/uwb/uwb-internal.h | 3 ++-
 3 files changed, 6 insertions(+), 6 deletions(-)

-- 
1.8.3.2

--
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 1/2] uwb: create a uwb bus type and add in-range peer devices to it

2014-09-16 Thread Thomas Pugliese
Documentation/usb/WUSB-Design-overview.txt states that UWB devices seen 
by a UWB radio controller are added to /sys/bus/uwb/devices, but this 
was not actually being done.  This functionality is needed in order for 
UWB peer devices to be enumerated by user mode tools.  This patch 
creates a uwb bus type and adds UWB peer devices to it as they are 
discovered by the radio controller.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/driver.c   | 11 +++
 drivers/uwb/lc-dev.c   | 11 +++
 drivers/uwb/uwb-internal.h |  1 +
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c
index 3e5454a..776bcb3 100644
--- a/drivers/uwb/driver.c
+++ b/drivers/uwb/driver.c
@@ -121,9 +121,19 @@ static int __init uwb_subsys_init(void)
result = class_register(uwb_rc_class);
if (result  0)
goto error_uwb_rc_class_register;
+
+   /* Register the UWB bus */
+   result = bus_register(uwb_bus_type);
+   if (result) {
+   pr_err(%s - registering bus driver failed\n, __func__);
+   goto exit_bus;
+   }
+
uwb_dbg_init();
return 0;
 
+exit_bus:
+   class_unregister(uwb_rc_class);
 error_uwb_rc_class_register:
uwb_est_destroy();
 error_est_init:
@@ -134,6 +144,7 @@ module_init(uwb_subsys_init);
 static void __exit uwb_subsys_exit(void)
 {
uwb_dbg_exit();
+   bus_unregister(uwb_bus_type);
class_unregister(uwb_rc_class);
uwb_est_destroy();
return;
diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c
index ba76810..8c7cfab 100644
--- a/drivers/uwb/lc-dev.c
+++ b/drivers/uwb/lc-dev.c
@@ -255,6 +255,12 @@ static struct attribute *uwb_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(uwb_dev);
 
+/* UWB bus type. */
+struct bus_type uwb_bus_type = {
+   .name = uwb,
+   .dev_groups =   uwb_dev_groups,
+};
+
 /**
  * Device SYSFS registration
  */
@@ -263,10 +269,6 @@ static int __uwb_dev_sys_add(struct uwb_dev *uwb_dev, 
struct device *parent_dev)
struct device *dev;
 
dev = uwb_dev-dev;
-   /* Device sysfs files are only useful for neighbor devices not
-  local radio controllers. */
-   if (uwb_dev-rc-uwb_dev != uwb_dev)
-   dev-groups = uwb_dev_groups;
dev-parent = parent_dev;
dev_set_drvdata(dev, uwb_dev);
 
@@ -428,6 +430,7 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e 
*bce)
return;
}
uwb_dev_init(uwb_dev);  /* This sets refcnt to one, we own it */
+   uwb_dev-dev.bus = uwb_bus_type;
uwb_dev-mac_addr = *bce-mac_addr;
uwb_dev-dev_addr = bce-dev_addr;
dev_set_name(uwb_dev-dev, %s, macbuf);
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h
index 6d1bed1..353c055 100644
--- a/drivers/uwb/uwb-internal.h
+++ b/drivers/uwb/uwb-internal.h
@@ -314,6 +314,7 @@ int uwb_radio_force_channel(struct uwb_rc *rc, int channel);
 
 /* -- UWB Sysfs representation */
 extern struct class uwb_rc_class;
+extern struct bus_type uwb_bus_type;
 extern struct device_attribute dev_attr_mac_address;
 extern struct device_attribute dev_attr_beacon;
 extern struct device_attribute dev_attr_scan;
-- 
1.8.3.2

--
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 2/2] uwb: doc: bring uwb documentation up to date

2014-09-16 Thread Thomas Pugliese
The existing UWB documentation states that UWB devices show up in
/sys/class/uwb and /sys/bus/uwb/devices.  Up until the most recent
changes to add uwb devices to their own bus, neither of these statements
were actually true.  Now, UWB devices do show up in /sys/bus/uwb/devices
so the documentation has been updated to reflect that and removed
references to /sys/class/uwb.

The existing documentation also states that local UWB radio controller
(RC) devices also show up as UWB devices along with their wireless peer
UWB devices under /sys/class/uwb.  This is not true so that statement
has been removed.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 Documentation/usb/WUSB-Design-overview.txt | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/Documentation/usb/WUSB-Design-overview.txt 
b/Documentation/usb/WUSB-Design-overview.txt
index 1cd07c0..512238c 100644
--- a/Documentation/usb/WUSB-Design-overview.txt
+++ b/Documentation/usb/WUSB-Design-overview.txt
@@ -161,19 +161,10 @@ now on), such as to start/stop beaconing, scan, allocate 
bandwidth, etc.
 The main building block here is the UWB device (struct uwb_dev). For
 each device that pops up in radio presence (ie: the UWB host receives a
 beacon from it) you get a struct uwb_dev that will show up in
-/sys/class/uwb and in /sys/bus/uwb/devices.
+/sys/bus/uwb/devices.
 
-For each RC that is detected, a new struct uwb_rc is created. In turn, a
-RC is also a device, so they also show in /sys/class/uwb and
-/sys/bus/uwb/devices, but at the same time, only radio controllers show
-up in /sys/class/uwb_rc.
-
-*
-
-  [*] The reason for RCs being also devices is that not only we can
-  see them while enumerating the system device tree, but also on the
-  radio (their beacons and stuff), so the handling has to be
-  likewise to that of a device.
+For each RC that is detected, a new struct uwb_rc and struct uwb_dev are
+created. An entry is also created in /sys/class/uwb_rc for each RC.
 
 Each RC driver is implemented by a separate driver that plugs into the
 interface that the UWB stack provides through a struct uwb_rc_ops. The
@@ -246,7 +237,7 @@ the beacon cache of dead devices].
 
   Device lists
 
-All UWB devices are kept in the list of the struct bus_type uwb_bus.
+All UWB devices are kept in the list of the struct bus_type uwb_bus_type.
 
 
   Bandwidth allocation
-- 
1.8.3.2

--
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 0/2] uwb: add a bus for uwb devices

2014-09-16 Thread Thomas Pugliese
Create a system bus for UWB devices and add in-range UWB devices to it 
as they are detected.  Prior to this change, UWB devices were added to 
the device tree, but since they did not exist on a bus, they would be 
enumerated by udev.

Thomas Pugliese (2):
  uwb: create a uwb bus type and add in-range peer devices to it
  uwb: doc: bring uwb documentation up to date

 Documentation/usb/WUSB-Design-overview.txt | 17 -
 drivers/uwb/driver.c   | 11 +++
 drivers/uwb/lc-dev.c   | 11 +++
 drivers/uwb/uwb-internal.h |  1 +
 4 files changed, 23 insertions(+), 17 deletions(-)

-- 
1.8.3.2

--
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 0/2] add an ASIE sysfs attribute to uwb_rc devices

2014-09-16 Thread Thomas Pugliese
Add an ASIE sysfs attribute to uwb_rc devices.  This allows user mode to 
add and remove application specific information elements (ASIEs) to the 
beacon of a uwb_rc device.

Thomas Pugliese (2):
  uwb: add an ASIE sysfs attribute to uwb_rc devices
  uwb: doc: add documentation for ASIE sysfs attribute

 Documentation/ABI/testing/sysfs-class-uwb_rc | 13 
 drivers/uwb/lc-rc.c  | 99 
 2 files changed, 112 insertions(+)

-- 
1.8.3.2

--
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 2/2] uwb: doc: add documentation for ASIE sysfs attribute

2014-09-16 Thread Thomas Pugliese
Document the /sys/class/uwb_rc/uwbN/ASIE sysfs attribute

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 Documentation/ABI/testing/sysfs-class-uwb_rc | 13 +
 1 file changed, 13 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc 
b/Documentation/ABI/testing/sysfs-class-uwb_rc
index 6a5fd07..85f4875 100644
--- a/Documentation/ABI/testing/sysfs-class-uwb_rc
+++ b/Documentation/ABI/testing/sysfs-class-uwb_rc
@@ -43,6 +43,19 @@ Description:
 Reading returns the currently active channel, or -1 if
 the radio controller is not beaconing.
 
+What:   /sys/class/uwb_rc/uwbN/ASIE
+Date:   August 2014
+KernelVersion:  3.18
+Contact:linux-usb@vger.kernel.org
+Description:
+
+The application-specific information element (ASIE)
+included in this device's beacon, in space separated
+hex octets.
+
+Reading returns the current ASIE.  Writing replaces
+the current ASIE with the one written.
+
 What:   /sys/class/uwb_rc/uwbN/scan
 Date:   July 2008
 KernelVersion:  2.6.27
-- 
1.8.3.2

--
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 1/2] uwb: add an ASIE sysfs attribute to uwb_rc devices

2014-09-16 Thread Thomas Pugliese
Allow user mode to add and remove application specific information
elements (ASIEs) to the beacon of a uwb_rc device.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/lc-rc.c | 99 +
 1 file changed, 99 insertions(+)

diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c
index 3eca6ce..d059ad4 100644
--- a/drivers/uwb/lc-rc.c
+++ b/drivers/uwb/lc-rc.c
@@ -119,10 +119,109 @@ struct uwb_rc *uwb_rc_alloc(void)
 }
 EXPORT_SYMBOL_GPL(uwb_rc_alloc);
 
+/*
+ * Show the ASIE that is broadcast in the UWB beacon by this uwb_rc device.
+ */
+static ssize_t ASIE_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct uwb_dev *uwb_dev = to_uwb_dev(dev);
+   struct uwb_rc *rc = uwb_dev-rc;
+   struct uwb_ie_hdr *ie;
+   void *ptr;
+   size_t len;
+   int result = 0;
+
+   /* init empty buffer. */
+   result = scnprintf(buf, PAGE_SIZE, \n);
+   mutex_lock(rc-ies_mutex);
+   /* walk IEData looking for an ASIE. */
+   ptr = rc-ies-IEData;
+   len = le16_to_cpu(rc-ies-wIELength);
+   for (;;) {
+   ie = uwb_ie_next(ptr, len);
+   if (!ie)
+   break;
+   if (ie-element_id == UWB_APP_SPEC_IE) {
+   result = uwb_ie_dump_hex(ie,
+   ie-length + sizeof(struct uwb_ie_hdr),
+   buf, PAGE_SIZE);
+   break;
+   }
+   }
+   mutex_unlock(rc-ies_mutex);
+
+   return result;
+}
+
+/*
+ * Update the ASIE that is broadcast in the UWB beacon by this uwb_rc device.
+ */
+static ssize_t ASIE_store(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t size)
+{
+   struct uwb_dev *uwb_dev = to_uwb_dev(dev);
+   struct uwb_rc *rc = uwb_dev-rc;
+   char ie_buf[255];
+   int result, ie_len = 0;
+   const char *cur_ptr = buf;
+   struct uwb_ie_hdr *ie;
+
+   /* empty string means clear the ASIE. */
+   if (strlen(buf) = 1) {
+   uwb_rc_ie_rm(rc, UWB_APP_SPEC_IE);
+   return size;
+   }
+
+   /* if non-empty string, convert string of hex chars to binary. */
+   while (ie_len  sizeof(ie_buf)) {
+   int char_count;
+
+   if (sscanf(cur_ptr,  %02hhX %n,
+   (ie_buf[ie_len]), char_count)  0) {
+   ++ie_len;
+   /* skip chars read from cur_ptr. */
+   cur_ptr += char_count;
+   } else {
+   break;
+   }
+   }
+
+   /* validate IE length and type. */
+   if (ie_len  sizeof(struct uwb_ie_hdr)) {
+   dev_err(dev, %s: Invalid ASIE size %d.\n, __func__, ie_len);
+   return -EINVAL;
+   }
+
+   ie = (struct uwb_ie_hdr *)ie_buf;
+   if (ie-element_id != UWB_APP_SPEC_IE) {
+   dev_err(dev, %s: Invalid IE element type size = 0x%02X.\n,
+   __func__, ie-element_id);
+   return -EINVAL;
+   }
+
+   /* bounds check length field from user. */
+   if (ie-length  (ie_len - sizeof(struct uwb_ie_hdr)))
+   ie-length = ie_len - sizeof(struct uwb_ie_hdr);
+
+   /*
+* Valid ASIE received. Remove current ASIE then add the new one using
+* uwb_rc_ie_add.
+*/
+   uwb_rc_ie_rm(rc, UWB_APP_SPEC_IE);
+
+   result = uwb_rc_ie_add(rc, ie, ie-length + sizeof(struct uwb_ie_hdr));
+
+   return result = 0 ? size : result;
+}
+static DEVICE_ATTR_RW(ASIE);
+
 static struct attribute *rc_attrs[] = {
dev_attr_mac_address.attr,
dev_attr_scan.attr,
dev_attr_beacon.attr,
+   dev_attr_ASIE.attr,
NULL,
 };
 
-- 
1.8.3.2

--
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 2/3] usb: wusbcore: remove USB_WUSB build dependency on PCI

2014-09-16 Thread Thomas Pugliese
Wireless USB does not require PCI so remove USB_WUSB build dependency on 
PCI.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig
index 0e17b96..f5c92f6 100644
--- a/drivers/usb/wusbcore/Kconfig
+++ b/drivers/usb/wusbcore/Kconfig
@@ -3,7 +3,6 @@
 #
 config USB_WUSB
tristate Enable Wireless USB extensions
-   depends on PCI
depends on UWB
 select CRYPTO
 select CRYPTO_BLKCIPHER
-- 
1.8.3.2

--
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 3/3] usb: wusbcore: USB_WUSB_CBAF depends on USB

2014-09-16 Thread Thomas Pugliese
Add USB build dependency for USB_WUSB_CBAF.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig
index f5c92f6..348de1d 100644
--- a/drivers/usb/wusbcore/Kconfig
+++ b/drivers/usb/wusbcore/Kconfig
@@ -17,6 +17,7 @@ config USB_WUSB
 
 config USB_WUSB_CBAF
tristate Support WUSB Cable Based Association (CBA)
+   depends on USB
help
  Some WUSB devices support Cable Based Association. It's used to
  enable the secure communication between the host and the
-- 
1.8.3.2

--
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 1/3] usb: hwa: add USB build dependency for USB_HWA_HCD

2014-09-16 Thread Thomas Pugliese
An HWA is a USB device so it depends on USB.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/host/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 82800a7..64805d9 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -709,7 +709,7 @@ config USB_WHCI_HCD
 
 config USB_HWA_HCD
tristate Host Wire Adapter (HWA) driver
-   depends on UWB
+   depends on USB  UWB
select USB_WUSB
select UWB_HWA
help
-- 
1.8.3.2

--
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 0/3] wusb build dependency fixes

2014-09-16 Thread Thomas Pugliese
Fix build dependencies for WUSB devices.

Thomas Pugliese (3):
  usb: hwa: add USB build dependency for USB_HWA_HCD
  usb: wusbcore: remove USB_WUSB build dependency on PCI
  usb: wusbcore: USB_WUSB_CBAF depends on USB

 drivers/usb/host/Kconfig | 2 +-
 drivers/usb/wusbcore/Kconfig | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

-- 
1.8.3.2

--
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] usb: wusbcore: skip done segs before completing aborted transfer

2014-09-16 Thread Thomas Pugliese
When completing an aborted transfer, skip done segs before calling 
wa_complete_remaining_xfer_segs to avoid a runtime warning.  The warning 
is harmless in this case but avoiding it prevents false error reports.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index e279015..69af4fd 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -459,14 +459,25 @@ static void __wa_xfer_abort_cb(struct urb *urb)
__func__, urb-status);
if (xfer) {
unsigned long flags;
-   int done;
+   int done, seg_index = 0;
struct wa_rpipe *rpipe = xfer-ep-hcpriv;
 
dev_err(dev, %s: cleaning up xfer %p ID 0x%08X.\n,
__func__, xfer, wa_xfer_id(xfer));
spin_lock_irqsave(xfer-lock, flags);
-   /* mark all segs as aborted. */
-   wa_complete_remaining_xfer_segs(xfer, 0,
+   /* skip done segs. */
+   while (seg_index  xfer-segs) {
+   struct wa_seg *seg = xfer-seg[seg_index];
+
+   if ((seg-status == WA_SEG_DONE) ||
+   (seg-status == WA_SEG_ERROR)) {
+   ++seg_index;
+   } else {
+   break;
+   }
+   }
+   /* mark remaining segs as aborted. */
+   wa_complete_remaining_xfer_segs(xfer, seg_index,
WA_SEG_ABORTED);
done = __wa_xfer_is_done(xfer);
spin_unlock_irqrestore(xfer-lock, flags);
-- 
1.8.3.2

--
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 3/3] usb: wusbcore: fix below build warning

2014-08-18 Thread Thomas Pugliese


On Mon, 18 Aug 2014, Peter Chen wrote:

 linux-2.6/drivers/usb/wusbcore/wa-xfer.c: In function 'wa_buf_in_cb':
 linux-2.6/drivers/usb/wusbcore/wa-xfer.c:2590: warning: 'rpipe' may be used 
 uninitialized in this function
 
 Signed-off-by: Peter Chen peter.c...@freescale.com
 ---
  drivers/usb/wusbcore/wa-xfer.c |4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
 index 3e2e4ed..11c2ec0 100644
 --- a/drivers/usb/wusbcore/wa-xfer.c
 +++ b/drivers/usb/wusbcore/wa-xfer.c
 @@ -2587,7 +2587,7 @@ static void wa_buf_in_cb(struct urb *urb)
   struct wa_xfer *xfer = seg-xfer;
   struct wahc *wa;
   struct device *dev;
 - struct wa_rpipe *rpipe;
 + struct wa_rpipe *rpipe = NULL;
   unsigned rpipe_ready = 0, isoc_data_frame_count = 0;
   unsigned long flags;
   int resubmit_dti = 0, active_buf_in_urbs;
 @@ -2671,7 +2671,7 @@ static void wa_buf_in_cb(struct urb *urb)
   spin_unlock_irqrestore(xfer-lock, flags);
   if (done)
   wa_xfer_completion(xfer);
 - if (rpipe_ready)
 + if (rpipe_ready  rpipe)
   wa_xfer_delayed_run(rpipe);
   break;
   case -ECONNRESET:   /* URB unlinked; no need to do anything */
 -- 
 1.7.9.5
 
 

Hi Peter, 
This change isn't strictly necessary because rpipe_ready is initialized to 
0 and rpipe is guaranteed to be initialized if rpipe_ready is true.  That 
being said, if you want to clean up the warning, you could just move the 
rpipe initialization up so that it will always be initialized in the 
context of the rpipe_ready test like this:

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 3e2e4ed..c4fb9e1 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2633,6 +2633,7 @@ static void wa_buf_in_cb(struct urb *urb)
spin_lock_irqsave(xfer-lock, flags);
 
seg-result += urb-actual_length;
+   rpipe = xfer-ep-hcpriv;
if (isoc_data_frame_count  0) {
int result, urb_frame_count;
 
@@ -2659,7 +2660,6 @@ static void wa_buf_in_cb(struct urb *urb)
  resubmit_dti = (isoc_data_frame_count ==
urb_frame_count);
} else if (active_buf_in_urbs == 0) {
-   rpipe = xfer-ep-hcpriv;
dev_dbg(dev,
xfer %p 0x%08X#%u: data in done (%zu bytes)\n,
xfer, wa_xfer_id(xfer), seg-index,

---

That way, the variable is only initialized once.

Tom
--
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] uwb: init beacon cache entry before registering uwb device

2014-08-07 Thread Thomas Pugliese
Make sure the uwb_dev-bce entry is set before calling uwb_dev_add in 
uwbd_dev_onair so that usermode will only see the device after it is 
properly initialized.  This fixes a kernel panic that can occur if 
usermode tries to access the IEs sysfs attribute of a UWB device before 
the driver has had a chance to set the beacon cache entry.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
Cc: sta...@vger.kernel.org
---
 drivers/uwb/lc-dev.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c
index 80079b8..d0303f0 100644
--- a/drivers/uwb/lc-dev.c
+++ b/drivers/uwb/lc-dev.c
@@ -431,16 +431,19 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e 
*bce)
uwb_dev-mac_addr = *bce-mac_addr;
uwb_dev-dev_addr = bce-dev_addr;
dev_set_name(uwb_dev-dev, %s, macbuf);
+
+   /* plug the beacon cache */
+   bce-uwb_dev = uwb_dev;
+   uwb_dev-bce = bce;
+   uwb_bce_get(bce);   /* released in uwb_dev_sys_release() */
+
result = uwb_dev_add(uwb_dev, rc-uwb_dev.dev, rc);
if (result  0) {
dev_err(dev, new device %s: cannot instantiate device\n,
macbuf);
goto error_dev_add;
}
-   /* plug the beacon cache */
-   bce-uwb_dev = uwb_dev;
-   uwb_dev-bce = bce;
-   uwb_bce_get(bce);   /* released in uwb_dev_sys_release() */
+
dev_info(dev, uwb device (mac %s dev %s) connected to %s %s\n,
 macbuf, devbuf, rc-uwb_dev.dev.parent-bus-name,
 dev_name(rc-uwb_dev.dev.parent));
@@ -448,6 +451,8 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e 
*bce)
return;
 
 error_dev_add:
+   bce-uwb_dev = NULL;
+   uwb_bce_put(bce);
kfree(uwb_dev);
return;
 }
-- 
1.8.3.2

--
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 0/3] uwb: formatting and compile warning fixes

2014-04-28 Thread Thomas Pugliese
This set contains a few fixes for formatting issues and compile warnings 
in UWB.  Some of the changes for lines over 80 chars required pulling 
deeply nested code into separate functions which makes that patch look 
more significant than it really is.

Thomas Pugliese (3):
  uwb: whitespace and line length cleanups
  uwb: comment typo fix
  uwb: fix variable set but not used warnings

 drivers/uwb/beacon.c |   3 -
 drivers/uwb/drp.c| 294 +--
 drivers/uwb/est.c|   2 -
 drivers/uwb/ie-rcv.c |   2 -
 drivers/uwb/radio.c  |   2 +-
 5 files changed, 167 insertions(+), 136 deletions(-)

-- 
1.8.3.2

--
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 3/3] uwb: fix variable set but not used warnings

2014-04-28 Thread Thomas Pugliese
Fix variable set but not used warnings in UWB.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/beacon.c | 3 ---
 drivers/uwb/est.c| 2 --
 drivers/uwb/ie-rcv.c | 2 --
 3 files changed, 7 deletions(-)

diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c
index b476187..f40745f 100644
--- a/drivers/uwb/beacon.c
+++ b/drivers/uwb/beacon.c
@@ -397,7 +397,6 @@ int uwbd_evt_handle_rc_beacon(struct uwb_event *evt)
struct uwb_rc_evt_beacon *be;
struct uwb_beacon_frame *bf;
struct uwb_beca_e *bce;
-   unsigned long last_ts;
 
rc = evt-rc;
be = container_of(evt-notif.rceb, struct uwb_rc_evt_beacon, rceb);
@@ -441,8 +440,6 @@ int uwbd_evt_handle_rc_beacon(struct uwb_event *evt)
/* purge old beacon data */
kfree(bce-be);
 
-   last_ts = bce-ts_jiffies;
-
/* Update commonly used fields */
bce-ts_jiffies = evt-ts_jiffies;
bce-be = be;
diff --git a/drivers/uwb/est.c b/drivers/uwb/est.c
index 457f31d..f3e2325 100644
--- a/drivers/uwb/est.c
+++ b/drivers/uwb/est.c
@@ -258,7 +258,6 @@ int uwb_est_register(u8 type, u8 event_high, u16 vendor, 
u16 product,
 {
unsigned long flags;
unsigned itr;
-   u16 type_event_high;
int result = 0;
 
write_lock_irqsave(uwb_est_lock, flags);
@@ -268,7 +267,6 @@ int uwb_est_register(u8 type, u8 event_high, u16 vendor, 
u16 product,
goto out;
}
/* Find the right spot to insert it in */
-   type_event_high = type  8 | event_high;
for (itr = 0; itr  uwb_est_used; itr++)
if (uwb_est[itr].type_event_high  type
 uwb_est[itr].vendor  vendor
diff --git a/drivers/uwb/ie-rcv.c b/drivers/uwb/ie-rcv.c
index 917e6d7..5fac574 100644
--- a/drivers/uwb/ie-rcv.c
+++ b/drivers/uwb/ie-rcv.c
@@ -31,7 +31,6 @@ int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *evt)
int result = -EINVAL;
struct device *dev = evt-rc-uwb_dev.dev;
struct uwb_rc_evt_ie_rcv *iercv;
-   size_t iesize;
 
/* Is there enough data to decode it? */
if (evt-notif.size  sizeof(*iercv)) {
@@ -41,7 +40,6 @@ int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *evt)
goto error;
}
iercv = container_of(evt-notif.rceb, struct uwb_rc_evt_ie_rcv, rceb);
-   iesize = le16_to_cpu(iercv-wIELength);
 
dev_dbg(dev, IE received, element ID=%d\n, iercv-IEData[0]);
 
-- 
1.8.3.2

--
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 2/3] uwb: comment typo fix

2014-04-28 Thread Thomas Pugliese
Comment typo fix.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/radio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/uwb/radio.c b/drivers/uwb/radio.c
index fd23d98..2427e94 100644
--- a/drivers/uwb/radio.c
+++ b/drivers/uwb/radio.c
@@ -115,7 +115,7 @@ int uwb_radio_start(struct uwb_pal *pal)
 EXPORT_SYMBOL_GPL(uwb_radio_start);
 
 /**
- * uwb_radio_stop - request tha the radio be stopped.
+ * uwb_radio_stop - request that the radio be stopped.
  * @pal: the PAL making the request.
  *
  * Stops the radio if no other PAL is making use of it.
-- 
1.8.3.2

--
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 1/3] uwb: whitespace and line length cleanups

2014-04-28 Thread Thomas Pugliese
Fix whitespace and line length issues reported by checkpatch.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/drp.c | 294 ++
 1 file changed, 166 insertions(+), 128 deletions(-)

diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c
index 468c89f..05b7bd7 100644
--- a/drivers/uwb/drp.c
+++ b/drivers/uwb/drp.c
@@ -29,19 +29,19 @@
 enum uwb_drp_conflict_action {
/* Reservation is maintained, no action needed */
UWB_DRP_CONFLICT_MANTAIN = 0,
-   
+
/* the device shall not transmit frames in conflicting MASs in
 * the following superframe. If the device is the reservation
 * target, it shall also set the Reason Code in its DRP IE to
 * Conflict in its beacon in the following superframe.
 */
UWB_DRP_CONFLICT_ACT1,
-   
+
/* the device shall not set the Reservation Status bit to ONE
 * and shall not transmit frames in conflicting MASs. If the
 * device is the reservation target, it shall also set the
 * Reason Code in its DRP IE to Conflict.
-*/ 
+*/
UWB_DRP_CONFLICT_ACT2,
 
/* the device shall not transmit frames in conflicting MASs in
@@ -115,7 +115,8 @@ int uwb_rc_send_all_drp_ie(struct uwb_rc *rc)
if (uwb_rsv_has_two_drp_ies(rsv) 
(rsv-mv.companion_drp_ie != NULL)) {
mv = rsv-mv;
-   num_bytes += mv-companion_drp_ie-hdr.length + 
2;  
+   num_bytes +=
+   mv-companion_drp_ie-hdr.length + 2;
}
}
}
@@ -139,21 +140,23 @@ int uwb_rc_send_all_drp_ie(struct uwb_rc *rc)
memcpy(IEDataptr, rsv-drp_ie,
   rsv-drp_ie-hdr.length + 2);
IEDataptr += rsv-drp_ie-hdr.length + 2;
-   
+
if (uwb_rsv_has_two_drp_ies(rsv) 
(rsv-mv.companion_drp_ie != NULL)) {
mv = rsv-mv;
memcpy(IEDataptr, mv-companion_drp_ie,
   mv-companion_drp_ie-hdr.length + 2);
-   IEDataptr += mv-companion_drp_ie-hdr.length + 
2;  
+   IEDataptr +=
+   mv-companion_drp_ie-hdr.length + 2;
}
}
}
 
-   result = uwb_rc_cmd_async(rc, SET-DRP-IE, cmd-rccb, sizeof(*cmd) + 
num_bytes,
- UWB_RC_CET_GENERAL, UWB_RC_CMD_SET_DRP_IE,
- uwb_rc_set_drp_cmd_done, NULL);
-   
+   result = uwb_rc_cmd_async(rc, SET-DRP-IE,
+   cmd-rccb, sizeof(*cmd) + num_bytes,
+   UWB_RC_CET_GENERAL, UWB_RC_CMD_SET_DRP_IE,
+   uwb_rc_set_drp_cmd_done, NULL);
+
rc-set_drp_ie_pending = 1;
 
kfree(cmd);
@@ -176,8 +179,8 @@ static int evaluate_conflict_action(struct uwb_ie_drp 
*ext_drp_ie, int ext_beaco
int ext_tie_breaker = uwb_ie_drp_tiebreaker(ext_drp_ie);
int ext_status  = uwb_ie_drp_status(ext_drp_ie);
int ext_type= uwb_ie_drp_type(ext_drp_ie);
-   
-   
+
+
/* [ECMA-368 2nd Edition] 17.4.6 */
if (ext_type == UWB_DRP_TYPE_PCA  our_type == UWB_DRP_TYPE_PCA) {
return UWB_DRP_CONFLICT_MANTAIN;
@@ -187,7 +190,7 @@ static int evaluate_conflict_action(struct uwb_ie_drp 
*ext_drp_ie, int ext_beaco
if (our_type == UWB_DRP_TYPE_ALIEN_BP) {
return UWB_DRP_CONFLICT_MANTAIN;
}
-   
+
/* [ECMA-368 2nd Edition] 17.4.6-2 */
if (ext_type == UWB_DRP_TYPE_ALIEN_BP) {
/* here we know our_type != UWB_DRP_TYPE_ALIEN_BP */
@@ -215,7 +218,7 @@ static int evaluate_conflict_action(struct uwb_ie_drp 
*ext_drp_ie, int ext_beaco
our_beacon_slot   ext_beacon_slot) {
return UWB_DRP_CONFLICT_MANTAIN;
}
-   
+
if (our_status == 0) {
if (our_tie_breaker == ext_tie_breaker) {
/* [ECMA-368 2nd Edition] 17.4.6-6a */
@@ -244,9 +247,9 @@ static int evaluate_conflict_action(struct uwb_ie_drp 
*ext_drp_ie, int ext_beaco
return UWB_DRP_CONFLICT_MANTAIN;
 }
 
-static void handle_conflict_normal(struct uwb_ie_drp *drp_ie, 
-  int ext_beacon_slot, 
-  struct uwb_rsv *rsv, 
+static void handle_conflict_normal(struct uwb_ie_drp *drp_ie,
+  int ext_beacon_slot,
+  struct uwb_rsv *rsv,
   struct uwb_mas_bm *conflicting_mas)
 {
struct

[PATCH 2/2] uwb: add error messages when reservation establish fails

2014-04-25 Thread Thomas Pugliese
Add better error messages during the channel change/reservation establish 
process.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/beacon.c |  4 +++-
 drivers/uwb/rsv.c| 14 --
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c
index 57b5ff6..b476187 100644
--- a/drivers/uwb/beacon.c
+++ b/drivers/uwb/beacon.c
@@ -125,8 +125,10 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned 
bpst_offset)
else {
/* channel = 0...dah */
result = uwb_rc_start_beacon(rc, bpst_offset, channel);
-   if (result  0)
+   if (result  0) {
+   dev_err(dev, Cannot start beaconing: %d\n, result);
return result;
+   }
if (le16_to_cpu(rc-ies-wIELength)  0) {
result = uwb_rc_set_ie(rc, rc-ies);
if (result  0) {
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c
index 4026f1a..0887ae9 100644
--- a/drivers/uwb/rsv.c
+++ b/drivers/uwb/rsv.c
@@ -163,8 +163,10 @@ static int uwb_rsv_get_stream(struct uwb_rsv *rsv)
}
 
stream = find_first_zero_bit(streams_bm, UWB_NUM_STREAMS);
-   if (stream = UWB_NUM_STREAMS)
+   if (stream = UWB_NUM_STREAMS) {
+   dev_err(dev, %s: no available stream found\n, __func__);
return -EBUSY;
+   }
 
rsv-stream = stream;
set_bit(stream, streams_bm);
@@ -555,12 +557,16 @@ int uwb_rsv_establish(struct uwb_rsv *rsv)
 {
struct uwb_rc *rc = rsv-rc;
struct uwb_mas_bm available;
+   struct device *dev = rc-uwb_dev.dev;
int ret;
 
mutex_lock(rc-rsvs_mutex);
ret = uwb_rsv_get_stream(rsv);
-   if (ret)
+   if (ret) {
+   dev_err(dev, %s: uwb_rsv_get_stream failed: %d\n,
+   __func__, ret);
goto out;
+   }
 
rsv-tiebreaker = prandom_u32()  1;
/* get available mas bitmap */
@@ -570,12 +576,16 @@ int uwb_rsv_establish(struct uwb_rsv *rsv)
if (ret == UWB_RSV_ALLOC_NOT_FOUND) {
ret = -EBUSY;
uwb_rsv_put_stream(rsv);
+   dev_err(dev, %s: uwb_rsv_find_best_allocation failed: %d\n,
+   __func__, ret);
goto out;
}
 
ret = uwb_drp_avail_reserve_pending(rc, rsv-mas);
if (ret != 0) {
uwb_rsv_put_stream(rsv);
+   dev_err(dev, %s: uwb_drp_avail_reserve_pending failed: %d\n,
+   __func__, ret);
goto out;
}
 
-- 
1.8.3.2

--
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 0/2] fix channel change failure

2014-04-25 Thread Thomas Pugliese
Fix an intermittent failure when changing channels and report better 
errors during the channel change process.

Thomas Pugliese (2):
  uwb: fix channel change failure
  uwb: add error messages when reservation establish fails

 drivers/uwb/beacon.c |  4 +++-
 drivers/uwb/rsv.c| 21 ++---
 2 files changed, 21 insertions(+), 4 deletions(-)

-- 
1.8.3.2

--
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] usb: wusbcore: fix panic in wusbhc_chid_set

2014-04-23 Thread Thomas Pugliese
If no valid CHID value has previously been set on an HWA, writing a 
value of all zeros will cause a kernel panic in uwb_radio_stop because 
wusbhc-uwb_rc has not been set.  This patch skips the call to 
uwb_radio_stop if wusbhc-uwb_rc has not been initialized.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/mmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c
index 4474126..3f485df 100644
--- a/drivers/usb/wusbcore/mmc.c
+++ b/drivers/usb/wusbcore/mmc.c
@@ -301,7 +301,7 @@ int wusbhc_chid_set(struct wusbhc *wusbhc, const struct 
wusb_ckhdid *chid)
 
if (chid)
result = uwb_radio_start(wusbhc-pal);
-   else
+   else if (wusbhc-uwb_rc)
uwb_radio_stop(wusbhc-pal);
 
return result;
-- 
1.8.3.2

--
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] usb: wusbcore: convert nested lock to use spin_lock instead of spin_lock_irq

2014-04-23 Thread Thomas Pugliese
Nesting a spin_lock_irq/unlock_irq inside a lock that has already
disabled interrupts will enable interrupts before we are ready when
spin_unlock_irq is called.  This patch converts the inner lock to use
spin_lock and spin_unlock instead.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index c8e2a47..3e2e4ed 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2390,10 +2390,10 @@ error_complete:
done) {
 
dev_info(dev, Control EP stall.  Queue delayed work.\n);
-   spin_lock_irq(wa-xfer_list_lock);
+   spin_lock(wa-xfer_list_lock);
/* move xfer from xfer_list to xfer_errored_list. */
list_move_tail(xfer-list_node, wa-xfer_errored_list);
-   spin_unlock_irq(wa-xfer_list_lock);
+   spin_unlock(wa-xfer_list_lock);
spin_unlock_irqrestore(xfer-lock, flags);
queue_work(wusbd, wa-xfer_error_work);
} else {
-- 
1.8.3.2

--
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] uvc: update uvc_endpoint_max_bpi to handle USB_SPEED_WIRELESS devices

2014-04-17 Thread Thomas Pugliese


On Thu, 17 Apr 2014, Laurent Pinchart wrote:

 Hi Thomas,
 
 On Wednesday 16 April 2014 12:29:22 Thomas Pugliese wrote:
  On Wed, 16 Apr 2014, Laurent Pinchart wrote:
   Hi Thomas,
   
   (CC'ing the linux-usb mailing list)
   
   On Tuesday 15 April 2014 16:45:28 Thomas Pugliese wrote:
On Tue, 15 Apr 2014, Laurent Pinchart wrote:
 Hi Thomas,
 
 Could you please send me a proper revert patch with the above
 description in the commit message and CC Mauro Carvalho Chehab
 m.che...@samsung.com ?

Hi Laurent,
I can submit a patch to revert but I should make a correction first.  I
had backported this change to an earlier kernel (2.6.39) which was
before super speed support was added and the regression I described was
based on that kernel.  It was actually the addition of super speed
support that broke windows compatible devices.  My previous change fixed
spec compliant devices but left windows compatible devices broken.

Basically, the timeline of changes is this:

1.  Prior to the addition of super speed support (commit
6fd90db8df379e215): all WUSB devices were treated as HIGH_SPEED devices.
This is how Windows works so Windows compatible devices would work.  For
spec compliant WUSB devices, the max packet size would be incorrectly
calculated which would result in high-bandwidth isoc streams being
unable to find an alt setting that provided enough bandwidth.

2.  After super speed support: all WUSB devices fell through to the
default case of uvc_endpoint_max_bpi which would mask off the upper bits
of the max packet size.  This broke both WUSB spec compliant and non
compliant devices because no endpoint with a large enough bpi would be
found.

3.  After 79af67e77f86404e77e: Spec compliant devices are fixed but
non-spec compliant (although Windows compatible) devices are broken.
Basically, this is the opposite of how it worked prior to super speed
support.

Given that, I can submit a patch to revert 79af67e77f86404e77e but that
would go back to having all WUSB devices broken.  Alternatively, the
change below will revert the behavior back to scenario 1 where Windows
compatible devices work but strictly spec complaint devices may not.

I can send a proper patch for whichever scenario you prefer.
   
   Thank you for the explanation.
   
   Reverting 79af67e77f86404e77e doesn't seem like a very good idea, given
   that all WUSB devices will be broken. We thus have two options:
   
   - leaving the code as-is, with support for spec-compliant WUSB devices but
   not for microsoft-specific devices
   
   - applying the patch below, with support for microsoft-specific USB
   devices but not for spec-compliant devices
   
   This isn't the first time this kind of situation occurs. Microsoft didn't
   support multiple configurations before Windows 8, making vendors come up
   with lots of creative MS-specific solutions. I consider those devices
   non USB compliant, and they should not be allowed to use the USB logo,
   but that would require a strong political move from the USB Implementers
   Forum which is more or less controlled by Microsoft... Welcome to the USB
   mafia.
   
   Anyway, I have no experience with WUSB devices, so I don't know what's
   more common in the wild. What would you suggest ?
  
  I think that almost all current devices support the Windows/USB 2.0 format
  rather than stricty follow the WUSB spec.  Even the prototype device that
  I initially used to test UVC with Wireless USB has been updated to use the
  USB 2.0 format prior to shipping in order to remain compatible with
  Windows.  That being said, these devices are not very common at all in the
  consumer market.  They are mostly used in embedded/industrial settings so
  that may factor in as to which direction you want to go.
  
   Would there be a way to support
   both categories of devices ?
  
  As you had mentioned previously, it should be possible to support both
  formats by ignoring the endpoint descriptor and looking at the bMaxBurst,
  bOverTheAirInterval and wOverTheAirPacketSize fields in the WUSB endpoint
  companion descriptor.  That is a more involved change to the UVC driver
  and also would require changes to USB core to store the WUSB endpoint
  companion descriptor in struct usb_host_endpoint similar to what is done
  for super speed devices.
 
 It's more complex indeed, but I believe it would be worth it. Any volunteer ? 
 ;-) In the meantime I'm fine with a patch that reverts to the previous 
 behaviour. Please include the explanation of the problem in the commit 
 message.
 
 -- 
 Regards,
 
 Laurent Pinchart
 

I may make an attempt at the more complete fix once I finish some of the 
other items in my queue.  

For clarification, would you like a patch that reverts to the pre-super 
speed behavior where windows-compatible devices work not but spec

Re: [PATCH] uvc: update uvc_endpoint_max_bpi to handle USB_SPEED_WIRELESS devices

2014-04-16 Thread Thomas Pugliese


On Wed, 16 Apr 2014, Laurent Pinchart wrote:

 Hi Thomas,
 
 (CC'ing the linux-usb mailing list)
 
 On Tuesday 15 April 2014 16:45:28 Thomas Pugliese wrote:
  On Tue, 15 Apr 2014, Laurent Pinchart wrote:
   Hi Thomas,
   
   Could you please send me a proper revert patch with the above description
   in the commit message and CC Mauro Carvalho Chehab m.che...@samsung.com
   ?
 
  Hi Laurent,
  I can submit a patch to revert but I should make a correction first.  I
  had backported this change to an earlier kernel (2.6.39) which was before
  super speed support was added and the regression I described was based on
  that kernel.  It was actually the addition of super speed support that
  broke windows compatible devices.  My previous change fixed spec compliant
  devices but left windows compatible devices broken.
  
  Basically, the timeline of changes is this:
  
  1.  Prior to the addition of super speed support (commit
  6fd90db8df379e215): all WUSB devices were treated as HIGH_SPEED devices.
  This is how Windows works so Windows compatible devices would work.  For
  spec compliant WUSB devices, the max packet size would be incorrectly
  calculated which would result in high-bandwidth isoc streams being unable
  to find an alt setting that provided enough bandwidth.
  
  2.  After super speed support: all WUSB devices fell through to the
  default case of uvc_endpoint_max_bpi which would mask off the upper bits
  of the max packet size.  This broke both WUSB spec compliant and non
  compliant devices because no endpoint with a large enough bpi would be
  found.
  
  3.  After 79af67e77f86404e77e: Spec compliant devices are fixed but
  non-spec compliant (although Windows compatible) devices are broken.
  Basically, this is the opposite of how it worked prior to super speed
  support.
  
  Given that, I can submit a patch to revert 79af67e77f86404e77e but that
  would go back to having all WUSB devices broken.  Alternatively, the
  change below will revert the behavior back to scenario 1 where Windows
  compatible devices work but strictly spec complaint devices may not.
  
  I can send a proper patch for whichever scenario you prefer.
 
 Thank you for the explanation.
 
 Reverting 79af67e77f86404e77e doesn't seem like a very good idea, given that 
 all WUSB devices will be broken. We thus have two options:
 
 - leaving the code as-is, with support for spec-compliant WUSB devices but 
 not 
 for microsoft-specific devices 
 
 - applying the patch below, with support for microsoft-specific USB devices 
 but not for spec-compliant devices
 
 This isn't the first time this kind of situation occurs. Microsoft didn't 
 support multiple configurations before Windows 8, making vendors come up with 
 lots of creative MS-specific solutions. I consider those devices non USB 
 compliant, and they should not be allowed to use the USB logo, but that would 
 require a strong political move from the USB Implementers Forum which is more 
 or less controlled by Microsoft... Welcome to the USB mafia.
 
 Anyway, I have no experience with WUSB devices, so I don't know what's more 
 common in the wild. What would you suggest ? 

I think that almost all current devices support the Windows/USB 2.0 format 
rather than stricty follow the WUSB spec.  Even the prototype device that 
I initially used to test UVC with Wireless USB has been updated to use the 
USB 2.0 format prior to shipping in order to remain compatible with 
Windows.  That being said, these devices are not very common at all in the 
consumer market.  They are mostly used in embedded/industrial settings so 
that may factor in as to which direction you want to go.

 Would there be a way to support 
 both categories of devices ?
 

As you had mentioned previously, it should be possible to support both 
formats by ignoring the endpoint descriptor and looking at the bMaxBurst, 
bOverTheAirInterval and wOverTheAirPacketSize fields in the WUSB endpoint 
companion descriptor.  That is a more involved change to the UVC driver 
and also would require changes to USB core to store the WUSB endpoint 
companion descriptor in struct usb_host_endpoint similar to what is done 
for super speed devices.

Regards,
Thomas
--
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] staging: octeon-usb: prevent memory corruption

2014-03-21 Thread Thomas Pugliese


On Thu, 20 Mar 2014, Aaro Koskinen wrote:

 octeon-hcd will crash the kernel when SLOB is used. This usually happens
 after the 18-byte control transfer when a device descriptor is read.
 The DMA engine is always transfering full 32-bit words and if the
 transfer is shorter, some random garbage appears after the buffer.
 The problem is not visible with SLUB since it rounds up the allocations
 to word boundary, and the extra bytes will go undetected.
 
 Fix by providing quirk functions for DMA map/unmap that allocate a bigger
 temporary buffer when necessary. Tested by booting EdgeRouter Lite
 to USB stick root file system with SLAB, SLOB and SLUB kernels.
 
 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=72121
 Reported-by: Sergey Popov pinkb...@gentoo.org
 Signed-off-by: Aaro Koskinen aaro.koski...@iki.fi
 ---
  drivers/staging/octeon-usb/octeon-hcd.c | 108 
 
  1 file changed, 108 insertions(+)
 
 diff --git a/drivers/staging/octeon-usb/octeon-hcd.c 
 b/drivers/staging/octeon-usb/octeon-hcd.c
 index 5a001d9..9c152f9 100644
 --- a/drivers/staging/octeon-usb/octeon-hcd.c
 +++ b/drivers/staging/octeon-usb/octeon-hcd.c
 @@ -465,6 +465,112 @@ struct octeon_hcd {
  #define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) 
 + ((channel)+1)*0x1000)
  
  /**
 + * struct octeon_temp_buffer - a bounce buffer for USB transfers
 + * @temp_buffer: the newly allocated temporary buffer (including meta-data)
 + * @orig_buffer: the original buffer passed by the USB stack
 + * @data: the newly allocated temporary buffer (excluding meta-data)
 + *
 + * Both the DMA engine and FIFO mode will always transfer full 32-bit words. 
 If
 + * the buffer is too short, we need to allocate a temporary one, and this 
 struct
 + * represents it.
 + */
 +struct octeon_temp_buffer {
 + void *temp_buffer;
 + void *orig_buffer;
 + u8 data[0];
 +};
 +
 +/**
 + * octeon_alloc_temp_buffer - allocate a temporary buffer for USB transfer
 + *(if needed)
 + * @urb: URB.
 + * @mem_flags:   Memory allocation flags.
 + *
 + * This function allocates a temporary bounce buffer whenever it's needed
 + * due to HW limitations.
 + */
 +static int octeon_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
 +{
 + struct octeon_temp_buffer *temp;
 +
 + if (urb-num_sgs || urb-sg ||
 + (urb-transfer_flags  URB_NO_TRANSFER_DMA_MAP) ||
 + !(urb-transfer_buffer_length % sizeof(u32)))
 + return 0;
 +
 + temp = kmalloc(ALIGN(urb-transfer_buffer_length, sizeof(u32)) +
 +sizeof(*temp), mem_flags);
 + if (!temp)
 + return -ENOMEM;
 +
 + temp-temp_buffer = temp;
 + temp-orig_buffer = urb-transfer_buffer;
 + if (usb_urb_dir_out(urb))
 + memcpy(temp-data, urb-transfer_buffer,
 +urb-transfer_buffer_length);
 + urb-transfer_buffer = temp-data;
 + urb-transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
 +
 + return 0;
 +}
 +
 

I don't think you need the temp_buffer in struct octeon_temp_buffer.  
Once you have temp in octeon_free_temp_buffer via container_of, just free 
temp.  There is no need to look at temp_buffer to get its address.

Thomas Pugliese
--
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 2/3] usb: wusbcore: combine iso transfer result frame reads when possible

2014-03-07 Thread Thomas Pugliese


On Fri, 7 Mar 2014, Greg KH wrote:

 On Thu, Mar 06, 2014 at 12:53:38PM -0600, Thomas Pugliese wrote:
  When reading the transfer result data for an isochronous in request, if 
  the current frame actual_length is contiguous with the next frame and 
  actual_length is a multiple of the DTI endpoint max packet size, combine 
  the current frame with the next frame in a single URB.  This reduces the 
  number of URBs that must be submitted in that case which increases 
  performance and reduces CPU interrupt overhead.
  
  Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
  ---
   drivers/usb/wusbcore/wa-xfer.c | 104 
  +
   1 file changed, 75 insertions(+), 29 deletions(-)
 
 This patch fails to apply to my tree:
 
 checking file drivers/usb/wusbcore/wa-xfer.c
 Hunk #5 FAILED at 2593.
 1 out of 7 hunks FAILED
 
 
 So I've stopped here in applying this series.  Can you please fix this
 up and resend?
 
 thanks,
 
 greg k-h
 

Looks like a one line comment change that I forgot to pull in messed up 
the diff context.  I'll resend the last two patches re-diffed correctly.

Thomas
--
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 0/2] usb: wusbcore: HWA performance optimizations

2014-03-07 Thread Thomas Pugliese
This is a resend of two previously sent patches that failed to apply

This series includes a set of performance optimizations for the HWA 
which improve webcam image quality and CPU utilization for isochronous 
read transfers.

Thomas Pugliese (2):
  usb: wusbcore: combine iso transfer result frame reads when possible
  usb: wusbcore: use multiple urbs for HWA iso transfer result frame reads

 drivers/usb/wusbcore/wa-hc.c   |   2 -
 drivers/usb/wusbcore/wa-hc.h   |  15 ++-
 drivers/usb/wusbcore/wa-xfer.c | 275 -
 3 files changed, 199 insertions(+), 93 deletions(-)

-- 
1.8.3.2

--
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 2/2] usb: wusbcore: use multiple urbs for HWA iso transfer result frame reads

2014-03-07 Thread Thomas Pugliese
Submit multiple concurrent urbs for HWA isochronous transfer result data 
frame reads.  This keeps the read pipeline full and significantly 
improves performance in cases where the frame reads cannot be combined 
because they are not contiguous or multiples of the max packet size.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-hc.c   |   2 -
 drivers/usb/wusbcore/wa-hc.h   |  15 +++-
 drivers/usb/wusbcore/wa-xfer.c | 191 ++---
 3 files changed, 134 insertions(+), 74 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c
index 368360f..252c7bd 100644
--- a/drivers/usb/wusbcore/wa-hc.c
+++ b/drivers/usb/wusbcore/wa-hc.c
@@ -75,8 +75,6 @@ void __wa_destroy(struct wahc *wa)
if (wa-dti_urb) {
usb_kill_urb(wa-dti_urb);
usb_put_urb(wa-dti_urb);
-   usb_kill_urb(wa-buf_in_urb);
-   usb_put_urb(wa-buf_in_urb);
}
kfree(wa-dti_buf);
wa_nep_destroy(wa);
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index 7510960..f2a8d29 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -125,7 +125,8 @@ struct wa_rpipe {
 
 enum wa_dti_state {
WA_DTI_TRANSFER_RESULT_PENDING,
-   WA_DTI_ISOC_PACKET_STATUS_PENDING
+   WA_DTI_ISOC_PACKET_STATUS_PENDING,
+   WA_DTI_BUF_IN_DATA_PENDING
 };
 
 enum wa_quirks {
@@ -146,6 +147,8 @@ enum wa_vendor_specific_requests {
WA_REQ_ALEREON_FEATURE_SET = 0x01,
WA_REQ_ALEREON_FEATURE_CLEAR = 0x00,
 };
+
+#define WA_MAX_BUF_IN_URBS 4
 /**
  * Instance of a HWA Host Controller
  *
@@ -216,7 +219,9 @@ struct wahc {
u32 dti_isoc_xfer_in_progress;
u8  dti_isoc_xfer_seg;
struct urb *dti_urb;/* URB for reading xfer results */
-   struct urb *buf_in_urb; /* URB for reading data in */
+   /* URBs for reading data in */
+   struct urb buf_in_urbs[WA_MAX_BUF_IN_URBS];
+   int active_buf_in_urbs; /* number of buf_in_urbs active. */
struct edc dti_edc; /* DTI error density counter */
void *dti_buf;
size_t dti_buf_size;
@@ -286,6 +291,8 @@ static inline void wa_rpipe_init(struct wahc *wa)
 
 static inline void wa_init(struct wahc *wa)
 {
+   int index;
+
edc_init(wa-nep_edc);
atomic_set(wa-notifs_queued, 0);
wa-dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
@@ -299,6 +306,10 @@ static inline void wa_init(struct wahc *wa)
INIT_WORK(wa-xfer_error_work, wa_process_errored_transfers_run);
wa-dto_in_use = 0;
atomic_set(wa-xfer_id_count, 1);
+   /* init the buf in URBs */
+   for (index = 0; index  WA_MAX_BUF_IN_URBS; ++index)
+   usb_init_urb((wa-buf_in_urbs[index]));
+   wa-active_buf_in_urbs = 0;
 }
 
 /**
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index f930bbb..c8e2a47 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2159,9 +2159,9 @@ static void wa_complete_remaining_xfer_segs(struct 
wa_xfer *xfer,
}
 }
 
-/* Populate the wa-buf_in_urb based on the current isoc transfer state. */
-static int __wa_populate_buf_in_urb_isoc(struct wahc *wa, struct wa_xfer *xfer,
-   struct wa_seg *seg)
+/* Populate the given urb based on the current isoc transfer state. */
+static int __wa_populate_buf_in_urb_isoc(struct wahc *wa,
+   struct urb *buf_in_urb, struct wa_xfer *xfer, struct wa_seg *seg)
 {
int urb_start_frame = seg-isoc_frame_index + seg-isoc_frame_offset;
int seg_index, total_len = 0, urb_frame_index = urb_start_frame;
@@ -2171,7 +2171,7 @@ static int __wa_populate_buf_in_urb_isoc(struct wahc *wa, 
struct wa_xfer *xfer,
int next_frame_contiguous;
struct usb_iso_packet_descriptor *iso_frame;
 
-   BUG_ON(wa-buf_in_urb-status == -EINPROGRESS);
+   BUG_ON(buf_in_urb-status == -EINPROGRESS);
 
/*
 * If the current frame actual_length is contiguous with the next frame
@@ -2201,68 +2201,68 @@ static int __wa_populate_buf_in_urb_isoc(struct wahc 
*wa, struct wa_xfer *xfer,
 ((iso_frame-actual_length % dti_packet_size) == 0));
 
/* this should always be 0 before a resubmit. */
-   wa-buf_in_urb-num_mapped_sgs  = 0;
-   wa-buf_in_urb-transfer_dma = xfer-urb-transfer_dma +
+   buf_in_urb-num_mapped_sgs  = 0;
+   buf_in_urb-transfer_dma = xfer-urb-transfer_dma +
iso_frame_desc[urb_start_frame].offset;
-   wa-buf_in_urb-transfer_buffer_length = total_len;
-   wa-buf_in_urb-transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-   wa-buf_in_urb-transfer_buffer = NULL;
-   wa-buf_in_urb-sg = NULL;
-   wa-buf_in_urb-num_sgs = 0;
-   wa-buf_in_urb-context = seg;
+   buf_in_urb-transfer_buffer_length = total_len

[PATCH 0/3] usb: wusbcore: HWA performance optimizations

2014-03-06 Thread Thomas Pugliese
This set of patches includes a set of performance optimizations for the 
HWA.  The first adds a quirk for Alereon HWAs to disable transfer 
notifications since they are never used.  The last two are generic 
optimizations to improve webcam image quality and CPU utilization for 
isochronous read transfers.

Thomas Pugliese (3):
  usb: wusbcore: disable transfer notifications for Alereon HWAs
  usb: wusbcore: combine iso transfer result frame reads when possible
  usb: wusbcore: use multiple urbs for HWA iso transfer result frame reads

 drivers/usb/host/hwa-hc.c  |  42 -
 drivers/usb/wusbcore/wa-hc.c   |   2 -
 drivers/usb/wusbcore/wa-hc.h   |  26 +++-
 drivers/usb/wusbcore/wa-xfer.c | 344 +++--
 4 files changed, 292 insertions(+), 122 deletions(-)

-- 
1.8.3.2

--
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 3/3] usb: wusbcore: use multiple urbs for HWA iso transfer result frame reads

2014-03-06 Thread Thomas Pugliese
Submit multiple concurrent urbs for HWA isochronous transfer result data 
frame reads. This keeps the read pipeline full and significantly 
improves performance in cases where the frame reads cannot be combined 
because they are not contiguous or multiples of the max packet size.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-hc.c   |   2 -
 drivers/usb/wusbcore/wa-hc.h   |  15 +++-
 drivers/usb/wusbcore/wa-xfer.c | 191 ++---
 3 files changed, 134 insertions(+), 74 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c
index 368360f..252c7bd 100644
--- a/drivers/usb/wusbcore/wa-hc.c
+++ b/drivers/usb/wusbcore/wa-hc.c
@@ -75,8 +75,6 @@ void __wa_destroy(struct wahc *wa)
if (wa-dti_urb) {
usb_kill_urb(wa-dti_urb);
usb_put_urb(wa-dti_urb);
-   usb_kill_urb(wa-buf_in_urb);
-   usb_put_urb(wa-buf_in_urb);
}
kfree(wa-dti_buf);
wa_nep_destroy(wa);
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index 7510960..f2a8d29 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -125,7 +125,8 @@ struct wa_rpipe {
 
 enum wa_dti_state {
WA_DTI_TRANSFER_RESULT_PENDING,
-   WA_DTI_ISOC_PACKET_STATUS_PENDING
+   WA_DTI_ISOC_PACKET_STATUS_PENDING,
+   WA_DTI_BUF_IN_DATA_PENDING
 };
 
 enum wa_quirks {
@@ -146,6 +147,8 @@ enum wa_vendor_specific_requests {
WA_REQ_ALEREON_FEATURE_SET = 0x01,
WA_REQ_ALEREON_FEATURE_CLEAR = 0x00,
 };
+
+#define WA_MAX_BUF_IN_URBS 4
 /**
  * Instance of a HWA Host Controller
  *
@@ -216,7 +219,9 @@ struct wahc {
u32 dti_isoc_xfer_in_progress;
u8  dti_isoc_xfer_seg;
struct urb *dti_urb;/* URB for reading xfer results */
-   struct urb *buf_in_urb; /* URB for reading data in */
+   /* URBs for reading data in */
+   struct urb buf_in_urbs[WA_MAX_BUF_IN_URBS];
+   int active_buf_in_urbs; /* number of buf_in_urbs active. */
struct edc dti_edc; /* DTI error density counter */
void *dti_buf;
size_t dti_buf_size;
@@ -286,6 +291,8 @@ static inline void wa_rpipe_init(struct wahc *wa)
 
 static inline void wa_init(struct wahc *wa)
 {
+   int index;
+
edc_init(wa-nep_edc);
atomic_set(wa-notifs_queued, 0);
wa-dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
@@ -299,6 +306,10 @@ static inline void wa_init(struct wahc *wa)
INIT_WORK(wa-xfer_error_work, wa_process_errored_transfers_run);
wa-dto_in_use = 0;
atomic_set(wa-xfer_id_count, 1);
+   /* init the buf in URBs */
+   for (index = 0; index  WA_MAX_BUF_IN_URBS; ++index)
+   usb_init_urb((wa-buf_in_urbs[index]));
+   wa-active_buf_in_urbs = 0;
 }
 
 /**
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index f930bbb..c8e2a47 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2159,9 +2159,9 @@ static void wa_complete_remaining_xfer_segs(struct 
wa_xfer *xfer,
}
 }
 
-/* Populate the wa-buf_in_urb based on the current isoc transfer state. */
-static int __wa_populate_buf_in_urb_isoc(struct wahc *wa, struct wa_xfer *xfer,
-   struct wa_seg *seg)
+/* Populate the given urb based on the current isoc transfer state. */
+static int __wa_populate_buf_in_urb_isoc(struct wahc *wa,
+   struct urb *buf_in_urb, struct wa_xfer *xfer, struct wa_seg *seg)
 {
int urb_start_frame = seg-isoc_frame_index + seg-isoc_frame_offset;
int seg_index, total_len = 0, urb_frame_index = urb_start_frame;
@@ -2171,7 +2171,7 @@ static int __wa_populate_buf_in_urb_isoc(struct wahc *wa, 
struct wa_xfer *xfer,
int next_frame_contiguous;
struct usb_iso_packet_descriptor *iso_frame;
 
-   BUG_ON(wa-buf_in_urb-status == -EINPROGRESS);
+   BUG_ON(buf_in_urb-status == -EINPROGRESS);
 
/*
 * If the current frame actual_length is contiguous with the next frame
@@ -2201,68 +2201,68 @@ static int __wa_populate_buf_in_urb_isoc(struct wahc 
*wa, struct wa_xfer *xfer,
 ((iso_frame-actual_length % dti_packet_size) == 0));
 
/* this should always be 0 before a resubmit. */
-   wa-buf_in_urb-num_mapped_sgs  = 0;
-   wa-buf_in_urb-transfer_dma = xfer-urb-transfer_dma +
+   buf_in_urb-num_mapped_sgs  = 0;
+   buf_in_urb-transfer_dma = xfer-urb-transfer_dma +
iso_frame_desc[urb_start_frame].offset;
-   wa-buf_in_urb-transfer_buffer_length = total_len;
-   wa-buf_in_urb-transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-   wa-buf_in_urb-transfer_buffer = NULL;
-   wa-buf_in_urb-sg = NULL;
-   wa-buf_in_urb-num_sgs = 0;
-   wa-buf_in_urb-context = seg;
+   buf_in_urb-transfer_buffer_length = total_len

[PATCH 2/3] usb: wusbcore: combine iso transfer result frame reads when possible

2014-03-06 Thread Thomas Pugliese
When reading the transfer result data for an isochronous in request, if 
the current frame actual_length is contiguous with the next frame and 
actual_length is a multiple of the DTI endpoint max packet size, combine 
the current frame with the next frame in a single URB.  This reduces the 
number of URBs that must be submitted in that case which increases 
performance and reduces CPU interrupt overhead.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 104 +
 1 file changed, 75 insertions(+), 29 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 6046fee..f930bbb 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2160,22 +2160,59 @@ static void wa_complete_remaining_xfer_segs(struct 
wa_xfer *xfer,
 }
 
 /* Populate the wa-buf_in_urb based on the current isoc transfer state. */
-static void __wa_populate_buf_in_urb_isoc(struct wahc *wa, struct wa_xfer 
*xfer,
-   struct wa_seg *seg, int curr_iso_frame)
+static int __wa_populate_buf_in_urb_isoc(struct wahc *wa, struct wa_xfer *xfer,
+   struct wa_seg *seg)
 {
+   int urb_start_frame = seg-isoc_frame_index + seg-isoc_frame_offset;
+   int seg_index, total_len = 0, urb_frame_index = urb_start_frame;
+   struct usb_iso_packet_descriptor *iso_frame_desc =
+   xfer-urb-iso_frame_desc;
+   const int dti_packet_size = usb_endpoint_maxp(wa-dti_epd);
+   int next_frame_contiguous;
+   struct usb_iso_packet_descriptor *iso_frame;
+
BUG_ON(wa-buf_in_urb-status == -EINPROGRESS);
 
+   /*
+* If the current frame actual_length is contiguous with the next frame
+* and actual_length is a multiple of the DTI endpoint max packet size,
+* combine the current frame with the next frame in a single URB.  This
+* reduces the number of URBs that must be submitted in that case.
+*/
+   seg_index = seg-isoc_frame_index;
+   do {
+   next_frame_contiguous = 0;
+
+   iso_frame = iso_frame_desc[urb_frame_index];
+   total_len += iso_frame-actual_length;
+   ++urb_frame_index;
+   ++seg_index;
+
+   if (seg_index  seg-isoc_frame_count) {
+   struct usb_iso_packet_descriptor *next_iso_frame;
+
+   next_iso_frame = iso_frame_desc[urb_frame_index];
+
+   if ((iso_frame-offset + iso_frame-actual_length) ==
+   next_iso_frame-offset)
+   next_frame_contiguous = 1;
+   }
+   } while (next_frame_contiguous
+((iso_frame-actual_length % dti_packet_size) == 0));
+
/* this should always be 0 before a resubmit. */
wa-buf_in_urb-num_mapped_sgs  = 0;
wa-buf_in_urb-transfer_dma = xfer-urb-transfer_dma +
-   xfer-urb-iso_frame_desc[curr_iso_frame].offset;
-   wa-buf_in_urb-transfer_buffer_length =
-   xfer-urb-iso_frame_desc[curr_iso_frame].actual_length;
+   iso_frame_desc[urb_start_frame].offset;
+   wa-buf_in_urb-transfer_buffer_length = total_len;
wa-buf_in_urb-transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
wa-buf_in_urb-transfer_buffer = NULL;
wa-buf_in_urb-sg = NULL;
wa-buf_in_urb-num_sgs = 0;
wa-buf_in_urb-context = seg;
+
+   /* return the number of frames included in this URB. */
+   return seg_index - seg-isoc_frame_index;
 }
 
 /* Populate the wa-buf_in_urb based on the current transfer state. */
@@ -2458,19 +2495,20 @@ static int wa_process_iso_packet_status(struct wahc 
*wa, struct urb *urb)
}
 
if (xfer-is_inbound  data_frame_count) {
-   int result;
+   int result, urb_frame_count;
 
seg-isoc_frame_index = first_frame_index;
/* submit a read URB for the first frame with data. */
-   __wa_populate_buf_in_urb_isoc(wa, xfer, seg,
-   seg-isoc_frame_index + seg-isoc_frame_offset);
+   urb_frame_count = __wa_populate_buf_in_urb_isoc(wa, xfer, seg);
+   /* advance index to start of next read URB. */
+   seg-isoc_frame_index += urb_frame_count;
 
result = usb_submit_urb(wa-buf_in_urb, GFP_ATOMIC);
if (result  0) {
dev_err(dev, DTI Error: Could not submit buf in URB 
(%d),
result);
wa_reset_all(wa);
-   } else if (data_frame_count  1)
+   } else if (data_frame_count  urb_frame_count)
/* If we need to read multiple frames, set DTI busy. */
dti_busy = 1;
} else {
@@ -2511,8 +2549,9 @@ static void wa_buf_in_cb(struct urb *urb)
struct

[PATCH 1/3] usb: wusbcore: disable transfer notifications for Alereon HWAs

2014-03-06 Thread Thomas Pugliese
The HWA driver does not do anything with transfer notifications after
receiving the first one and the Alereon HWA allows them to be disabled
as a performance optimization.  This patch sends a vendor specific
command to the Alereon HWA on startup to disable transfer notifications.
If the command is successful, the DTI system is started immediately
since that would normally be started upon the first reception of a
transfer notification which will no longer be sent.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/host/hwa-hc.c  | 42 -
 drivers/usb/wusbcore/wa-hc.h   | 11 ++
 drivers/usb/wusbcore/wa-xfer.c | 83 +-
 3 files changed, 100 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index e076699..d0d8fad 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -261,8 +261,44 @@ static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc)
dev_err(dev, cannot listen to notifications: %d\n, result);
goto error_stop;
}
+   /*
+* If WUSB_QUIRK_ALEREON_HWA_DISABLE_XFER_NOTIFICATIONS is set,
+*  disable transfer notifications.
+*/
+   if (hwahc-wa.quirks 
+   WUSB_QUIRK_ALEREON_HWA_DISABLE_XFER_NOTIFICATIONS) {
+   struct usb_host_interface *cur_altsetting =
+   hwahc-wa.usb_iface-cur_altsetting;
+
+   result = usb_control_msg(hwahc-wa.usb_dev,
+   usb_sndctrlpipe(hwahc-wa.usb_dev, 0),
+   WA_REQ_ALEREON_DISABLE_XFER_NOTIFICATIONS,
+   USB_DIR_OUT | USB_TYPE_VENDOR |
+   USB_RECIP_INTERFACE,
+   WA_REQ_ALEREON_FEATURE_SET,
+   cur_altsetting-desc.bInterfaceNumber,
+   NULL, 0,
+   USB_CTRL_SET_TIMEOUT);
+   /*
+* If we successfully sent the control message, start DTI here
+* because no transfer notifications will be received which is
+* where DTI is normally started.
+*/
+   if (result == 0)
+   result = wa_dti_start(hwahc-wa);
+   else
+   result = 0; /* OK.  Continue normally. */
+
+   if (result  0) {
+   dev_err(dev, cannot start DTI: %d\n, result);
+   goto error_dti_start;
+   }
+   }
+
return result;
 
+error_dti_start:
+   wa_nep_disarm(hwahc-wa);
 error_stop:
__wa_clear_feature(hwahc-wa, WA_ENABLE);
return result;
@@ -827,10 +863,12 @@ static void hwahc_disconnect(struct usb_interface 
*usb_iface)
 static struct usb_device_id hwahc_id_table[] = {
/* Alereon 5310 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5310, 0xe0, 0x02, 0x01),
- .driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC },
+ .driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC |
+   WUSB_QUIRK_ALEREON_HWA_DISABLE_XFER_NOTIFICATIONS },
/* Alereon 5611 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5611, 0xe0, 0x02, 0x01),
- .driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC },
+ .driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC |
+   WUSB_QUIRK_ALEREON_HWA_DISABLE_XFER_NOTIFICATIONS },
/* FIXME: use class labels for this */
{ USB_INTERFACE_INFO(0xe0, 0x02, 0x01), },
{},
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index a2ef84b..7510960 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -134,8 +134,18 @@ enum wa_quirks {
 * requests to be concatenated and not sent as separate packets.
 */
WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC  = 0x01,
+   /*
+* The Alereon HWA can be instructed to not send transfer notifications
+* as an optimization.
+*/
+   WUSB_QUIRK_ALEREON_HWA_DISABLE_XFER_NOTIFICATIONS   = 0x02,
 };
 
+enum wa_vendor_specific_requests {
+   WA_REQ_ALEREON_DISABLE_XFER_NOTIFICATIONS = 0x4C,
+   WA_REQ_ALEREON_FEATURE_SET = 0x01,
+   WA_REQ_ALEREON_FEATURE_CLEAR = 0x00,
+};
 /**
  * Instance of a HWA Host Controller
  *
@@ -234,6 +244,7 @@ struct wahc {
 extern int wa_create(struct wahc *wa, struct usb_interface *iface,
kernel_ulong_t);
 extern void __wa_destroy(struct wahc *wa);
+extern int wa_dti_start(struct wahc *wa);
 void wa_reset_all(struct wahc *wa);
 
 
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 12b764e..6046fee 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2741,41 +2741,15 @@ out:
 }
 
 /*
- * Transfer complete notification
- *
- * Called from the notif.c code. We get

[PATCH 1/2] usb: wusbcore: fix potential double list_del on urb dequeue

2014-03-04 Thread Thomas Pugliese
This patch locks rpipe-seg_lock around the entire transfer segment 
cleanup loop in wa_urb_dequeue instead of just one case of the switch 
statement.  This fixes a race between __wa_xfer_delayed_run and 
wa_urb_dequeue where a transfer segment in the WA_SEG_DELAYED state 
could be removed from the rpipe seg_list twice leading to memory 
corruption.  It also switches the spin_lock call to use the non-irqsave 
version since the xfer-lock is already held and irqs already disabled.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index c688afa..1cd0f61 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -1974,6 +1974,11 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int 
status)
goto out_unlock;/* setup(), enqueue_b() completes */
/* Ok, the xfer is in flight already, it's been setup and submitted.*/
xfer_abort_pending = __wa_xfer_abort(xfer) = 0;
+   /*
+* grab the rpipe-seg_lock here to prevent racing with
+* __wa_xfer_delayed_run.
+*/
+   spin_lock(rpipe-seg_lock);
for (cnt = 0; cnt  xfer-segs; cnt++) {
seg = xfer-seg[cnt];
pr_debug(%s: xfer id 0x%08X#%d status = %d\n,
@@ -1994,10 +1999,8 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int 
status)
 */
seg-status = WA_SEG_ABORTED;
seg-result = -ENOENT;
-   spin_lock_irqsave(rpipe-seg_lock, flags2);
list_del(seg-list_node);
xfer-segs_done++;
-   spin_unlock_irqrestore(rpipe-seg_lock, flags2);
break;
case WA_SEG_DONE:
case WA_SEG_ERROR:
@@ -2026,6 +2029,7 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int 
status)
break;
}
}
+   spin_unlock(rpipe-seg_lock);
xfer-result = urb-status; /* -ENOENT or -ECONNRESET */
done = __wa_xfer_is_done(xfer);
spin_unlock_irqrestore(xfer-lock, flags);
-- 
1.8.3.2

--
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 0/2] usb: wusbcore: additional urb dequeue cleanups

2014-03-04 Thread Thomas Pugliese
Fix two race conditions that could cause memory corruption when 
unlinking WUSB urbs.

Thomas Pugliese (2):
  usb: wusbcore: fix potential double list_del on urb dequeue
  usb: wusbcore: don't mark WA_SEG_DTI_PENDING segs as done in
urb_dequeue

 drivers/usb/wusbcore/wa-xfer.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

-- 
1.8.3.2

--
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 2/2] usb: wusbcore: don't mark WA_SEG_DTI_PENDING segs as done in urb_dequeue

2014-03-04 Thread Thomas Pugliese
Data for transfer segments in the WA_SEG_DTI_PENDING state is actively
being read by the driver.  Let the buffer read callback handle the
transfer cleanup since cleaning it up in wa_urb_dequeue will cause the
read callback to access invalid memory if the transfer is completed.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 1cd0f61..12b764e 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2007,6 +2007,16 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int 
status)
case WA_SEG_ABORTED:
break;
/*
+* The buf_in data for a segment in the
+* WA_SEG_DTI_PENDING state is actively being read.
+* Let wa_buf_in_cb handle it since it will be called
+* and will increment xfer-segs_done.  Cleaning up
+* here could cause wa_buf_in_cb to access the xfer
+* after it has been completed/freed.
+*/
+   case WA_SEG_DTI_PENDING:
+   break;
+   /*
 * In the states below, the HWA device already knows
 * about the transfer.  If an abort request was sent,
 * allow the HWA to process it and wait for the
@@ -2015,7 +2025,6 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int 
status)
 */
case WA_SEG_SUBMITTED:
case WA_SEG_PENDING:
-   case WA_SEG_DTI_PENDING:
/*
 * Check if the abort was successfully sent.  This could
 * be false if the HWA has been removed but we haven't
-- 
1.8.3.2

--
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 4/4] usb: wusbcore: add a convenience function for completing a transfer segment

2014-02-28 Thread Thomas Pugliese
This patch adds a convenience function for the commonly performed task
of marking a transfer segment as done.  It combines the 3 steps of
setting the segment status, incrementing the segs_done field of the
transfer and checking if the completed segment results in the transfer
also being done.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 48 --
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 5e5343e..3d6b30d 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -392,6 +392,24 @@ out:
 }
 
 /*
+ * Mark the given segment as done.  Return true if this completes the xfer.
+ * This should only be called for segs that have been submitted to an RPIPE.
+ * Delayed segs are not marked as submitted so they do not need to be marked
+ * as done when cleaning up.
+ *
+ * xfer-lock has to be locked
+ */
+static unsigned __wa_xfer_mark_seg_as_done(struct wa_xfer *xfer,
+   struct wa_seg *seg, enum wa_seg_status status)
+{
+   seg-status = status;
+   xfer-segs_done++;
+
+   /* check for done. */
+   return __wa_xfer_is_done(xfer);
+}
+
+/*
  * Search for a transfer list ID on the HCD's URB list
  *
  * For 32 bit architectures, we use the pointer itself; for 64 bits, a
@@ -821,12 +839,10 @@ error_default:
wa_reset_all(wa);
}
if (seg-status != WA_SEG_ERROR) {
-   seg-status = WA_SEG_ERROR;
seg-result = urb-status;
-   xfer-segs_done++;
__wa_xfer_abort(xfer);
rpipe_ready = rpipe_avail_inc(rpipe);
-   done = __wa_xfer_is_done(xfer);
+   done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_ERROR);
}
spin_unlock_irqrestore(xfer-lock, flags);
if (holding_dto) {
@@ -892,12 +908,11 @@ static void wa_seg_iso_pack_desc_cb(struct urb *urb)
}
if (seg-status != WA_SEG_ERROR) {
usb_unlink_urb(seg-dto_urb);
-   seg-status = WA_SEG_ERROR;
seg-result = urb-status;
-   xfer-segs_done++;
__wa_xfer_abort(xfer);
rpipe_ready = rpipe_avail_inc(rpipe);
-   done = __wa_xfer_is_done(xfer);
+   done = __wa_xfer_mark_seg_as_done(xfer, seg,
+   WA_SEG_ERROR);
}
spin_unlock_irqrestore(xfer-lock, flags);
if (done)
@@ -971,12 +986,10 @@ static void wa_seg_tr_cb(struct urb *urb)
}
usb_unlink_urb(seg-isoc_pack_desc_urb);
usb_unlink_urb(seg-dto_urb);
-   seg-status = WA_SEG_ERROR;
seg-result = urb-status;
-   xfer-segs_done++;
__wa_xfer_abort(xfer);
rpipe_ready = rpipe_avail_inc(rpipe);
-   done = __wa_xfer_is_done(xfer);
+   done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_ERROR);
spin_unlock_irqrestore(xfer-lock, flags);
if (done)
wa_xfer_completion(xfer);
@@ -2285,11 +2298,9 @@ static void wa_xfer_result_chew(struct wahc *wa, struct 
wa_xfer *xfer,
goto error_submit_buf_in;
} else {
/* OUT data phase or no data, complete it -- */
-   seg-status = WA_SEG_DONE;
seg-result = bytes_transferred;
-   xfer-segs_done++;
rpipe_ready = rpipe_avail_inc(rpipe);
-   done = __wa_xfer_is_done(xfer);
+   done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_DONE);
}
spin_unlock_irqrestore(xfer-lock, flags);
if (done)
@@ -2453,10 +2464,8 @@ static int wa_process_iso_packet_status(struct wahc *wa, 
struct urb *urb)
dti_busy = 1;
} else {
/* OUT transfer or no more IN data, complete it -- */
-   seg-status = WA_SEG_DONE;
-   xfer-segs_done++;
rpipe_ready = rpipe_avail_inc(rpipe);
-   done = __wa_xfer_is_done(xfer);
+   done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_DONE);
}
spin_unlock_irqrestore(xfer-lock, flags);
wa-dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
@@ -2547,12 +2556,11 @@ static void wa_buf_in_cb(struct urb *urb)
}
} else {
rpipe = xfer-ep-hcpriv;
-   seg-status = WA_SEG_DONE;
dev_dbg(dev, xfer %p#%u: data in done (%zu bytes)\n,
xfer, seg-index, seg-result);
-   xfer-segs_done++;
rpipe_ready = rpipe_avail_inc(rpipe

[PATCH 2/4] usb: wusbcore: fix stranded URB after HWA unplug

2014-02-28 Thread Thomas Pugliese
This patch adds error checking to the abort request callback to forcibly 
clean up the dequeued transfers if the abort request failed.  The 
wa_complete_remaining_xfer_segs was modified so that it could be used in 
this situation as well.  This fixes a stranded URB/PNP hang when the HWA 
is unplugged while playing audio to a wireless audio device.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 56 ++
 1 file changed, 51 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 3ca0555..cb06191 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -167,6 +167,8 @@ struct wa_xfer {
 
 static void __wa_populate_dto_urb_isoc(struct wa_xfer *xfer,
struct wa_seg *seg, int curr_iso_frame);
+static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer,
+   int starting_index, enum wa_seg_status status);
 
 static inline void wa_xfer_init(struct wa_xfer *xfer)
 {
@@ -416,12 +418,51 @@ out:
 
 struct wa_xfer_abort_buffer {
struct urb urb;
+   struct wahc *wa;
struct wa_xfer_abort cmd;
 };
 
 static void __wa_xfer_abort_cb(struct urb *urb)
 {
struct wa_xfer_abort_buffer *b = urb-context;
+   struct wahc *wa = b-wa;
+
+   /*
+* If the abort request URB failed, then the HWA did not get the abort
+* command.  Forcibly clean up the xfer without waiting for a Transfer
+* Result from the HWA.
+*/
+   if (urb-status  0) {
+   struct wa_xfer *xfer;
+   struct device *dev = wa-usb_iface-dev;
+
+   xfer = wa_xfer_get_by_id(wa, le32_to_cpu(b-cmd.dwTransferID));
+   dev_err(dev, %s: Transfer Abort request failed. result: %d\n,
+   __func__, urb-status);
+   if (xfer) {
+   unsigned long flags;
+   int done;
+   struct wa_rpipe *rpipe = xfer-ep-hcpriv;
+
+   dev_err(dev, %s: cleaning up xfer %p ID 0x%08X.\n,
+   __func__, xfer, wa_xfer_id(xfer));
+   spin_lock_irqsave(xfer-lock, flags);
+   /* mark all segs as aborted. */
+   wa_complete_remaining_xfer_segs(xfer, 0,
+   WA_SEG_ABORTED);
+   done = __wa_xfer_is_done(xfer);
+   spin_unlock_irqrestore(xfer-lock, flags);
+   if (done)
+   wa_xfer_completion(xfer);
+   wa_xfer_delayed_run(rpipe);
+   wa_xfer_put(xfer);
+   } else {
+   dev_err(dev, %s: xfer ID 0x%08X already gone.\n,
+__func__, le32_to_cpu(b-cmd.dwTransferID));
+   }
+   }
+
+   wa_put(wa); /* taken in __wa_xfer_abort */
usb_put_urb(b-urb);
 }
 
@@ -449,6 +490,7 @@ static int __wa_xfer_abort(struct wa_xfer *xfer)
b-cmd.bRequestType = WA_XFER_ABORT;
b-cmd.wRPipe = rpipe-descr.wRPipeIndex;
b-cmd.dwTransferID = wa_xfer_id_le32(xfer);
+   b-wa = wa_get(xfer-wa);
 
usb_init_urb(b-urb);
usb_fill_bulk_urb(b-urb, xfer-wa-usb_dev,
@@ -462,6 +504,7 @@ static int __wa_xfer_abort(struct wa_xfer *xfer)
 
 
 error_submit:
+   wa_put(xfer-wa);
if (printk_ratelimit())
dev_err(dev, xfer %p: Can't submit abort request: %d\n,
xfer, result);
@@ -2036,15 +2079,17 @@ static int wa_xfer_status_to_errno(u8 status)
  * no other segment transfer results will be returned from the device.
  * Mark the remaining submitted or pending xfers as completed so that
  * the xfer will complete cleanly.
+ *
+ * xfer-lock must be held
+ *
  */
 static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer,
-   struct wa_seg *incoming_seg, enum wa_seg_status status)
+   int starting_index, enum wa_seg_status status)
 {
int index;
struct wa_rpipe *rpipe = xfer-ep-hcpriv;
 
-   for (index = incoming_seg-index + 1; index  xfer-segs_submitted;
-   index++) {
+   for (index = starting_index; index  xfer-segs_submitted; index++) {
struct wa_seg *current_seg = xfer-seg[index];
 
BUG_ON(current_seg == NULL);
@@ -2202,7 +2247,8 @@ static void wa_xfer_result_chew(struct wahc *wa, struct 
wa_xfer *xfer,
 * transfers with data or below for no data, the xfer will complete.
 */
if (xfer_result-bTransferSegment  0x80)
-   wa_complete_remaining_xfer_segs(xfer, seg, WA_SEG_DONE);
+   wa_complete_remaining_xfer_segs(xfer, seg-index + 1,
+   WA_SEG_DONE);
if (usb_pipeisoc(xfer-urb-pipe)
 (le32_to_cpu(xfer_result-dwNumOfPackets)  0

[PATCH 3/4] usb: wusbcore: prevent urb dequeue and giveback race

2014-02-28 Thread Thomas Pugliese
This patch takes a reference to the wa_xfer object in wa_urb_dequeue to 
prevent the urb giveback code from completing the xfer and freeing it 
while wa_urb_dequeue is executing.  It also checks for done at the start 
to avoid a double completion scenario.  Adding the check for done in 
urb_dequeue means that any other place where a submitted transfer 
segment is marked as done must complete the transfer if it is done.  
__wa_xfer_delayed_run was not checking this case so that check was added 
as well.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 37 +++--
 1 file changed, 27 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index cb06191..5e5343e 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -1471,6 +1471,8 @@ static int __wa_xfer_delayed_run(struct wa_rpipe *rpipe, 
int *dto_waiting)
xfer, wa_xfer_id(xfer), seg-index,
atomic_read(rpipe-segs_available), result);
if (unlikely(result  0)) {
+   int done;
+
spin_unlock_irqrestore(rpipe-seg_lock, flags);
spin_lock_irqsave(xfer-lock, flags);
__wa_xfer_abort(xfer);
@@ -1479,7 +1481,10 @@ static int __wa_xfer_delayed_run(struct wa_rpipe *rpipe, 
int *dto_waiting)
 * the RPIPE seg_list.  Mark it done.
 */
xfer-segs_done++;
+   done = __wa_xfer_is_done(xfer);
spin_unlock_irqrestore(xfer-lock, flags);
+   if (done)
+   wa_xfer_completion(xfer);
spin_lock_irqsave(rpipe-seg_lock, flags);
}
wa_xfer_put(xfer);
@@ -1915,20 +1920,20 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, 
int status)
/* check if it is safe to unlink. */
spin_lock_irqsave(wa-xfer_list_lock, flags);
result = usb_hcd_check_unlink_urb((wa-wusb-usb_hcd), urb, status);
+   if ((result == 0)  urb-hcpriv) {
+   /*
+* Get a xfer ref to prevent a race with wa_xfer_giveback
+* cleaning up the xfer while we are working with it.
+*/
+   wa_xfer_get(urb-hcpriv);
+   }
spin_unlock_irqrestore(wa-xfer_list_lock, flags);
if (result)
return result;
 
xfer = urb-hcpriv;
-   if (xfer == NULL) {
-   /*
-* Nothing setup yet enqueue will see urb-status !=
-* -EINPROGRESS (by hcd layer) and bail out with
-* error, no need to do completion
-*/
-   BUG_ON(urb-status == -EINPROGRESS);
-   goto out;
-   }
+   if (xfer == NULL)
+   return -ENOENT;
spin_lock_irqsave(xfer-lock, flags);
pr_debug(%s: DEQUEUE xfer id 0x%08X\n, __func__, wa_xfer_id(xfer));
rpipe = xfer-ep-hcpriv;
@@ -1939,6 +1944,16 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int 
status)
result = -ENOENT;
goto out_unlock;
}
+   /*
+* Check for done to avoid racing with wa_xfer_giveback and completing
+* twice.
+*/
+   if (__wa_xfer_is_done(xfer)) {
+   pr_debug(%s: xfer %p id 0x%08X already done.\n, __func__,
+   xfer, wa_xfer_id(xfer));
+   result = -ENOENT;
+   goto out_unlock;
+   }
/* Check the delayed list - if there, release and complete */
spin_lock_irqsave(wa-xfer_list_lock, flags2);
if (!list_empty(xfer-list_node)  xfer-seg == NULL)
@@ -2007,11 +2022,12 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, 
int status)
wa_xfer_completion(xfer);
if (rpipe_ready)
wa_xfer_delayed_run(rpipe);
+   wa_xfer_put(xfer);
return result;
 
 out_unlock:
spin_unlock_irqrestore(xfer-lock, flags);
-out:
+   wa_xfer_put(xfer);
return result;
 
 dequeue_delayed:
@@ -2020,6 +2036,7 @@ dequeue_delayed:
xfer-result = urb-status;
spin_unlock_irqrestore(xfer-lock, flags);
wa_xfer_giveback(xfer);
+   wa_xfer_put(xfer);
usb_put_urb(urb);   /* we got a ref in enqueue() */
return 0;
 }
-- 
1.8.3.2

--
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 1/4] usb: wusbcore: fix kernel panic on HWA unplug

2014-02-28 Thread Thomas Pugliese
This patch adds ref counting to sections of code that operate on struct
wa_xfer objects that were missing it.  Specifically, error handling
cases need to be protected from freeing the xfer while it is still in
use elsewhere.  This fixes a kernel panic that can occur when pulling
the HWA dongle while data is being transferred to a wireless device.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 48 ++
 1 file changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 3cd96e9..3ca0555 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -733,6 +733,8 @@ static void wa_seg_dto_cb(struct urb *urb)
seg-isoc_frame_offset + seg-isoc_frame_index);
 
/* resubmit the URB with the next isoc frame. */
+   /* take a ref on resubmit. */
+   wa_xfer_get(xfer);
result = usb_submit_urb(seg-dto_urb, GFP_ATOMIC);
if (result  0) {
dev_err(dev, xfer 0x%08X#%u: DTO submit 
failed: %d\n,
@@ -760,9 +762,13 @@ static void wa_seg_dto_cb(struct urb *urb)
goto error_default;
}
 
+   /* taken when this URB was submitted. */
+   wa_xfer_put(xfer);
return;
 
 error_dto_submit:
+   /* taken on resubmit attempt. */
+   wa_xfer_put(xfer);
 error_default:
spin_lock_irqsave(xfer-lock, flags);
rpipe = xfer-ep-hcpriv;
@@ -788,7 +794,8 @@ error_default:
wa_xfer_completion(xfer);
if (rpipe_ready)
wa_xfer_delayed_run(rpipe);
-
+   /* taken when this URB was submitted. */
+   wa_xfer_put(xfer);
 }
 
 /*
@@ -855,6 +862,8 @@ static void wa_seg_iso_pack_desc_cb(struct urb *urb)
if (rpipe_ready)
wa_xfer_delayed_run(rpipe);
}
+   /* taken when this URB was submitted. */
+   wa_xfer_put(xfer);
 }
 
 /*
@@ -931,6 +940,8 @@ static void wa_seg_tr_cb(struct urb *urb)
if (rpipe_ready)
wa_xfer_delayed_run(rpipe);
}
+   /* taken when this URB was submitted. */
+   wa_xfer_put(xfer);
 }
 
 /*
@@ -1318,30 +1329,41 @@ static int __wa_seg_submit(struct wa_rpipe *rpipe, 
struct wa_xfer *xfer,
/* default to done unless we encounter a multi-frame isoc segment. */
*dto_done = 1;
 
+   /*
+* Take a ref for each segment urb so the xfer cannot disappear until
+* all of the callbacks run.
+*/
+   wa_xfer_get(xfer);
/* submit the transfer request. */
+   seg-status = WA_SEG_SUBMITTED;
result = usb_submit_urb(seg-tr_urb, GFP_ATOMIC);
if (result  0) {
pr_err(%s: xfer %p#%u: REQ submit failed: %d\n,
   __func__, xfer, seg-index, result);
-   goto error_seg_submit;
+   wa_xfer_put(xfer);
+   goto error_tr_submit;
}
/* submit the isoc packet descriptor if present. */
if (seg-isoc_pack_desc_urb) {
+   wa_xfer_get(xfer);
result = usb_submit_urb(seg-isoc_pack_desc_urb, GFP_ATOMIC);
seg-isoc_frame_index = 0;
if (result  0) {
pr_err(%s: xfer %p#%u: ISO packet descriptor submit 
failed: %d\n,
   __func__, xfer, seg-index, result);
+   wa_xfer_put(xfer);
goto error_iso_pack_desc_submit;
}
}
/* submit the out data if this is an out request. */
if (seg-dto_urb) {
struct wahc *wa = xfer-wa;
+   wa_xfer_get(xfer);
result = usb_submit_urb(seg-dto_urb, GFP_ATOMIC);
if (result  0) {
pr_err(%s: xfer %p#%u: DTO submit failed: %d\n,
   __func__, xfer, seg-index, result);
+   wa_xfer_put(xfer);
goto error_dto_submit;
}
/*
@@ -1353,7 +1375,6 @@ static int __wa_seg_submit(struct wa_rpipe *rpipe, struct 
wa_xfer *xfer,
 (seg-isoc_frame_count  1))
*dto_done = 0;
}
-   seg-status = WA_SEG_SUBMITTED;
rpipe_avail_dec(rpipe);
return 0;
 
@@ -1361,7 +1382,7 @@ error_dto_submit:
usb_unlink_urb(seg-isoc_pack_desc_urb);
 error_iso_pack_desc_submit:
usb_unlink_urb(seg-tr_urb);
-error_seg_submit:
+error_tr_submit:
seg-status = WA_SEG_ERROR;
seg-result = result;
*dto_done = 1;
@@ -1393,6 +1414,12 @@ static int __wa_xfer_delayed_run(struct wa_rpipe *rpipe, 
int *dto_waiting)
 list_node);
list_del(seg-list_node

[PATCH 0/4] usb: wusbcore: HWA unplug and URB dequeue fixes

2014-02-28 Thread Thomas Pugliese
This set of patches fixes some issues with the URB dequeue process in 
the HWA.  In particular, problems that occur when unplugging the HWA 
dongle while transferring data to a device.  The last patch in the set 
is just code cleanup to hopefully make this case a little less error 
prone.

Thomas Pugliese (4):
  usb: wusbcore: fix kernel panic on HWA unplug
  usb: wusbcore: fix stranded URB after HWA unplug
  usb: wusbcore: prevent urb dequeue and giveback race
  usb: wusbcore: add a convenience function for completing a transfer segment

 drivers/usb/wusbcore/wa-xfer.c | 189 -
 1 file changed, 149 insertions(+), 40 deletions(-)

-- 
1.8.3.2

--
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] usb: wusbcore: add info to HWA debug prints

2014-02-28 Thread Thomas Pugliese
This patch adds a debug print in the transfer dequeue case where a
transfer result arrives for a transfer that has already been cleaned up.
It also adds the transfer ID to some debug prints and prints error codes
as signed integers in a couple of others.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 25 -
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 3d6b30d..7c9887c 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -369,13 +369,13 @@ static unsigned __wa_xfer_is_done(struct wa_xfer *xfer)
break;
case WA_SEG_ERROR:
xfer-result = seg-result;
-   dev_dbg(dev, xfer %p ID %08X#%u: ERROR result 
%zu(0x%08zX)\n,
+   dev_dbg(dev, xfer %p ID %08X#%u: ERROR result 
%zi(0x%08zX)\n,
xfer, wa_xfer_id(xfer), seg-index, seg-result,
seg-result);
goto out;
case WA_SEG_ABORTED:
xfer-result = seg-result;
-   dev_dbg(dev, xfer %p ID %08X#%u: ABORTED result 
%zu(0x%08zX)\n,
+   dev_dbg(dev, xfer %p ID %08X#%u: ABORTED result 
%zi(0x%08zX)\n,
xfer, wa_xfer_id(xfer), seg-index, seg-result,
seg-result);
goto out;
@@ -2262,7 +2262,7 @@ static void wa_xfer_result_chew(struct wahc *wa, struct 
wa_xfer *xfer,
}
if (usb_status  0x80) {
seg-result = wa_xfer_status_to_errno(usb_status);
-   dev_err(dev, DTI: xfer %p#:%08X:%u failed (0x%02x)\n,
+   dev_err(dev, DTI: xfer %p 0x%08X:#%u failed (0x%02x)\n,
xfer, xfer-id, seg-index, usb_status);
seg-status = ((usb_status  0x7F) == WA_XFER_STATUS_ABORTED) ?
WA_SEG_ABORTED : WA_SEG_ERROR;
@@ -2556,8 +2556,10 @@ static void wa_buf_in_cb(struct urb *urb)
}
} else {
rpipe = xfer-ep-hcpriv;
-   dev_dbg(dev, xfer %p#%u: data in done (%zu bytes)\n,
-   xfer, seg-index, seg-result);
+   dev_dbg(dev,
+   xfer %p 0x%08X#%u: data in done (%zu bytes)\n,
+   xfer, wa_xfer_id(xfer), seg-index,
+   seg-result);
rpipe_ready = rpipe_avail_inc(rpipe);
done = __wa_xfer_mark_seg_as_done(xfer, seg,
WA_SEG_DONE);
@@ -2575,8 +2577,9 @@ static void wa_buf_in_cb(struct urb *urb)
spin_lock_irqsave(xfer-lock, flags);
rpipe = xfer-ep-hcpriv;
if (printk_ratelimit())
-   dev_err(dev, xfer %p#%u: data in error %d\n,
-   xfer, seg-index, urb-status);
+   dev_err(dev, xfer %p 0x%08X#%u: data in error %d\n,
+   xfer, wa_xfer_id(xfer), seg-index,
+   urb-status);
if (edc_inc(wa-nep_edc, EDC_MAX_ERRORS,
EDC_ERROR_TIMEFRAME)){
dev_err(dev, DTO: URB max acceptable errors 
@@ -2670,11 +2673,15 @@ static void wa_dti_cb(struct urb *urb)
xfer_result-hdr.bNotifyType);
break;
}
+   xfer_id = le32_to_cpu(xfer_result-dwTransferID);
usb_status = xfer_result-bTransferStatus  0x3f;
-   if (usb_status == WA_XFER_STATUS_NOT_FOUND)
+   if (usb_status == WA_XFER_STATUS_NOT_FOUND) {
/* taken care of already */
+   dev_dbg(dev, %s: xfer 0x%08X#%u not found.\n,
+   __func__, xfer_id,
+   xfer_result-bTransferSegment  0x7f);
break;
-   xfer_id = le32_to_cpu(xfer_result-dwTransferID);
+   }
xfer = wa_xfer_get_by_id(wa, xfer_id);
if (xfer == NULL) {
/* FIXME: transaction not found. */
-- 
1.8.3.2

--
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] usb: wusbcore: read actual_length bytes isoc in segments

2014-02-28 Thread Thomas Pugliese
Use the iso_frame_desc.actual_length field instead of length when
reading isoc in data segments from the HWA.  This fixes a case where the
isoc in read URB would never complete because it expected the HWA to
send more data than it actually did.  When this happened the URB would
be stuck in the driver preventing module unload and clean shutdown.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 7c9887c..0636206 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2159,7 +2159,7 @@ static void __wa_populate_buf_in_urb_isoc(struct wahc 
*wa, struct wa_xfer *xfer,
wa-buf_in_urb-transfer_dma = xfer-urb-transfer_dma +
xfer-urb-iso_frame_desc[curr_iso_frame].offset;
wa-buf_in_urb-transfer_buffer_length =
-   xfer-urb-iso_frame_desc[curr_iso_frame].length;
+   xfer-urb-iso_frame_desc[curr_iso_frame].actual_length;
wa-buf_in_urb-transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
wa-buf_in_urb-transfer_buffer = NULL;
wa-buf_in_urb-sg = NULL;
-- 
1.8.3.2

--
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] usb: wusbcore: adjust iterator correctly when searching for ep comp descriptor

2014-02-28 Thread Thomas Pugliese
If the endpoint companion descriptor is not the first descriptor in the
extra descriptor buffer of a usb_host_endpoint, the loop in
rpipe_epc_find will get its buffer pointer and remaining size values out
of sync.  The buffer ptr 'itr' is advanced by the descriptor's bLength
field but the remaining size value 'itr_size' is decremented by the
bDescriptorType field which is incorrect.  This patch fixes the loop to
decrement itr_size by bLength as it should.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-rpipe.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index 6ca80a4..6d6da12 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -298,7 +298,7 @@ static struct usb_wireless_ep_comp_descriptor 
*rpipe_epc_find(
break;
}
itr += hdr-bLength;
-   itr_size -= hdr-bDescriptorType;
+   itr_size -= hdr-bLength;
}
 out:
return epcd;
-- 
1.8.3.2

--
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: request for pointer to documentation on WUSB

2014-02-28 Thread Thomas Pugliese


On Fri, 28 Feb 2014, Oliver Neukum wrote:

 On Thu, 2014-02-27 at 11:51 -0600, Thomas Pugliese wrote:
  
  On Thu, 27 Feb 2014, Oliver Neukum wrote:
  
   On Thu, 2014-02-27 at 10:46 -0600, Thomas Pugliese wrote:
   
I could be wrong about the chipset.  If I recall correctly, IOGear has 
used multiple chipset vendors across different products.  Do you have a 
link to the product page for the device?
   
   For what it is worth:
   https://www.olidata.com/partners/?module=productstask=subcategoryid=5
   
  
  Ah. That devices is based on the Wisair chipset.  I don't know anything 
  about them other than the fact that they haven't made WUSB devices for 
  several years and may be out of business.  It's possible that you could 
  get it working but you would probably need to take a USB trace under 
  windows and reverse engineer any quirks that are causing it to fail with 
  the Linux driver.
 
 Urgh. Unfortunately I need to do certification tests soon.
 Can you recommend a working model?
 
   Regards
   Oliver
 

Well, the only WUSB association model supported in Linux is cable-based 
association (CBAF).  I don't know of any shipping consumer device that 
uses that model anymore.  In that process the CHID, CDID, and CKEY 
exchange is done by plugging the wireless device into the host PC once 
before it can be connected wirelessly.  Devices currently on the market 
such as this:

http://store.warpia.com/product_p/SWP120A.htm?gclid=COCZpvHo77wCFSFo7AodQg0AWA

use either the ConnectToMe association method that was included in the 
WUSB 1.1 draft spec or some proprietary version of that.

The devices I have been using are targetted for industrial environments 
and come pre-associated with each other.  The CHID, CDID, and CKEY values 
are provided with the device and thus will work with the existing Linux 
driver.

So the short answer is that I don't know of any consumer WUSB product that 
will work as is under Linux.  Sorry.

Thomas
--
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] usb: wusbcore: fix compile warnings

2014-02-28 Thread Thomas Pugliese
Fix pointer targets differ in signedness and variable set but not
used warnings

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/devconnect.c | 4 +---
 drivers/usb/wusbcore/wa-xfer.c| 6 ++
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/wusbcore/devconnect.c 
b/drivers/usb/wusbcore/devconnect.c
index 3b959e8..0677139 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -284,7 +284,7 @@ void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct 
wusb_dn_connect *dnc,
struct device *dev = wusbhc-dev;
struct wusb_dev *wusb_dev;
struct wusb_port *port;
-   unsigned idx, devnum;
+   unsigned idx;
 
mutex_lock(wusbhc-mutex);
 
@@ -312,8 +312,6 @@ void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct 
wusb_dn_connect *dnc,
goto error_unlock;
}
 
-   devnum = idx + 2;
-
/* Make sure we are using no crypto on that virtual port */
wusbhc-set_ptk(wusbhc, idx, 0, NULL, 0);
 
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 0636206..404ce81 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -1007,7 +1007,7 @@ static void wa_seg_tr_cb(struct urb *urb)
  */
 static struct scatterlist *wa_xfer_create_subset_sg(struct scatterlist *in_sg,
const unsigned int bytes_transferred,
-   const unsigned int bytes_to_transfer, unsigned int *out_num_sgs)
+   const unsigned int bytes_to_transfer, int *out_num_sgs)
 {
struct scatterlist *out_sg;
unsigned int bytes_processed = 0, offset_into_current_page_data = 0,
@@ -1161,14 +1161,13 @@ static int __wa_populate_dto_urb(struct wa_xfer *xfer,
  */
 static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size)
 {
-   int result, cnt, iso_frame_offset;
+   int result, cnt, isoc_frame_offset = 0;
size_t alloc_size = sizeof(*xfer-seg[0])
- sizeof(xfer-seg[0]-xfer_hdr) + xfer_hdr_size;
struct usb_device *usb_dev = xfer-wa-usb_dev;
const struct usb_endpoint_descriptor *dto_epd = xfer-wa-dto_epd;
struct wa_seg *seg;
size_t buf_itr, buf_size, buf_itr_size;
-   int isoc_frame_offset = 0;
 
result = -ENOMEM;
xfer-seg = kcalloc(xfer-segs, sizeof(xfer-seg[0]), GFP_ATOMIC);
@@ -1176,7 +1175,6 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, 
size_t xfer_hdr_size)
goto error_segs_kzalloc;
buf_itr = 0;
buf_size = xfer-urb-transfer_buffer_length;
-   iso_frame_offset = 0;
for (cnt = 0; cnt  xfer-segs; cnt++) {
size_t iso_pkt_descr_size = 0;
int seg_isoc_frame_count = 0, seg_isoc_size = 0;
-- 
1.8.3.2

--
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: request for pointer to documentation on WUSB

2014-02-27 Thread Thomas Pugliese


On Thu, 27 Feb 2014, Oliver Neukum wrote:

 On Tue, 2014-02-25 at 14:26 -0600, Thomas Pugliese wrote:
 
  Hi Oliver,
 
  1.  Start the wireless channel by storing a CHID value to the host 
  controller's wusb_chid sysfs attribute.
 
 That unfortunately fails:
 [66488.705043] usb 1-1.2: new high-speed USB device number 9 using
 ehci-pci
 [66488.791581] usb 1-1.2: New USB device found, idVendor=13cf,
 idProduct=1200
 [66488.791587] usb 1-1.2: New USB device strings: Mfr=2, Product=1,
 SerialNumber=3
 [66488.791599] usb 1-1.2: Product: Wireless USB Dongle
 [66488.791601] usb 1-1.2: Manufacturer:  
 [66488.791603] usb 1-1.2: SerialNumber: 123456789
 [66489.947323] usb 1-1.2: supported encryption types: CCM-1 (0x01) 
 [66489.947347] hwa-hc 1-1.2:1.0: Wireless USB HWA host controller
 [66489.947355] hwa-hc 1-1.2:1.0: new USB bus registered, assigned bus
 number 5
 [66490.000964] hwa-hc 1-1.2:1.0: Wireless USB Cluster ID set to 0xfe
 [66490.001146] usb usb5: New USB device found, idVendor=1d6b,
 idProduct=0002
 [66490.001150] usb usb5: New USB device strings: Mfr=3, Product=2,
 SerialNumber=1
 [66490.001152] usb usb5: Product: Wireless USB HWA host controller
 [66490.001154] usb usb5: Manufacturer: Linux 3.14.0-rc1-12-desktop+
 hwa-hcd
 [66490.001156] usb usb5: SerialNumber: wusb-hwa
 [66490.001346] hub 5-0:1.0: USB hub found
 [66490.001378] hub 5-0:1.0: 5 ports detected
 [66490.004861] uwb_rc uwb0: new uwb radio controller (mac
 03:00:00:00:1c:af dev 70:b6) on usb 1-1.2:1.1
 
 [66571.177082] uwb_rc uwb0: Cannot set new IE on device: -110
 
 

I believe that device is based on an older Alereon chipset which along 
with most other HWAs uses the updated WHCI protocol for UWB/URC commands.  
Try this patch and see if it helps.

Thomas


diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c
index 0257f35..645789e 100644
--- a/drivers/uwb/hwa-rc.c
+++ b/drivers/uwb/hwa-rc.c
@@ -920,6 +920,9 @@ static const struct usb_device_id hwarc_id_table[] = {
/* Alereon 5611 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5611, 0xe0, 0x01, 0x02),
  .driver_info = WUSB_QUIRK_WHCI_CMD_EVT },
+   /* IOGear 1200 */
+   { USB_DEVICE_AND_INTERFACE_INFO(0x13cf, 0x1200, 0xe0, 0x01, 0x02),
+ .driver_info = WUSB_QUIRK_WHCI_CMD_EVT },
/* Generic match for the Radio Control interface */
{ USB_INTERFACE_INFO(0xe0, 0x01, 0x02), },
{ },
--
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: request for pointer to documentation on WUSB

2014-02-27 Thread Thomas Pugliese


On Thu, 27 Feb 2014, Oliver Neukum wrote:

 On Thu, 2014-02-27 at 08:05 -0600, Thomas Pugliese wrote:
  
  On Thu, 27 Feb 2014, Oliver Neukum wrote:
   
   
  
  I believe that device is based on an older Alereon chipset which along 
  with most other HWAs uses the updated WHCI protocol for UWB/URC commands.  
  Try this patch and see if it helps.
 
 I am afraid it does not help.
 
   Regards
   Oliver
 
 [  885.978133] usb 1-1.2: new high-speed USB device number 5 using
 ehci-pci
 [  886.064733] usb 1-1.2: New USB device found, idVendor=13cf,
 idProduct=1200
 [  886.064741] usb 1-1.2: New USB device strings: Mfr=2, Product=1,
 SerialNumber=3
 [  886.064745] usb 1-1.2: Product: Wireless USB Dongle
 [  886.064748] usb 1-1.2: Manufacturer:  
 [  886.064750] usb 1-1.2: SerialNumber: 123456789
 [  887.251811] uwb_rc uwb0: new uwb radio controller (mac
 03:00:00:00:1c:af dev 9d:7b) on usb 1-1.2:1.1
 [  887.251846] usbcore: registered new interface driver hwa-rc
 [  887.271700] usb 1-1.2: supported encryption types: CCM-1 (0x01) 
 [  887.271738] hwa-hc 1-1.2:1.0: Wireless USB HWA host controller
 [  887.271751] hwa-hc 1-1.2:1.0: new USB bus registered, assigned bus
 number 5
 [  887.325053] hwa-hc 1-1.2:1.0: Wireless USB Cluster ID set to 0xfe
 [  887.325112] usb usb5: New USB device found, idVendor=1d6b,
 idProduct=0002
 [  887.325116] usb usb5: New USB device strings: Mfr=3, Product=2,
 SerialNumber=1
 [  887.325120] usb usb5: Product: Wireless USB HWA host controller
 [  887.325123] usb usb5: Manufacturer: Linux 3.14.0-rc3-12-desktop+
 hwa-hcd
 [  887.325126] usb usb5: SerialNumber: wusb-hwa
 [  887.325390] hub 5-0:1.0: USB hub found
 [  887.325403] hub 5-0:1.0: 5 ports detected
 [  887.326799] usbcore: registered new interface driver hwa-hc
 [ 1042.153236] uwb_rc uwb0: Cannot set new IE on device: -110


I could be wrong about the chipset.  If I recall correctly, IOGear has 
used multiple chipset vendors across different products.  Do you have a 
link to the product page for the device?

Another possiblity is that the HWA is in DFU mode and it will need a 
firmware image downloaded before it will function properly.  I am actually 
working on a user service to download firmware images for devices based on 
the Alereon chipset but I don't have an estimate on the completion date.

Regards,
Thomas
--
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: request for pointer to documentation on WUSB

2014-02-27 Thread Thomas Pugliese


On Thu, 27 Feb 2014, Oliver Neukum wrote:

 On Thu, 2014-02-27 at 10:46 -0600, Thomas Pugliese wrote:
 
  I could be wrong about the chipset.  If I recall correctly, IOGear has 
  used multiple chipset vendors across different products.  Do you have a 
  link to the product page for the device?
 
 For what it is worth:
 https://www.olidata.com/partners/?module=productstask=subcategoryid=5
 

Ah. That devices is based on the Wisair chipset.  I don't know anything 
about them other than the fact that they haven't made WUSB devices for 
several years and may be out of business.  It's possible that you could 
get it working but you would probably need to take a USB trace under 
windows and reverse engineer any quirks that are causing it to fail with 
the Linux driver.

  Another possiblity is that the HWA is in DFU mode and it will need a 
  firmware image downloaded before it will function properly.  I am actually 
  working on a user service to download firmware images for devices based on 
  the Alereon chipset but I don't have an estimate on the completion date.
 
 There is no separate firmware on the CD, but the Win driver is huge
 (11MB).
 
   Regards
   Oliver
 
--
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: request for pointer to documentation on WUSB

2014-02-25 Thread Thomas Pugliese


On Tue, 25 Feb 2014, Oliver Neukum wrote:

 Hi,
 
 does anybody have a pointer to documentation on how to setup
 a WUSB connection?
 
   Regards
   Oliver
 
 
 --
 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
 

Hi Oliver,
There is some documentation for WUSB scattered across the files below but 
it is not very detailed.

Documentation/usb/wusb-cbaf
Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc
Documentation/ABI/testing/sysfs-wusb_cbaf
Documentation/ABI/testing/sysfs-bus-usb

The basic set of steps to set up a WUSB connection are:

1.  Start the wireless channel by storing a CHID value to the host 
controller's wusb_chid sysfs attribute.

2.  As child devices connect, verify that the value read from their 
wusb_cdid sysfs attribute matches a known device.

3.  If the device is known, set the device's wusb_ck attribute to the 
private CKEY value for that device in order to authenticate it.

4.  Once authenticated, set the authorized attribute to 1 to allow the usb 
core to enumerate the device.

Once that is done, the device should look like any other USB device in the 
system.

Hope this helps,

Thomas
--
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] staging/usbip: Add missing speeds to userspace speed_strings array

2014-01-24 Thread Thomas Pugliese


On Wed, 22 Jan 2014, Shuah Khan wrote:

 Add speed strings for usb wireless and 3.0 to speed_strings array.
 
 Signed-off-by: Shuah Khan shuah...@samsung.com
 ---
  drivers/staging/usbip/userspace/libsrc/usbip_common.c | 2 ++
  1 file changed, 2 insertions(+)
 
 diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.c 
 b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
 index 66f03cc..8cb4fcc 100644
 --- a/drivers/staging/usbip/userspace/libsrc/usbip_common.c
 +++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
 @@ -23,6 +23,8 @@ static const struct speed_string speed_strings[] = {
   { USB_SPEED_LOW,  1.5, Low Speed(1.5Mbps)  },
   { USB_SPEED_FULL, 12,  Full Speed(12Mbps) },
   { USB_SPEED_HIGH, 480, High Speed(480Mbps) },
 + { USB_SPEED_WIRELESS, 2.5, Wireless},
 + { USB_SPEED_SUPER, 5000, Super Speed(5000Mbps) },
   { 0, NULL, NULL }
  };
  
 -- 

Wireless USB supports variable speeds from 53.3Mbps to 480Mbps.  I'm not 
sure how you want to represent that but 2.5 doesn't seem to apply.

Thanks,
Thomas
--
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] staging/usbip: Add missing speeds to userspace speed_strings array

2014-01-24 Thread Thomas Pugliese


On Fri, 24 Jan 2014, Shuah Khan wrote:

 On 01/24/2014 10:08 AM, Thomas Pugliese wrote:
  
  
  On Wed, 22 Jan 2014, Shuah Khan wrote:
  
   Add speed strings for usb wireless and 3.0 to speed_strings array.
   
   Signed-off-by: Shuah Khan shuah...@samsung.com
   ---
 drivers/staging/usbip/userspace/libsrc/usbip_common.c | 2 ++
 1 file changed, 2 insertions(+)
   
   diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.c
   b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
   index 66f03cc..8cb4fcc 100644
   --- a/drivers/staging/usbip/userspace/libsrc/usbip_common.c
   +++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
   @@ -23,6 +23,8 @@ static const struct speed_string speed_strings[] = {
 { USB_SPEED_LOW,  1.5, Low Speed(1.5Mbps)  },
 { USB_SPEED_FULL, 12,  Full Speed(12Mbps) },
 { USB_SPEED_HIGH, 480, High Speed(480Mbps) },
   + { USB_SPEED_WIRELESS, 2.5, Wireless},
   + { USB_SPEED_SUPER, 5000, Super Speed(5000Mbps) },
 { 0, NULL, NULL }
 };
   
   --
  
  Wireless USB supports variable speeds from 53.3Mbps to 480Mbps.  I'm not
  sure how you want to represent that but 2.5 doesn't seem to apply.
  
 
 Would variable be better suited in this case?
 

Sure.  You could also use something like 53.3-480 since that would more 
closely match the other entires which are numerical values in Mbps units.

Thomas
--
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] usb: wusbcore: add debug prints to reservation and channel change

2013-12-20 Thread Thomas Pugliese
This patch adds debug prints to the reservation and channel change 
sequence to help with debugging channel change problems.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/pal.c |1 +
 drivers/usb/wusbcore/reservation.c |1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/usb/wusbcore/pal.c b/drivers/usb/wusbcore/pal.c
index 59e100c..d427e62 100644
--- a/drivers/usb/wusbcore/pal.c
+++ b/drivers/usb/wusbcore/pal.c
@@ -22,6 +22,7 @@ static void wusbhc_channel_changed(struct uwb_pal *pal, int 
channel)
 {
struct wusbhc *wusbhc = container_of(pal, struct wusbhc, pal);
 
+   pr_info(%s: channel = %d\n, __func__, channel);
if (channel  0)
wusbhc_stop(wusbhc);
else
diff --git a/drivers/usb/wusbcore/reservation.c 
b/drivers/usb/wusbcore/reservation.c
index ead79f7..438e175 100644
--- a/drivers/usb/wusbcore/reservation.c
+++ b/drivers/usb/wusbcore/reservation.c
@@ -51,6 +51,7 @@ static void wusbhc_rsv_complete_cb(struct uwb_rsv *rsv)
struct uwb_mas_bm mas;
char buf[72];
 
+   pr_info(%s: state = %d\n, __func__, rsv-state);
switch (rsv-state) {
case UWB_RSV_STATE_O_ESTABLISHED:
uwb_rsv_get_usable_mas(rsv, mas);
-- 
1.7.10.4

--
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 3/3] uwb: use uwb_rsv_callback instead of calling rsv-callback directly

2013-12-20 Thread Thomas Pugliese
Use uwb_rsv_callback wrapper instead of calling rsv-callback directly.
uwb_rsv_callback checks for NULL and is used by other callers of the
callback routine.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/rsv.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c
index 4e7e4bf..3fe6119 100644
--- a/drivers/uwb/rsv.c
+++ b/drivers/uwb/rsv.c
@@ -919,7 +919,7 @@ static void uwb_rsv_alien_bp_work(struct work_struct *work)
 
list_for_each_entry(rsv, rc-reservations, rc_node) {
if (rsv-type != UWB_DRP_TYPE_ALIEN_BP) {
-   rsv-callback(rsv);
+   uwb_rsv_callback(rsv);
}
}
 
-- 
1.7.10.4

--
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 0/3] uwb: minor cleanups

2013-12-20 Thread Thomas Pugliese
This patch set adds some debug prints, cleans up whitespace and comments 
and modifies one location to use the proper wrapper for calling 
reservation callbacks.

Thomas Pugliese (3):
  uwb: add debug prints during channel change and beacon actions
  uwb: whitespace and comment cleanups
  uwb: use uwb_rsv_callback instead of calling rsv-callback directly

 drivers/uwb/beacon.c |5 +++--
 drivers/uwb/radio.c  |6 +-
 drivers/uwb/rsv.c|   16 
 3 files changed, 16 insertions(+), 11 deletions(-)

-- 
1.7.10.4

--
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 1/3] uwb: add debug prints during channel change and beacon actions

2013-12-20 Thread Thomas Pugliese
Add debug prints during channel change and beacon actions.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/beacon.c |3 ++-
 drivers/uwb/radio.c  |4 
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c
index dcdd59b..7b76361 100644
--- a/drivers/uwb/beacon.c
+++ b/drivers/uwb/beacon.c
@@ -117,6 +117,7 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned 
bpst_offset)
int result;
struct device *dev = rc-uwb_dev.dev;
 
+   dev_dbg(dev, %s: channel = %d\n, __func__, channel);
if (channel  0)
channel = -1;
if (channel == -1)
@@ -517,7 +518,7 @@ int uwbd_evt_handle_rc_bp_slot_change(struct uwb_event *evt)
 
mutex_lock(rc-uwb_dev.mutex);
if (uwb_rc_evt_bp_slot_change_no_slot(bpsc)) {
-   dev_info(dev, stopped beaconing: No free slots in BP\n);
+   dev_err(dev, stopped beaconing: No free slots in BP\n);
rc-beaconing = -1;
} else
rc-uwb_dev.beacon_slot = 
uwb_rc_evt_bp_slot_change_slot_num(bpsc);
diff --git a/drivers/uwb/radio.c b/drivers/uwb/radio.c
index d58dfec..10adb98 100644
--- a/drivers/uwb/radio.c
+++ b/drivers/uwb/radio.c
@@ -62,6 +62,10 @@ static void uwb_radio_channel_changed(struct uwb_rc *rc, int 
channel)
 static int uwb_radio_change_channel(struct uwb_rc *rc, int channel)
 {
int ret = 0;
+   struct device *dev = rc-uwb_dev.dev;
+
+   dev_dbg(dev, %s: channel = %d, rc-beaconing = %d\n, __func__,
+   channel, rc-beaconing);
 
if (channel == -1)
uwb_radio_channel_changed(rc, channel);
-- 
1.7.10.4

--
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] uwb: move mutex_lock to error case in uwbd_evt_handle_rc_bp_slot_change

2013-12-20 Thread Thomas Pugliese
Only acquire rc-uwb_dev.mutex in the error case in
uwbd_evt_handle_rc_bp_slot_change.  This fixes a bug where establishing
a reservation on a new channel will fail if we were unable to establish
a reservation on the previous channel due to DRP conflict.

If rc-uwb_dev.mutex is acquired in the non-error case when the uwb
system is attempting to start beaconing, it will block because the start
beaconing code is holding this mutex.  This prevents any other
notifications from the URC from being processed.  In particular, the
DRP_AVAILABILITY notification will not be processed during the start
beaconing process which can result in a failure to establish a
reservation.  It is safe to not hold the mutex in the non-error
case since the only other place rc-uwb_dev.beacon_slot is accessed is
in the same worker thread that uwbd_evt_handle_rc_bp_slot_change
executes in.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/beacon.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c
index 4190f29..92407e8 100644
--- a/drivers/uwb/beacon.c
+++ b/drivers/uwb/beacon.c
@@ -516,13 +516,13 @@ int uwbd_evt_handle_rc_bp_slot_change(struct uwb_event 
*evt)
}
bpsc = container_of(evt-notif.rceb, struct uwb_rc_evt_bp_slot_change, 
rceb);
 
-   mutex_lock(rc-uwb_dev.mutex);
if (uwb_rc_evt_bp_slot_change_no_slot(bpsc)) {
+   mutex_lock(rc-uwb_dev.mutex);
dev_err(dev, stopped beaconing: No free slots in BP\n);
rc-beaconing = -1;
+   mutex_unlock(rc-uwb_dev.mutex);
} else
rc-uwb_dev.beacon_slot = 
uwb_rc_evt_bp_slot_change_slot_num(bpsc);
-   mutex_unlock(rc-uwb_dev.mutex);
 
return 0;
 }
-- 
1.7.10.4

--
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] uwb: move mutex_lock to error case in uwbd_evt_handle_rc_bp_slot_change

2013-12-20 Thread Thomas Pugliese


On Fri, 20 Dec 2013, David Cohen wrote:

 On Fri, Dec 20, 2013 at 11:55:53AM -0600, Thomas Pugliese wrote:
  Only acquire rc-uwb_dev.mutex in the error case in
  uwbd_evt_handle_rc_bp_slot_change.  This fixes a bug where establishing
  a reservation on a new channel will fail if we were unable to establish
  a reservation on the previous channel due to DRP conflict.
  
  If rc-uwb_dev.mutex is acquired in the non-error case when the uwb
  system is attempting to start beaconing, it will block because the start
  beaconing code is holding this mutex.  This prevents any other
  notifications from the URC from being processed.  In particular, the
  DRP_AVAILABILITY notification will not be processed during the start
  beaconing process which can result in a failure to establish a
  reservation.  It is safe to not hold the mutex in the non-error
  case since the only other place rc-uwb_dev.beacon_slot is accessed is
  in the same worker thread that uwbd_evt_handle_rc_bp_slot_change
  executes in.
  
  Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
  ---
   drivers/uwb/beacon.c |4 ++--
   1 file changed, 2 insertions(+), 2 deletions(-)
  
  diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c
  index 4190f29..92407e8 100644
  --- a/drivers/uwb/beacon.c
  +++ b/drivers/uwb/beacon.c
  @@ -516,13 +516,13 @@ int uwbd_evt_handle_rc_bp_slot_change(struct 
  uwb_event *evt)
  }
  bpsc = container_of(evt-notif.rceb, struct uwb_rc_evt_bp_slot_change, 
  rceb);
   
  -   mutex_lock(rc-uwb_dev.mutex);
  if (uwb_rc_evt_bp_slot_change_no_slot(bpsc)) {
  +   mutex_lock(rc-uwb_dev.mutex);
  dev_err(dev, stopped beaconing: No free slots in BP\n);
 
 It could be just nitpicking, but I think it's a waste of resource to
 unnecessarily print to console while holding a lock.
 If you move this dev_err() to after mutex_unlock() you'd achieve the
 same result with a cheaper lock.
 

That's a fair point.  Might as well lock only what is absolutely 
necessary.

  rc-beaconing = -1;
 
 Although I'm not sure how useful it is to protect this single line of
 code.
 

I'm not ready to get rid of the lock altogether in this function.  There 
are other users of the beaconing flag that don't expect the value to 
change out from under them while holding the lock.

 Br, David Cohen
 
  +   mutex_unlock(rc-uwb_dev.mutex);
  } else
  rc-uwb_dev.beacon_slot = 
  uwb_rc_evt_bp_slot_change_slot_num(bpsc);
  -   mutex_unlock(rc-uwb_dev.mutex);
   
  return 0;
   }
  -- 

I'll resend this with the lock surrounding just the variable assignment.

Tom
--
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] uwb: move mutex_lock to error case in uwbd_evt_handle_rc_bp_slot_change

2013-12-20 Thread Thomas Pugliese
Only acquire rc-uwb_dev.mutex in the error case in
uwbd_evt_handle_rc_bp_slot_change.  This fixes a bug where establishing
a reservation on a new channel will fail if we were unable to establish
a reservation on the previous channel due to DRP conflict.

If rc-uwb_dev.mutex is acquired in the non-error case when the uwb
system is attempting to start beaconing, it will block because the start
beaconing code is holding this mutex.  This prevents any other
notifications from the URC from being processed.  In particular, the
DRP_AVAILABILITY notification will not be processed during the start
beaconing process which can result in a failure to establish a
reservation.  It is safe to not hold the mutex in the non-error
case since the only other place rc-uwb_dev.beacon_slot is accessed is
in the same worker thread that uwbd_evt_handle_rc_bp_slot_change
executes in.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/uwb/beacon.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c
index 4190f29..57b5ff6 100644
--- a/drivers/uwb/beacon.c
+++ b/drivers/uwb/beacon.c
@@ -516,13 +516,13 @@ int uwbd_evt_handle_rc_bp_slot_change(struct uwb_event 
*evt)
}
bpsc = container_of(evt-notif.rceb, struct uwb_rc_evt_bp_slot_change, 
rceb);
 
-   mutex_lock(rc-uwb_dev.mutex);
if (uwb_rc_evt_bp_slot_change_no_slot(bpsc)) {
dev_err(dev, stopped beaconing: No free slots in BP\n);
+   mutex_lock(rc-uwb_dev.mutex);
rc-beaconing = -1;
+   mutex_unlock(rc-uwb_dev.mutex);
} else
rc-uwb_dev.beacon_slot = 
uwb_rc_evt_bp_slot_change_slot_num(bpsc);
-   mutex_unlock(rc-uwb_dev.mutex);
 
return 0;
 }
-- 
1.7.10.4

--
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] usb: wusbcore: fix short transfers

2013-12-10 Thread Thomas Pugliese


On Tue, 10 Dec 2013, David Laight wrote:

  From: Thomas Pugliese
  Sent: 09 December 2013 19:11
  To: linux-usb@vger.kernel.org
  Cc: gre...@linuxfoundation.org; Thomas Pugliese
  Subject: [PATCH] usb: wusbcore: fix short transfers
  
  If a URB is broken up into multiple transfer segments and a short
  transfer occurs in any segment other than the last, the URB will
  currently get stuck in the driver forever.  This patch adds a check for
  a short transfer and cleans up any pending segments so the URB can
  complete properly.
 
 I thought that generic code ensured that this never happens.
 I thought that only xhci supports arbitrary fragmentation.
 
   David
 
 
 
 

Hi David, 
WUSB actually does support arbitrary fragmentation but that is not the 
type of fragmentation that is addressed with this fix.  The HWA can break 
up large URBs into smaller transfer segments that are not visible to the 
USB core.  These segments are similar to TRBs in xHCI.  If a large read 
request was broken up into multiple transfer segments and the read 
completed early due to a short transfer, the tracking data for the 
remaining segments would not be cleaned up and the URB would stay in the 
driver forever.  This patch solves that problem.

Tom
--
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] usb: wusbcore: add isochronous IN support to HWA

2013-12-10 Thread Thomas Pugliese
This patch adds support for isochronous IN transfers to the HWA driver.  
The changes include removing the checks that return errors for isoc IN 
URBs and adding functionality to read the isoc data returned from the 
HWA.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |  305 +++-
 1 file changed, 207 insertions(+), 98 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index a70e142..2afa886 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -488,13 +488,14 @@ static int __wa_seg_calculate_isoc_frame_count(struct 
wa_xfer *xfer,
 ((segment_size + iso_frame_desc[index].length)
= xfer-seg_size)) {
/*
-* For Alereon HWA devices, only include an isoc frame in a
-* segment if it is physically contiguous with the previous
+* For Alereon HWA devices, only include an isoc frame in an
+* out segment if it is physically contiguous with the previous
 * frame.  This is required because those devices expect
 * the isoc frames to be sent as a single USB transaction as
 * opposed to one transaction per frame with standard HWA.
 */
if ((xfer-wa-quirks  WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC)
+(xfer-is_inbound == 0)
 (index  isoc_frame_offset)
 ((iso_frame_desc[index - 1].offset +
iso_frame_desc[index - 1].length) !=
@@ -537,14 +538,8 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
result = sizeof(struct wa_xfer_bi);
break;
case USB_ENDPOINT_XFER_ISOC:
-   if (usb_pipeout(urb-pipe)) {
-   *pxfer_type = WA_XFER_TYPE_ISO;
-   result = sizeof(struct wa_xfer_hwaiso);
-   } else {
-   dev_err(dev, FIXME: ISOC IN not implemented\n);
-   result = -ENOSYS;
-   goto error;
-   }
+   *pxfer_type = WA_XFER_TYPE_ISO;
+   result = sizeof(struct wa_xfer_hwaiso);
break;
default:
/* never happens */
@@ -555,10 +550,22 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
xfer-is_dma = urb-transfer_flags  URB_NO_TRANSFER_DMA_MAP ? 1 : 0;
 
maxpktsize = le16_to_cpu(rpipe-descr.wMaxPacketSize);
+   xfer-seg_size = le16_to_cpu(rpipe-descr.wBlocks)
+   * 1  (xfer-wa-wa_descr-bRPipeBlockSize - 1);
+   /* Compute the segment size and make sure it is a multiple of
+* the maxpktsize (WUSB1.0[8.3.3.1])...not really too much of
+* a check (FIXME) */
+   if (xfer-seg_size  maxpktsize) {
+   dev_err(dev,
+   HW BUG? seg_size %zu smaller than maxpktsize %zu\n,
+   xfer-seg_size, maxpktsize);
+   result = -EINVAL;
+   goto error;
+   }
+   xfer-seg_size = (xfer-seg_size / maxpktsize) * maxpktsize;
if ((rpipe-descr.bmAttribute  0x3) == USB_ENDPOINT_XFER_ISOC) {
int index = 0;
 
-   xfer-seg_size = maxpktsize;
xfer-segs = 0;
/*
 * loop over urb-number_of_packets to determine how many
@@ -571,19 +578,6 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
++xfer-segs;
}
} else {
-   xfer-seg_size = le16_to_cpu(rpipe-descr.wBlocks)
-   * 1  (xfer-wa-wa_descr-bRPipeBlockSize - 1);
-   /* Compute the segment size and make sure it is a multiple of
-* the maxpktsize (WUSB1.0[8.3.3.1])...not really too much of
-* a check (FIXME) */
-   if (xfer-seg_size  maxpktsize) {
-   dev_err(dev,
-   HW BUG? seg_size %zu smaller than maxpktsize 
%zu\n,
-   xfer-seg_size, maxpktsize);
-   result = -EINVAL;
-   goto error;
-   }
-   xfer-seg_size = (xfer-seg_size / maxpktsize) * maxpktsize;
xfer-segs = DIV_ROUND_UP(urb-transfer_buffer_length,
xfer-seg_size);
if (xfer-segs == 0  *pxfer_type == WA_XFER_TYPE_CTL)
@@ -844,7 +838,7 @@ static void wa_seg_iso_pack_desc_cb(struct urb *urb)
wa_xfer_id(xfer), seg-index, urb-status);
if (edc_inc(wa-nep_edc, EDC_MAX_ERRORS,
EDC_ERROR_TIMEFRAME)){
-   dev_err(dev, DTO: URB max acceptable errors exceeded, 
resetting device\n

[PATCH] usb: wusbcore: fix short transfers

2013-12-09 Thread Thomas Pugliese
If a URB is broken up into multiple transfer segments and a short 
transfer occurs in any segment other than the last, the URB will 
currently get stuck in the driver forever.  This patch adds a check for 
a short transfer and cleans up any pending segments so the URB can 
complete properly.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |  128 +++-
 1 file changed, 74 insertions(+), 54 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index a88b8c6..673ad80 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -1993,7 +1993,7 @@ static int wa_xfer_status_to_errno(u8 status)
  * the xfer will complete cleanly.
  */
 static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer,
-   struct wa_seg *incoming_seg)
+   struct wa_seg *incoming_seg, enum wa_seg_status status)
 {
int index;
struct wa_rpipe *rpipe = xfer-ep-hcpriv;
@@ -2015,7 +2015,7 @@ static void wa_complete_remaining_xfer_segs(struct 
wa_xfer *xfer,
 */
case WA_SEG_DELAYED:
xfer-segs_done++;
-   current_seg-status = incoming_seg-status;
+   current_seg-status = status;
break;
case WA_SEG_ABORTED:
break;
@@ -2028,6 +2028,58 @@ static void wa_complete_remaining_xfer_segs(struct 
wa_xfer *xfer,
}
 }
 
+/* Populate the wa-buf_in_urb based on the current transfer state. */
+static int wa_populate_buf_in_urb(struct wahc *wa, struct wa_xfer *xfer,
+   unsigned int seg_idx, unsigned int bytes_transferred)
+{
+   int result = 0;
+   struct wa_seg *seg = xfer-seg[seg_idx];
+
+   BUG_ON(wa-buf_in_urb-status == -EINPROGRESS);
+   /* this should always be 0 before a resubmit. */
+   wa-buf_in_urb-num_mapped_sgs  = 0;
+
+   if (xfer-is_dma) {
+   wa-buf_in_urb-transfer_dma = xfer-urb-transfer_dma
+   + (seg_idx * xfer-seg_size);
+   wa-buf_in_urb-transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+   wa-buf_in_urb-transfer_buffer = NULL;
+   wa-buf_in_urb-sg = NULL;
+   wa-buf_in_urb-num_sgs = 0;
+   } else {
+   /* do buffer or SG processing. */
+   wa-buf_in_urb-transfer_flags = ~URB_NO_TRANSFER_DMA_MAP;
+
+   if (xfer-urb-transfer_buffer) {
+   wa-buf_in_urb-transfer_buffer =
+   xfer-urb-transfer_buffer
+   + (seg_idx * xfer-seg_size);
+   wa-buf_in_urb-sg = NULL;
+   wa-buf_in_urb-num_sgs = 0;
+   } else {
+   /* allocate an SG list to store seg_size bytes
+   and copy the subset of the xfer-urb-sg
+   that matches the buffer subset we are
+   about to read. */
+   wa-buf_in_urb-sg = wa_xfer_create_subset_sg(
+   xfer-urb-sg,
+   seg_idx * xfer-seg_size,
+   bytes_transferred,
+   (wa-buf_in_urb-num_sgs));
+
+   if (!(wa-buf_in_urb-sg)) {
+   wa-buf_in_urb-num_sgs = 0;
+   result = -ENOMEM;
+   }
+   wa-buf_in_urb-transfer_buffer = NULL;
+   }
+   }
+   wa-buf_in_urb-transfer_buffer_length = bytes_transferred;
+   wa-buf_in_urb-context = seg;
+
+   return result;
+}
+
 /*
  * Process a xfer result completion message
  *
@@ -2041,12 +2093,13 @@ static void wa_xfer_result_chew(struct wahc *wa, struct 
wa_xfer *xfer,
int result;
struct device *dev = wa-usb_iface-dev;
unsigned long flags;
-   u8 seg_idx;
+   unsigned int seg_idx;
struct wa_seg *seg;
struct wa_rpipe *rpipe;
unsigned done = 0;
u8 usb_status;
unsigned rpipe_ready = 0;
+   unsigned bytes_transferred = le32_to_cpu(xfer_result-dwTransferLength);
 
spin_lock_irqsave(xfer-lock, flags);
seg_idx = xfer_result-bTransferSegment  0x7f;
@@ -2079,66 +2132,33 @@ static void wa_xfer_result_chew(struct wahc *wa, struct 
wa_xfer *xfer,
/* FIXME: we ignore warnings, tally them for stats */
if (usb_status  0x40)  /* Warning?... */
usb_status = 0; /* ... pass */
+   /*
+* If the last segment bit is set, complete the remaining segments.
+* When the current segment is completed, either in wa_buf_in_cb for
+* transfers with data or below for no data, the xfer will complete.
+*/
+   if (xfer_result-bTransferSegment  0x80

[PATCH] usb: wusbcore: use USB_CTRL_SET_TIMEOUT and USB_CTRL_GET_TIMEOUT

2013-12-09 Thread Thomas Pugliese
Use USB_CTRL_SET_TIMEOUT and USB_CTRL_GET_TIMEOUT for USB control
messages instead of an arbitrary 1s timeout value.  This is particularly
useful for WUSB since in the worst case RF scanario, a WUSB device can
be unresponsive for up to 4s and still be connected.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/host/hwa-hc.c   |   20 ++--
 drivers/usb/wusbcore/cbaf.c |8 
 drivers/usb/wusbcore/security.c |   22 --
 drivers/usb/wusbcore/wa-hc.h|5 ++---
 drivers/usb/wusbcore/wa-rpipe.c |   10 +-
 5 files changed, 33 insertions(+), 32 deletions(-)

diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index a4ec9e6..8279097 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -86,7 +86,7 @@ static int __hwahc_set_cluster_id(struct hwahc *hwahc, u8 
cluster_id)
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
cluster_id,
wa-usb_iface-cur_altsetting-desc.bInterfaceNumber,
-   NULL, 0, 1000 /* FIXME: arbitrary */);
+   NULL, 0, USB_CTRL_SET_TIMEOUT);
if (result  0)
dev_err(dev, Cannot set WUSB Cluster ID to 0x%02x: %d\n,
cluster_id, result);
@@ -106,7 +106,7 @@ static int __hwahc_op_set_num_dnts(struct wusbhc *wusbhc, 
u8 interval, u8 slots)
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
interval  8 | slots,
wa-usb_iface-cur_altsetting-desc.bInterfaceNumber,
-   NULL, 0, 1000 /* FIXME: arbitrary */);
+   NULL, 0, USB_CTRL_SET_TIMEOUT);
 }
 
 /*
@@ -281,7 +281,7 @@ static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc, 
int delay)
  USB_DIR_OUT | USB_TYPE_CLASS | 
USB_RECIP_INTERFACE,
  delay * 1000,
  iface_no,
- NULL, 0, 1000 /* FIXME: arbitrary */);
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
if (ret == 0)
msleep(delay);
 
@@ -310,7 +310,7 @@ static int __hwahc_op_bwa_set(struct wusbhc *wusbhc, s8 
stream_index,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
stream_index,
wa-usb_iface-cur_altsetting-desc.bInterfaceNumber,
-   NULL, 0, 1000 /* FIXME: arbitrary */);
+   NULL, 0, USB_CTRL_SET_TIMEOUT);
if (result  0) {
dev_err(dev, Cannot set WUSB stream index: %d\n, result);
goto out;
@@ -321,7 +321,7 @@ static int __hwahc_op_bwa_set(struct wusbhc *wusbhc, s8 
stream_index,
WUSB_REQ_SET_WUSB_MAS,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, wa-usb_iface-cur_altsetting-desc.bInterfaceNumber,
-   mas_le, 32, 1000 /* FIXME: arbitrary */);
+   mas_le, 32, USB_CTRL_SET_TIMEOUT);
if (result  0)
dev_err(dev, Cannot set WUSB MAS allocation: %d\n, result);
 out:
@@ -355,7 +355,7 @@ static int __hwahc_op_mmcie_add(struct wusbhc *wusbhc, u8 
interval,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
interval  8 | repeat_cnt,
handle  8 | iface_no,
-   wuie, wuie-bLength, 1000 /* FIXME: arbitrary */);
+   wuie, wuie-bLength, USB_CTRL_SET_TIMEOUT);
 }
 
 /*
@@ -372,7 +372,7 @@ static int __hwahc_op_mmcie_rm(struct wusbhc *wusbhc, u8 
handle)
WUSB_REQ_REMOVE_MMC_IE,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, handle  8 | iface_no,
-   NULL, 0, 1000 /* FIXME: arbitrary */);
+   NULL, 0, USB_CTRL_SET_TIMEOUT);
 }
 
 /*
@@ -415,7 +415,7 @@ static int __hwahc_op_dev_info_set(struct wusbhc *wusbhc,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, wusb_dev-port_idx  8 | iface_no,
dev_info, sizeof(struct hwa_dev_info),
-   1000 /* FIXME: arbitrary */);
+   USB_CTRL_SET_TIMEOUT);
kfree(dev_info);
return ret;
 }
@@ -455,7 +455,7 @@ static int __hwahc_dev_set_key(struct wusbhc *wusbhc, u8 
port_idx, u32 tkid,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
USB_DT_KEY  8 | key_idx,
port_idx  8 | iface_no,
-   keyd, keyd_len, 1000 /* FIXME: arbitrary */);
+   keyd, keyd_len, USB_CTRL_SET_TIMEOUT);
 
kzfree(keyd); /* clear keys etc. */
return result;
@@ -497,7 +497,7 @@ static int

[PATCH] usb: core: get config and string descriptors for unauthorized devices

2013-12-09 Thread Thomas Pugliese
There is no need to skip querying the config and string descriptors for 
unauthorized WUSB devices when usb_new_device is called.  It is allowed 
by WUSB spec.  The only action that needs to be delayed until 
authorization time is the set config.  This change allows user mode 
tools to see the config and string descriptors earlier in enumeration 
which is needed for some WUSB devices to function properly on Android 
systems.  It also reduces the amount of divergent code paths needed 
for WUSB devices.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/core/config.c |7 ---
 drivers/usb/core/hub.c|   39 +++
 2 files changed, 7 insertions(+), 39 deletions(-)

diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index a6b2cab..548d199 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -651,10 +651,6 @@ void usb_destroy_configuration(struct usb_device *dev)
  *
  * hub-only!! ... and only in reset path, or usb_new_device()
  * (used by real hubs and virtual root hubs)
- *
- * NOTE: if this is a WUSB device and is not authorized, we skip the
- *   whole thing. A non-authorized USB device has no
- *   configurations.
  */
 int usb_get_configuration(struct usb_device *dev)
 {
@@ -666,8 +662,6 @@ int usb_get_configuration(struct usb_device *dev)
struct usb_config_descriptor *desc;
 
cfgno = 0;
-   if (dev-authorized == 0)   /* Not really an error */
-   goto out_not_authorized;
result = -ENOMEM;
if (ncfg  USB_MAXCONFIG) {
dev_warn(ddev, too many configurations: %d, 
@@ -751,7 +745,6 @@ int usb_get_configuration(struct usb_device *dev)
 
 err:
kfree(desc);
-out_not_authorized:
dev-descriptor.bNumConfigurations = cfgno;
 err2:
if (result == -ENOMEM)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a7c04e2..32e1035 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2235,17 +2235,13 @@ static int usb_enumerate_device(struct usb_device *udev)
return err;
}
}
-   if (udev-wusb == 1  udev-authorized == 0) {
-   udev-product = kstrdup(n/a (unauthorized), GFP_KERNEL);
-   udev-manufacturer = kstrdup(n/a (unauthorized), GFP_KERNEL);
-   udev-serial = kstrdup(n/a (unauthorized), GFP_KERNEL);
-   } else {
-   /* read the standard strings and cache them if present */
-   udev-product = usb_cache_string(udev, 
udev-descriptor.iProduct);
-   udev-manufacturer = usb_cache_string(udev,
- 
udev-descriptor.iManufacturer);
-   udev-serial = usb_cache_string(udev, 
udev-descriptor.iSerialNumber);
-   }
+
+   /* read the standard strings and cache them if present */
+   udev-product = usb_cache_string(udev, udev-descriptor.iProduct);
+   udev-manufacturer = usb_cache_string(udev,
+ udev-descriptor.iManufacturer);
+   udev-serial = usb_cache_string(udev, udev-descriptor.iSerialNumber);
+
err = usb_enumerate_device_otg(udev);
if (err  0)
return err;
@@ -2427,16 +2423,6 @@ int usb_deauthorize_device(struct usb_device *usb_dev)
usb_dev-authorized = 0;
usb_set_configuration(usb_dev, -1);
 
-   kfree(usb_dev-product);
-   usb_dev-product = kstrdup(n/a (unauthorized), GFP_KERNEL);
-   kfree(usb_dev-manufacturer);
-   usb_dev-manufacturer = kstrdup(n/a (unauthorized), GFP_KERNEL);
-   kfree(usb_dev-serial);
-   usb_dev-serial = kstrdup(n/a (unauthorized), GFP_KERNEL);
-
-   usb_destroy_configuration(usb_dev);
-   usb_dev-descriptor.bNumConfigurations = 0;
-
 out_unauthorized:
usb_unlock_device(usb_dev);
return 0;
@@ -2464,17 +2450,7 @@ int usb_authorize_device(struct usb_device *usb_dev)
goto error_device_descriptor;
}
 
-   kfree(usb_dev-product);
-   usb_dev-product = NULL;
-   kfree(usb_dev-manufacturer);
-   usb_dev-manufacturer = NULL;
-   kfree(usb_dev-serial);
-   usb_dev-serial = NULL;
-
usb_dev-authorized = 1;
-   result = usb_enumerate_device(usb_dev);
-   if (result  0)
-   goto error_enumerate;
/* Choose and set the configuration.  This registers the interfaces
 * with the driver core and lets interface drivers bind to them.
 */
@@ -2490,7 +2466,6 @@ int usb_authorize_device(struct usb_device *usb_dev)
}
dev_info(usb_dev-dev, authorized to connect\n);
 
-error_enumerate:
 error_device_descriptor:
usb_autosuspend_device(usb_dev);
 error_autoresume:
-- 
1.7.10.4

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

[PATCH] usb: core: allow isoc URBs for wireless devices with an interval 6

2013-12-09 Thread Thomas Pugliese
In usb_submit_urb, do not fail if an isoc URB for a wireless USB device
has an interval  6.  Per WUSB spec, isoc endpoints can support values
from 1-16.  Valid values for interrupt URBs for wireless USB devices are
still 6-16.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/core/urb.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index e622083..07c58af 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -492,9 +492,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
/* too small? */
switch (dev-speed) {
case USB_SPEED_WIRELESS:
-   if (urb-interval  6)
+   if ((urb-interval  6)
+(xfertype == USB_ENDPOINT_XFER_INT))
return -EINVAL;
-   break;
default:
if (urb-interval = 0)
return -EINVAL;
-- 
1.7.10.4

--
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 2/2] usb: wusbcore: set packet count correctly on isoc transfers

2013-12-09 Thread Thomas Pugliese
This patch correctly sets the dwNumOfPackets field of the HWA transfer
request for isochronous transfers with multiple segments.  Previously
all segments used the value that was set for the first segment which may
not be correct.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 6aeb52c..a70e142 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -1259,8 +1259,11 @@ static int __wa_xfer_setup(struct wa_xfer *xfer, struct 
urb *urb)
for (cnt = 1; cnt  xfer-segs; cnt++) {
struct wa_xfer_packet_info_hwaiso *packet_desc;
struct wa_seg *seg = xfer-seg[cnt];
+   struct wa_xfer_hwaiso *xfer_iso;
 
xfer_hdr = seg-xfer_hdr;
+   xfer_iso = container_of(xfer_hdr,
+   struct wa_xfer_hwaiso, hdr);
packet_desc = ((void *)xfer_hdr) + xfer_hdr_size;
/*
 * Copy values from the 0th header. Segment specific
@@ -1270,6 +1273,8 @@ static int __wa_xfer_setup(struct wa_xfer *xfer, struct 
urb *urb)
xfer_hdr-bTransferSegment = cnt;
xfer_hdr-dwTransferLength =
cpu_to_le32(seg-isoc_size);
+   xfer_iso-dwNumOfPackets =
+   cpu_to_le32(seg-isoc_frame_count);
__wa_setup_isoc_packet_descr(packet_desc, xfer, seg);
seg-status = WA_SEG_READY;
}
-- 
1.7.10.4

--
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 1/2] usb: wusbcore: move isoc_frame_index from wa_xfer to wa_seg

2013-12-09 Thread Thomas Pugliese
If multiple segments belonging to an isoc transfer are submitted
concurrently, the isoc_frame_index field in struct wa_xfer can get
corrupted.  This patch moves the isoc_frame_index field from struct
wa_xfer to struct wa_seg to prevent this from happening.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |   21 ++---
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 673ad80..6aeb52c 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -124,6 +124,8 @@ struct wa_seg {
u8 index;   /* which segment we are */
int isoc_frame_count;   /* number of isoc frames in this segment. */
int isoc_frame_offset;  /* starting frame offset in the xfer URB. */
+   /* Isoc frame that the current transfer buffer corresponds to. */
+   int isoc_frame_index;
int isoc_size;  /* size of all isoc frames sent by this seg. */
enum wa_seg_status status;
ssize_t result; /* bytes xfered or error */
@@ -158,8 +160,6 @@ struct wa_xfer {
unsigned is_dma:1;
size_t seg_size;
int result;
-   /* Isoc frame that the current transfer buffer corresponds to. */
-   int dto_isoc_frame_index;
 
gfp_t gfp;  /* allocation mask */
 
@@ -701,23 +701,23 @@ static void wa_seg_dto_cb(struct urb *urb)
if (usb_pipeisoc(xfer-urb-pipe)) {
/* Alereon HWA sends all isoc frames in a single transfer. */
if (wa-quirks  WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC)
-   xfer-dto_isoc_frame_index += seg-isoc_frame_count;
+   seg-isoc_frame_index += seg-isoc_frame_count;
else
-   xfer-dto_isoc_frame_index += 1;
-   if (xfer-dto_isoc_frame_index  seg-isoc_frame_count) {
+   seg-isoc_frame_index += 1;
+   if (seg-isoc_frame_index  seg-isoc_frame_count) {
data_send_done = 0;
holding_dto = 1; /* checked in error cases. */
/*
 * if this is the last isoc frame of the segment, we
 * can release DTO after sending this frame.
 */
-   if ((xfer-dto_isoc_frame_index + 1) =
+   if ((seg-isoc_frame_index + 1) =
seg-isoc_frame_count)
release_dto = 1;
}
dev_dbg(dev, xfer 0x%08X#%u: isoc frame = %d, holding_dto = 
%d, release_dto = %d.\n,
-   wa_xfer_id(xfer), seg-index,
-   xfer-dto_isoc_frame_index, holding_dto, release_dto);
+   wa_xfer_id(xfer), seg-index, seg-isoc_frame_index,
+   holding_dto, release_dto);
}
spin_unlock_irqrestore(xfer-lock, flags);
 
@@ -737,8 +737,7 @@ static void wa_seg_dto_cb(struct urb *urb)
 * send the URB and release DTO if we no longer need it.
 */
 __wa_populate_dto_urb_isoc(xfer, seg,
-   seg-isoc_frame_offset +
-   xfer-dto_isoc_frame_index);
+   seg-isoc_frame_offset + seg-isoc_frame_index);
 
/* resubmit the URB with the next isoc frame. */
result = usb_submit_urb(seg-dto_urb, GFP_ATOMIC);
@@ -1324,12 +1323,12 @@ static int __wa_seg_submit(struct wa_rpipe *rpipe, 
struct wa_xfer *xfer,
struct wahc *wa = xfer-wa;
 
result = usb_submit_urb(seg-isoc_pack_desc_urb, GFP_ATOMIC);
+   seg-isoc_frame_index = 0;
if (result  0) {
pr_err(%s: xfer %p#%u: ISO packet descriptor submit 
failed: %d\n,
   __func__, xfer, seg-index, result);
goto error_iso_pack_desc_submit;
}
-   xfer-dto_isoc_frame_index = 0;
/*
 * If this segment contains more than one isoc frame, hold
 * onto the dto resource until we send all frames.
-- 
1.7.10.4

--
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 0/2] usb: wusbcore isoc transfer fixes

2013-12-09 Thread Thomas Pugliese
This set includes two fixes for problems that can occur when isochronous 
transfers are split into multiple transfer segments.

Thomas Pugliese (2):
  usb: wusbcore: move isoc_frame_index from wa_xfer to wa_seg
  usb: wusbcore: set packet count correctly on multi-segment isoc
transfers

 drivers/usb/wusbcore/wa-xfer.c |   26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

-- 
1.7.10.4

--
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 0/3] usb: wusbcore: connect/disconnect fixes

2013-12-02 Thread Thomas Pugliese
This set of patches fixes various problems that can occur when connecting 
and disconnecting Wireless USB devices.

Thomas Pugliese (3):
  usb: wusbcore: send keepalives to unauthenticated devices
  usb: wusbcore: do device lookup while holding the hc mutex
  usb: wusbcore: fix deadlock in wusbhc_gtk_rekey

 drivers/usb/wusbcore/devconnect.c |   72 ++-
 drivers/usb/wusbcore/security.c   |   98 +
 drivers/usb/wusbcore/wusbhc.h |6 +--
 include/linux/usb/wusb.h  |2 +
 4 files changed, 88 insertions(+), 90 deletions(-)

-- 
1.7.10.4

--
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 2/3] usb: wusbcore: do device lookup while holding the hc mutex

2013-12-02 Thread Thomas Pugliese
This patch modifies the device notification handler to not look up the 
wusb_dev object before it calls the lower-level handler routines since 
the wusbhc mutex is not held when calling those routines and the device 
could go away in the meantime.  Instead, let the individual notification 
handlers get the device ptr if they need to after they have taken the 
mutex.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/devconnect.c |   43 +
 1 file changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/wusbcore/devconnect.c 
b/drivers/usb/wusbcore/devconnect.c
index d1af4e8..5107ca9 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -521,11 +521,19 @@ static struct wusb_dev *wusbhc_find_dev_by_addr(struct 
wusbhc *wusbhc, u8 addr)
  *
  * @wusbhc shall be referenced and unlocked
  */
-static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev 
*wusb_dev)
+static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, u8 srcaddr)
 {
+   struct wusb_dev *wusb_dev;
+
mutex_lock(wusbhc-mutex);
-   wusb_dev-entry_ts = jiffies;
-   __wusbhc_keep_alive(wusbhc);
+   wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
+   if (wusb_dev == NULL) {
+   dev_dbg(wusbhc-dev, ignoring DN_Alive from unconnected device 
%02x\n,
+   srcaddr);
+   } else {
+   wusb_dev-entry_ts = jiffies;
+   __wusbhc_keep_alive(wusbhc);
+   }
mutex_unlock(wusbhc-mutex);
 }
 
@@ -579,14 +587,22 @@ static void wusbhc_handle_dn_connect(struct wusbhc 
*wusbhc,
  *
  * @wusbhc shall be referenced and unlocked
  */
-static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev 
*wusb_dev)
+static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, u8 srcaddr)
 {
struct device *dev = wusbhc-dev;
-
-   dev_info(dev, DN DISCONNECT: device 0x%02x going down\n, 
wusb_dev-addr);
+   struct wusb_dev *wusb_dev;
 
mutex_lock(wusbhc-mutex);
-   __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, 
wusb_dev-port_idx));
+   wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
+   if (wusb_dev == NULL) {
+   dev_dbg(dev, ignoring DN DISCONNECT from unconnected device 
%02x\n,
+   srcaddr);
+   } else {
+   dev_info(dev, DN DISCONNECT: device 0x%02x going down\n,
+   wusb_dev-addr);
+   __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc,
+   wusb_dev-port_idx));
+   }
mutex_unlock(wusbhc-mutex);
 }
 
@@ -608,30 +624,21 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr,
  struct wusb_dn_hdr *dn_hdr, size_t size)
 {
struct device *dev = wusbhc-dev;
-   struct wusb_dev *wusb_dev;
 
if (size  sizeof(struct wusb_dn_hdr)) {
dev_err(dev, DN data shorter than DN header (%d  %d)\n,
(int)size, (int)sizeof(struct wusb_dn_hdr));
return;
}
-
-   wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
-   if (wusb_dev == NULL  dn_hdr-bType != WUSB_DN_CONNECT) {
-   dev_dbg(dev, ignoring DN %d from unconnected device %02x\n,
-   dn_hdr-bType, srcaddr);
-   return;
-   }
-
switch (dn_hdr-bType) {
case WUSB_DN_CONNECT:
wusbhc_handle_dn_connect(wusbhc, dn_hdr, size);
break;
case WUSB_DN_ALIVE:
-   wusbhc_handle_dn_alive(wusbhc, wusb_dev);
+   wusbhc_handle_dn_alive(wusbhc, srcaddr);
break;
case WUSB_DN_DISCONNECT:
-   wusbhc_handle_dn_disconnect(wusbhc, wusb_dev);
+   wusbhc_handle_dn_disconnect(wusbhc, srcaddr);
break;
case WUSB_DN_MASAVAILCHANGED:
case WUSB_DN_RWAKE:
-- 
1.7.10.4

--
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 3/3] usb: wusbcore: fix deadlock in wusbhc_gtk_rekey

2013-12-02 Thread Thomas Pugliese
When multiple wireless USB devices are connected and one of the devices 
disconnects, the host will distribute a new group key to the remaining 
devicese using wusbhc_gtk_rekey.  wusbhc_gtk_rekey takes the 
wusbhc-mutex and holds it while it submits a URB to set the new key. 
This causes a deadlock in wa_urb_enqueue when it calls a device lookup 
helper function that takes the same lock.

This patch changes wusbhc_gtk_rekey to submit a work item to set the GTK
so that the URB is submitted without holding wusbhc-mutex.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/devconnect.c |   24 +
 drivers/usb/wusbcore/security.c   |   98 +
 drivers/usb/wusbcore/wusbhc.h |6 +--
 include/linux/usb/wusb.h  |2 +
 4 files changed, 62 insertions(+), 68 deletions(-)

diff --git a/drivers/usb/wusbcore/devconnect.c 
b/drivers/usb/wusbcore/devconnect.c
index 5107ca9..f14e792 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -97,18 +97,12 @@ static void wusbhc_devconnect_acked_work(struct work_struct 
*work);
 
 static void wusb_dev_free(struct wusb_dev *wusb_dev)
 {
-   if (wusb_dev) {
-   kfree(wusb_dev-set_gtk_req);
-   usb_free_urb(wusb_dev-set_gtk_urb);
-   kfree(wusb_dev);
-   }
+   kfree(wusb_dev);
 }
 
 static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc)
 {
struct wusb_dev *wusb_dev;
-   struct urb *urb;
-   struct usb_ctrlrequest *req;
 
wusb_dev = kzalloc(sizeof(*wusb_dev), GFP_KERNEL);
if (wusb_dev == NULL)
@@ -118,22 +112,6 @@ static struct wusb_dev *wusb_dev_alloc(struct wusbhc 
*wusbhc)
 
INIT_WORK(wusb_dev-devconnect_acked_work, 
wusbhc_devconnect_acked_work);
 
-   urb = usb_alloc_urb(0, GFP_KERNEL);
-   if (urb == NULL)
-   goto err;
-   wusb_dev-set_gtk_urb = urb;
-
-   req = kmalloc(sizeof(*req), GFP_KERNEL);
-   if (req == NULL)
-   goto err;
-   wusb_dev-set_gtk_req = req;
-
-   req-bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
-   req-bRequest = USB_REQ_SET_DESCRIPTOR;
-   req-wValue = cpu_to_le16(USB_DT_KEY  8 | wusbhc-gtk_index);
-   req-wIndex = 0;
-   req-wLength = cpu_to_le16(wusbhc-gtk.descr.bLength);
-
return wusb_dev;
 err:
wusb_dev_free(wusb_dev);
diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c
index dd88441..4c40d0d 100644
--- a/drivers/usb/wusbcore/security.c
+++ b/drivers/usb/wusbcore/security.c
@@ -29,19 +29,16 @@
 #include linux/export.h
 #include wusbhc.h
 
-static void wusbhc_set_gtk_callback(struct urb *urb);
-static void wusbhc_gtk_rekey_done_work(struct work_struct *work);
+static void wusbhc_gtk_rekey_work(struct work_struct *work);
 
 int wusbhc_sec_create(struct wusbhc *wusbhc)
 {
wusbhc-gtk.descr.bLength = sizeof(wusbhc-gtk.descr) + 
sizeof(wusbhc-gtk.data);
wusbhc-gtk.descr.bDescriptorType = USB_DT_KEY;
wusbhc-gtk.descr.bReserved = 0;
+   wusbhc-gtk_index = 0;
 
-   wusbhc-gtk_index = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_GTK,
-  WUSB_KEY_INDEX_ORIGINATOR_HOST);
-
-   INIT_WORK(wusbhc-gtk_rekey_done_work, wusbhc_gtk_rekey_done_work);
+   INIT_WORK(wusbhc-gtk_rekey_work, wusbhc_gtk_rekey_work);
 
return 0;
 }
@@ -113,7 +110,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc)
wusbhc_generate_gtk(wusbhc);
 
result = wusbhc-set_gtk(wusbhc, wusbhc-gtk_tkid,
-wusbhc-gtk.descr.bKeyData, key_size);
+   wusbhc-gtk.descr.bKeyData, key_size);
if (result  0)
dev_err(wusbhc-dev, cannot set GTK for the host: %d\n,
result);
@@ -129,7 +126,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc)
  */
 void wusbhc_sec_stop(struct wusbhc *wusbhc)
 {
-   cancel_work_sync(wusbhc-gtk_rekey_done_work);
+   cancel_work_sync(wusbhc-gtk_rekey_work);
 }
 
 
@@ -185,12 +182,14 @@ static int wusb_dev_set_encryption(struct usb_device 
*usb_dev, int value)
 static int wusb_dev_set_gtk(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 {
struct usb_device *usb_dev = wusb_dev-usb_dev;
+   u8 key_index = wusb_key_index(wusbhc-gtk_index,
+   WUSB_KEY_INDEX_TYPE_GTK, WUSB_KEY_INDEX_ORIGINATOR_HOST);
 
return usb_control_msg(
usb_dev, usb_sndctrlpipe(usb_dev, 0),
USB_REQ_SET_DESCRIPTOR,
USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
-   USB_DT_KEY  8 | wusbhc-gtk_index, 0,
+   USB_DT_KEY  8 | key_index, 0,
wusbhc-gtk.descr, wusbhc-gtk.descr.bLength,
1000);
 }
@@ -520,24 +519,55 @@ error_kzalloc:
  * Once all connected and authenticated devices have received the new
  * GTK, switch the host to using

[PATCH 1/3] usb: wusbcore: send keepalives to unauthenticated devices

2013-12-02 Thread Thomas Pugliese
This patch modifies the WUSB device disconnect timer code to send 
keepalives to all connected devices even if they are not authenticated.  
This fixes a problem where unauthenticated devices that lose their 
connection before they are authenticated will stay in the device tree 
forever.  More importantly, devices in this situation will never 
relinquish their port on the root hub so eventually all root ports will 
be taken up and no other devices can connect.

A comment in the existing code states that there are some devices that 
may not respond to keepalives if they have not been authenticated.  That 
comment is about 5 years old and I don't know of any WUSB devices that 
act that way.  Either way, any buggy devices that may still be around 
will continue to work as long as they can transition to the 
authenticated state within the WUSB LOA timeout of 4s, which is not 
unreasonable to expect.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/devconnect.c |5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/usb/wusbcore/devconnect.c 
b/drivers/usb/wusbcore/devconnect.c
index e538b72..d1af4e8 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -411,9 +411,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc,
 /*
  * Refresh the list of keep alives to emit in the MMC
  *
- * Some devices don't respond to keep alives unless they've been
- * authenticated, so skip unauthenticated devices.
- *
  * We only publish the first four devices that have a coming timeout
  * condition. Then when we are done processing those, we go for the
  * next ones. We ignore the ones that have timed out already (they'll
@@ -448,7 +445,7 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc)
 
if (wusb_dev == NULL)
continue;
-   if (wusb_dev-usb_dev == NULL || 
!wusb_dev-usb_dev-authenticated)
+   if (wusb_dev-usb_dev == NULL)
continue;
 
if (time_after(jiffies, wusb_dev-entry_ts + tt)) {
-- 
1.7.10.4

--
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 0/3] usb: wusbcore: connect/disconnect fixes

2013-12-02 Thread Thomas Pugliese


On Mon, 2 Dec 2013, Greg KH wrote:

 On Mon, Dec 02, 2013 at 03:39:42PM -0600, Thomas Pugliese wrote:
  This set of patches fixes various problems that can occur when connecting 
  and disconnecting Wireless USB devices.
  
  Thomas Pugliese (3):
usb: wusbcore: send keepalives to unauthenticated devices
usb: wusbcore: do device lookup while holding the hc mutex
usb: wusbcore: fix deadlock in wusbhc_gtk_rekey
 
 Should these go to 3.13-final or can they wait for 3.14-rc1?
 
 thanks,
 
 greg k-h
 

I think they could be considered for 3.13 since they do fix real issues 
that I have encountered.  I'm not sure how much time is left for 3.13 and 
how high the bar for acceptance is right now.  Patch 1/3 fixes the most 
likely to occur issue.  The other two cover less common cases and can 
probably wait until 3.14.

Tom
--
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 1/3] usb: wusbcore: add calls to usb_hcd_link_urb_to_ep, usb_hcd_unlink_urb_from_ep, and

2013-11-25 Thread Thomas Pugliese
Add calls to usb_hcd_link_urb_to_ep, usb_hcd_unlink_urb_from_ep, and 
usb_hcd_check_unlink_urb in the appropriate locations.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/host/hwa-hc.c  |2 +-
 drivers/usb/wusbcore/wa-hc.h   |2 +-
 drivers/usb/wusbcore/wa-xfer.c |   26 --
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index ada0a52..a4ec9e6 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -224,7 +224,7 @@ static int hwahc_op_urb_dequeue(struct usb_hcd *usb_hcd, 
struct urb *urb,
struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
 
-   return wa_urb_dequeue(hwahc-wa, urb);
+   return wa_urb_dequeue(hwahc-wa, urb, status);
 }
 
 /*
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index e614f02..5b6ae3a 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -332,7 +332,7 @@ static inline int rpipe_avail_inc(struct wa_rpipe *rpipe)
 /* Transferring data */
 extern int wa_urb_enqueue(struct wahc *, struct usb_host_endpoint *,
  struct urb *, gfp_t);
-extern int wa_urb_dequeue(struct wahc *, struct urb *);
+extern int wa_urb_dequeue(struct wahc *, struct urb *, int);
 extern void wa_handle_notif_xfer(struct wahc *, struct wa_notif_hdr *);
 
 
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index ed5abe8..5957e48 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -282,6 +282,7 @@ static void wa_xfer_giveback(struct wa_xfer *xfer)
 
spin_lock_irqsave(xfer-wa-xfer_list_lock, flags);
list_del_init(xfer-list_node);
+   usb_hcd_unlink_urb_from_ep((xfer-wa-wusb-usb_hcd), xfer-urb);
spin_unlock_irqrestore(xfer-wa-xfer_list_lock, flags);
/* FIXME: segmentation broken -- kills DWA */
wusbhc_giveback_urb(xfer-wa-wusb, xfer-urb, xfer-result);
@@ -1730,6 +1731,12 @@ int wa_urb_enqueue(struct wahc *wa, struct 
usb_host_endpoint *ep,
dump_stack();
}
 
+   spin_lock_irqsave(wa-xfer_list_lock, my_flags);
+   result = usb_hcd_link_urb_to_ep((wa-wusb-usb_hcd), urb);
+   spin_unlock_irqrestore(wa-xfer_list_lock, my_flags);
+   if (result  0)
+   goto error_link_urb;
+
result = -ENOMEM;
xfer = kzalloc(sizeof(*xfer), gfp);
if (xfer == NULL)
@@ -1769,6 +1776,9 @@ int wa_urb_enqueue(struct wahc *wa, struct 
usb_host_endpoint *ep,
   __func__, result);
wa_put(xfer-wa);
wa_xfer_put(xfer);
+   spin_lock_irqsave(wa-xfer_list_lock, my_flags);
+   usb_hcd_unlink_urb_from_ep((wa-wusb-usb_hcd), urb);
+   spin_unlock_irqrestore(wa-xfer_list_lock, my_flags);
return result;
}
}
@@ -1777,6 +1787,10 @@ int wa_urb_enqueue(struct wahc *wa, struct 
usb_host_endpoint *ep,
 error_dequeued:
kfree(xfer);
 error_kmalloc:
+   spin_lock_irqsave(wa-xfer_list_lock, my_flags);
+   usb_hcd_unlink_urb_from_ep((wa-wusb-usb_hcd), urb);
+   spin_unlock_irqrestore(wa-xfer_list_lock, my_flags);
+error_link_urb:
return result;
 }
 EXPORT_SYMBOL_GPL(wa_urb_enqueue);
@@ -1799,7 +1813,7 @@ EXPORT_SYMBOL_GPL(wa_urb_enqueue);
  * asynch request] and then make sure we cancel each segment.
  *
  */
-int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
+int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status)
 {
unsigned long flags, flags2;
struct wa_xfer *xfer;
@@ -1807,6 +1821,14 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
struct wa_rpipe *rpipe;
unsigned cnt, done = 0, xfer_abort_pending;
unsigned rpipe_ready = 0;
+   int result;
+
+   /* check if it is safe to unlink. */
+   spin_lock_irqsave(wa-xfer_list_lock, flags);
+   result = usb_hcd_check_unlink_urb((wa-wusb-usb_hcd), urb, status);
+   spin_unlock_irqrestore(wa-xfer_list_lock, flags);
+   if (result)
+   return result;
 
xfer = urb-hcpriv;
if (xfer == NULL) {
@@ -2172,7 +2194,7 @@ error_complete:
 
 error_bad_seg:
spin_unlock_irqrestore(xfer-lock, flags);
-   wa_urb_dequeue(wa, xfer-urb);
+   wa_urb_dequeue(wa, xfer-urb, -ENOENT);
if (printk_ratelimit())
dev_err(dev, xfer %p#%u: bad segment\n, xfer, seg_idx);
if (edc_inc(wa-dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
-- 
1.7.10.4

--
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 3/3] usb: wusbcore: return -ENOENT for unlinked URBs.

2013-11-25 Thread Thomas Pugliese
Return -ENOENT for unlinked URBs.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 3220c62..a88b8c6 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -1848,6 +1848,7 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int 
status)
pr_debug(%s: xfer %p id 0x%08X has no RPIPE.  %s,
__func__, xfer, wa_xfer_id(xfer),
Probably already aborted.\n );
+   result = -ENOENT;
goto out_unlock;
}
/* Check the delayed list - if there, release and complete */
@@ -1878,6 +1879,7 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int 
status)
 * segments will be completed in the DTI interrupt.
 */
seg-status = WA_SEG_ABORTED;
+   seg-result = -ENOENT;
spin_lock_irqsave(rpipe-seg_lock, flags2);
list_del(seg-list_node);
xfer-segs_done++;
@@ -1917,12 +1919,12 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, 
int status)
wa_xfer_completion(xfer);
if (rpipe_ready)
wa_xfer_delayed_run(rpipe);
-   return 0;
+   return result;
 
 out_unlock:
spin_unlock_irqrestore(xfer-lock, flags);
 out:
-   return 0;
+   return result;
 
 dequeue_delayed:
list_del_init(xfer-list_node);
@@ -1958,7 +1960,7 @@ static int wa_xfer_status_to_errno(u8 status)
[WA_XFER_STATUS_NOT_FOUND] =0,
[WA_XFER_STATUS_INSUFFICIENT_RESOURCE] = -ENOMEM,
[WA_XFER_STATUS_TRANSACTION_ERROR] =-EILSEQ,
-   [WA_XFER_STATUS_ABORTED] =  -EINTR,
+   [WA_XFER_STATUS_ABORTED] =  -ENOENT,
[WA_XFER_STATUS_RPIPE_NOT_READY] =  EINVAL,
[WA_XFER_INVALID_FORMAT] =  EINVAL,
[WA_XFER_UNEXPECTED_SEGMENT_NUMBER] =   EINVAL,
-- 
1.7.10.4

--
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 2/3] usb: wusbcore: add more info to debug prints in urb_unlink path

2013-11-25 Thread Thomas Pugliese
Add more info to debug prints in urb_unlink path

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |   21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 5957e48..3220c62 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -373,10 +373,10 @@ static unsigned __wa_xfer_is_done(struct wa_xfer *xfer)
seg-result);
goto out;
case WA_SEG_ABORTED:
-   dev_dbg(dev, xfer %p ID %08X#%u ABORTED: result %d\n,
-   xfer, wa_xfer_id(xfer), seg-index,
-   urb-status);
-   xfer-result = urb-status;
+   xfer-result = seg-result;
+   dev_dbg(dev, xfer %p ID %08X#%u: ABORTED result 
%zu(0x%08zX)\n,
+   xfer, wa_xfer_id(xfer), seg-index, seg-result,
+   seg-result);
goto out;
default:
dev_warn(dev, xfer %p ID %08X#%u: is_done bad state 
%d\n,
@@ -1568,7 +1568,8 @@ static int wa_urb_enqueue_b(struct wa_xfer *xfer)
wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb-dev);
if (wusb_dev == NULL) {
mutex_unlock(wusbhc-mutex);
-   pr_err(%s: error wusb dev gone\n, __func__);
+   dev_err((urb-dev-dev), %s: error wusb dev gone\n,
+   __func__);
goto error_dev_gone;
}
mutex_unlock(wusbhc-mutex);
@@ -1577,18 +1578,18 @@ static int wa_urb_enqueue_b(struct wa_xfer *xfer)
xfer-wusb_dev = wusb_dev;
result = urb-status;
if (urb-status != -EINPROGRESS) {
-   pr_err(%s: error_dequeued\n, __func__);
+   dev_err((urb-dev-dev), %s: error_dequeued\n, __func__);
goto error_dequeued;
}
 
result = __wa_xfer_setup(xfer, urb);
if (result  0) {
-   pr_err(%s: error_xfer_setup\n, __func__);
+   dev_err((urb-dev-dev), %s: error_xfer_setup\n, __func__);
goto error_xfer_setup;
}
result = __wa_xfer_submit(xfer);
if (result  0) {
-   pr_err(%s: error_xfer_submit\n, __func__);
+   dev_err((urb-dev-dev), %s: error_xfer_submit\n, __func__);
goto error_xfer_submit;
}
spin_unlock_irqrestore(xfer-lock, flags);
@@ -1844,8 +1845,8 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int 
status)
pr_debug(%s: DEQUEUE xfer id 0x%08X\n, __func__, wa_xfer_id(xfer));
rpipe = xfer-ep-hcpriv;
if (rpipe == NULL) {
-   pr_debug(%s: xfer id 0x%08X has no RPIPE.  %s,
-   __func__, wa_xfer_id(xfer),
+   pr_debug(%s: xfer %p id 0x%08X has no RPIPE.  %s,
+   __func__, xfer, wa_xfer_id(xfer),
Probably already aborted.\n );
goto out_unlock;
}
-- 
1.7.10.4

--
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 0/3] usb: wusbcore: URB unlink cleanup

2013-11-25 Thread Thomas Pugliese
This patch set cleans up the urb_unlink path in wusbcore.  The most 
important change is the addition of calls to usb_hcd_link_urb_to_ep, 
usb_hcd_unlink_urb_from_ep, and usb_hcd_check_unlink_urb to the HWA for 
proper URB tracking.  The error status for unlinked URBs is also set to 
-ENOENT if the URB was canceled before completing.  These could be 
candidates for 3.13rc2 as well.

Thomas Pugliese (3):
  usb: wusbcore: add calls to usb_hcd_link_urb_to_ep,
usb_hcd_unlink_urb_from_ep, and usb_hcd_check_unlink_urb
  usb: wusbcore: add more info to debug prints in urb_unlink case
  usb: wusbcore: return -ENOENT for unlinked URBs.

 drivers/usb/host/hwa-hc.c  |2 +-
 drivers/usb/wusbcore/wa-hc.h   |2 +-
 drivers/usb/wusbcore/wa-xfer.c |   55 +---
 3 files changed, 42 insertions(+), 17 deletions(-)

-- 
1.7.10.4

--
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 4/4] usb: wusbcore: change WA_SEGS_MAX to a legal value

2013-10-24 Thread Thomas Pugliese


On Thu, 24 Oct 2013, Greg KH wrote:

 On Thu, Oct 24, 2013 at 10:04:08AM +0200, Oliver Neukum wrote:
  On Wed, 2013-10-23 at 14:44 -0500, Thomas Pugliese wrote:
   change WA_SEGS_MAX to a number that is legal according to the WUSB 
   spec.
   
   Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
  
  This should go to stable.
 
 Good catch, I'll do that.
 
 thanks,
 
 greg k-h
 

This patch and the other one Oliver commented on will probably not apply 
cleanly to the stable trees due to the changes that have gone into 3.13.  
I will backport them to stable and submit those patches separately.

Thomas
--
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] usb: wusbcore: change WA_SEGS_MAX to a legal value

2013-10-24 Thread Thomas Pugliese
Change WA_SEGS_MAX to a number that is legal according to the WUSB spec 
and correct the test for exceeding this value.  This patch is against 
3.11.6 and is intended for -stable.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
Cc: sta...@vger.kernel.org
---
 drivers/usb/wusbcore/wa-xfer.c |5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index d3493ca..19b5d24 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -91,7 +91,8 @@
 #include wusbhc.h
 
 enum {
-   WA_SEGS_MAX = 255,
+   /* [WUSB] section 8.3.3 allocates 7 bits for the segment index. */
+   WA_SEGS_MAX = 128,
 };
 
 enum wa_seg_status {
@@ -444,7 +445,7 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
}
xfer-seg_size = (xfer-seg_size / maxpktsize) * maxpktsize;
xfer-segs = DIV_ROUND_UP(urb-transfer_buffer_length, xfer-seg_size);
-   if (xfer-segs = WA_SEGS_MAX) {
+   if (xfer-segs  WA_SEGS_MAX) {
dev_err(dev, BUG? ops, number of segments %d bigger than %d\n,
(int)(urb-transfer_buffer_length / xfer-seg_size),
WA_SEGS_MAX);
-- 
1.7.10.4

--
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] usb: wusbcore: remove unneccessary byte-swap when assigning RPIPE wMaxPacketSize

2013-10-24 Thread Thomas Pugliese
This patch removes an unneccessary byte-swap when assigning RPIPE
wMaxPacketSize.  Both sides of the assignment are __le16 members of a
USB descriptor so no byte swap is needed.  This patch is against 3.11.6
and is intended for -stable.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
Cc: sta...@vger.kernel.org
---
 drivers/usb/wusbcore/wa-rpipe.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index 9a595c1..5645af0 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -333,7 +333,7 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc 
*wa,
/* FIXME: compute so seg_size  ep-maxpktsize */
rpipe-descr.wBlocks = cpu_to_le16(16); /* given */
/* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */
-   rpipe-descr.wMaxPacketSize = cpu_to_le16(ep-desc.wMaxPacketSize);
+   rpipe-descr.wMaxPacketSize = ep-desc.wMaxPacketSize;
 
rpipe-descr.hwa_bMaxBurst = max(min_t(unsigned int,
epcd-bMaxBurst, 16U), 1U);
-- 
1.7.10.4

--
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 0/4] usb: wusbcore: HWA isoc enhancements

2013-10-23 Thread Thomas Pugliese
This patch set contains a few enhancements to isochronous support in 
the HWA which improve audio quality for wireless USB audio devices.  
These have been sitting in my testing branch for a few weeks and look 
to be solid.

Thomas Pugliese (4):
  usb: wusbcore: set the RPIPE wMaxPacketSize value correctly
  usb: wusbcore: combine multiple isoc frames in a single transfer request.
  usb: wusbcore: add a quirk for Alereon HWA device isoc behavior
  usb: wusbcore: change WA_SEGS_MAX to a number that is legal according to WUSB

 drivers/usb/host/hwa-hc.c   |   13 +-
 drivers/usb/wusbcore/wa-hc.c|4 +-
 drivers/usb/wusbcore/wa-hc.h|   13 +-
 drivers/usb/wusbcore/wa-rpipe.c |5 +-
 drivers/usb/wusbcore/wa-xfer.c  |  410 +++
 5 files changed, 319 insertions(+), 126 deletions(-)

-- 
1.7.10.4

--
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 2/4] usb: wusbcore: combine multiple isoc frames in a single transfer request.

2013-10-23 Thread Thomas Pugliese
Combine multiple isoc frames in a single transfer request.  This allows 
the HWA to take advantage of bursting to deliver data to endpoints 
whose logical service interval is less than the minimum wireless USB 
service interval of 4ms.  Wireless audio quality is much improved after 
this update.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |  366 
 1 file changed, 255 insertions(+), 111 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 2bc6c80..16918e9 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -121,6 +121,9 @@ struct wa_seg {
struct list_head list_node; /* for rpipe-req_list */
struct wa_xfer *xfer;   /* out xfer */
u8 index;   /* which segment we are */
+   int isoc_frame_count;   /* number of isoc frames in this segment. */
+   int isoc_frame_offset;  /* starting frame offset in the xfer URB. */
+   int isoc_size;  /* size of all isoc frames sent by this seg. */
enum wa_seg_status status;
ssize_t result; /* bytes xfered or error */
struct wa_xfer_hdr xfer_hdr;
@@ -154,12 +157,17 @@ struct wa_xfer {
unsigned is_dma:1;
size_t seg_size;
int result;
+   /* Isoc frame that the current transfer buffer corresponds to. */
+   int dto_isoc_frame_index;
 
gfp_t gfp;  /* allocation mask */
 
struct wusb_dev *wusb_dev;  /* for activity timestamps */
 };
 
+static void __wa_populate_dto_urb_isoc(struct wa_xfer *xfer,
+   struct wa_seg *seg, int curr_iso_frame);
+
 static inline void wa_xfer_init(struct wa_xfer *xfer)
 {
kref_init(xfer-refcnt);
@@ -463,6 +471,31 @@ error_kmalloc:
 }
 
 /*
+ * Calculate the number of isoc frames starting from isoc_frame_offset
+ * that will fit a in transfer segment.
+ */
+static int __wa_seg_calculate_isoc_frame_count(struct wa_xfer *xfer,
+   int isoc_frame_offset, int *total_size)
+{
+   int segment_size = 0, frame_count = 0;
+   int index = isoc_frame_offset;
+
+   while ((index  xfer-urb-number_of_packets)
+((segment_size + xfer-urb-iso_frame_desc[index].length)
+   = xfer-seg_size)) {
+   /* this frame fits. count it. */
+   ++frame_count;
+   segment_size += xfer-urb-iso_frame_desc[index].length;
+
+   /* move to the next isoc frame. */
+   ++index;
+   }
+
+   *total_size = segment_size;
+   return frame_count;
+}
+
+/*
  *
  * @returns  0 on error, transfer segment request size if ok
  */
@@ -505,8 +538,20 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
 
maxpktsize = le16_to_cpu(rpipe-descr.wMaxPacketSize);
if ((rpipe-descr.bmAttribute  0x3) == USB_ENDPOINT_XFER_ISOC) {
+   int index = 0;
+
xfer-seg_size = maxpktsize;
-   xfer-segs = urb-number_of_packets;
+   xfer-segs = 0;
+   /*
+* loop over urb-number_of_packets to determine how many
+* xfer segments will be needed to send the isoc frames.
+*/
+   while (index  urb-number_of_packets) {
+   int seg_size; /* don't care. */
+   index += __wa_seg_calculate_isoc_frame_count(xfer,
+   index, seg_size);
+   ++xfer-segs;
+   }
} else {
xfer-seg_size = le16_to_cpu(rpipe-descr.wBlocks)
* 1  (xfer-wa-wa_descr-bRPipeBlockSize - 1);
@@ -523,20 +568,43 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
xfer-seg_size = (xfer-seg_size / maxpktsize) * maxpktsize;
xfer-segs = DIV_ROUND_UP(urb-transfer_buffer_length,
xfer-seg_size);
-   if (xfer-segs = WA_SEGS_MAX) {
-   dev_err(dev, BUG? oops, number of segments %zu bigger 
than %d\n,
-   (urb-transfer_buffer_length/xfer-seg_size),
-   WA_SEGS_MAX);
-   result = -EINVAL;
-   goto error;
-   }
if (xfer-segs == 0  *pxfer_type == WA_XFER_TYPE_CTL)
xfer-segs = 1;
}
+
+   if (xfer-segs = WA_SEGS_MAX) {
+   dev_err(dev, BUG? oops, number of segments %zu bigger than 
%d\n,
+   (urb-transfer_buffer_length/xfer-seg_size),
+   WA_SEGS_MAX);
+   result = -EINVAL;
+   goto error;
+   }
 error:
return result;
 }
 
+static void __wa_setup_isoc_packet_descr(
+   struct wa_xfer_packet_info_hwaiso *packet_desc,
+   struct

[PATCH 4/4] usb: wusbcore: change WA_SEGS_MAX to a legal value

2013-10-23 Thread Thomas Pugliese
change WA_SEGS_MAX to a number that is legal according to the WUSB 
spec.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 2a69175..0b93161 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -91,7 +91,8 @@
 #include wusbhc.h
 
 enum {
-   WA_SEGS_MAX = 255,
+   /* [WUSB] section 8.3.3 allocates 7 bits for the segment index. */
+   WA_SEGS_MAX = 128,
 };
 
 enum wa_seg_status {
@@ -588,7 +589,7 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
xfer-segs = 1;
}
 
-   if (xfer-segs = WA_SEGS_MAX) {
+   if (xfer-segs  WA_SEGS_MAX) {
dev_err(dev, BUG? oops, number of segments %zu bigger than 
%d\n,
(urb-transfer_buffer_length/xfer-seg_size),
WA_SEGS_MAX);
-- 
1.7.10.4

--
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 3/4] usb: wusbcore: add a quirk for Alereon HWA device isoc behavior

2013-10-23 Thread Thomas Pugliese
Add a quirk for Alereon HWA devices to concatenate the frames of isoc 
transfer requests.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/host/hwa-hc.c  |   13 ---
 drivers/usb/wusbcore/wa-hc.c   |4 +++-
 drivers/usb/wusbcore/wa-hc.h   |   13 ++-
 drivers/usb/wusbcore/wa-xfer.c |   49 ++--
 4 files changed, 62 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index e5fb3cf..ada0a52 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -679,7 +679,8 @@ static void hwahc_security_release(struct hwahc *hwahc)
/* nothing to do here so far... */
 }
 
-static int hwahc_create(struct hwahc *hwahc, struct usb_interface *iface)
+static int hwahc_create(struct hwahc *hwahc, struct usb_interface *iface,
+   kernel_ulong_t quirks)
 {
int result;
struct device *dev = iface-dev;
@@ -724,7 +725,7 @@ static int hwahc_create(struct hwahc *hwahc, struct 
usb_interface *iface)
dev_err(dev, Can't create WUSB HC structures: %d\n, result);
goto error_wusbhc_create;
}
-   result = wa_create(hwahc-wa, iface);
+   result = wa_create(hwahc-wa, iface, quirks);
if (result  0)
goto error_wa_create;
return 0;
@@ -780,7 +781,7 @@ static int hwahc_probe(struct usb_interface *usb_iface,
wusbhc = usb_hcd_to_wusbhc(usb_hcd);
hwahc = container_of(wusbhc, struct hwahc, wusbhc);
hwahc_init(hwahc);
-   result = hwahc_create(hwahc, usb_iface);
+   result = hwahc_create(hwahc, usb_iface, id-driver_info);
if (result  0) {
dev_err(dev, Cannot initialize internals: %d\n, result);
goto error_hwahc_create;
@@ -824,6 +825,12 @@ static void hwahc_disconnect(struct usb_interface 
*usb_iface)
 }
 
 static struct usb_device_id hwahc_id_table[] = {
+   /* Alereon 5310 */
+   { USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5310, 0xe0, 0x02, 0x01),
+ .driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC },
+   /* Alereon 5611 */
+   { USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5611, 0xe0, 0x02, 0x01),
+ .driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC },
/* FIXME: use class labels for this */
{ USB_INTERFACE_INFO(0xe0, 0x02, 0x01), },
{},
diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c
index 6c09b0e..368360f 100644
--- a/drivers/usb/wusbcore/wa-hc.c
+++ b/drivers/usb/wusbcore/wa-hc.c
@@ -33,7 +33,8 @@
  * wa-usb_dev and wa-usb_iface initialized and refcounted,
  * wa-wa_descr initialized.
  */
-int wa_create(struct wahc *wa, struct usb_interface *iface)
+int wa_create(struct wahc *wa, struct usb_interface *iface,
+   kernel_ulong_t quirks)
 {
int result;
struct device *dev = iface-dev;
@@ -41,6 +42,7 @@ int wa_create(struct wahc *wa, struct usb_interface *iface)
result = wa_rpipes_create(wa);
if (result  0)
goto error_rpipes_create;
+   wa-quirks = quirks;
/* Fill up Data Transfer EP pointers */
wa-dti_epd = iface-cur_altsetting-endpoint[1].desc;
wa-dto_epd = iface-cur_altsetting-endpoint[2].desc;
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index 41afaa6..e614f02 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -128,6 +128,14 @@ enum wa_dti_state {
WA_DTI_ISOC_PACKET_STATUS_PENDING
 };
 
+enum wa_quirks {
+   /*
+* The Alereon HWA expects the data frames in isochronous transfer
+* requests to be concatenated and not sent as separate packets.
+*/
+   WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC  = 0x01,
+};
+
 /**
  * Instance of a HWA Host Controller
  *
@@ -218,10 +226,13 @@ struct wahc {
struct work_struct xfer_enqueue_work;
struct work_struct xfer_error_work;
atomic_t xfer_id_count;
+
+   kernel_ulong_t  quirks;
 };
 
 
-extern int wa_create(struct wahc *wa, struct usb_interface *iface);
+extern int wa_create(struct wahc *wa, struct usb_interface *iface,
+   kernel_ulong_t);
 extern void __wa_destroy(struct wahc *wa);
 void wa_reset_all(struct wahc *wa);
 
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 16918e9..2a69175 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -479,13 +479,29 @@ static int __wa_seg_calculate_isoc_frame_count(struct 
wa_xfer *xfer,
 {
int segment_size = 0, frame_count = 0;
int index = isoc_frame_offset;
+   struct usb_iso_packet_descriptor *iso_frame_desc =
+   xfer-urb-iso_frame_desc;
 
while ((index  xfer-urb-number_of_packets)
-((segment_size + xfer-urb-iso_frame_desc[index].length)
+((segment_size + iso_frame_desc[index].length)
= xfer-seg_size

[PATCH 1/4] usb: wusbcore: set the RPIPE wMaxPacketSize value correctly

2013-10-23 Thread Thomas Pugliese
For isochronous endpoints, set the RPIPE wMaxPacketSize value using 
wOverTheAirPacketSize from the endpoint companion descriptor instead of 
wMaxPacketSize from the normal endpoint descriptor.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-rpipe.c |5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index 1ed068a..b48e74c 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -334,7 +334,10 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc 
*wa,
/* FIXME: compute so seg_size  ep-maxpktsize */
rpipe-descr.wBlocks = cpu_to_le16(16); /* given */
/* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */
-   rpipe-descr.wMaxPacketSize = cpu_to_le16(ep-desc.wMaxPacketSize);
+   if (usb_endpoint_xfer_isoc(ep-desc))
+   rpipe-descr.wMaxPacketSize = epcd-wOverTheAirPacketSize;
+   else
+   rpipe-descr.wMaxPacketSize = ep-desc.wMaxPacketSize;
 
rpipe-descr.hwa_bMaxBurst = max(min_t(unsigned int,
epcd-bMaxBurst, 16U), 1U);
-- 
1.7.10.4

--
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] usb: wusbcore: preserve endianness of cached descriptors

2013-10-07 Thread Thomas Pugliese
Do not overwrite the multi-byte fields of usb_wa_descriptor with their 
cpu format values after reading the descriptor.  Leave the values as 
__le16 and swap on use.  This is more consistent with other uses of USB 
descriptors.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/host/hwa-hc.c   |   10 +++---
 drivers/usb/wusbcore/wa-rpipe.c |2 +-
 include/linux/usb/wusb-wa.h |6 +++---
 3 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index e58b924..e5fb3cf 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -570,14 +570,10 @@ found:
goto error;
}
wa-wa_descr = wa_descr = (struct usb_wa_descriptor *) hdr;
-   /* Make LE fields CPU order */
-   wa_descr-bcdWAVersion = le16_to_cpu(wa_descr-bcdWAVersion);
-   wa_descr-wNumRPipes = le16_to_cpu(wa_descr-wNumRPipes);
-   wa_descr-wRPipeMaxBlock = le16_to_cpu(wa_descr-wRPipeMaxBlock);
-   if (wa_descr-bcdWAVersion  0x0100)
+   if (le16_to_cpu(wa_descr-bcdWAVersion)  0x0100)
dev_warn(dev, Wire Adapter v%d.%d newer than groked v1.0\n,
-wa_descr-bcdWAVersion  0xff00  8,
-wa_descr-bcdWAVersion  0x00ff);
+le16_to_cpu(wa_descr-bcdWAVersion)  0xff00  8,
+le16_to_cpu(wa_descr-bcdWAVersion)  0x00ff);
result = 0;
 error:
return result;
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index 554b16b..a76e2d9 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -479,7 +479,7 @@ error:
  */
 int wa_rpipes_create(struct wahc *wa)
 {
-   wa-rpipes = wa-wa_descr-wNumRPipes;
+   wa-rpipes = le16_to_cpu(wa-wa_descr-wNumRPipes);
wa-rpipe_bm = kzalloc(BITS_TO_LONGS(wa-rpipes)*sizeof(unsigned long),
   GFP_KERNEL);
if (wa-rpipe_bm == NULL)
diff --git a/include/linux/usb/wusb-wa.h b/include/linux/usb/wusb-wa.h
index 9ae7e29..c125713 100644
--- a/include/linux/usb/wusb-wa.h
+++ b/include/linux/usb/wusb-wa.h
@@ -279,11 +279,11 @@ struct wa_xfer_result {
 struct usb_wa_descriptor {
u8  bLength;
u8  bDescriptorType;
-   u16 bcdWAVersion;
+   __le16  bcdWAVersion;
u8  bNumPorts;  /* don't use!! */
u8  bmAttributes;   /* Reserved == 0 */
-   u16 wNumRPipes;
-   u16 wRPipeMaxBlock;
+   __le16  wNumRPipes;
+   __le16  wRPipeMaxBlock;
u8  bRPipeBlockSize;
u8  bPwrOn2PwrGood;
u8  bNumMMCIEs;
-- 
1.7.10.4

--
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] usb: wusbcore: serialize access to the HWA data out endpoint

2013-10-07 Thread Thomas Pugliese
This patch serializes access to the HWA data transfer out (DTO) 
endpoint.  This prevents a situation where two transfer requests being 
sent concurrently to separate downstream endpoints could interleave 
their transfer request and transfer data packets causing data 
corruption.  The transfer processing code will now attempt to acquire 
the DTO resource before sending a transfer to the HWA.  If it cannot 
acquire the resource, the RPIPE that the transfer is assigned to will 
be placed on a waiting list.  When the DTO resource is released, the 
actor releasing the resource will serivce the RPIPEs that are waiting.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-hc.h|   10 ++-
 drivers/usb/wusbcore/wa-rpipe.c |9 ++-
 drivers/usb/wusbcore/wa-xfer.c  |  154 +++
 3 files changed, 152 insertions(+), 21 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index b44aca3..41afaa6 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -117,6 +117,7 @@ struct wa_rpipe {
struct wahc *wa;
spinlock_t seg_lock;
struct list_head seg_list;
+   struct list_head list_node;
atomic_t segs_available;
u8 buffer[1];   /* For reads/writes on USB */
 };
@@ -183,7 +184,8 @@ struct wahc {
 
u16 rpipes;
unsigned long *rpipe_bm;/* rpipe usage bitmap */
-   spinlock_t rpipe_bm_lock;   /* protect rpipe_bm */
+   struct list_head rpipe_delayed_list;/* delayed RPIPES. */
+   spinlock_t rpipe_lock;  /* protect rpipe_bm and delayed list */
struct mutex rpipe_mutex;   /* assigning resources to endpoints */
 
/*
@@ -201,6 +203,8 @@ struct wahc {
void *dti_buf;
size_t dti_buf_size;
 
+   unsigned long dto_in_use;   /* protect dto endoint serialization. */
+
s32 status; /* For reading status */
 
struct list_head xfer_list;
@@ -253,7 +257,8 @@ static inline void wa_nep_disarm(struct wahc *wa)
 /* RPipes */
 static inline void wa_rpipe_init(struct wahc *wa)
 {
-   spin_lock_init(wa-rpipe_bm_lock);
+   INIT_LIST_HEAD(wa-rpipe_delayed_list);
+   spin_lock_init(wa-rpipe_lock);
mutex_init(wa-rpipe_mutex);
 }
 
@@ -270,6 +275,7 @@ static inline void wa_init(struct wahc *wa)
spin_lock_init(wa-xfer_list_lock);
INIT_WORK(wa-xfer_enqueue_work, wa_urb_enqueue_run);
INIT_WORK(wa-xfer_error_work, wa_process_errored_transfers_run);
+   wa-dto_in_use = 0;
atomic_set(wa-xfer_id_count, 1);
 }
 
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index a76e2d9..1ed068a 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -143,17 +143,18 @@ static void rpipe_init(struct wa_rpipe *rpipe)
kref_init(rpipe-refcnt);
spin_lock_init(rpipe-seg_lock);
INIT_LIST_HEAD(rpipe-seg_list);
+   INIT_LIST_HEAD(rpipe-list_node);
 }
 
 static unsigned rpipe_get_idx(struct wahc *wa, unsigned rpipe_idx)
 {
unsigned long flags;
 
-   spin_lock_irqsave(wa-rpipe_bm_lock, flags);
+   spin_lock_irqsave(wa-rpipe_lock, flags);
rpipe_idx = find_next_zero_bit(wa-rpipe_bm, wa-rpipes, rpipe_idx);
if (rpipe_idx  wa-rpipes)
set_bit(rpipe_idx, wa-rpipe_bm);
-   spin_unlock_irqrestore(wa-rpipe_bm_lock, flags);
+   spin_unlock_irqrestore(wa-rpipe_lock, flags);
 
return rpipe_idx;
 }
@@ -162,9 +163,9 @@ static void rpipe_put_idx(struct wahc *wa, unsigned 
rpipe_idx)
 {
unsigned long flags;
 
-   spin_lock_irqsave(wa-rpipe_bm_lock, flags);
+   spin_lock_irqsave(wa-rpipe_lock, flags);
clear_bit(rpipe_idx, wa-rpipe_bm);
-   spin_unlock_irqrestore(wa-rpipe_bm_lock, flags);
+   spin_unlock_irqrestore(wa-rpipe_lock, flags);
 }
 
 void rpipe_destroy(struct kref *_rpipe)
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 2dba8b6..2bc6c80 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -107,6 +107,7 @@ enum wa_seg_status {
 };
 
 static void wa_xfer_delayed_run(struct wa_rpipe *);
+static int __wa_xfer_delayed_run(struct wa_rpipe *rpipe, int *dto_waiting);
 
 /*
  * Life cycle governed by 'struct urb' (the refcount of the struct is
@@ -204,6 +205,59 @@ static void wa_xfer_put(struct wa_xfer *xfer)
 }
 
 /*
+ * Try to get exclusive access to the DTO endpoint resource.  Return true
+ * if successful.
+ */
+static inline int __wa_dto_try_get(struct wahc *wa)
+{
+   return (test_and_set_bit(0, wa-dto_in_use) == 0);
+}
+
+/* Release the DTO endpoint resource. */
+static inline void __wa_dto_put(struct wahc *wa)
+{
+   clear_bit_unlock(0, wa-dto_in_use);
+}
+
+/* Service RPIPEs that are waiting on the DTO resource. */
+static void wa_check_for_delayed_rpipes(struct wahc *wa)
+{
+   unsigned long

Re: [PATCH] usb: wusbcore: add support for isoc out transfers

2013-10-06 Thread Thomas Pugliese


On Sat, 5 Oct 2013, Greg KH wrote:

 On Fri, Oct 04, 2013 at 10:40:45AM -0500, Thomas Pugliese wrote:
  This patch adds support for isochronous out transfers to the HWA.  The 
  primary changes are:
  
  1.  Add a isoc_pack_desc_urb field to struct wa_seg.  This urb is used 
  to send the isochronous packet info message to the HWA which describes 
  the isoc data segment(s) that will be sent as the payload of the 
  transfer request.
  
  2.  Use the URB iso_frame_desc field to populate the isochronous packet 
  info message and data segments sent to the HWA.
  
  3.  After the data is sent and transfer result is returned from the 
  HWA, read the isoc packet status message from the HWA.  The contents of 
  the isoc packet status message are used to set the iso_frame_desc 
  status and actual_length fields in the original isoc URB.  This feature 
  required the addition of a some state tracking variables in struct wahc 
  so the dti_urb knows what type of packet it expects to receive next.
  
  
  Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
  ---
   drivers/usb/wusbcore/wa-hc.h   |   15 ++
   drivers/usb/wusbcore/wa-xfer.c |  493 
  +++-
   2 files changed, 406 insertions(+), 102 deletions(-)
 
 Nice job, I've applied this, but I'm getting build warnings again, you
 should really try to test your changes on a 64bit box:
 
 drivers/usb/wusbcore/wa-xfer.c: In function ‘__wa_xfer_setup_sizes’:
 drivers/usb/wusbcore/wa-xfer.c:475:5: warning: format ‘%d’ expects argument 
 of type ‘int’, but argument 3 has type ‘size_t’ [-Wformat]
 drivers/usb/wusbcore/wa-xfer.c: In function ‘wa_process_iso_packet_status’:
 drivers/usb/wusbcore/wa-xfer.c:1924:4: warning: format ‘%zu’ expects argument 
 of type ‘size_t’, but argument 4 has type ‘int’ [-Wformat]
 
 Can you send a follow-on patch fixing this up?
 
 thanks,
 
 greg k-h
 

Yes. I really need to switch to using my 64-bit machine by default.  I had 
these fixed but I forgot to merge them before submitting.  I will send a 
follow on patch that fixes the warnings.

Thanks,

Tom

[PATCH] usb: wusbcore: fix string formatting warnings on 64-bit builds

2013-10-06 Thread Thomas Pugliese
This patch fixes compile warnings on 64-bit builds that were introduced 
by the recent isoc changes.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index a5543e9..2dba8b6 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -470,7 +470,7 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
xfer-segs = DIV_ROUND_UP(urb-transfer_buffer_length,
xfer-seg_size);
if (xfer-segs = WA_SEGS_MAX) {
-   dev_err(dev, BUG? oops, number of segments %d bigger 
than %d\n,
+   dev_err(dev, BUG? oops, number of segments %zu bigger 
than %d\n,
(urb-transfer_buffer_length/xfer-seg_size),
WA_SEGS_MAX);
result = -EINVAL;
@@ -1922,7 +1922,7 @@ static void wa_process_iso_packet_status(struct wahc *wa, 
struct urb *urb)
dev_dbg(dev, DTI: isoc packet status %d bytes at %p\n,
urb-actual_length, urb-transfer_buffer);
if (urb-actual_length != expected_size) {
-   dev_err(dev, DTI Error: isoc packet status--bad urb length (%d 
bytes vs %zu needed)\n,
+   dev_err(dev, DTI Error: isoc packet status--bad urb length (%d 
bytes vs %d needed)\n,
urb-actual_length, expected_size);
goto error_parse_buffer;
}
-- 
1.7.10.4

--
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] usb: wusbcore: add support for isoc out transfers

2013-10-04 Thread Thomas Pugliese
This patch adds support for isochronous out transfers to the HWA.  The 
primary changes are:

1.  Add a isoc_pack_desc_urb field to struct wa_seg.  This urb is used 
to send the isochronous packet info message to the HWA which describes 
the isoc data segment(s) that will be sent as the payload of the 
transfer request.

2.  Use the URB iso_frame_desc field to populate the isochronous packet 
info message and data segments sent to the HWA.

3.  After the data is sent and transfer result is returned from the 
HWA, read the isoc packet status message from the HWA.  The contents of 
the isoc packet status message are used to set the iso_frame_desc 
status and actual_length fields in the original isoc URB.  This feature 
required the addition of a some state tracking variables in struct wahc 
so the dti_urb knows what type of packet it expects to receive next.


Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-hc.h   |   15 ++
 drivers/usb/wusbcore/wa-xfer.c |  493 +++-
 2 files changed, 406 insertions(+), 102 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index ab39934..b44aca3 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -122,6 +122,11 @@ struct wa_rpipe {
 };
 
 
+enum wa_dti_state {
+   WA_DTI_TRANSFER_RESULT_PENDING,
+   WA_DTI_ISOC_PACKET_STATUS_PENDING
+};
+
 /**
  * Instance of a HWA Host Controller
  *
@@ -181,6 +186,15 @@ struct wahc {
spinlock_t rpipe_bm_lock;   /* protect rpipe_bm */
struct mutex rpipe_mutex;   /* assigning resources to endpoints */
 
+   /*
+* dti_state is used to track the state of the dti_urb.  When dti_state
+* is WA_DTI_ISOC_PACKET_STATUS_PENDING, dti_isoc_xfer_in_progress and
+* dti_isoc_xfer_seg identify which xfer the incoming isoc packet status
+* refers to.
+*/
+   enum wa_dti_state dti_state;
+   u32 dti_isoc_xfer_in_progress;
+   u8  dti_isoc_xfer_seg;
struct urb *dti_urb;/* URB for reading xfer results */
struct urb *buf_in_urb; /* URB for reading data in */
struct edc dti_edc; /* DTI error density counter */
@@ -247,6 +261,7 @@ static inline void wa_init(struct wahc *wa)
 {
edc_init(wa-nep_edc);
atomic_set(wa-notifs_queued, 0);
+   wa-dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
wa_rpipe_init(wa);
edc_init(wa-dti_edc);
INIT_LIST_HEAD(wa-xfer_list);
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 7a78240..a5543e9 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -115,6 +115,7 @@ static void wa_xfer_delayed_run(struct wa_rpipe *);
  */
 struct wa_seg {
struct urb tr_urb;  /* transfer request urb. */
+   struct urb *isoc_pack_desc_urb; /* for isoc packet descriptor. */
struct urb *dto_urb;/* for data output. */
struct list_head list_node; /* for rpipe-req_list */
struct wa_xfer *xfer;   /* out xfer */
@@ -122,7 +123,6 @@ struct wa_seg {
enum wa_seg_status status;
ssize_t result; /* bytes xfered or error */
struct wa_xfer_hdr xfer_hdr;
-   u8 xfer_extra[];/* xtra space for xfer_hdr_ctl */
 };
 
 static inline void wa_seg_init(struct wa_seg *seg)
@@ -169,7 +169,7 @@ static inline void wa_xfer_init(struct wa_xfer *xfer)
 /*
  * Destroy a transfer structure
  *
- * Note that freeing xfer-seg[cnt]-urb will free the containing
+ * Note that freeing xfer-seg[cnt]-tr_urb will free the containing
  * xfer-seg[cnt] memory that was allocated by __wa_xfer_setup_segs.
  */
 static void wa_xfer_destroy(struct kref *_xfer)
@@ -178,12 +178,14 @@ static void wa_xfer_destroy(struct kref *_xfer)
if (xfer-seg) {
unsigned cnt;
for (cnt = 0; cnt  xfer-segs; cnt++) {
-   if (xfer-seg[cnt]) {
-   if (xfer-seg[cnt]-dto_urb) {
-   kfree(xfer-seg[cnt]-dto_urb-sg);
-   usb_free_urb(xfer-seg[cnt]-dto_urb);
+   struct wa_seg *seg = xfer-seg[cnt];
+   if (seg) {
+   usb_free_urb(seg-isoc_pack_desc_urb);
+   if (seg-dto_urb) {
+   kfree(seg-dto_urb-sg);
+   usb_free_urb(seg-dto_urb);
}
-   usb_free_urb(xfer-seg[cnt]-tr_urb);
+   usb_free_urb(seg-tr_urb);
}
}
kfree(xfer-seg);
@@ -291,7 +293,8 @@ static unsigned __wa_xfer_is_done(struct wa_xfer *xfer)
goto out

Re: [PATCH] sound: usb: add support for wireless USB devices

2013-10-02 Thread Thomas Pugliese


On Wed, 2 Oct 2013, Daniel Mack wrote:

 On 01.10.2013 21:32, Thomas Pugliese wrote:
  This patch updates snd_usb_audio_create also support devices whose 
  speed == USB_SPEED_WIRELESS.
 
 Interesting. What device are you testing this with?
 
 
 Daniel
 

The device I am testing with is a C-Media USB Audio device (VID:0x0d8c, 
PID:0x0103) connected to a wireless USB host using an Alereon Wireless USB 
bridge.

Tom

 
  
  Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
  ---
   sound/usb/card.c |1 +
   1 file changed, 1 insertion(+)
  
  diff --git a/sound/usb/card.c b/sound/usb/card.c
  index 64952e2..ef76aa0 100644
  --- a/sound/usb/card.c
  +++ b/sound/usb/card.c
  @@ -349,6 +349,7 @@ static int snd_usb_audio_create(struct usb_device *dev, 
  int idx,
  case USB_SPEED_LOW:
  case USB_SPEED_FULL:
  case USB_SPEED_HIGH:
  +   case USB_SPEED_WIRELESS:
  case USB_SPEED_SUPER:
  break;
  default:
  
 
 
--
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] usb: wusbcore: fix build warning on 64-bit builds

2013-10-01 Thread Thomas Pugliese


On Mon, 30 Sep 2013, Greg KH wrote:

 On Mon, Sep 30, 2013 at 10:48:46PM -0500, Thomas Pugliese wrote:
  Fix a build warning found by the kbuild test robot in the most recent 
  wusbcore patches.
  
  Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
 
 You forgot a Reported-by: line here :(
 
 I'll go add it...
 
 Oh, does this fix all 3 of the build warnings that the build robot
 reported?  Or just one of them?
 
 thanks,
 
 greg k-h
 

Ah.  OK.  I wasn't aware of the Reported-by: tag.  I'll use that in the 
future.  This should resolve all 3 warnings.

Thomas
--
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] usb: wusbcore: avoid stack overflow in URB enqueue error path

2013-10-01 Thread Thomas Pugliese
This patch modifies wa_urb_enqueue to return an error and not call the 
urb completion routine if it failed to enqueue the urb because the HWA 
device is gone.  This prevents a stack overflow due to infinite 
submit/complete recursion when unplugging the HWA while connected to a 
HID device.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |   51 ++--
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 6327df0..7a78240 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -1052,7 +1052,7 @@ error_seg_submit:
  * result never kicks in, the xfer will timeout from the USB code and
  * dequeue() will be called.
  */
-static void wa_urb_enqueue_b(struct wa_xfer *xfer)
+static int wa_urb_enqueue_b(struct wa_xfer *xfer)
 {
int result;
unsigned long flags;
@@ -1063,18 +1063,22 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer)
unsigned done;
 
result = rpipe_get_by_ep(wa, xfer-ep, urb, xfer-gfp);
-   if (result  0)
+   if (result  0) {
+   pr_err(%s: error_rpipe_get\n, __func__);
goto error_rpipe_get;
+   }
result = -ENODEV;
/* FIXME: segmentation broken -- kills DWA */
mutex_lock(wusbhc-mutex); /* get a WUSB dev */
if (urb-dev == NULL) {
mutex_unlock(wusbhc-mutex);
+   pr_err(%s: error usb dev gone\n, __func__);
goto error_dev_gone;
}
wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb-dev);
if (wusb_dev == NULL) {
mutex_unlock(wusbhc-mutex);
+   pr_err(%s: error wusb dev gone\n, __func__);
goto error_dev_gone;
}
mutex_unlock(wusbhc-mutex);
@@ -1082,21 +1086,28 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer)
spin_lock_irqsave(xfer-lock, flags);
xfer-wusb_dev = wusb_dev;
result = urb-status;
-   if (urb-status != -EINPROGRESS)
+   if (urb-status != -EINPROGRESS) {
+   pr_err(%s: error_dequeued\n, __func__);
goto error_dequeued;
+   }
 
result = __wa_xfer_setup(xfer, urb);
-   if (result  0)
+   if (result  0) {
+   pr_err(%s: error_xfer_setup\n, __func__);
goto error_xfer_setup;
+   }
result = __wa_xfer_submit(xfer);
-   if (result  0)
+   if (result  0) {
+   pr_err(%s: error_xfer_submit\n, __func__);
goto error_xfer_submit;
+   }
spin_unlock_irqrestore(xfer-lock, flags);
-   return;
+   return 0;
 
-   /* this is basically wa_xfer_completion() broken up wa_xfer_giveback()
-* does a wa_xfer_put() that will call wa_xfer_destroy() and clean
-* upundo setup().
+   /*
+* this is basically wa_xfer_completion() broken up wa_xfer_giveback()
+* does a wa_xfer_put() that will call wa_xfer_destroy() and undo
+* setup().
 */
 error_xfer_setup:
 error_dequeued:
@@ -1108,8 +1119,7 @@ error_dev_gone:
rpipe_put(xfer-ep-hcpriv);
 error_rpipe_get:
xfer-result = result;
-   wa_xfer_giveback(xfer);
-   return;
+   return result;
 
 error_xfer_submit:
done = __wa_xfer_is_done(xfer);
@@ -1117,6 +1127,8 @@ error_xfer_submit:
spin_unlock_irqrestore(xfer-lock, flags);
if (done)
wa_xfer_completion(xfer);
+   /* return success since the completion routine will run. */
+   return 0;
 }
 
 /*
@@ -1150,7 +1162,8 @@ void wa_urb_enqueue_run(struct work_struct *ws)
list_del_init(xfer-list_node);
 
urb = xfer-urb;
-   wa_urb_enqueue_b(xfer);
+   if (wa_urb_enqueue_b(xfer)  0)
+   wa_xfer_giveback(xfer);
usb_put_urb(urb);   /* taken when queuing */
}
 }
@@ -1256,7 +1269,19 @@ int wa_urb_enqueue(struct wahc *wa, struct 
usb_host_endpoint *ep,
spin_unlock_irqrestore(wa-xfer_list_lock, my_flags);
queue_work(wusbd, wa-xfer_enqueue_work);
} else {
-   wa_urb_enqueue_b(xfer);
+   result = wa_urb_enqueue_b(xfer);
+   if (result  0) {
+   /*
+* URB submit/enqueue failed.  Clean up, return an
+* error and do not run the callback.  This avoids
+* an infinite submit/complete loop.
+*/
+   dev_err(dev, %s: URB enqueue failed: %d\n,
+  __func__, result);
+   wa_put(xfer-wa);
+   wa_xfer_put(xfer);
+   return result;
+   }
}
return 0;
 
-- 
1.7.10.4

--
To unsubscribe from this list: send the line

[PATCH 2/3] usb: wusbcore: set the RPIPE bOverTheAirInterval for isoc endpoints

2013-10-01 Thread Thomas Pugliese
This patch sets the RPIPE bOverTheAirInterval field for RPIPES which 
refer to isochronous endpoints.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-rpipe.c |6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index fd4f1ce..554b16b 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -361,8 +361,10 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc 
*wa,
epcd-bMaxSequence, 32U), 2U);
rpipe-descr.bMaxDataSequence = epcd_max_sequence - 1;
rpipe-descr.bInterval = ep-desc.bInterval;
-   /* FIXME: bOverTheAirInterval */
-   rpipe-descr.bOverTheAirInterval = 0;   /* 0 if not isoc */
+   if (usb_endpoint_xfer_isoc(ep-desc))
+   rpipe-descr.bOverTheAirInterval = epcd-bOverTheAirInterval;
+   else
+   rpipe-descr.bOverTheAirInterval = 0;   /* 0 if not isoc */
/* FIXME: xmit power  preamble blah blah */
rpipe-descr.bmAttribute = (ep-desc.bmAttributes 
USB_ENDPOINT_XFERTYPE_MASK);
-- 
1.7.10.4

--
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] sound: usb: support wireless devices in snd_usb_parse_datainterval

2013-10-01 Thread Thomas Pugliese
Hi, 
This patch adds support for dev speed USB_SPEED_WIRELESS in 
snd_usb_parse_datainterval which allows the usb sound core to create 
ISO urbs with the correct number and size of buffers.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 sound/usb/helper.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index 6209024..51ed1ac 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -118,6 +118,7 @@ unsigned char snd_usb_parse_datainterval(struct 
snd_usb_audio *chip,
 {
switch (snd_usb_get_speed(chip-dev)) {
case USB_SPEED_HIGH:
+   case USB_SPEED_WIRELESS:
case USB_SPEED_SUPER:
if (get_endpoint(alts, 0)-bInterval = 1 
get_endpoint(alts, 0)-bInterval = 4)
-- 
1.7.10.4

--
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] sound: usb: add support for wireless USB devices

2013-10-01 Thread Thomas Pugliese
This patch updates snd_usb_audio_create also support devices whose 
speed == USB_SPEED_WIRELESS.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 sound/usb/card.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 64952e2..ef76aa0 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -349,6 +349,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int 
idx,
case USB_SPEED_LOW:
case USB_SPEED_FULL:
case USB_SPEED_HIGH:
+   case USB_SPEED_WIRELESS:
case USB_SPEED_SUPER:
break;
default:
-- 
1.7.10.4

--
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] usb: wusbcore: clean up urb dequeue process

2013-09-30 Thread Thomas Pugliese
This patch updates URB dequeue handling in wusbcore to make it more 
reliable when a URB has been broken up into multiple WUSB transfer 
request segments.

In wa_urb_dequeue, don't mark segments in the WA_SEG_SUBMITTED, 
WA_SEG_PENDING or WA_SEG_DTI_PENDING states as completed if an ABORT 
TRANSFER request was sent to the HWA to clean them up.  Wait for the 
HWA to return a transfer result indicating that it has aborted the 
request before cleaning it up.  This prevents the DTI state machine 
from losing track of transfers and avoids confusion in the case where a 
read transfer segment is dequeued after the driver has received the 
transfer result but before the data is received.

Signed-off-by: Thomas Pugliese thomas.pugli...@gmail.com
---
 drivers/usb/wusbcore/wa-xfer.c |  122 
 1 file changed, 87 insertions(+), 35 deletions(-)

diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 9b6501e..f19318d 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -367,15 +367,11 @@ static void __wa_xfer_abort_cb(struct urb *urb)
  *
  * The callback (see above) does nothing but freeing up the data by
  * putting the URB. Because the URB is allocated at the head of the
- * struct, the whole space we allocated is kfreed.
- *
- * We'll get an 'aborted transaction' xfer result on DTI, that'll
- * politely ignore because at this point the transaction has been
- * marked as aborted already.
+ * struct, the whole space we allocated is kfreed. *
  */
-static void __wa_xfer_abort(struct wa_xfer *xfer)
+static int __wa_xfer_abort(struct wa_xfer *xfer)
 {
-   int result;
+   int result = -ENOMEM;
struct device *dev = xfer-wa-usb_iface-dev;
struct wa_xfer_abort_buffer *b;
struct wa_rpipe *rpipe = xfer-ep-hcpriv;
@@ -396,7 +392,7 @@ static void __wa_xfer_abort(struct wa_xfer *xfer)
result = usb_submit_urb(b-urb, GFP_ATOMIC);
if (result  0)
goto error_submit;
-   return; /* callback frees! */
+   return result;  /* callback frees! */
 
 
 error_submit:
@@ -405,7 +401,7 @@ error_submit:
xfer, result);
kfree(b);
 error_kmalloc:
-   return;
+   return result;
 
 }
 
@@ -1295,7 +1291,7 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
struct wa_xfer *xfer;
struct wa_seg *seg;
struct wa_rpipe *rpipe;
-   unsigned cnt;
+   unsigned cnt, done = 0, xfer_abort_pending;
unsigned rpipe_ready = 0;
 
xfer = urb-hcpriv;
@@ -1309,6 +1305,7 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
goto out;
}
spin_lock_irqsave(xfer-lock, flags);
+   pr_debug(%s: DEQUEUE xfer id 0x%08X\n, __func__, wa_xfer_id(xfer));
rpipe = xfer-ep-hcpriv;
if (rpipe == NULL) {
pr_debug(%s: xfer id 0x%08X has no RPIPE.  %s,
@@ -1324,9 +1321,11 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
if (xfer-seg == NULL)  /* still hasn't reached */
goto out_unlock;/* setup(), enqueue_b() completes */
/* Ok, the xfer is in flight already, it's been setup and submitted.*/
-   __wa_xfer_abort(xfer);
+   xfer_abort_pending = __wa_xfer_abort(xfer) = 0;
for (cnt = 0; cnt  xfer-segs; cnt++) {
seg = xfer-seg[cnt];
+   pr_debug(%s: xfer id 0x%08X#%d status = %d\n,
+   __func__, wa_xfer_id(xfer), cnt, seg-status);
switch (seg-status) {
case WA_SEG_NOTREADY:
case WA_SEG_READY:
@@ -1335,42 +1334,50 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
WARN_ON(1);
break;
case WA_SEG_DELAYED:
+   /*
+* delete from rpipe delayed list.  If no segments on
+* this xfer have been submitted, __wa_xfer_is_done will
+* trigger a giveback below.  Otherwise, the submitted
+* segments will be completed in the DTI interrupt.
+*/
seg-status = WA_SEG_ABORTED;
spin_lock_irqsave(rpipe-seg_lock, flags2);
list_del(seg-list_node);
xfer-segs_done++;
-   rpipe_ready = rpipe_avail_inc(rpipe);
spin_unlock_irqrestore(rpipe-seg_lock, flags2);
break;
-   case WA_SEG_SUBMITTED:
-   seg-status = WA_SEG_ABORTED;
-   usb_unlink_urb(seg-tr_urb);
-   if (xfer-is_inbound == 0)
-   usb_unlink_urb(seg-dto_urb);
-   xfer-segs_done++;
-   rpipe_ready = rpipe_avail_inc(rpipe

  1   2   >