aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorFelix Beck <felix.beck@de.ibm.com>2009-06-22 06:08:16 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-22 06:08:21 -0400
commit772f54720ab82a6e88f0a8a84d76e7af15ca1f0c (patch)
treedfb9bc04a9b83c13b84ec4dd4d3119b64756b1e5 /drivers/s390
parent6618241b47cd131503610d8df68dd6f4948e5c1a (diff)
[S390] ap/zcrypt: Suspend/Resume ap bus and zcrypt
Add Suspend/Resume support to ap bus and zcrypt. All enhancements are done in the ap bus. No changes in the crypto card specific part are necessary. Signed-off-by: Felix Beck <felix.beck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/crypto/ap_bus.c85
1 files changed, 83 insertions, 2 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 9c148406b980..727a809636d8 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -54,6 +54,12 @@ static int ap_poll_thread_start(void);
54static void ap_poll_thread_stop(void); 54static void ap_poll_thread_stop(void);
55static void ap_request_timeout(unsigned long); 55static void ap_request_timeout(unsigned long);
56static inline void ap_schedule_poll_timer(void); 56static inline void ap_schedule_poll_timer(void);
57static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags);
58static int ap_device_remove(struct device *dev);
59static int ap_device_probe(struct device *dev);
60static void ap_interrupt_handler(void *unused1, void *unused2);
61static void ap_reset(struct ap_device *ap_dev);
62static void ap_config_timeout(unsigned long ptr);
57 63
58/* 64/*
59 * Module description. 65 * Module description.
@@ -101,6 +107,10 @@ static struct hrtimer ap_poll_timer;
101 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/ 107 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
102static unsigned long long poll_timeout = 250000; 108static unsigned long long poll_timeout = 250000;
103 109
110/* Suspend flag */
111static int ap_suspend_flag;
112static struct bus_type ap_bus_type;
113
104/** 114/**
105 * ap_using_interrupts() - Returns non-zero if interrupt support is 115 * ap_using_interrupts() - Returns non-zero if interrupt support is
106 * available. 116 * available.
@@ -617,10 +627,79 @@ static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
617 return retval; 627 return retval;
618} 628}
619 629
630static int ap_bus_suspend(struct device *dev, pm_message_t state)
631{
632 struct ap_device *ap_dev = to_ap_dev(dev);
633 unsigned long flags;
634
635 if (!ap_suspend_flag) {
636 ap_suspend_flag = 1;
637
638 /* Disable scanning for devices, thus we do not want to scan
639 * for them after removing.
640 */
641 del_timer_sync(&ap_config_timer);
642 if (ap_work_queue != NULL) {
643 destroy_workqueue(ap_work_queue);
644 ap_work_queue = NULL;
645 }
646 tasklet_disable(&ap_tasklet);
647 }
648 /* Poll on the device until all requests are finished. */
649 do {
650 flags = 0;
651 __ap_poll_device(ap_dev, &flags);
652 } while ((flags & 1) || (flags & 2));
653
654 ap_device_remove(dev);
655 return 0;
656}
657
658static int ap_bus_resume(struct device *dev)
659{
660 int rc = 0;
661 struct ap_device *ap_dev = to_ap_dev(dev);
662
663 if (ap_suspend_flag) {
664 ap_suspend_flag = 0;
665 if (!ap_interrupts_available())
666 ap_interrupt_indicator = NULL;
667 ap_device_probe(dev);
668 ap_reset(ap_dev);
669 setup_timer(&ap_dev->timeout, ap_request_timeout,
670 (unsigned long) ap_dev);
671 ap_scan_bus(NULL);
672 init_timer(&ap_config_timer);
673 ap_config_timer.function = ap_config_timeout;
674 ap_config_timer.data = 0;
675 ap_config_timer.expires = jiffies + ap_config_time * HZ;
676 add_timer(&ap_config_timer);
677 ap_work_queue = create_singlethread_workqueue("kapwork");
678 if (!ap_work_queue)
679 return -ENOMEM;
680 tasklet_enable(&ap_tasklet);
681 if (!ap_using_interrupts())
682 ap_schedule_poll_timer();
683 else
684 tasklet_schedule(&ap_tasklet);
685 if (ap_thread_flag)
686 rc = ap_poll_thread_start();
687 } else {
688 ap_device_probe(dev);
689 ap_reset(ap_dev);
690 setup_timer(&ap_dev->timeout, ap_request_timeout,
691 (unsigned long) ap_dev);
692 }
693
694 return rc;
695}
696
620static struct bus_type ap_bus_type = { 697static struct bus_type ap_bus_type = {
621 .name = "ap", 698 .name = "ap",
622 .match = &ap_bus_match, 699 .match = &ap_bus_match,
623 .uevent = &ap_uevent, 700 .uevent = &ap_uevent,
701 .suspend = ap_bus_suspend,
702 .resume = ap_bus_resume
624}; 703};
625 704
626static int ap_device_probe(struct device *dev) 705static int ap_device_probe(struct device *dev)
@@ -1066,7 +1145,7 @@ ap_config_timeout(unsigned long ptr)
1066 */ 1145 */
1067static inline void ap_schedule_poll_timer(void) 1146static inline void ap_schedule_poll_timer(void)
1068{ 1147{
1069 if (ap_using_interrupts()) 1148 if (ap_using_interrupts() || ap_suspend_flag)
1070 return; 1149 return;
1071 if (hrtimer_is_queued(&ap_poll_timer)) 1150 if (hrtimer_is_queued(&ap_poll_timer))
1072 return; 1151 return;
@@ -1384,6 +1463,8 @@ static int ap_poll_thread(void *data)
1384 1463
1385 set_user_nice(current, 19); 1464 set_user_nice(current, 19);
1386 while (1) { 1465 while (1) {
1466 if (ap_suspend_flag)
1467 return 0;
1387 if (need_resched()) { 1468 if (need_resched()) {
1388 schedule(); 1469 schedule();
1389 continue; 1470 continue;
@@ -1414,7 +1495,7 @@ static int ap_poll_thread_start(void)
1414{ 1495{
1415 int rc; 1496 int rc;
1416 1497
1417 if (ap_using_interrupts()) 1498 if (ap_using_interrupts() || ap_suspend_flag)
1418 return 0; 1499 return 0;
1419 mutex_lock(&ap_poll_thread_mutex); 1500 mutex_lock(&ap_poll_thread_mutex);
1420 if (!ap_poll_kthread) { 1501 if (!ap_poll_kthread) {