diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-08-03 09:36:00 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-08-03 09:36:00 +0000 |
commit | fee4accd62794697667999837ae71fd10f7d92e8 (patch) | |
tree | 67081eb261e99089d2c010e165bfcf203ed77ff7 /linux-2.4.26-xen-sparse | |
parent | be4989adb0e4f14e7b6a99cdc60e5e3640c2c692 (diff) | |
download | xen-fee4accd62794697667999837ae71fd10f7d92e8.tar.gz xen-fee4accd62794697667999837ae71fd10f7d92e8.tar.bz2 xen-fee4accd62794697667999837ae71fd10f7d92e8.zip |
bitkeeper revision 1.1108.33.39 (410f5c80HHs32Qoh3S41tB5KdiU-uA)
Fix pci_alloc_consistent() to always return contiguous
machine memory.
Diffstat (limited to 'linux-2.4.26-xen-sparse')
-rw-r--r-- | linux-2.4.26-xen-sparse/arch/xen/kernel/pci-dma.c | 52 | ||||
-rwxr-xr-x | linux-2.4.26-xen-sparse/mkbuildtree | 1 |
2 files changed, 48 insertions, 5 deletions
diff --git a/linux-2.4.26-xen-sparse/arch/xen/kernel/pci-dma.c b/linux-2.4.26-xen-sparse/arch/xen/kernel/pci-dma.c index dd8842719e..e841ba86ca 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/kernel/pci-dma.c +++ b/linux-2.4.26-xen-sparse/arch/xen/kernel/pci-dma.c @@ -18,15 +18,59 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, { void *ret; int gfp = GFP_ATOMIC; + unsigned int order = get_order(size); + unsigned long vstart; if (hwdev == NULL || ((u32)hwdev->dma_mask < 0xffffffff)) gfp |= GFP_DMA; - ret = (void *)__get_free_pages(gfp, get_order(size)); - if (ret != NULL) { - memset(ret, 0, size); - *dma_handle = virt_to_bus(ret); + ret = (void *)vstart = __get_free_pages(gfp, order); + if (ret == NULL) + return ret; + + /* + * Ensure multi-page extents are contiguous in machine memory. + * This code could be cleaned up some, and the number of + * hypercalls reduced. + */ + if (size > PAGE_SIZE) { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + unsigned long pfn, i; + /* 1. Zap current PTEs, giving away the underlying pages. */ + for (i = 0; i < (1<<order); i++) { + pgd = pgd_offset_k( (vstart + (i*PAGE_SIZE))); + pmd = pmd_offset(pgd, (vstart + (i*PAGE_SIZE))); + pte = pte_offset(pmd, (vstart + (i*PAGE_SIZE))); + pfn = pte->pte_low >> PAGE_SHIFT; + queue_l1_entry_update(pte, 0); + flush_page_update_queue(); + if (HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, + &pfn, 1, 0) != 1) BUG(); + } + /* 2. Get a new contiguous memory extent. */ + if (HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, + &pfn, 1, order) != 1) BUG(); + /* 3. Map the new extent in place of old pages. */ + for (i = 0; i < (1<<order); i++) { + pgd = pgd_offset_k( (vstart + (i*PAGE_SIZE))); + pmd = pmd_offset(pgd, (vstart + (i*PAGE_SIZE))); + pte = pte_offset(pmd, (vstart + (i*PAGE_SIZE))); + queue_l1_entry_update(pte, + ((pfn+i)<<PAGE_SHIFT)|__PAGE_KERNEL); + queue_machphys_update(pfn+i, + (__pa(ret)>>PAGE_SHIFT)+i); + phys_to_machine_mapping[(__pa(ret)>>PAGE_SHIFT)+i] = + pfn+i; + flush_page_update_queue(); + } + flush_page_update_queue(); } + + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + return ret; } diff --git a/linux-2.4.26-xen-sparse/mkbuildtree b/linux-2.4.26-xen-sparse/mkbuildtree index 3dd6515b88..bb06d9b978 100755 --- a/linux-2.4.26-xen-sparse/mkbuildtree +++ b/linux-2.4.26-xen-sparse/mkbuildtree @@ -213,7 +213,6 @@ ln -sf ../../${LINUX_26}/include/asm-xen/xen_proc.h cd ${AD}/arch/xen/kernel ln -sf ../../i386/kernel/i387.c ln -sf ../../i386/kernel/init_task.c -ln -sf ../../i386/kernel/pci-dma.c ln -sf ../../i386/kernel/pci-i386.c ln -sf ../../i386/kernel/pci-i386.h ln -sf ../../i386/kernel/ptrace.c |