|
@@ -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
|