Commit a12b8db0 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

USB: fix scatterlist PIO case (IOMMU)

Update the scatterlist logic so that PIO options are also disabled
when an IOMMU may have coalesced pages during dma_map_sg() ... it's
not just HIGHMEM that can make trouble supporting both PIO and DMA
based host controller drivers.

There also seems to be a cross-arch issue here, with 64bit powerpc
not using an IOMMU define ... and its IOMMU_VMERGE config can always
be overridden on the kernel command line.  So this is better, but
still imperfect.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e31c1880
...@@ -411,15 +411,22 @@ int usb_sg_init ( ...@@ -411,15 +411,22 @@ int usb_sg_init (
* Some systems need to revert to PIO when DMA is temporarily * Some systems need to revert to PIO when DMA is temporarily
* unavailable. For their sakes, both transfer_buffer and * unavailable. For their sakes, both transfer_buffer and
* transfer_dma are set when possible. However this can only * transfer_dma are set when possible. However this can only
* work on systems without HIGHMEM, since DMA buffers located * work on systems without:
* in high memory are not directly addressable by the CPU for *
* PIO ... so when HIGHMEM is in use, transfer_buffer is NULL * - HIGHMEM, since DMA buffers located in high memory are
* not directly addressable by the CPU for PIO;
*
* - IOMMU, since dma_map_sg() is allowed to use an IOMMU to
* make virtually discontiguous buffers be "dma-contiguous"
* so that PIO and DMA need diferent numbers of URBs.
*
* So when HIGHMEM or IOMMU are in use, transfer_buffer is NULL
* to prevent stale pointers and to help spot bugs. * to prevent stale pointers and to help spot bugs.
*/ */
if (dma) { if (dma) {
io->urbs [i]->transfer_dma = sg_dma_address (sg + i); io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
len = sg_dma_len (sg + i); len = sg_dma_len (sg + i);
#ifdef CONFIG_HIGHMEM #if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU)
io->urbs[i]->transfer_buffer = NULL; io->urbs[i]->transfer_buffer = NULL;
#else #else
io->urbs[i]->transfer_buffer = io->urbs[i]->transfer_buffer =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment