|
@@ -724,6 +724,53 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+/*
|
|
|
+ * Calculate the precise size of the DMA zone (first 16 MB of RAM),
|
|
|
+ * and pass it to the MM layer - to help it set zone watermarks more
|
|
|
+ * accurately.
|
|
|
+ *
|
|
|
+ * Done on 64-bit systems only for the time being, although 32-bit systems
|
|
|
+ * might benefit from this as well.
|
|
|
+ */
|
|
|
+void __init memblock_find_dma_reserve(void)
|
|
|
+{
|
|
|
+#ifdef CONFIG_X86_64
|
|
|
+ u64 nr_pages = 0, nr_free_pages = 0;
|
|
|
+ unsigned long start_pfn, end_pfn;
|
|
|
+ phys_addr_t start_addr, end_addr;
|
|
|
+ int i;
|
|
|
+ u64 u;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Iterate over all memory ranges (free and reserved ones alike),
|
|
|
+ * to calculate the total number of pages in the first 16 MB of RAM:
|
|
|
+ */
|
|
|
+ nr_pages = 0;
|
|
|
+ for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) {
|
|
|
+ start_pfn = min(start_pfn, MAX_DMA_PFN);
|
|
|
+ end_pfn = min(end_pfn, MAX_DMA_PFN);
|
|
|
+
|
|
|
+ nr_pages += end_pfn - start_pfn;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Iterate over free memory ranges to calculate the number of free
|
|
|
+ * pages in the DMA zone, while not counting potential partial
|
|
|
+ * pages at the beginning or the end of the range:
|
|
|
+ */
|
|
|
+ nr_free_pages = 0;
|
|
|
+ for_each_free_mem_range(u, NUMA_NO_NODE, MEMBLOCK_NONE, &start_addr, &end_addr, NULL) {
|
|
|
+ start_pfn = min_t(unsigned long, PFN_UP(start_addr), MAX_DMA_PFN);
|
|
|
+ end_pfn = min_t(unsigned long, PFN_DOWN(end_addr), MAX_DMA_PFN);
|
|
|
+
|
|
|
+ if (start_pfn < end_pfn)
|
|
|
+ nr_free_pages += end_pfn - start_pfn;
|
|
|
+ }
|
|
|
+
|
|
|
+ set_dma_reserve(nr_pages - nr_free_pages);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
void __init zone_sizes_init(void)
|
|
|
{
|
|
|
unsigned long max_zone_pfns[MAX_NR_ZONES];
|