This rev looks much better to me, at least. Thanks for fixing it up.

M.

> 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 <[EMAIL PROTECTED]>
> 
> -------------------------------------------------------------------
> 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 [EMAIL PROTECTED]  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"[EMAIL PROTECTED]"> [EMAIL PROTECTED] </a>
> 
> 


-
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to