On Sat, Mar 19, 2005 at 08:26:45PM +0100, Andi Kleen wrote: > On Fri, Mar 18, 2005 at 03:23:44PM -0600, Matt Domsch wrote: > > For review and comment. > > > > On x86_64 systems with no IOMMU and with >4GB RAM (in fact, whenever > > there are any pages mapped above 4GB), pci_alloc_consistent() falls > > back to using ZONE_DMA for all allocations, even if the device's > > dma_mask could have supported using memory from other zones. Problems > > can be seen when other ZONE_DMA users (SWIOTLB, scsi_malloc()) consume > > all of ZONE_DMA, leaving none left for pci_alloc_consistent() use. > > > > Patch below makes pci_alloc_consistent() for the nommu case (EM64T > > processors) match the 2.6 implementation of dma_alloc_coherent(), with > > the exception that this continues to use GFP_ATOMIC. > > You fixed the wrong code. The pci-nommu code is only used > when IOMMU is disabled in the Kconfig. But most kernels have > it enabled. You would need to change it in pci-gart.c too.
OK, then how's this for review? Compiles clean, can't test it myself for a few days. -- Matt Domsch Software Architect Dell Linux Solutions linux.dell.com & www.dell.com/linux Linux on Dell mailing lists @ http://lists.us.dell.com ===== arch/x86_64/kernel/pci-gart.c 1.12 vs edited ===== --- 1.12/arch/x86_64/kernel/pci-gart.c 2004-06-03 05:29:36 -05:00 +++ edited/arch/x86_64/kernel/pci-gart.c 2005-03-19 15:56:34 -06:00 @@ -154,27 +154,37 @@ void *pci_alloc_consistent(struct pci_de int gfp = GFP_ATOMIC; int i; unsigned long iommu_page; + dma_addr_t dma_mask; - if (hwdev == NULL || hwdev->dma_mask < 0xffffffff || no_iommu) + if (hwdev == NULL || hwdev->dma_mask < 0xffffffff) gfp |= GFP_DMA; + dma_mask = hwdev ? hwdev->dma_mask : 0xffffffffULL; + if (dma_mask == 0) + dma_mask = 0xffffffffULL; + /* - * First try to allocate continuous and use directly if already - * in lowmem. + * First try to allocate continuous and use directly if + * our device supports it */ size = round_up(size, PAGE_SIZE); + again: memory = (void *)__get_free_pages(gfp, get_order(size)); if (memory == NULL) { return NULL; } else { - int high = 0, mmu; - if (((unsigned long)virt_to_bus(memory) + size) > 0xffffffffUL) - high = 1; - mmu = high; + int high = (((unsigned long)virt_to_bus(memory) + size) & ~dma_mask) != 0; + int mmu = high; if (force_mmu && !(gfp & GFP_DMA)) mmu = 1; if (no_iommu) { - if (high) goto error; + if (high && (gfp & GFP_DMA)) + goto error; + if (high) { + free_pages((unsigned long)memory, get_order(size)); + gfp |= GFP_DMA; + goto again; + } mmu = 0; } memset(memory, 0, size); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/