linux/drivers
Soeren Moch 85ecd0322b USB: EHCI: fix bug in iTD/siTD DMA pool allocation
[Description written by Alan Stern]

Soeren tracked down a very difficult bug in ehci-hcd's DMA pool
management of iTD and siTD structures.  Some background: ehci-hcd
gives each isochronous endpoint its own set of active and free itd's
(or sitd's for full-speed devices).  When a new itd is needed, it is
taken from the head of the free list, if possible.  However, itd's
must not be used twice in a single frame because the hardware
continues to access the data structure for the entire duration of a
frame.  Therefore if the itd at the head of the free list has its
"frame" member equal to the current value of ehci->now_frame, it
cannot be reused and instead a new itd is allocated from the DMA pool.
The entries on the free list are not released back to the pool until
the endpoint is no longer in use.

The bug arises from the fact that sometimes an itd can be moved back
onto the free list before itd->frame has been set properly.  In
Soeren's case, this happened because ehci-hcd can allocate one more
itd than it actually needs for an URB; the extra itd may or may not be
required depending on how the transfer aligns with a frame boundary.
For example, an URB with 8 isochronous packets will cause two itd's to
be allocated.  If the URB is scheduled to start in microframe 3 of
frame N then it will require both itds: one for microframes 3 - 7 of
frame N and one for microframes 0 - 2 of frame N+1.  But if the URB
had been scheduled to start in microframe 0 then it would require only
the first itd, which could cover microframes 0 - 7 of frame N.  The
second itd would be returned to the end of the free list.

The itd allocation routine initializes the entire structure to 0, so
the extra itd ends up on the free list with itd->frame set to 0
instead of a meaningful value.  After a while the itd reaches the head
of the list, and occasionally this happens when ehci->now_frame is
equal to 0.  Then, even though it would be okay to reuse this itd, the
driver thinks it must get another itd from the DMA pool.

For as long as the isochronous endpoint remains in use, this flaw in
the mechanism causes more and more itd's to be taken slowly from the
DMA pool.  Since none are released back, the pool eventually becomes
exhausted.

This reuslts in memory allocation failures, which typically show up
during a long-running audio stream.  Video might suffer the same
effect.

The fix is very simple.  To prevent allocations from the pool when
they aren't needed, make sure that itd's sent back to the free list
prematurely have itd->frame set to an invalid value which can never be
equal to ehci->now_frame.

This should be applied to -stable kernels going back to 3.6.

Signed-off-by: Soeren Moch <smoch@web.de>
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-25 13:59:04 -07:00
..
accessibility
acpi Fixes: 2013-03-12 20:25:53 -07:00
amba ARM: 7675/1: amba: tegra-ahb: Fix build error w/ PM_SLEEP w/o PM_RUNTIME 2013-03-15 17:20:02 +00:00
ata Simple stuff. See one-line summaries. 2013-03-23 12:33:36 -07:00
atm hlist: drop the node parameter from iterators 2013-02-27 19:10:24 -08:00
auxdisplay
base ACPI and power management fixes for 3.9-rc2 2013-03-07 14:54:28 -08:00
bcma Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem 2013-03-01 13:52:03 -05:00
block Merge git://git.infradead.org/users/willy/linux-nvme 2013-03-22 16:43:53 -07:00
bluetooth Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth 2013-03-13 13:29:56 -04:00
bus
cdrom
char Simple virtio-rng fix. 2013-03-12 20:28:45 -07:00
clk clk: vt8500: Fix "fix device clock divisor calculations" 2013-03-14 22:34:26 +01:00
clocksource ImgTec Meta architecture changes for v3.9-rc1 2013-03-03 12:06:09 -08:00
connector proc connector: reject unprivileged listener bumps 2013-02-27 13:08:35 -05:00
cpufreq cpufreq / intel_pstate: Do not load on VM that does not report max P state. 2013-03-06 23:40:11 +01:00
cpuidle arm-soc: soc-specific updates 2013-02-21 15:27:22 -08:00
crypto Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6 2013-02-25 15:56:15 -08:00
dca dca: convert to idr_alloc() 2013-02-27 19:10:15 -08:00
devfreq
dio
dma Merge branch 'next' of git://git.infradead.org/users/vkoul/slave-dma 2013-03-03 10:20:22 -08:00
edac EDAC: Merge mci.mem_is_per_rank with mci.csbased 2013-03-16 06:32:30 +01:00
eisa
extcon Char/Misc driver patches for 3.9-rc1 2013-02-21 13:57:13 -08:00
firewire firewire: convert to idr_alloc() 2013-02-27 19:10:15 -08:00
firmware Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace 2013-03-09 16:51:13 -08:00
gpio Two patches for Device Tree on at91sam9x5/NAND. 2013-03-14 23:55:59 +01:00
gpu KMS: fix EDID detailed timing frame rate 2013-03-23 10:46:10 -07:00
hid Merge branch 'for-3.9/upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid 2013-03-08 14:42:52 -08:00
hsi hsi: fix kernel-doc warnings 2013-03-01 13:39:00 -08:00
hv Drivers: hv: vmbus: Use the new infrastructure for delivering VMBUS interrupts 2013-02-27 10:15:53 -08:00
hwmon hwmon: (lm75.h) Update header inclusion 2013-03-18 21:19:49 +01:00
hwspinlock
i2c Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux 2013-03-23 12:32:14 -07:00
ide Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-02-26 20:16:07 -08:00
idle Merge branch 'core-locking-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2013-02-22 19:25:09 -08:00
iio First round of iio fixes post the 3.9 merge window. 2013-03-06 05:48:24 +08:00
infiniband Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2013-03-19 13:20:51 -07:00
input arm-soc: bug fixes for 3.9-rc3 2013-03-18 08:17:14 -07:00
iommu iommu, x86: Add DMA remap fault reason 2013-03-06 09:41:51 +01:00
ipack Char/Misc driver patches for 3.9-rc1 2013-02-21 13:57:13 -08:00
irqchip irqchip: fix typo when moving gic_raise_softirq() 2013-03-04 17:15:33 -08:00
isdn isdn: hisax: netjet requires VIRT_TO_BUS 2013-03-17 12:01:10 -04:00
leds Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds 2013-02-26 09:29:02 -08:00
lguest All trivial, thanks to the stuff which didn't quite make it time. 2013-02-26 14:49:12 -08:00
macintosh Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc 2013-02-23 17:09:55 -08:00
mailbox mailbox, pl320-ipc: remove __init from probe function 2013-03-04 14:23:11 +01:00
md A few bugfixes for md 2013-03-23 15:49:49 -07:00
media arm-soc: late OMAP changes 2013-02-28 20:00:40 -08:00
memory
memstick memstick: move the dereference below the NULL test 2013-02-27 19:10:23 -08:00
message
mfd mfd: twl4030-madc: Remove __exit_p annotation 2013-03-15 07:42:22 +01:00
misc fs: Limit sys_mount to only request filesystem modules. 2013-03-03 19:36:31 -08:00
mmc Merge branches 'devel-stable', 'fixes' and 'mmci' into for-linus 2013-03-03 00:32:50 +00:00
mtd MTD fixes for 3.9 2013-03-18 08:27:41 -07:00
net bnx2x: fix occasional statistics off-by-4GB error 2013-03-18 13:12:20 -04:00
nfc
ntb
nubus
of Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2013-02-21 17:40:58 -08:00
oprofile fs: Limit sys_mount to only request filesystem modules. 2013-03-03 19:36:31 -08:00
parisc Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-02-26 20:16:07 -08:00
parport Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux 2013-02-21 17:54:03 -08:00
pci PCI: Use ROM images from firmware only if no other ROM source available 2013-03-19 14:51:14 -07:00
pcmcia Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2013-02-21 17:40:58 -08:00
pinctrl ARM: at91: add gpio suspend/resume support when using pinctrl 2013-03-14 09:37:42 +01:00
platform Platform: x86: chromeos_laptop : Add basic platform data for atmel devices 2013-03-08 16:03:29 -08:00
pnp ACPI / glue: Add .match() callback to struct acpi_bus_type 2013-03-04 14:23:40 +01:00
power power: convert to idr_alloc() 2013-02-27 19:10:18 -08:00
pps drivers/pps/clients/pps-gpio.c: use devm_kzalloc 2013-02-27 19:10:23 -08:00
ps3
ptp
pwm pwm: Changes for v3.9-rc1 2013-02-26 09:34:29 -08:00
rapidio
regulator Merge remote-tracking branch 'regulator/fix/twl' into tmp 2013-03-05 10:12:43 +08:00
remoteproc remoteproc: convert to idr_alloc() 2013-02-27 19:10:18 -08:00
rpmsg rpmsg: convert to idr_alloc() 2013-02-27 19:10:18 -08:00
rtc drivers/rtc/rtc-at91rm9200.c: use a variable for storing IMR 2013-03-22 16:41:20 -07:00
s390 Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2013-03-19 13:20:51 -07:00
sbus Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-02-26 20:16:07 -08:00
scsi ACPI / glue: Add .match() callback to struct acpi_bus_type 2013-03-04 14:23:40 +01:00
sfi
sh
sn
spi arm-soc: soc-specific updates 2013-02-21 15:27:22 -08:00
ssb Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into mips-for-linux-next 2013-02-22 10:07:30 +01:00
staging Merge branch 'akpm' (fixes from Andrew) 2013-03-13 15:21:57 -07:00
target target/pscsi: Reject cross page boundary case in pscsi_map_sg 2013-03-19 17:31:14 -07:00
tc
thermal thermal: exynos_thermal: return a proper error code while thermal_zone_device_register fail. 2013-03-11 23:09:29 +08:00
tty Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc 2013-03-19 14:47:11 -07:00
uio uio: convert to idr_alloc() 2013-02-27 19:10:19 -08:00
usb USB: EHCI: fix bug in iTD/siTD DMA pool allocation 2013-03-25 13:59:04 -07:00
uwb
vfio vfio: include <linux/slab.h> for kmalloc 2013-03-15 12:58:20 -06:00
vhost Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2013-03-23 16:51:55 -07:00
video drivers/video/ep93xx-fb.c: include <linux/io.h> for devm_ioremap() 2013-03-22 16:41:20 -07:00
virt
virtio All trivial, thanks to the stuff which didn't quite make it time. 2013-02-26 14:49:12 -08:00
vlynq
vme
w1 w1: fix oops when w1_search is called from netlink connector 2013-03-12 16:20:46 -07:00
watchdog watchdog: sp5100_tco: Set the AcpiMmioSel bitmask value to 1 instead of 2 2013-03-22 23:21:55 +01:00
xen Fixes: 2013-03-12 20:25:53 -07:00
zorro new helper: file_inode(file) 2013-02-22 23:31:31 -05:00
Kconfig Char/Misc driver patches for 3.9-rc1 2013-02-21 13:57:13 -08:00
Makefile Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc 2013-02-23 17:09:55 -08:00