aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Beck <felix.beck@de.ibm.com>2009-09-22 16:58:51 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-09-22 16:58:46 -0400
commit5314af693da5149c2361d290bb184cf18ee21cdd (patch)
tree17a34e85f22a2316cc95ead2739df8729e3767b3
parent2573a575304c5ce4765fc88f9d09ed4dbf8d04bf (diff)
[S390] zcrypt: Do not add/remove devices in s/r callbacks
Devices are no longer removed or added in the suspend and resume callbacks. Instead they are marked unregistered in suspend. In the resume callback the ap_scan_bus method is scheduled. The bus scan function will remove the old device and add new ones. This way all the device handling will be done in only one function. Additionaly the case where the domain might change during suspend/resume is caught. In that case the devices qid needs to re-calculated in order of having it found by the scan method. Signed-off-by: Felix Beck <felix.beck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--drivers/s390/crypto/ap_bus.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 090b32a339c6..1294876bf7b4 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -60,6 +60,7 @@ static int ap_device_probe(struct device *dev);
60static void ap_interrupt_handler(void *unused1, void *unused2); 60static void ap_interrupt_handler(void *unused1, void *unused2);
61static void ap_reset(struct ap_device *ap_dev); 61static void ap_reset(struct ap_device *ap_dev);
62static void ap_config_timeout(unsigned long ptr); 62static void ap_config_timeout(unsigned long ptr);
63static int ap_select_domain(void);
63 64
64/* 65/*
65 * Module description. 66 * Module description.
@@ -109,6 +110,10 @@ static unsigned long long poll_timeout = 250000;
109 110
110/* Suspend flag */ 111/* Suspend flag */
111static int ap_suspend_flag; 112static int ap_suspend_flag;
113/* Flag to check if domain was set through module parameter domain=. This is
114 * important when supsend and resume is done in a z/VM environment where the
115 * domain might change. */
116static int user_set_domain = 0;
112static struct bus_type ap_bus_type; 117static struct bus_type ap_bus_type;
113 118
114/** 119/**
@@ -643,6 +648,7 @@ static int ap_bus_suspend(struct device *dev, pm_message_t state)
643 destroy_workqueue(ap_work_queue); 648 destroy_workqueue(ap_work_queue);
644 ap_work_queue = NULL; 649 ap_work_queue = NULL;
645 } 650 }
651
646 tasklet_disable(&ap_tasklet); 652 tasklet_disable(&ap_tasklet);
647 } 653 }
648 /* Poll on the device until all requests are finished. */ 654 /* Poll on the device until all requests are finished. */
@@ -653,7 +659,10 @@ static int ap_bus_suspend(struct device *dev, pm_message_t state)
653 spin_unlock_bh(&ap_dev->lock); 659 spin_unlock_bh(&ap_dev->lock);
654 } while ((flags & 1) || (flags & 2)); 660 } while ((flags & 1) || (flags & 2));
655 661
656 ap_device_remove(dev); 662 spin_lock_bh(&ap_dev->lock);
663 ap_dev->unregistered = 1;
664 spin_unlock_bh(&ap_dev->lock);
665
657 return 0; 666 return 0;
658} 667}
659 668
@@ -666,11 +675,10 @@ static int ap_bus_resume(struct device *dev)
666 ap_suspend_flag = 0; 675 ap_suspend_flag = 0;
667 if (!ap_interrupts_available()) 676 if (!ap_interrupts_available())
668 ap_interrupt_indicator = NULL; 677 ap_interrupt_indicator = NULL;
669 ap_device_probe(dev); 678 if (!user_set_domain) {
670 ap_reset(ap_dev); 679 ap_domain_index = -1;
671 setup_timer(&ap_dev->timeout, ap_request_timeout, 680 ap_select_domain();
672 (unsigned long) ap_dev); 681 }
673 ap_scan_bus(NULL);
674 init_timer(&ap_config_timer); 682 init_timer(&ap_config_timer);
675 ap_config_timer.function = ap_config_timeout; 683 ap_config_timer.function = ap_config_timeout;
676 ap_config_timer.data = 0; 684 ap_config_timer.data = 0;
@@ -686,12 +694,14 @@ static int ap_bus_resume(struct device *dev)
686 tasklet_schedule(&ap_tasklet); 694 tasklet_schedule(&ap_tasklet);
687 if (ap_thread_flag) 695 if (ap_thread_flag)
688 rc = ap_poll_thread_start(); 696 rc = ap_poll_thread_start();
689 } else {
690 ap_device_probe(dev);
691 ap_reset(ap_dev);
692 setup_timer(&ap_dev->timeout, ap_request_timeout,
693 (unsigned long) ap_dev);
694 } 697 }
698 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
699 spin_lock_bh(&ap_dev->lock);
700 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
701 ap_domain_index);
702 spin_unlock_bh(&ap_dev->lock);
703 }
704 queue_work(ap_work_queue, &ap_config_work);
695 705
696 return rc; 706 return rc;
697} 707}
@@ -1079,6 +1089,8 @@ static void ap_scan_bus(struct work_struct *unused)
1079 spin_lock_bh(&ap_dev->lock); 1089 spin_lock_bh(&ap_dev->lock);
1080 if (rc || ap_dev->unregistered) { 1090 if (rc || ap_dev->unregistered) {
1081 spin_unlock_bh(&ap_dev->lock); 1091 spin_unlock_bh(&ap_dev->lock);
1092 if (ap_dev->unregistered)
1093 i--;
1082 device_unregister(dev); 1094 device_unregister(dev);
1083 put_device(dev); 1095 put_device(dev);
1084 continue; 1096 continue;
@@ -1586,6 +1598,12 @@ int __init ap_module_init(void)
1586 ap_domain_index); 1598 ap_domain_index);
1587 return -EINVAL; 1599 return -EINVAL;
1588 } 1600 }
1601 /* In resume callback we need to know if the user had set the domain.
1602 * If so, we can not just reset it.
1603 */
1604 if (ap_domain_index >= 0)
1605 user_set_domain = 1;
1606
1589 if (ap_instructions_available() != 0) { 1607 if (ap_instructions_available() != 0) {
1590 pr_warning("The hardware system does not support " 1608 pr_warning("The hardware system does not support "
1591 "AP instructions\n"); 1609 "AP instructions\n");