On memory unplug reduce DirectMap page count correctly.
root@ubuntu-guest:# grep Direct /proc/meminfo
DirectMap4k:           0 kB
DirectMap64k:           0 kB
DirectMap2M:    115343360 kB
DirectMap1G:           0 kB

Before fix:
root@ubuntu-guest:# ndctl disable-namespace all
disabled 1 namespace
root@ubuntu-guest:# grep Direct /proc/meminfo
DirectMap4k:           0 kB
DirectMap64k:           0 kB
DirectMap2M:    115343360 kB
DirectMap1G:           0 kB

After fix:
root@ubuntu-guest:# ndctl disable-namespace all
disabled 1 namespace
root@ubuntu-guest:# grep Direct /proc/meminfo
DirectMap4k:           0 kB
DirectMap64k:           0 kB
DirectMap2M:    104857600 kB
DirectMap1G:           0 kB

Fixes: a2dc009afa9a ("powerpc/mm/book3s/radix: Add mapping statistics")
Signed-off-by: Aneesh Kumar K.V <aneesh.ku...@linux.ibm.com>
---
 arch/powerpc/mm/book3s64/radix_pgtable.c | 34 +++++++++++++++---------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c 
b/arch/powerpc/mm/book3s64/radix_pgtable.c
index 570add33c02d..15a099e53cde 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -743,9 +743,9 @@ static void free_pud_table(pud_t *pud_start, p4d_t *p4d)
 }
 
 static void remove_pte_table(pte_t *pte_start, unsigned long addr,
-                            unsigned long end)
+                            unsigned long end, bool direct)
 {
-       unsigned long next;
+       unsigned long next, pages = 0;
        pte_t *pte;
 
        pte = pte_start + pte_index(addr);
@@ -767,13 +767,16 @@ static void remove_pte_table(pte_t *pte_start, unsigned 
long addr,
                }
 
                pte_clear(&init_mm, addr, pte);
+               pages++;
        }
+       if (direct)
+               update_page_count(mmu_virtual_psize, -pages);
 }
 
 static void __meminit remove_pmd_table(pmd_t *pmd_start, unsigned long addr,
-                            unsigned long end)
+                                      unsigned long end, bool direct)
 {
-       unsigned long next;
+       unsigned long next, pages = 0;
        pte_t *pte_base;
        pmd_t *pmd;
 
@@ -791,19 +794,22 @@ static void __meminit remove_pmd_table(pmd_t *pmd_start, 
unsigned long addr,
                                continue;
                        }
                        pte_clear(&init_mm, addr, (pte_t *)pmd);
+                       pages++;
                        continue;
                }
 
                pte_base = (pte_t *)pmd_page_vaddr(*pmd);
-               remove_pte_table(pte_base, addr, next);
+               remove_pte_table(pte_base, addr, next, direct);
                free_pte_table(pte_base, pmd);
        }
+       if (direct)
+               update_page_count(MMU_PAGE_2M, -pages);
 }
 
 static void __meminit remove_pud_table(pud_t *pud_start, unsigned long addr,
-                            unsigned long end)
+                                      unsigned long end, bool direct)
 {
-       unsigned long next;
+       unsigned long next, pages = 0;
        pmd_t *pmd_base;
        pud_t *pud;
 
@@ -821,16 +827,20 @@ static void __meminit remove_pud_table(pud_t *pud_start, 
unsigned long addr,
                                continue;
                        }
                        pte_clear(&init_mm, addr, (pte_t *)pud);
+                       pages++;
                        continue;
                }
 
                pmd_base = pud_pgtable(*pud);
-               remove_pmd_table(pmd_base, addr, next);
+               remove_pmd_table(pmd_base, addr, next, direct);
                free_pmd_table(pmd_base, pud);
        }
+       if (direct)
+               update_page_count(MMU_PAGE_1G, -pages);
 }
 
-static void __meminit remove_pagetable(unsigned long start, unsigned long end)
+static void __meminit remove_pagetable(unsigned long start, unsigned long end,
+                                      bool direct)
 {
        unsigned long addr, next;
        pud_t *pud_base;
@@ -859,7 +869,7 @@ static void __meminit remove_pagetable(unsigned long start, 
unsigned long end)
                }
 
                pud_base = p4d_pgtable(*p4d);
-               remove_pud_table(pud_base, addr, next);
+               remove_pud_table(pud_base, addr, next, direct);
                free_pud_table(pud_base, p4d);
        }
 
@@ -882,7 +892,7 @@ int __meminit radix__create_section_mapping(unsigned long 
start,
 
 int __meminit radix__remove_section_mapping(unsigned long start, unsigned long 
end)
 {
-       remove_pagetable(start, end);
+       remove_pagetable(start, end, true);
        return 0;
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
@@ -918,7 +928,7 @@ int __meminit radix__vmemmap_create_mapping(unsigned long 
start,
 #ifdef CONFIG_MEMORY_HOTPLUG
 void __meminit radix__vmemmap_remove_mapping(unsigned long start, unsigned 
long page_size)
 {
-       remove_pagetable(start, start + page_size);
+       remove_pagetable(start, start + page_size, false);
 }
 #endif
 #endif
-- 
2.40.1

Reply via email to