aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/memory.c')
-rw-r--r--drivers/base/memory.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 7dda4f790f00..86c88216a503 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -248,26 +248,23 @@ static bool pages_correctly_reserved(unsigned long start_pfn,
248static int 248static int
249memory_block_action(unsigned long phys_index, unsigned long action) 249memory_block_action(unsigned long phys_index, unsigned long action)
250{ 250{
251 unsigned long start_pfn, start_paddr; 251 unsigned long start_pfn;
252 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; 252 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
253 struct page *first_page; 253 struct page *first_page;
254 int ret; 254 int ret;
255 255
256 first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT); 256 first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
257 start_pfn = page_to_pfn(first_page);
257 258
258 switch (action) { 259 switch (action) {
259 case MEM_ONLINE: 260 case MEM_ONLINE:
260 start_pfn = page_to_pfn(first_page);
261
262 if (!pages_correctly_reserved(start_pfn, nr_pages)) 261 if (!pages_correctly_reserved(start_pfn, nr_pages))
263 return -EBUSY; 262 return -EBUSY;
264 263
265 ret = online_pages(start_pfn, nr_pages); 264 ret = online_pages(start_pfn, nr_pages);
266 break; 265 break;
267 case MEM_OFFLINE: 266 case MEM_OFFLINE:
268 start_paddr = page_to_pfn(first_page) << PAGE_SHIFT; 267 ret = offline_pages(start_pfn, nr_pages);
269 ret = remove_memory(start_paddr,
270 nr_pages << PAGE_SHIFT);
271 break; 268 break;
272 default: 269 default:
273 WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: " 270 WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
@@ -278,13 +275,11 @@ memory_block_action(unsigned long phys_index, unsigned long action)
278 return ret; 275 return ret;
279} 276}
280 277
281static int memory_block_change_state(struct memory_block *mem, 278static int __memory_block_change_state(struct memory_block *mem,
282 unsigned long to_state, unsigned long from_state_req) 279 unsigned long to_state, unsigned long from_state_req)
283{ 280{
284 int ret = 0; 281 int ret = 0;
285 282
286 mutex_lock(&mem->state_mutex);
287
288 if (mem->state != from_state_req) { 283 if (mem->state != from_state_req) {
289 ret = -EINVAL; 284 ret = -EINVAL;
290 goto out; 285 goto out;
@@ -312,10 +307,20 @@ static int memory_block_change_state(struct memory_block *mem,
312 break; 307 break;
313 } 308 }
314out: 309out:
315 mutex_unlock(&mem->state_mutex);
316 return ret; 310 return ret;
317} 311}
318 312
313static int memory_block_change_state(struct memory_block *mem,
314 unsigned long to_state, unsigned long from_state_req)
315{
316 int ret;
317
318 mutex_lock(&mem->state_mutex);
319 ret = __memory_block_change_state(mem, to_state, from_state_req);
320 mutex_unlock(&mem->state_mutex);
321
322 return ret;
323}
319static ssize_t 324static ssize_t
320store_mem_state(struct device *dev, 325store_mem_state(struct device *dev,
321 struct device_attribute *attr, const char *buf, size_t count) 326 struct device_attribute *attr, const char *buf, size_t count)
@@ -656,6 +661,21 @@ int unregister_memory_section(struct mem_section *section)
656} 661}
657 662
658/* 663/*
664 * offline one memory block. If the memory block has been offlined, do nothing.
665 */
666int offline_memory_block(struct memory_block *mem)
667{
668 int ret = 0;
669
670 mutex_lock(&mem->state_mutex);
671 if (mem->state != MEM_OFFLINE)
672 ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
673 mutex_unlock(&mem->state_mutex);
674
675 return ret;
676}
677
678/*
659 * Initialize the sysfs support for memory devices... 679 * Initialize the sysfs support for memory devices...
660 */ 680 */
661int __init memory_dev_init(void) 681int __init memory_dev_init(void)