diff options
| author | David Brownell <david-b@pacbell.net> | 2007-07-22 15:13:13 -0700 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-30 13:27:45 -0700 | 
| commit | a12b8db02035673153bbf19bb3641a08bed9e4b8 (patch) | |
| tree | c168c7816fb9da3e3a1596f42c1def295addf77b /drivers/usb/core/message.c | |
| parent | e31c18804f584dd838a752f6628e8c15bd7a3372 (diff) | |
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: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/message.c')
| -rw-r--r-- | drivers/usb/core/message.c | 15 | 
1 files changed, 11 insertions, 4 deletions
| diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 25f63f1096b..ad4b956380d 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -411,15 +411,22 @@ int usb_sg_init (  		 * Some systems need to revert to PIO when DMA is temporarily  		 * unavailable.  For their sakes, both transfer_buffer and  		 * transfer_dma are set when possible.  However this can only -		 * work on systems without HIGHMEM, since DMA buffers located -		 * in high memory are not directly addressable by the CPU for -		 * PIO ... so when HIGHMEM is in use, transfer_buffer is NULL +		 * work on systems without: +		 * +		 *  - 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.  		 */  		if (dma) {  			io->urbs [i]->transfer_dma = sg_dma_address (sg + i);  			len = sg_dma_len (sg + i); -#ifdef CONFIG_HIGHMEM +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU)  			io->urbs[i]->transfer_buffer = NULL;  #else  			io->urbs[i]->transfer_buffer = | 
