diff -ru usr/src/nv/nv-linux.h usr/src/nv.1175225/nv-linux.h --- usr/src/nv/nv-linux.h 2004-11-03 22:53:00.000000000 +0100 +++ usr/src/nv.1175225/nv-linux.h 2004-12-21 21:03:33.000000000 +0100 @@ -533,6 +533,7 @@ */ #if defined(CONFIG_SWIOTLB) #define NV_SWIOTLB 1 +#define NV_SWIOTLB_MAX_RETRIES 16 extern int nv_swiotlb; #endif @@ -950,10 +951,48 @@ sg_ptr->offset = (unsigned long)base & ~PAGE_MASK; sg_ptr->length = num_pages * PAGE_SIZE; +#if defined(NV_SWIOTLB) + i = NV_SWIOTLB_MAX_RETRIES; + do { + if (pci_map_sg(dev, sg_ptr, 1, PCI_DMA_BIDIRECTIONAL) == 0) + return 1; + + if (sg_ptr->dma_address & ~PAGE_MASK) + { + struct scatterlist sg_tmp; + pci_unmap_sg(dev, sg_ptr, num_pages, PCI_DMA_BIDIRECTIONAL); + + memset(&sg_tmp, 0, sizeof(struct scatterlist)); + sg_tmp.page = sg_ptr->page; + sg_tmp.offset = sg_ptr->offset; + sg_tmp.length = 2048; + + if (pci_map_sg(dev, &sg_tmp, 1, PCI_DMA_BIDIRECTIONAL) == 0) + return 1; + + if (pci_map_sg(dev, sg_ptr, 1, PCI_DMA_BIDIRECTIONAL) == 0) + { + pci_unmap_sg(dev, &sg_tmp, num_pages, PCI_DMA_BIDIRECTIONAL); + return 1; + } + + pci_unmap_sg(dev, &sg_tmp, num_pages, PCI_DMA_BIDIRECTIONAL); + } + } while (i-- && sg_ptr->dma_address & ~PAGE_MASK); +#else if (pci_map_sg(dev, sg_ptr, 1, PCI_DMA_BIDIRECTIONAL) == 0) { return 1; } +#endif + + if (sg_ptr->dma_address & ~PAGE_MASK) + { + nv_printf(NV_DBG_ERRORS, + "NVRM: VM: nv_sg_map_buffer: failed to obtain aligned mapping\n"); + pci_unmap_sg(dev, sg_ptr, num_pages, PCI_DMA_BIDIRECTIONAL); + return 1; + } NV_FIXUP_SWIOTLB_VIRT_ADDR_BUG(sg_ptr->dma_address);