6c9b12c2e17e80629a9e3f55bbf93d9d28b3479d
[openwrt/openwrt.git] / target / linux / generic / patches-4.4 / 103-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch
1 From: Tobias Wolf <dev-NTEO@vplace.de>
2 Date: Wed, 30 Nov 2016 09:16:41 +0100
3 Subject: [PATCH] mm: Fix alloc_node_mem_map with ARCH_PFN_OFFSET
4 calculation
5
6 Dear folks,
7
8 An rt288x (ralink) based router (Belkin F5D8235 v1) does not boot with any
9 kernel beyond version 4.3 resulting in:
10
11 BUG: Bad page state in process swapper pfn:086ac
12
13 bisect resulted in:
14
15 a1c34a3bf00af2cede839879502e12dc68491ad5 is the first bad commit
16 commit a1c34a3bf00af2cede839879502e12dc68491ad5
17 Author: Laura Abbott <laura@labbott.name>
18 Date: Thu Nov 5 18:48:46 2015 -0800
19
20 mm: Don't offset memmap for flatmem
21
22 Srinivas Kandagatla reported bad page messages when trying to remove the
23 bottom 2MB on an ARM based IFC6410 board
24
25 BUG: Bad page state in process swapper pfn:fffa8
26 page:ef7fb500 count:0 mapcount:0 mapping: (null) index:0x0
27 flags: 0x96640253(locked|error|dirty|active|arch_1|reclaim|mlocked)
28 page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set
29 bad because of flags:
30 flags: 0x200041(locked|active|mlocked)
31 Modules linked in:
32 CPU: 0 PID: 0 Comm: swapper Not tainted 3.19.0-rc3-00007-g412f9ba-dirty
33 #816
34 Hardware name: Qualcomm (Flattened Device Tree)
35 unwind_backtrace
36 show_stack
37 dump_stack
38 bad_page
39 free_pages_prepare
40 free_hot_cold_page
41 __free_pages
42 free_highmem_page
43 mem_init
44 start_kernel
45 Disabling lock debugging due to kernel taint
46 [...]
47 :040000 040000 2de013c372345fd471cd58f0553c9b38b0ef1cc4
48 0a8156f848733dfa21e16c196dfb6c0a76290709 M mm
49
50 This fix for ARM does not account ARCH_PFN_OFFSET for mem_map as later used by
51 page_to_pfn anymore.
52
53 The following output was generated with two hacked in printk statements:
54
55 printk("before %p vs. %p or %p\n", mem_map, mem_map - offset, mem_map -
56 (pgdat->node_start_pfn - ARCH_PFN_OFFSET));
57 if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
58 mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET);
59 printk("after %p\n", mem_map);
60
61 Output:
62
63 [ 0.000000] before 8861b280 vs. 8861b280 or 8851b280
64 [ 0.000000] after 8851b280
65
66 As seen in the first line mem_map with subtraction of offset does not equal the
67 mem_map after subtraction of ARCH_PFN_OFFSET.
68
69 After adding the offset of ARCH_PFN_OFFSET as well to mem_map as the
70 previously calculated offset is zero for the named platform it is able to boot
71 4.4 and 4.9-rc7 again.
72
73 Signed-off-by: Tobias Wolf <dev-NTEO@vplace.de>
74 ---
75
76 --- a/mm/page_alloc.c
77 +++ b/mm/page_alloc.c
78 @@ -5357,7 +5357,7 @@ static void __init_refok alloc_node_mem_
79 mem_map = NODE_DATA(0)->node_mem_map;
80 #if defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) || defined(CONFIG_FLATMEM)
81 if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
82 - mem_map -= offset;
83 + mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET);
84 #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
85 }
86 #endif