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/host | |
| 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/host')
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 2 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-q.c | 2 | ||||
| -rw-r--r-- | drivers/usb/host/whci/qset.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 4 |
4 files changed, 6 insertions, 6 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 0917e3a3246..2499b3bce36 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
| @@ -649,7 +649,7 @@ qh_urb_transaction ( | |||
| 649 | /* | 649 | /* |
| 650 | * data transfer stage: buffer setup | 650 | * data transfer stage: buffer setup |
| 651 | */ | 651 | */ |
| 652 | i = urb->num_sgs; | 652 | i = urb->num_mapped_sgs; |
| 653 | if (len > 0 && i > 0) { | 653 | if (len > 0 && i > 0) { |
| 654 | sg = urb->sg; | 654 | sg = urb->sg; |
| 655 | buf = sg_dma_address(sg); | 655 | buf = sg_dma_address(sg); |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 84ed28b34f9..82539913ad8 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
| @@ -943,7 +943,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
| 943 | if (usb_pipein(urb->pipe)) | 943 | if (usb_pipein(urb->pipe)) |
| 944 | status |= TD_CTRL_SPD; | 944 | status |= TD_CTRL_SPD; |
| 945 | 945 | ||
| 946 | i = urb->num_sgs; | 946 | i = urb->num_mapped_sgs; |
| 947 | if (len > 0 && i > 0) { | 947 | if (len > 0 && i > 0) { |
| 948 | sg = urb->sg; | 948 | sg = urb->sg; |
| 949 | data = sg_dma_address(sg); | 949 | data = sg_dma_address(sg); |
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index a403b53e86b..76083ae9213 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c | |||
| @@ -443,7 +443,7 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u | |||
| 443 | 443 | ||
| 444 | remaining = urb->transfer_buffer_length; | 444 | remaining = urb->transfer_buffer_length; |
| 445 | 445 | ||
| 446 | for_each_sg(urb->sg, sg, urb->num_sgs, i) { | 446 | for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) { |
| 447 | dma_addr_t dma_addr; | 447 | dma_addr_t dma_addr; |
| 448 | size_t dma_remaining; | 448 | size_t dma_remaining; |
| 449 | dma_addr_t sp, ep; | 449 | dma_addr_t sp, ep; |
| @@ -561,7 +561,7 @@ static int qset_add_urb_sg_linearize(struct whc *whc, struct whc_qset *qset, | |||
| 561 | 561 | ||
| 562 | remaining = urb->transfer_buffer_length; | 562 | remaining = urb->transfer_buffer_length; |
| 563 | 563 | ||
| 564 | for_each_sg(urb->sg, sg, urb->num_sgs, i) { | 564 | for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) { |
| 565 | size_t len; | 565 | size_t len; |
| 566 | size_t sg_remaining; | 566 | size_t sg_remaining; |
| 567 | void *orig; | 567 | void *orig; |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b4b06910f68..c0c5d6c7cb6 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
| @@ -2570,7 +2570,7 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) | |||
| 2570 | struct scatterlist *sg; | 2570 | struct scatterlist *sg; |
| 2571 | 2571 | ||
| 2572 | sg = NULL; | 2572 | sg = NULL; |
| 2573 | num_sgs = urb->num_sgs; | 2573 | num_sgs = urb->num_mapped_sgs; |
| 2574 | temp = urb->transfer_buffer_length; | 2574 | temp = urb->transfer_buffer_length; |
| 2575 | 2575 | ||
| 2576 | xhci_dbg(xhci, "count sg list trbs: \n"); | 2576 | xhci_dbg(xhci, "count sg list trbs: \n"); |
| @@ -2754,7 +2754,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
| 2754 | return -EINVAL; | 2754 | return -EINVAL; |
| 2755 | 2755 | ||
| 2756 | num_trbs = count_sg_trbs_needed(xhci, urb); | 2756 | num_trbs = count_sg_trbs_needed(xhci, urb); |
| 2757 | num_sgs = urb->num_sgs; | 2757 | num_sgs = urb->num_mapped_sgs; |
| 2758 | total_packet_count = roundup(urb->transfer_buffer_length, | 2758 | total_packet_count = roundup(urb->transfer_buffer_length, |
| 2759 | le16_to_cpu(urb->ep->desc.wMaxPacketSize)); | 2759 | le16_to_cpu(urb->ep->desc.wMaxPacketSize)); |
| 2760 | 2760 | ||
