return section_nr / sections_per_block;
 }
 
+static inline int pfn_to_block_id(unsigned long pfn)
+{
+       return base_memory_block_id(pfn_to_section_nr(pfn));
+}
+
 static int memory_subsys_online(struct device *dev);
 static int memory_subsys_offline(struct device *dev);
 
  * A reference for the returned object is held and the reference for the
  * hinted object is released.
  */
-struct memory_block *find_memory_block_hinted(struct mem_section *section,
-                                             struct memory_block *hint)
+static struct memory_block *find_memory_block_by_id(int block_id,
+                                                   struct memory_block *hint)
 {
-       int block_id = base_memory_block_id(__section_nr(section));
        struct device *hintdev = hint ? &hint->dev : NULL;
        struct device *dev;
 
        return to_memory_block(dev);
 }
 
+struct memory_block *find_memory_block_hinted(struct mem_section *section,
+                                             struct memory_block *hint)
+{
+       int block_id = base_memory_block_id(__section_nr(section));
+
+       return find_memory_block_by_id(block_id, hint);
+}
+
 /*
  * For now, we have a linear search to go find the appropriate
  * memory_block corresponding to a particular phys_index. If
        unsigned long start_pfn;
        int ret = 0;
 
+       mem = find_memory_block_by_id(block_id, NULL);
+       if (mem) {
+               put_device(&mem->dev);
+               return -EEXIST;
+       }
        mem = kzalloc(sizeof(*mem), GFP_KERNEL);
        if (!mem)
                return -ENOMEM;
        return 0;
 }
 
+static void unregister_memory(struct memory_block *memory)
+{
+       if (WARN_ON_ONCE(memory->dev.bus != &memory_subsys))
+               return;
+
+       /* drop the ref. we got via find_memory_block() */
+       put_device(&memory->dev);
+       device_unregister(&memory->dev);
+}
+
 /*
- * need an interface for the VM to add new memory regions,
- * but without onlining it.
+ * Create memory block devices for the given memory area. Start and size
+ * have to be aligned to memory block granularity. Memory block devices
+ * will be initialized as offline.
  */
-int hotplug_memory_register(int nid, struct mem_section *section)
+int create_memory_block_devices(unsigned long start, unsigned long size)
 {
-       int block_id = base_memory_block_id(__section_nr(section));
-       int ret = 0;
+       const int start_block_id = pfn_to_block_id(PFN_DOWN(start));
+       int end_block_id = pfn_to_block_id(PFN_DOWN(start + size));
        struct memory_block *mem;
+       unsigned long block_id;
+       int ret = 0;
 
-       mutex_lock(&mem_sysfs_mutex);
+       if (WARN_ON_ONCE(!IS_ALIGNED(start, memory_block_size_bytes()) ||
+                        !IS_ALIGNED(size, memory_block_size_bytes())))
+               return -EINVAL;
 
-       mem = find_memory_block(section);
-       if (mem) {
-               mem->section_count++;
-               put_device(&mem->dev);
-       } else {
+       mutex_lock(&mem_sysfs_mutex);
+       for (block_id = start_block_id; block_id != end_block_id; block_id++) {
                ret = init_memory_block(&mem, block_id, MEM_OFFLINE);
                if (ret)
-                       goto out;
-               mem->section_count++;
+                       break;
+               mem->section_count = sections_per_block;
+       }
+       if (ret) {
+               end_block_id = block_id;
+               for (block_id = start_block_id; block_id != end_block_id;
+                    block_id++) {
+                       mem = find_memory_block_by_id(block_id, NULL);
+                       mem->section_count = 0;
+                       unregister_memory(mem);
+               }
        }
-
-out:
        mutex_unlock(&mem_sysfs_mutex);
        return ret;
 }
 
-static void
-unregister_memory(struct memory_block *memory)
-{
-       BUG_ON(memory->dev.bus != &memory_subsys);
-
-       /* drop the ref. we got via find_memory_block() */
-       put_device(&memory->dev);
-       device_unregister(&memory->dev);
-}
-
 void unregister_memory_section(struct mem_section *section)
 {
        struct memory_block *mem;