|  | @@ -184,3 +184,108 @@ static void __init arm_bootmem_init(unsigned long start_pfn,
 | 
	
		
			
				|  |  |  			break;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Reserve the lowmem memblock reserved regions in bootmem. */
 | 
	
		
			
				|  |  | +	for_each_memblock(reserved, reg) {
 | 
	
		
			
				|  |  | +		unsigned long start = memblock_region_reserved_base_pfn(reg);
 | 
	
		
			
				|  |  | +		unsigned long end = memblock_region_reserved_end_pfn(reg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (end >= end_pfn)
 | 
	
		
			
				|  |  | +			end = end_pfn;
 | 
	
		
			
				|  |  | +		if (start >= end)
 | 
	
		
			
				|  |  | +			break;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		reserve_bootmem(__pfn_to_phys(start),
 | 
	
		
			
				|  |  | +			        (end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef CONFIG_ZONE_DMA
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +unsigned long arm_dma_zone_size __read_mostly;
 | 
	
		
			
				|  |  | +EXPORT_SYMBOL(arm_dma_zone_size);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * The DMA mask corresponding to the maximum bus address allocatable
 | 
	
		
			
				|  |  | + * using GFP_DMA.  The default here places no restriction on DMA
 | 
	
		
			
				|  |  | + * allocations.  This must be the smallest DMA mask in the system,
 | 
	
		
			
				|  |  | + * so a successful GFP_DMA allocation will always satisfy this.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +phys_addr_t arm_dma_limit;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
 | 
	
		
			
				|  |  | +	unsigned long dma_size)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (size[0] <= dma_size)
 | 
	
		
			
				|  |  | +		return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	size[ZONE_NORMAL] = size[0] - dma_size;
 | 
	
		
			
				|  |  | +	size[ZONE_DMA] = dma_size;
 | 
	
		
			
				|  |  | +	hole[ZONE_NORMAL] = hole[0];
 | 
	
		
			
				|  |  | +	hole[ZONE_DMA] = 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void __init setup_dma_zone(struct machine_desc *mdesc)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +#ifdef CONFIG_ZONE_DMA
 | 
	
		
			
				|  |  | +	if (mdesc->dma_zone_size) {
 | 
	
		
			
				|  |  | +		arm_dma_zone_size = mdesc->dma_zone_size;
 | 
	
		
			
				|  |  | +		arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
 | 
	
		
			
				|  |  | +	} else
 | 
	
		
			
				|  |  | +		arm_dma_limit = 0xffffffff;
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
 | 
	
		
			
				|  |  | +	unsigned long max_high)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
 | 
	
		
			
				|  |  | +	struct memblock_region *reg;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * initialise the zones.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	memset(zone_size, 0, sizeof(zone_size));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * The memory size has already been determined.  If we need
 | 
	
		
			
				|  |  | +	 * to do anything fancy with the allocation of this memory
 | 
	
		
			
				|  |  | +	 * to the zones, now is the time to do it.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	zone_size[0] = max_low - min;
 | 
	
		
			
				|  |  | +#ifdef CONFIG_HIGHMEM
 | 
	
		
			
				|  |  | +	zone_size[ZONE_HIGHMEM] = max_high - max_low;
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Calculate the size of the holes.
 | 
	
		
			
				|  |  | +	 *  holes = node_size - sum(bank_sizes)
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	memcpy(zhole_size, zone_size, sizeof(zhole_size));
 | 
	
		
			
				|  |  | +	for_each_memblock(memory, reg) {
 | 
	
		
			
				|  |  | +		unsigned long start = memblock_region_memory_base_pfn(reg);
 | 
	
		
			
				|  |  | +		unsigned long end = memblock_region_memory_end_pfn(reg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (start < max_low) {
 | 
	
		
			
				|  |  | +			unsigned long low_end = min(end, max_low);
 | 
	
		
			
				|  |  | +			zhole_size[0] -= low_end - start;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +#ifdef CONFIG_HIGHMEM
 | 
	
		
			
				|  |  | +		if (end > max_low) {
 | 
	
		
			
				|  |  | +			unsigned long high_start = max(start, max_low);
 | 
	
		
			
				|  |  | +			zhole_size[ZONE_HIGHMEM] -= end - high_start;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef CONFIG_ZONE_DMA
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Adjust the sizes according to any special requirements for
 | 
	
		
			
				|  |  | +	 * this machine type.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (arm_dma_zone_size)
 | 
	
		
			
				|  |  | +		arm_adjust_dma_zone(zone_size, zhole_size,
 | 
	
		
			
				|  |  | +			arm_dma_zone_size >> PAGE_SHIFT);
 | 
	
		
			
				|  |  | +#endif
 |