public inbox for linuxppc-dev@ozlabs.org 
 help / color / mirror / Atom feed
From: Shawn Jin <shawnxjin@gmail•com>
To: ppcembed <linuxppc-embedded@ozlabs•org>,
	"Ahamed K, Rafiq (HP)" <rafiq.ahamed@hp•com>
Subject: [PATCH] [RFC] ppc32 (linux-2.6.11.4): remove the limitation of 2MB consistent DMA memory on ppc440
Date: Wed, 1 Jun 2005 14:55:03 -0700	[thread overview]
Message-ID: <c3d0340b0506011455317d79f6@mail.gmail.com> (raw)
In-Reply-To: <1B5A11557D6A86458B1AD15DBBDB6CE2066D8CF4@tayexc13.americas.cpqcorp.net>

[-- 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;

           reply	other threads:[~2005-06-01 21:55 UTC|newest]

Thread overview: expand[flat|nested]  mbox.gz  Atom feed
 [parent not found: <1B5A11557D6A86458B1AD15DBBDB6CE2066D8CF4@tayexc13.americas.cpqcorp.net>]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c3d0340b0506011455317d79f6@mail.gmail.com \
    --to=shawnxjin@gmail$(echo .)com \
    --cc=linuxppc-embedded@ozlabs$(echo .)org \
    --cc=rafiq.ahamed@hp$(echo .)com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox