Memory hotplug presently auto-onlines memory into a zone the kernel deems
appropriate if CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y.
The memhp_default_state boot param enables runtime config, but it's not
possible to do this at build-time.
Remove CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE, and replace it with
CONFIG_MHP_DEFAULT_ONLINE_TYPE_* choices that sync with the boot param.
Selections:
  CONFIG_MHP_DEFAULT_ONLINE_TYPE_OFFLINE
    => mhp_default_online_type = "offline"
       Memory will not be onlined automatically.
  CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_AUTO
    => mhp_default_online_type = "online"
       Memory will be onlined automatically in a zone deemed.
       appropriate by the kernel.
  CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_KERNEL
    => mhp_default_online_type = "online_kernel"
       Memory will be onlined automatically.
       The zone may allow kernel data (e.g. ZONE_NORMAL).
  CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE
    => mhp_default_online_type = "online_movable"
       Memory will be onlined automatically.
       The zone will be ZONE_MOVABLE.
Default to CONFIG_MHP_DEFAULT_ONLINE_TYPE_OFFLINE to match the existing
default CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=n behavior.
Existing users of CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y should use
CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_AUTO.
[gourry@gourry.net: update KConfig comments]
Link: https://lkml.kernel.org/r/20241226182918.648799-1-gourry@gourry.net
Link: https://lkml.kernel.org/r/20241220210709.300066-1-gourry@gourry.net
Signed-off-by: Gregory Price <gourry@gourry.net>
Acked-by: David Hildenbrand <david@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: WANG Xuerui <kernel@xen0n.name>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
 
                        [KNL] Set the initial state for the memory hotplug
                        onlining policy. If not specified, the default value is
                        set according to the
-                       CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE kernel config
-                       option.
+                       CONFIG_MHP_DEFAULT_ONLINE_TYPE kernel config
+                       options.
                        See Documentation/admin-guide/mm/memory-hotplug.rst.
 
        memmap=exactmap [KNL,X86,EARLY] Enable setting of an exact
 
                       blocks; configure auto-onlining.
 
                       The default value depends on the
-                      CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE kernel configuration
-                      option.
+                      CONFIG_MHP_DEFAULT_ONLINE_TYPE kernel configuration
+                      options.
 
                       See the ``state`` property of memory blocks for details.
 ``block_size_bytes``   read-only: the size in bytes of a memory block.
 
 CONFIG_ZSMALLOC=m
 # CONFIG_COMPAT_BRK is not set
 CONFIG_MEMORY_HOTPLUG=y
-CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y
+# CONFIG_MHP_DEFAULT_ONLINE_TYPE_OFFLINE is not set
+CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_AUTO=y
+# CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_KERNEL is not set
+# CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE is not set
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
 
                                       struct device_attribute *attr, char *buf)
 {
        return sysfs_emit(buf, "%s\n",
-                         online_type_to_str[mhp_default_online_type]);
+                         online_type_to_str[mhp_get_default_online_type()]);
 }
 
 static ssize_t auto_online_blocks_store(struct device *dev,
        if (online_type < 0)
                return -EINVAL;
 
-       mhp_default_online_type = online_type;
+       mhp_set_default_online_type(online_type);
        return count;
 }
 
 
 
 extern int mhp_online_type_from_str(const char *str);
 
-/* Default online_type (MMOP_*) when new memory blocks are added. */
-extern int mhp_default_online_type;
 /* If movable_node boot option specified */
 extern bool movable_node_enabled;
 static inline bool movable_node_is_enabled(void)
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
+/* Default online_type (MMOP_*) when new memory blocks are added. */
+extern int mhp_get_default_online_type(void);
+extern void mhp_set_default_online_type(int online_type);
 extern void __ref free_area_init_core_hotplug(struct pglist_data *pgdat);
 extern int __add_memory(int nid, u64 start, u64 size, mhp_t mhp_flags);
 extern int add_memory(int nid, u64 start, u64 size, mhp_t mhp_flags);
 
 
 if MEMORY_HOTPLUG
 
-config MEMORY_HOTPLUG_DEFAULT_ONLINE
-       bool "Online the newly added memory blocks by default"
-       depends on MEMORY_HOTPLUG
+choice
+       prompt "Memory Hotplug Default Online Type"
+       default MHP_DEFAULT_ONLINE_TYPE_OFFLINE
        help
