Hi, Alan: Please look at the attached patch. It allows the "new" usbmon to show the storage data in kernels that could possibly be running on systems with GART-based IOMMUs, but aren't actually. These #ifdefs always bothered me. Greetings, -- Pete diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index b626283..e2ecf36 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -421,30 +421,21 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, /* * 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: + * transfer_dma are set when possible. * - * - 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. + * Note that if the IOMMU coalescing occured, we cannot + * trust sg_page anymore, so check if S/G list shrunk. */ + if (io->nents == io->entries && !PageHighMem(sg_page(sg))) { + io->urbs[i]->transfer_buffer = sg_virt(sg); + } else { + io->urbs[i]->transfer_buffer = NULL; + } if (dma) { io->urbs[i]->transfer_dma = sg_dma_address(sg); len = sg_dma_len(sg); -#if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU) - io->urbs[i]->transfer_buffer = NULL; -#else - io->urbs[i]->transfer_buffer = sg_virt(sg); -#endif } else { /* hc may use _only_ transfer_buffer */ - io->urbs[i]->transfer_buffer = sg_virt(sg); len = sg->length; } -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html