powerpc/pseries: Revert 'Auto-online hotplugged memory'
authorNathan Fontenot <nfont@linux.vnet.ibm.com>
Wed, 15 Feb 2017 18:45:30 +0000 (13:45 -0500)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 21 Feb 2017 01:57:01 +0000 (12:57 +1100)
This reverts commit ec999072442a ("powerpc/pseries: Auto-online
hotplugged memory"), and 9dc512819e4b ("powerpc: Fix unused function
warning 'lmb_to_memblock'").

Using the auto-online acpability does online added memory but does not
update the associated device struct to indicate that the memory is
online. This causes the pseries memory DLPAR code to fail when trying to
remove a LMB that was previously removed and added back. This happens
when validating that the LMB is removable.

This patch reverts to the previous behavior of calling device_online()
to online the LMB when it is DLPAR added and moves the lmb_to_memblock()
routine out of CONFIG_MEMORY_HOTREMOVE now that we call it for add.

Fixes: ec999072442a ("powerpc/pseries: Auto-online hotplugged memory")
Cc: stable@vger.kernel.org # v4.8+
Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/configs/pseries_defconfig
arch/powerpc/platforms/pseries/hotplug-memory.c

index 6d0eb02fefa471a436a15d2baae1465a4f417615..4ff68b752618e31405093c95dba253d8cab02684 100644 (file)
@@ -58,7 +58,6 @@ CONFIG_KEXEC_FILE=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
-CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_PPC_64K_PAGES=y
index e28abfa013e523275a3213710ccb31cf8c7a721f..e104c71ea44ab5bf715fa5720c0a1ed47c6221c7 100644 (file)
@@ -320,6 +320,19 @@ static int dlpar_remove_device_tree_lmb(struct of_drconf_cell *lmb)
        return dlpar_update_device_tree_lmb(lmb);
 }
 
+static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
+{
+       unsigned long section_nr;
+       struct mem_section *mem_sect;
+       struct memory_block *mem_block;
+
+       section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
+       mem_sect = __nr_to_section(section_nr);
+
+       mem_block = find_memory_block(mem_sect);
+       return mem_block;
+}
+
 #ifdef CONFIG_MEMORY_HOTREMOVE
 static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
 {
@@ -407,19 +420,6 @@ static bool lmb_is_removable(struct of_drconf_cell *lmb)
 
 static int dlpar_add_lmb(struct of_drconf_cell *);
 
-static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
-{
-       unsigned long section_nr;
-       struct mem_section *mem_sect;
-       struct memory_block *mem_block;
-
-       section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
-       mem_sect = __nr_to_section(section_nr);
-
-       mem_block = find_memory_block(mem_sect);
-       return mem_block;
-}
-
 static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
 {
        struct memory_block *mem_block;
@@ -728,6 +728,20 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index,
 }
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
+static int dlpar_online_lmb(struct of_drconf_cell *lmb)
+{
+       struct memory_block *mem_block;
+       int rc;
+
+       mem_block = lmb_to_memblock(lmb);
+       if (!mem_block)
+               return -EINVAL;
+
+       rc = device_online(&mem_block->dev);
+       put_device(&mem_block->dev);
+       return rc;
+}
+
 static int dlpar_add_lmb(struct of_drconf_cell *lmb)
 {
        unsigned long block_sz;
@@ -751,10 +765,18 @@ static int dlpar_add_lmb(struct of_drconf_cell *lmb)
 
        /* Add the memory */
        rc = add_memory(nid, lmb->base_addr, block_sz);
-       if (rc)
+       if (rc) {
                dlpar_remove_device_tree_lmb(lmb);
-       else
+               return rc;
+       }
+
+       rc = dlpar_online_lmb(lmb);
+       if (rc) {
+               remove_memory(nid, lmb->base_addr, block_sz);
+               dlpar_remove_device_tree_lmb(lmb);
+       } else {
                lmb->flags |= DRCONF_MEM_ASSIGNED;
+       }
 
        return rc;
 }