diff options
Diffstat (limited to 'drivers/base/memory.c')
-rw-r--r-- | drivers/base/memory.c | 40 |
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, | |||
248 | static int | 248 | static int |
249 | memory_block_action(unsigned long phys_index, unsigned long action) | 249 | memory_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 | ||
281 | static int memory_block_change_state(struct memory_block *mem, | 278 | static 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 | } |
314 | out: | 309 | out: |
315 | mutex_unlock(&mem->state_mutex); | ||
316 | return ret; | 310 | return ret; |
317 | } | 311 | } |
318 | 312 | ||
313 | static 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 | } | ||
319 | static ssize_t | 324 | static ssize_t |
320 | store_mem_state(struct device *dev, | 325 | store_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 | */ | ||
666 | int 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 | */ |
661 | int __init memory_dev_init(void) | 681 | int __init memory_dev_init(void) |