aboutsummaryrefslogtreecommitdiffstats
path: root/linux-2.4.26-xen-sparse
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-08-03 09:36:00 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-08-03 09:36:00 +0000
commitfee4accd62794697667999837ae71fd10f7d92e8 (patch)
tree67081eb261e99089d2c010e165bfcf203ed77ff7 /linux-2.4.26-xen-sparse
parentbe4989adb0e4f14e7b6a99cdc60e5e3640c2c692 (diff)
downloadxen-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.c52
-rwxr-xr-xlinux-2.4.26-xen-sparse/mkbuildtree1
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