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. Signed-off-by: Matt Domsch <[EMAIL PROTECTED]> Thanks, Matt -- Matt Domsch Software Architect Dell Linux Solutions linux.dell.com & www.dell.com/linux Linux on Dell mailing lists @ http://lists.us.dell.com --- linux-2.4/arch/x86_64/kernel/pci-nommu.c Fri Feb 25 13:01:44 2005 +++ linux-2.4/arch/x86_64/kernel/pci-nommu.c Fri Feb 25 06:56:55 2005 @@ -13,18 +13,28 @@ void *pci_alloc_consistent(struct pci_de dma_addr_t *dma_handle) { void *ret; + u64 mask; + int order = get_order(size); int gfp = GFP_ATOMIC; - - if (hwdev == NULL || - end_pfn > (hwdev->dma_mask>>PAGE_SHIFT) || /* XXX */ - (u32)hwdev->dma_mask < 0xffffffff) - gfp |= GFP_DMA; - ret = (void *)__get_free_pages(gfp, get_order(size)); - if (ret != NULL) { - memset(ret, 0, size); + if (hwdev) + mask = hwdev->dma_mask; + else + mask = 0xffffffffULL; + + for (;;) { + ret = (void *)__get_free_pages(gfp, order); + if (ret == NULL) + return NULL; *dma_handle = virt_to_bus(ret); + if ((*dma_handle & ~mask) == 0) + break; + free_pages((unsigned long)ret, order); + if (gfp & GFP_DMA) + return NULL; + gfp |= GFP_DMA; } + memset(ret, 0, size); return ret; } - To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html