#include <linux/mm.h>
 #include <linux/mmzone.h>
 #include <linux/memory.h>
+#include <linux/memory_hotplug.h>
 #include <linux/module.h>
 #include <asm/ctlreg.h>
 #include <asm/chpid.h>
 #include <asm/sclp.h>
 #include <asm/numa.h>
 #include <asm/facility.h>
+#include <asm/page-states.h>
 
 #include "sclp.h"
 
                if (contains_standby_increment(start, start + size))
                        rc = -EPERM;
                break;
-       case MEM_GOING_ONLINE:
+       case MEM_PREPARE_ONLINE:
+               /*
+                * Access the altmap_start_pfn and altmap_nr_pages fields
+                * within the struct memory_notify specifically when dealing
+                * with only MEM_PREPARE_ONLINE/MEM_FINISH_OFFLINE notifiers.
+                *
+                * When altmap is in use, take the specified memory range
+                * online, which includes the altmap.
+                */
+               if (arg->altmap_nr_pages) {
+                       start = PFN_PHYS(arg->altmap_start_pfn);
+                       size += PFN_PHYS(arg->altmap_nr_pages);
+               }
                rc = sclp_mem_change_state(start, size, 1);
+               if (rc || !arg->altmap_nr_pages)
+                       break;
+               /*
+                * Set CMMA state to nodat here, since the struct page memory
+                * at the beginning of the memory block will not go through the
+                * buddy allocator later.
+                */
+               __arch_set_page_nodat((void *)__va(start), arg->altmap_nr_pages);
                break;
-       case MEM_CANCEL_ONLINE:
-               sclp_mem_change_state(start, size, 0);
-               break;
-       case MEM_OFFLINE:
+       case MEM_FINISH_OFFLINE:
+               /*
+                * When altmap is in use, take the specified memory range
+                * offline, which includes the altmap.
+                */
+               if (arg->altmap_nr_pages) {
+                       start = PFN_PHYS(arg->altmap_start_pfn);
+                       size += PFN_PHYS(arg->altmap_nr_pages);
+               }
                sclp_mem_change_state(start, size, 0);
                break;
        default:
        if (!size)
                goto skip_add;
        for (addr = start; addr < start + size; addr += block_size)
-               add_memory(0, addr, block_size, MHP_NONE);
+               add_memory(0, addr, block_size,
+                          MACHINE_HAS_EDAT1 ?
+                          MHP_MEMMAP_ON_MEMORY | MHP_OFFLINE_INACCESSIBLE : MHP_NONE);
 skip_add:
        first_rn = rn;
        num = 1;