]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - mm/memory_hotplug.c
memory-hotplug: suppress "Trying to free nonexistent resource <XXXXXXXXXXXXXXXX-YYYYY...
[linux-imx.git] / mm / memory_hotplug.c
index ce690a911f1b7faeaba5ce3f2829c937e37cc2fa..56b758ae57d2eeb2230bbcaf3f8e8d4538a15a9d 100644 (file)
@@ -369,11 +369,11 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
        BUG_ON(phys_start_pfn & ~PAGE_SECTION_MASK);
        BUG_ON(nr_pages % PAGES_PER_SECTION);
 
+       release_mem_region(phys_start_pfn << PAGE_SHIFT, nr_pages * PAGE_SIZE);
+
        sections_to_remove = nr_pages / PAGES_PER_SECTION;
        for (i = 0; i < sections_to_remove; i++) {
                unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION;
-               release_mem_region(pfn << PAGE_SHIFT,
-                                  PAGES_PER_SECTION << PAGE_SHIFT);
                ret = __remove_section(zone, __pfn_to_section(pfn));
                if (ret)
                        break;
@@ -874,7 +874,7 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
        return offlined;
 }
 
-static int __ref offline_pages(unsigned long start_pfn,
+static int __ref __offline_pages(unsigned long start_pfn,
                  unsigned long end_pfn, unsigned long timeout)
 {
        unsigned long pfn, nr_pages, expire;
@@ -1007,15 +1007,55 @@ out:
        return ret;
 }
 
+int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
+{
+       return __offline_pages(start_pfn, start_pfn + nr_pages, 120 * HZ);
+}
+
 int remove_memory(u64 start, u64 size)
 {
+       struct memory_block *mem = NULL;
+       struct mem_section *section;
        unsigned long start_pfn, end_pfn;
+       unsigned long pfn, section_nr;
+       int ret;
 
        start_pfn = PFN_DOWN(start);
        end_pfn = start_pfn + PFN_DOWN(size);
-       return offline_pages(start_pfn, end_pfn, 120 * HZ);
+
+       for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+               section_nr = pfn_to_section_nr(pfn);
+               if (!present_section_nr(section_nr))
+                       continue;
+
+               section = __nr_to_section(section_nr);
+               /* same memblock? */
+               if (mem)
+                       if ((section_nr >= mem->start_section_nr) &&
+                           (section_nr <= mem->end_section_nr))
+                               continue;
+
+               mem = find_memory_block_hinted(section, mem);
+               if (!mem)
+                       continue;
+
+               ret = offline_memory_block(mem);
+               if (ret) {
+                       kobject_put(&mem->dev.kobj);
+                       return ret;
+               }
+       }
+
+       if (mem)
+               kobject_put(&mem->dev.kobj);
+
+       return 0;
 }
 #else
+int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
+{
+       return -EINVAL;
+}
 int remove_memory(u64 start, u64 size)
 {
        return -EINVAL;