diff options
author | Gerald Schaefer <gerald.schaefer@de.ibm.com> | 2009-06-16 04:30:48 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-16 04:31:20 -0400 |
commit | 039979049834bde56f67f8078c802b416bd4763c (patch) | |
tree | a7fe7b8b8912d4137fd026db3286100faac097fb /drivers/s390 | |
parent | 4b214a0c7720bfcfaca936047a359f8859fc8424 (diff) |
[S390] pm: memory hotplug power management callbacks
Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/char/sclp_cmd.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 77ab6e34a100..5cc11c636d38 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
@@ -1,9 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/char/sclp_cmd.c | 2 | * Copyright IBM Corp. 2007, 2009 |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2007 | 4 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>, |
5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>, | 5 | * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> |
6 | * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> | ||
7 | */ | 6 | */ |
8 | 7 | ||
9 | #define KMSG_COMPONENT "sclp_cmd" | 8 | #define KMSG_COMPONENT "sclp_cmd" |
@@ -12,11 +11,13 @@ | |||
12 | #include <linux/completion.h> | 11 | #include <linux/completion.h> |
13 | #include <linux/init.h> | 12 | #include <linux/init.h> |
14 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/err.h> | ||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/mmzone.h> | 18 | #include <linux/mmzone.h> |
19 | #include <linux/memory.h> | 19 | #include <linux/memory.h> |
20 | #include <linux/platform_device.h> | ||
20 | #include <asm/chpid.h> | 21 | #include <asm/chpid.h> |
21 | #include <asm/sclp.h> | 22 | #include <asm/sclp.h> |
22 | #include <asm/setup.h> | 23 | #include <asm/setup.h> |
@@ -292,6 +293,7 @@ static DEFINE_MUTEX(sclp_mem_mutex); | |||
292 | static LIST_HEAD(sclp_mem_list); | 293 | static LIST_HEAD(sclp_mem_list); |
293 | static u8 sclp_max_storage_id; | 294 | static u8 sclp_max_storage_id; |
294 | static unsigned long sclp_storage_ids[256 / BITS_PER_LONG]; | 295 | static unsigned long sclp_storage_ids[256 / BITS_PER_LONG]; |
296 | static int sclp_mem_state_changed; | ||
295 | 297 | ||
296 | struct memory_increment { | 298 | struct memory_increment { |
297 | struct list_head list; | 299 | struct list_head list; |
@@ -450,6 +452,8 @@ static int sclp_mem_notifier(struct notifier_block *nb, | |||
450 | rc = -EINVAL; | 452 | rc = -EINVAL; |
451 | break; | 453 | break; |
452 | } | 454 | } |
455 | if (!rc) | ||
456 | sclp_mem_state_changed = 1; | ||
453 | mutex_unlock(&sclp_mem_mutex); | 457 | mutex_unlock(&sclp_mem_mutex); |
454 | return rc ? NOTIFY_BAD : NOTIFY_OK; | 458 | return rc ? NOTIFY_BAD : NOTIFY_OK; |
455 | } | 459 | } |
@@ -525,6 +529,14 @@ static void __init insert_increment(u16 rn, int standby, int assigned) | |||
525 | list_add(&new_incr->list, prev); | 529 | list_add(&new_incr->list, prev); |
526 | } | 530 | } |
527 | 531 | ||
532 | static int sclp_mem_freeze(struct device *dev) | ||
533 | { | ||
534 | if (!sclp_mem_state_changed) | ||
535 | return 0; | ||
536 | pr_err("Memory hotplug state changed, suspend refused.\n"); | ||
537 | return -EPERM; | ||
538 | } | ||
539 | |||
528 | struct read_storage_sccb { | 540 | struct read_storage_sccb { |
529 | struct sccb_header header; | 541 | struct sccb_header header; |
530 | u16 max_id; | 542 | u16 max_id; |
@@ -534,8 +546,20 @@ struct read_storage_sccb { | |||
534 | u32 entries[0]; | 546 | u32 entries[0]; |
535 | } __packed; | 547 | } __packed; |
536 | 548 | ||
549 | static struct dev_pm_ops sclp_mem_pm_ops = { | ||
550 | .freeze = sclp_mem_freeze, | ||
551 | }; | ||
552 | |||
553 | static struct platform_driver sclp_mem_pdrv = { | ||
554 | .driver = { | ||
555 | .name = "sclp_mem", | ||
556 | .pm = &sclp_mem_pm_ops, | ||
557 | }, | ||
558 | }; | ||
559 | |||
537 | static int __init sclp_detect_standby_memory(void) | 560 | static int __init sclp_detect_standby_memory(void) |
538 | { | 561 | { |
562 | struct platform_device *sclp_pdev; | ||
539 | struct read_storage_sccb *sccb; | 563 | struct read_storage_sccb *sccb; |
540 | int i, id, assigned, rc; | 564 | int i, id, assigned, rc; |
541 | 565 | ||
@@ -588,7 +612,17 @@ static int __init sclp_detect_standby_memory(void) | |||
588 | rc = register_memory_notifier(&sclp_mem_nb); | 612 | rc = register_memory_notifier(&sclp_mem_nb); |
589 | if (rc) | 613 | if (rc) |
590 | goto out; | 614 | goto out; |
615 | rc = platform_driver_register(&sclp_mem_pdrv); | ||
616 | if (rc) | ||
617 | goto out; | ||
618 | sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0); | ||
619 | rc = IS_ERR(sclp_pdev) ? PTR_ERR(sclp_pdev) : 0; | ||
620 | if (rc) | ||
621 | goto out_driver; | ||
591 | sclp_add_standby_memory(); | 622 | sclp_add_standby_memory(); |
623 | goto out; | ||
624 | out_driver: | ||
625 | platform_driver_unregister(&sclp_mem_pdrv); | ||
592 | out: | 626 | out: |
593 | free_page((unsigned long) sccb); | 627 | free_page((unsigned long) sccb); |
594 | return rc; | 628 | return rc; |