* [PATCH] [RFC] ppc32 (linux-2.6.11.4): remove the limitation of 2MB consistent DMA memory on ppc440
[not found] <1B5A11557D6A86458B1AD15DBBDB6CE2066D8CF4@tayexc13.americas.cpqcorp.net>
@ 2005-06-01 21:55 ` Shawn Jin
0 siblings, 0 replies; only message in thread
From: Shawn Jin @ 2005-06-01 21:55 UTC (permalink / raw)
To: ppcembed, Ahamed K, Rafiq (HP)
[-- Attachment #1: Type: text/plain, Size: 905 bytes --]
Hi,
This patch removes the limitation of 2MB consistent DMA memory on
ppc440. Originally consistent_pte was allocated only one page no
matter what value of CONFIG_CONSISTENT_SIZE is set. By default
CONFIG_CONSISTENT_SIZE is 0x200000. This causes some troubles on high
performance I/O applications which may require more than 2MB
consistent DMA memory.
The modifications allocate multiple pages for consistent pte table
according to CONFIG_CONSISTENT_SIZE. For example if
CONFIG_CONSISTENT_SIZE is set to 4MB, 2 pages are allocated for
consistent pte table. Please note that CONFIG_CONSISTENT_SIZE cannot
be any value. You have to find a free continuous memory space on your
system memory mapping.
The patch was tested successfully on Ocotea board. But I'm not sure if
it works on other systems. Use it at your own risk. However feedback
is more than welcome. :)
Regards,
-Shawn.
[-- Attachment #2: dma-mapping.patch --]
[-- Type: application/octet-stream, Size: 4203 bytes --]
--- orig/linux-2.6.11.4/arch/ppc/kernel/dma-mapping.c 2005-03-15 16:08:58.000000000 -0800
+++ linux-2.6.11.4/arch/ppc/kernel/dma-mapping.c 2005-05-27 19:06:27.956937000 -0700
@@ -17,6 +17,11 @@
* implementation. This is pulled straight from ARM and barely
* modified. -Matt
*
+ * Changed consistent_pte to consistent_ptes, in order to remove the
+ * limitation of 2MB consistent DMA memory. Now the size is confined by
+ * CONFIG_CONSISTENT_SIZE. And there are multiple pages containing PTE.
+ * - Xiaogeng (Shawn) Jin (Agilent Technologies), 2005
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -66,11 +71,14 @@
#define CONSISTENT_BASE (CONFIG_CONSISTENT_START)
#define CONSISTENT_END (CONFIG_CONSISTENT_START + CONFIG_CONSISTENT_SIZE)
#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
+#define CONSISTENT_PTE_PAGENR ((CONFIG_CONSISTENT_SIZE >> PAGE_SHIFT) >> PTE_SHIFT)
+#define CONSISTENT_SIZE_PER_PTEPAGE (1UL << (PAGE_SHIFT + PTE_SHIFT))
/*
- * This is the page table (2MB) covering uncached, DMA consistent allocations
+ * This is page tables covering uncached, DMA consistent allocations,
+ * with the size of CONFIG_CONSISTENT_SIZE
*/
-static pte_t *consistent_pte;
+pte_t **consistent_ptes = NULL;
static DEFINE_SPINLOCK(consistent_lock);
/*
@@ -180,7 +188,7 @@
unsigned long order;
u64 mask = 0x00ffffff, limit; /* ISA default */
- if (!consistent_pte) {
+ if (!consistent_ptes) {
printk(KERN_ERR "%s: not initialised\n", __func__);
dump_stack();
return NULL;
@@ -219,9 +227,14 @@
c = vm_region_alloc(&consistent_head, size,
gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
if (c) {
- pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+ pte_t *pte;
+ int offset = CONSISTENT_OFFSET(c->vm_start);
+ int idx = offset >> PTE_SHIFT;
struct page *end = page + (1 << order);
+ offset &= (1 << PTE_SHIFT) - 1;
+ pte = consistent_ptes[idx] + offset;
+
/*
* Set the "dma handle"
*/
@@ -235,6 +248,11 @@
set_pte(pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
page++;
pte++;
+ offset++;
+ if (offset > ((1 << PTE_SHIFT) - 1)) {
+ pte = consistent_ptes[++idx];
+ offset = 0;
+ }
} while (size -= PAGE_SIZE);
/*
@@ -264,6 +282,7 @@
struct vm_region *c;
unsigned long flags;
pte_t *ptep;
+ int offset, idx;
size = PAGE_ALIGN(size);
@@ -280,12 +299,21 @@
size = c->vm_end - c->vm_start;
}
- ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+ offset = CONSISTENT_OFFSET(c->vm_start);
+ idx = offset >> PTE_SHIFT;
+ offset &= (1 << PTE_SHIFT) - 1;
+ ptep = consistent_ptes[idx] + offset;
+
do {
pte_t pte = ptep_get_and_clear(ptep);
unsigned long pfn;
ptep++;
+ offset++;
+ if (offset > ((1 << PTE_SHIFT) - 1)) {
+ ptep = consistent_ptes[++idx];
+ offset = 0;
+ }
if (!pte_none(pte) && pte_present(pte)) {
pfn = pte_pfn(pte);
@@ -328,13 +356,22 @@
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int ret = 0;
+ int ret = 0, i;
+ unsigned long address;
spin_lock(&init_mm.page_table_lock);
- do {
- pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
- pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+ consistent_ptes = (pte_t **)kmalloc(sizeof(pte_t **) *
+ CONSISTENT_PTE_PAGENR, GFP_KERNEL);
+ if (!consistent_ptes) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+
+ for (i = 0, address = CONSISTENT_BASE; i < CONSISTENT_PTE_PAGENR; i++) {
+ pgd = pgd_offset(&init_mm, address);
+ pmd = pmd_alloc(&init_mm, pgd, address);
if (!pmd) {
printk(KERN_ERR "%s: no pmd tables\n", __func__);
ret = -ENOMEM;
@@ -342,16 +379,19 @@
}
WARN_ON(!pmd_none(*pmd));
- pte = pte_alloc_kernel(&init_mm, pmd, CONSISTENT_BASE);
+ pte = pte_alloc_kernel(&init_mm, pmd, address);
if (!pte) {
printk(KERN_ERR "%s: no pte tables\n", __func__);
ret = -ENOMEM;
break;
}
- consistent_pte = pte;
- } while (0);
+ consistent_ptes[i] = pte;
+
+ address += CONSISTENT_SIZE_PER_PTEPAGE;
+ }
+out:
spin_unlock(&init_mm.page_table_lock);
return ret;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-06-01 21:55 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1B5A11557D6A86458B1AD15DBBDB6CE2066D8CF4@tayexc13.americas.cpqcorp.net>
2005-06-01 21:55 ` [PATCH] [RFC] ppc32 (linux-2.6.11.4): remove the limitation of 2MB consistent DMA memory on ppc440 Shawn Jin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).