linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Yasunori Goto <y-goto@jp.fujitsu.com>
To: linux-mm <linux-mm@kvack.org>, Andrew Morton <akpm@osdl.org>
Cc: "Martin J. Bligh" <mbligh@mbligh.org>,
	linux-ia64@vger.kernel.org, Mike Kravetz <kravetz@us.ibm.com>,
	"Luck, Tony" <tony.luck@intel.com>
Subject: [PATCH] gurantee DMA area for alloc_bootmem_low() ver. 2.
Date: Tue, 09 Aug 2005 20:11:20 +0900	[thread overview]
Message-ID: <20050809194115.C370.Y-GOTO@jp.fujitsu.com> (raw)

Hello.

I modified the patch which guarantees allocation of DMA area
at alloc_bootmem_low().

I tested this patch. Please apply.

The differences from previous one are ....
  - Confirmation that allocated area is really DMA area.
  - max_dma_physaddr() is defined for some architecture that
    all of memory is DMA area.

    (Note: Mike Kravez-san's code was defined by MACRO like this.
        #ifndef MAX_DMA_PHYSADDR
        #if MAX_DMA_ADDRESS == ~0UL
                :
                :
      However, MAX_DMA_ADDRESS is defined with cast "(unsigned long)"
      in some architecture like i386. And, preprocessor doesn't like 
      this cast in #IF sentence and displays error message as
      "missing binary operator befor token "long"".
      So, I changed it to static inline function.)

Thanks.

----------------------

This is a patch to guarantee that alloc_bootmem_low() allocate DMA area.

Current alloc_bootmem_low() is just specify "goal=0". And it is 
used for __alloc_bootmem_core() to decide which address is better.
However, there is no guarantee that __alloc_bootmem_core()
allocate DMA area when goal=0 is specified.
Even if there is no DMA'ble area in searching node, it allocates
higher address than MAX_DMA_ADDRESS.

__alloc_bootmem_core() is called by order of for_each_pgdat()
in __alloc_bootmem(). So, if first node (node_id = 0) has
DMA'ble area, no trouble will occur. However, our new Itanium2 server
can change which node has lower address. And panic really occurred on it.
The message was "bounce buffer is not DMA'ble" in swiothl_map_single().

To avoid this panic, following patch confirms allocated area, and retry
if it is not in DMA.
I tested this patch on my Tiger 4 and our new server.


Signed-off by Yasunori Goto <y-goto@jp.fujitsu.com>

-------------------------------------------------------------------
Index: bootmem/mm/bootmem.c
===================================================================
--- bootmem.orig/mm/bootmem.c	2005-08-09 15:50:06.000000000 +0900
+++ bootmem/mm/bootmem.c	2005-08-09 16:11:57.076880203 +0900
@@ -374,10 +374,25 @@ void * __init __alloc_bootmem (unsigned 
 	pg_data_t *pgdat = pgdat_list;
 	void *ptr;
 
-	for_each_pgdat(pgdat)
-		if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
-						align, goal)))
-			return(ptr);
+	for_each_pgdat(pgdat){
+
+		ptr = __alloc_bootmem_core(pgdat->bdata, size,
+					   align, goal);
+
+		if (!ptr)
+			continue;
+
+		if (goal < max_dma_physaddr() &&
+		    (unsigned long)ptr >= MAX_DMA_ADDRESS){
+			/* DMA area is required, but ptr is not DMA area.
+			   Trying other nodes */
+
+			free_bootmem_core(pgdat->bdata, virt_to_phys(ptr), size);
+			continue;
+		}
+
+		return(ptr);
+
+	}
 
 	/*
 	 * Whoops, we cannot satisfy the allocation request.
Index: bootmem/include/linux/bootmem.h
===================================================================
--- bootmem.orig/include/linux/bootmem.h	2005-08-09 15:50:06.000000000 +0900
+++ bootmem/include/linux/bootmem.h	2005-08-09 16:05:17.929424155 +0900
@@ -36,6 +36,15 @@ typedef struct bootmem_data {
 					 * up searching */
 } bootmem_data_t;
 
+static inline unsigned long max_dma_physaddr(void)
+{
+
+	if (MAX_DMA_ADDRESS == ~0UL)
+		return MAX_DMA_ADDRESS;
+	else
+		return __pa(MAX_DMA_ADDRESS);
+}
+
 extern unsigned long __init bootmem_bootmap_pages (unsigned long);
 extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend);
 extern void __init free_bootmem (unsigned long addr, unsigned long size);
@@ -43,11 +52,11 @@ extern void * __init __alloc_bootmem (un
 #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
 extern void __init reserve_bootmem (unsigned long addr, unsigned long size);
 #define alloc_bootmem(x) \
-	__alloc_bootmem((x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+	__alloc_bootmem((x), SMP_CACHE_BYTES, max_dma_physaddr())
 #define alloc_bootmem_low(x) \
 	__alloc_bootmem((x), SMP_CACHE_BYTES, 0)
 #define alloc_bootmem_pages(x) \
-	__alloc_bootmem((x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
+	__alloc_bootmem((x), PAGE_SIZE, max_dma_physaddr())
 #define alloc_bootmem_low_pages(x) \
 	__alloc_bootmem((x), PAGE_SIZE, 0)
 #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
@@ -60,9 +69,9 @@ extern unsigned long __init free_all_boo
 extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal);
 #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
 #define alloc_bootmem_node(pgdat, x) \
-	__alloc_bootmem_node((pgdat), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+	__alloc_bootmem_node((pgdat), (x), SMP_CACHE_BYTES, max_dma_physaddr())
 #define alloc_bootmem_pages_node(pgdat, x) \
-	__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
+	__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, max_dma_physaddr())
 #define alloc_bootmem_low_pages_node(pgdat, x) \
 	__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0)
 #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */

-- 
Yasunori Goto 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

             reply	other threads:[~2005-08-09 11:11 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-08-09 11:11 Yasunori Goto [this message]
2005-08-09 15:05 ` Martin J. Bligh
2005-08-09 21:15 ` Mike Kravetz
2005-08-10  3:06   ` Dave Hansen
2005-08-10 16:23     ` Dave Hansen
2005-08-11 20:46   ` Christoph Lameter
2005-08-11 21:14     ` Mike Kravetz
2005-08-11 22:37       ` Christoph Lameter
2005-08-09 23:02 ` Peter Chubb
2005-08-10  6:10   ` Yasunori Goto
2005-08-18 19:52     ` Andrew Morton
2005-08-18 21:39       ` Andi Kleen
2005-08-19  2:29         ` Yasunori Goto
2005-08-19  3:03           ` Andi Kleen
2005-08-19  1:26       ` Yasunori Goto
2005-08-25  9:15       ` Yasunori Goto

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=20050809194115.C370.Y-GOTO@jp.fujitsu.com \
    --to=y-goto@jp.fujitsu.com \
    --cc=akpm@osdl.org \
    --cc=kravetz@us.ibm.com \
    --cc=linux-ia64@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mbligh@mbligh.org \
    --cc=tony.luck@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
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