diff options
| author | Clemens Ladisch <clemens@ladisch.de> | 2011-12-03 17:41:31 -0500 |
|---|---|---|
| committer | Brad Figg <brad.figg@canonical.com> | 2012-01-23 18:36:37 -0500 |
| commit | 23d14236d028d6bc69c861935d1405c46075d121 (patch) | |
| tree | 2142fafb76dd2bd7c6f214fe4ca0a24b1fae4f7a /drivers/usb/core | |
| parent | 0d49c76debe2bc91a5c8dc8a59ee29a44d87afab (diff) | |
usb: fix number of mapped SG DMA entries
BugLink: http://bugs.launchpad.net/bugs/915926
commit bc677d5b64644c399cd3db6a905453e611f402ab upstream.
Add a new field num_mapped_sgs to struct urb so that we have a place to
store the number of mapped entries and can also retain the original
value of entries in num_sgs. Previously, usb_hcd_map_urb_for_dma()
would overwrite this with the number of mapped entries, which would
break dma_unmap_sg() because it requires the original number of entries.
This fixes warnings like the following when using USB storage devices:
------------[ cut here ]------------
WARNING: at lib/dma-debug.c:902 check_unmap+0x4e4/0x695()
ehci_hcd 0000:00:12.2: DMA-API: device driver frees DMA sg list with different entry count [map count=4] [unmap count=1]
Modules linked in: ohci_hcd ehci_hcd
Pid: 0, comm: kworker/0:1 Not tainted 3.2.0-rc2+ #319
Call Trace:
<IRQ> [<ffffffff81036d3b>] warn_slowpath_common+0x80/0x98
[<ffffffff81036de7>] warn_slowpath_fmt+0x41/0x43
[<ffffffff811fa5ae>] check_unmap+0x4e4/0x695
[<ffffffff8105e92c>] ? trace_hardirqs_off+0xd/0xf
[<ffffffff8147208b>] ? _raw_spin_unlock_irqrestore+0x33/0x50
[<ffffffff811fa84a>] debug_dma_unmap_sg+0xeb/0x117
[<ffffffff8137b02f>] usb_hcd_unmap_urb_for_dma+0x71/0x188
[<ffffffff8137b166>] unmap_urb_for_dma+0x20/0x22
[<ffffffff8137b1c5>] usb_hcd_giveback_urb+0x5d/0xc0
[<ffffffffa0000d02>] ehci_urb_done+0xf7/0x10c [ehci_hcd]
[<ffffffffa0001140>] qh_completions+0x429/0x4bd [ehci_hcd]
[<ffffffffa000340a>] ehci_work+0x95/0x9c0 [ehci_hcd]
...
---[ end trace f29ac88a5a48c580 ]---
Mapped at:
[<ffffffff811faac4>] debug_dma_map_sg+0x45/0x139
[<ffffffff8137bc0b>] usb_hcd_map_urb_for_dma+0x22e/0x478
[<ffffffff8137c494>] usb_hcd_submit_urb+0x63f/0x6fa
[<ffffffff8137d01c>] usb_submit_urb+0x2c7/0x2de
[<ffffffff8137dcd4>] usb_sg_wait+0x55/0x161
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
Signed-off-by: Brad Figg <brad.figg@canonical.com>
Diffstat (limited to 'drivers/usb/core')
| -rw-r--r-- | drivers/usb/core/hcd.c | 5 |
1 files changed, 2 insertions, 3 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 39ea00bfb9c..691d212cac4 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
| @@ -1387,11 +1387,10 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | |||
| 1387 | ret = -EAGAIN; | 1387 | ret = -EAGAIN; |
| 1388 | else | 1388 | else |
| 1389 | urb->transfer_flags |= URB_DMA_MAP_SG; | 1389 | urb->transfer_flags |= URB_DMA_MAP_SG; |
| 1390 | if (n != urb->num_sgs) { | 1390 | urb->num_mapped_sgs = n; |
| 1391 | urb->num_sgs = n; | 1391 | if (n != urb->num_sgs) |
| 1392 | urb->transfer_flags |= | 1392 | urb->transfer_flags |= |
| 1393 | URB_DMA_SG_COMBINED; | 1393 | URB_DMA_SG_COMBINED; |
| 1394 | } | ||
| 1395 | } else if (urb->sg) { | 1394 | } else if (urb->sg) { |
| 1396 | struct scatterlist *sg = urb->sg; | 1395 | struct scatterlist *sg = urb->sg; |
| 1397 | urb->transfer_dma = dma_map_page( | 1396 | urb->transfer_dma = dma_map_page( |