+         Default memory type for hotplugged memory.
+
          This option sets the default policy setting for memory hotplug
          onlining policy (/sys/devices/system/memory/auto_online_blocks) which
          determines what happens to newly added memory regions. Policy setting
          can always be changed at runtime.
+
+         The default is 'offline'.
+
+         Select offline to defer onlining to drivers and user policy.
+         Select auto to let the kernel choose what zones to utilize.
+         Select online_kernel to generally allow kernel usage of this memory.
+         Select online_movable to generally disallow kernel usage of this memory.
+
+         Example kernel usage would be page structs and page tables.
+
          See Documentation/admin-guide/mm/memory-hotplug.rst for more information.
 
-         Say Y here if you want all hot-plugged memory blocks to appear in
-         'online' state by default.
-         Say N here if you want the default policy to keep all hot-plugged
-         memory blocks in 'offline' state.
+config MHP_DEFAULT_ONLINE_TYPE_OFFLINE
+       bool "offline"
+       help
+         Hotplugged memory will not be onlined by default.
+         Choose this for systems with drivers and user policy that
+         handle onlining of hotplug memory policy.
+
+config MHP_DEFAULT_ONLINE_TYPE_ONLINE_AUTO
+       bool "auto"
+       help
+         Select this if you want the kernel to automatically online
+         hotplugged memory into the zone it thinks is reasonable.
+         This memory may be utilized for kernel data.
+
+config MHP_DEFAULT_ONLINE_TYPE_ONLINE_KERNEL
+       bool "kernel"
+       help
+         Select this if you want the kernel to automatically online
+         hotplugged memory into a zone capable of being used for kernel
+         data. This typically means ZONE_NORMAL.
+
+config MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE
+       bool "movable"
+       help
+         Select this if you want the kernel to automatically online
+         hotplug memory into ZONE_MOVABLE. This memory will generally
+         not be utilized for kernel data.
+
+         This should only be used when the admin knows sufficient
+         ZONE_NORMAL memory is available to describe hotplug memory,
+         otherwise hotplug memory may fail to online. For example,
+         sufficient kernel-capable memory (ZONE_NORMAL) must be
+         available to allocate page structs to describe ZONE_MOVABLE.
+
+endchoice
 
 config MEMORY_HOTREMOVE
        bool "Allow for memory hot remove"
 
 
 bool movable_node_enabled = false;
 
-#ifndef CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE
-int mhp_default_online_type = MMOP_OFFLINE;
-#else
-int mhp_default_online_type = MMOP_ONLINE;
-#endif
+static int mhp_default_online_type = -1;
+int mhp_get_default_online_type(void)
+{
+       if (mhp_default_online_type >= 0)
+               return mhp_default_online_type;
+
+       if (IS_ENABLED(CONFIG_MHP_DEFAULT_ONLINE_TYPE_OFFLINE))
+               mhp_default_online_type = MMOP_OFFLINE;
+       else if (IS_ENABLED(CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_AUTO))
+               mhp_default_online_type = MMOP_ONLINE;
+       else if (IS_ENABLED(CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_KERNEL))
+               mhp_default_online_type = MMOP_ONLINE_KERNEL;
+       else if (IS_ENABLED(CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE))
+               mhp_default_online_type = MMOP_ONLINE_MOVABLE;
+       else
+               mhp_default_online_type = MMOP_OFFLINE;
+
+       return mhp_default_online_type;
+}
+
+void mhp_set_default_online_type(int online_type)
+{
+       mhp_default_online_type = online_type;
+}
 
 static int __init setup_memhp_default_state(char *str)
 {
 
 static int online_memory_block(struct memory_block *mem, void *arg)
 {
-       mem->online_type = mhp_default_online_type;
+       mem->online_type = mhp_get_default_online_type();
        return device_online(&mem->dev);
 }
 
                merge_system_ram_resource(res);
 
        /* online pages if requested */
-       if (mhp_default_online_type != MMOP_OFFLINE)
+       if (mhp_get_default_online_type() != MMOP_OFFLINE)
                walk_memory_blocks(start, size, NULL, online_memory_block);
 
        return ret;