[172/251] ALSA: usb-audio: do not trust too-big wMaxPacketSize values

From: Steven Rostedt
Date: Wed Sep 11 2013 - 00:59:32 EST


3.6.11.9-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Clemens Ladisch <clemens@xxxxxxxxxx>

[ Upstream commit 57e6dae1087bbaa6b33d3dd8a8e90b63888939a3 ]

The driver used to assume that the streaming endpoint's wMaxPacketSize
value would be an indication of how much data the endpoint expects or
sends, and compute the number of packets per URB using this value.

However, the Focusrite Scarlett 2i4 declares a value of 1024 bytes,
while only about 88 or 44 bytes are be actually used. This discrepancy
would result in URBs with far too few packets, which would not work
correctly on the EHCI driver.

To get correct URBs, use wMaxPacketSize only as an upper limit on the
packet size.

Reported-by: James Stone <jamesmstone@xxxxxxxxx>
Tested-by: James Stone <jamesmstone@xxxxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx> # 2.6.35+
Signed-off-by: Clemens Ladisch <clemens@xxxxxxxxxx>
Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx>
---
sound/usb/endpoint.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index eafc889..38e9583 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -599,17 +599,16 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
ep->stride = frame_bits >> 3;
ep->silence_value = format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0;

- /* calculate max. frequency */
- if (ep->maxpacksize) {
+ /* assume max. frequency is 25% higher than nominal */
+ ep->freqmax = ep->freqn + (ep->freqn >> 2);
+ maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
+ >> (16 - ep->datainterval);
+ /* but wMaxPacketSize might reduce this */
+ if (ep->maxpacksize && ep->maxpacksize < maxsize) {
/* whatever fits into a max. size packet */
maxsize = ep->maxpacksize;
ep->freqmax = (maxsize / (frame_bits >> 3))
<< (16 - ep->datainterval);
- } else {
- /* no max. packet size: just take 25% higher than nominal */
- ep->freqmax = ep->freqn + (ep->freqn >> 2);
- maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
- >> (16 - ep->datainterval);
}

if (ep->fill_max)
--
1.7.10.4


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/