From: David Brownell Date: Sun, 22 Jul 2007 22:13:13 +0000 (-0700) Subject: USB: fix scatterlist PIO case (IOMMU) X-Git-Tag: v2.6.23-rc2~151^2~10 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a12b8db02035673153bbf19bb3641a08bed9e4b8;p=linux-2.6 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 Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 25f63f1096..ad4b956380 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 =