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