[PATCH] x86_64: Try harder to allocate memory in pci_alloc_consistent()
Linux Kernel Mailing List <[email protected]> Tue, 24 May 2005 13:47:16 +0000
| Newsgroups | gmane.linux.kernel.commits.2-4 |
|---|---|
| Message-ID | <[email protected]> |
ChangeSet 1.1562, 2005/05/24 10:47:16-03:00, [email protected] [PATCH] x86_64: Try harder to allocate memory in pci_alloc_consistent() Try harder to allocate memory in pci_alloc_consistent() First try to allocate without GFP_DMA and see if we were lucky and the memory fits into the requested physical range. Only if that fails fall back to swiotlb. This makes pci_alloc_consistent more reliable, especially on systems without hardware IOMMU (Intel systems) Increase the default swiotlb window size to 64MB. Cc: [email protected] Cc: [email protected] Signed-off-by: Suresh Siddha <[email protected]> ia64/lib/swiotlb.c | 4 ++-- x86_64/kernel/pci-gart.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff -Nru a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c --- a/arch/ia64/lib/swiotlb.c 2005-05-24 14:07:31 -07:00 +++ b/arch/ia64/lib/swiotlb.c 2005-05-24 14:07:31 -07:00 @@ -50,13 +50,13 @@ * Used to do a quick range check in swiotlb_unmap_single and swiotlb_sync_single, to see * if the memory was in fact allocated by this API. */ -static char *io_tlb_start, *io_tlb_end; +char *io_tlb_start, *io_tlb_end; /* * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and io_tlb_end. * This is command line adjustable via setup_io_tlb_npages. */ -static unsigned long io_tlb_nslabs = 1024; +static unsigned long io_tlb_nslabs = 32768; /* * This is a free list describing the number of free entries available from each index diff -Nru a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c --- a/arch/x86_64/kernel/pci-gart.c 2005-05-24 14:07:31 -07:00 +++ b/arch/x86_64/kernel/pci-gart.c 2005-05-24 14:07:31 -07:00 @@ -155,7 +155,7 @@ int i; unsigned long iommu_page; - if (hwdev == NULL || hwdev->dma_mask < 0xffffffff || no_iommu) + if (hwdev == NULL || hwdev->dma_mask < 0xffffffff || (no_iommu && !swiotlb)) gfp |= GFP_DMA; /* @@ -174,6 +174,22 @@ if (force_mmu && !(gfp & GFP_DMA)) mmu = 1; if (no_iommu) { +#ifdef CONFIG_SWIOTLB + if (swiotlb && high && hwdev) { + unsigned long dma_mask = 0; + if (hwdev->dma_mask == ~0UL) { + hwdev->dma_mask = 0xffffffff; + dma_mask = ~0UL; + } + *dma_handle = swiotlb_map_single(hwdev, memory, size, + PCI_DMA_FROMDEVICE); + if (dma_mask) + hwdev->dma_mask = dma_mask; + memset(phys_to_virt(*dma_handle), 0, size); + free_pages((unsigned long)memory, get_order(size)); + return phys_to_virt(*dma_handle); + } +#endif if (high) goto error; mmu = 0; } @@ -218,8 +234,16 @@ void *vaddr, dma_addr_t bus) { unsigned long iommu_page; - + extern char *io_tlb_start, *io_tlb_end; + size = round_up(size, PAGE_SIZE); +#ifdef CONFIG_SWIOTLB + if (swiotlb && vaddr >= (void *)io_tlb_start && + vaddr < (void *)io_tlb_end) { + swiotlb_unmap_single (hwdev, bus, size, PCI_DMA_TODEVICE); + return; + } +#endif if (bus >= iommu_bus_base && bus < iommu_bus_base + iommu_size) { unsigned pages = size >> PAGE_SHIFT; iommu_page = (bus - iommu_bus_base) >> PAGE_SHIFT;