aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r--mm/memory_hotplug.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 6166ba5a15f3..4ebe696138e8 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1734,9 +1734,10 @@ static int check_memblock_offlined_cb(struct memory_block *mem, void *arg)
1734 endpa = PFN_PHYS(section_nr_to_pfn(mem->end_section_nr + 1))-1; 1734 endpa = PFN_PHYS(section_nr_to_pfn(mem->end_section_nr + 1))-1;
1735 pr_warn("removing memory fails, because memory [%pa-%pa] is onlined\n", 1735 pr_warn("removing memory fails, because memory [%pa-%pa] is onlined\n",
1736 &beginpa, &endpa); 1736 &beginpa, &endpa);
1737 }
1738 1737
1739 return ret; 1738 return -EBUSY;
1739 }
1740 return 0;
1740} 1741}
1741 1742
1742static int check_cpu_on_node(pg_data_t *pgdat) 1743static int check_cpu_on_node(pg_data_t *pgdat)
@@ -1819,19 +1820,9 @@ static void __release_memory_resource(resource_size_t start,
1819 } 1820 }
1820} 1821}
1821 1822
1822/** 1823static int __ref try_remove_memory(int nid, u64 start, u64 size)
1823 * remove_memory
1824 * @nid: the node ID
1825 * @start: physical address of the region to remove
1826 * @size: size of the region to remove
1827 *
1828 * NOTE: The caller must call lock_device_hotplug() to serialize hotplug
1829 * and online/offline operations before this call, as required by
1830 * try_offline_node().
1831 */
1832void __ref __remove_memory(int nid, u64 start, u64 size)
1833{ 1824{
1834 int ret; 1825 int rc = 0;
1835 1826
1836 BUG_ON(check_hotplug_memory_range(start, size)); 1827 BUG_ON(check_hotplug_memory_range(start, size));
1837 1828
@@ -1839,13 +1830,13 @@ void __ref __remove_memory(int nid, u64 start, u64 size)
1839 1830
1840 /* 1831 /*
1841 * All memory blocks must be offlined before removing memory. Check 1832 * All memory blocks must be offlined before removing memory. Check
1842 * whether all memory blocks in question are offline and trigger a BUG() 1833 * whether all memory blocks in question are offline and return error
1843 * if this is not the case. 1834 * if this is not the case.
1844 */ 1835 */
1845 ret = walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1), NULL, 1836 rc = walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1), NULL,
1846 check_memblock_offlined_cb); 1837 check_memblock_offlined_cb);
1847 if (ret) 1838 if (rc)
1848 BUG(); 1839 goto done;
1849 1840
1850 /* remove memmap entry */ 1841 /* remove memmap entry */
1851 firmware_map_remove(start, start + size, "System RAM"); 1842 firmware_map_remove(start, start + size, "System RAM");
@@ -1857,14 +1848,45 @@ void __ref __remove_memory(int nid, u64 start, u64 size)
1857 1848
1858 try_offline_node(nid); 1849 try_offline_node(nid);
1859 1850
1851done:
1860 mem_hotplug_done(); 1852 mem_hotplug_done();
1853 return rc;
1861} 1854}
1862 1855
1863void remove_memory(int nid, u64 start, u64 size) 1856/**
1857 * remove_memory
1858 * @nid: the node ID
1859 * @start: physical address of the region to remove
1860 * @size: size of the region to remove
1861 *
1862 * NOTE: The caller must call lock_device_hotplug() to serialize hotplug
1863 * and online/offline operations before this call, as required by
1864 * try_offline_node().
1865 */
1866void __remove_memory(int nid, u64 start, u64 size)
1867{
1868
1869 /*
1870 * trigger BUG() is some memory is not offlined prior to calling this
1871 * function
1872 */
1873 if (try_remove_memory(nid, start, size))
1874 BUG();
1875}
1876
1877/*
1878 * Remove memory if every memory block is offline, otherwise return -EBUSY is
1879 * some memory is not offline
1880 */
1881int remove_memory(int nid, u64 start, u64 size)
1864{ 1882{
1883 int rc;
1884
1865 lock_device_hotplug(); 1885 lock_device_hotplug();
1866 __remove_memory(nid, start, size); 1886 rc = try_remove_memory(nid, start, size);
1867 unlock_device_hotplug(); 1887 unlock_device_hotplug();
1888
1889 return rc;
1868} 1890}
1869EXPORT_SYMBOL_GPL(remove_memory); 1891EXPORT_SYMBOL_GPL(remove_memory);
1870#endif /* CONFIG_MEMORY_HOTREMOVE */ 1892#endif /* CONFIG_MEMORY_HOTREMOVE */