diff options
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 212 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.h | 6 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_cex2a.c | 10 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_pcica.c | 10 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_pcicc.c | 10 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_pcixcc.c | 10 |
6 files changed, 225 insertions, 33 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index e3fe6838293a..1f5f5d2d87d9 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> | 5 | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> |
6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
7 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | 7 | * Ralph Wuerthner <rwuerthn@de.ibm.com> |
8 | * Felix Beck <felix.beck@de.ibm.com> | ||
8 | * | 9 | * |
9 | * Adjunct processor bus. | 10 | * Adjunct processor bus. |
10 | * | 11 | * |
@@ -23,6 +24,9 @@ | |||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
24 | */ | 25 | */ |
25 | 26 | ||
27 | #define KMSG_COMPONENT "ap" | ||
28 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
29 | |||
26 | #include <linux/module.h> | 30 | #include <linux/module.h> |
27 | #include <linux/init.h> | 31 | #include <linux/init.h> |
28 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
@@ -34,6 +38,10 @@ | |||
34 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
35 | #include <asm/s390_rdev.h> | 39 | #include <asm/s390_rdev.h> |
36 | #include <asm/reset.h> | 40 | #include <asm/reset.h> |
41 | #include <asm/airq.h> | ||
42 | #include <asm/atomic.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/isc.h> | ||
37 | #include <linux/hrtimer.h> | 45 | #include <linux/hrtimer.h> |
38 | #include <linux/ktime.h> | 46 | #include <linux/ktime.h> |
39 | 47 | ||
@@ -46,6 +54,7 @@ static enum hrtimer_restart ap_poll_timeout(struct hrtimer *); | |||
46 | static int ap_poll_thread_start(void); | 54 | static int ap_poll_thread_start(void); |
47 | static void ap_poll_thread_stop(void); | 55 | static void ap_poll_thread_stop(void); |
48 | static void ap_request_timeout(unsigned long); | 56 | static void ap_request_timeout(unsigned long); |
57 | static inline void ap_schedule_poll_timer(void); | ||
49 | 58 | ||
50 | /* | 59 | /* |
51 | * Module description. | 60 | * Module description. |
@@ -68,7 +77,7 @@ module_param_named(poll_thread, ap_thread_flag, int, 0000); | |||
68 | MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off)."); | 77 | MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off)."); |
69 | 78 | ||
70 | static struct device *ap_root_device = NULL; | 79 | static struct device *ap_root_device = NULL; |
71 | static DEFINE_SPINLOCK(ap_device_lock); | 80 | static DEFINE_SPINLOCK(ap_device_list_lock); |
72 | static LIST_HEAD(ap_device_list); | 81 | static LIST_HEAD(ap_device_list); |
73 | 82 | ||
74 | /* | 83 | /* |
@@ -80,19 +89,29 @@ static int ap_config_time = AP_CONFIG_TIME; | |||
80 | static DECLARE_WORK(ap_config_work, ap_scan_bus); | 89 | static DECLARE_WORK(ap_config_work, ap_scan_bus); |
81 | 90 | ||
82 | /* | 91 | /* |
83 | * Tasklet & timer for AP request polling. | 92 | * Tasklet & timer for AP request polling and interrupts |
84 | */ | 93 | */ |
85 | static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0); | 94 | static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0); |
86 | static atomic_t ap_poll_requests = ATOMIC_INIT(0); | 95 | static atomic_t ap_poll_requests = ATOMIC_INIT(0); |
87 | static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait); | 96 | static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait); |
88 | static struct task_struct *ap_poll_kthread = NULL; | 97 | static struct task_struct *ap_poll_kthread = NULL; |
89 | static DEFINE_MUTEX(ap_poll_thread_mutex); | 98 | static DEFINE_MUTEX(ap_poll_thread_mutex); |
99 | static void *ap_interrupt_indicator; | ||
90 | static struct hrtimer ap_poll_timer; | 100 | static struct hrtimer ap_poll_timer; |
91 | /* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds. | 101 | /* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds. |
92 | * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/ | 102 | * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/ |
93 | static unsigned long long poll_timeout = 250000; | 103 | static unsigned long long poll_timeout = 250000; |
94 | 104 | ||
95 | /** | 105 | /** |
106 | * ap_using_interrupts() - Returns non-zero if interrupt support is | ||
107 | * available. | ||
108 | */ | ||
109 | static inline int ap_using_interrupts(void) | ||
110 | { | ||
111 | return ap_interrupt_indicator != NULL; | ||
112 | } | ||
113 | |||
114 | /** | ||
96 | * ap_intructions_available() - Test if AP instructions are available. | 115 | * ap_intructions_available() - Test if AP instructions are available. |
97 | * | 116 | * |
98 | * Returns 0 if the AP instructions are installed. | 117 | * Returns 0 if the AP instructions are installed. |
@@ -113,6 +132,23 @@ static inline int ap_instructions_available(void) | |||
113 | } | 132 | } |
114 | 133 | ||
115 | /** | 134 | /** |
135 | * ap_interrupts_available(): Test if AP interrupts are available. | ||
136 | * | ||
137 | * Returns 1 if AP interrupts are available. | ||
138 | */ | ||
139 | static int ap_interrupts_available(void) | ||
140 | { | ||
141 | unsigned long long facility_bits[2]; | ||
142 | |||
143 | if (stfle(facility_bits, 2) <= 1) | ||
144 | return 0; | ||
145 | if (!(facility_bits[0] & (1ULL << 61)) || | ||
146 | !(facility_bits[1] & (1ULL << 62))) | ||
147 | return 0; | ||
148 | return 1; | ||
149 | } | ||
150 | |||
151 | /** | ||
116 | * ap_test_queue(): Test adjunct processor queue. | 152 | * ap_test_queue(): Test adjunct processor queue. |
117 | * @qid: The AP queue number | 153 | * @qid: The AP queue number |
118 | * @queue_depth: Pointer to queue depth value | 154 | * @queue_depth: Pointer to queue depth value |
@@ -152,6 +188,80 @@ static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid) | |||
152 | return reg1; | 188 | return reg1; |
153 | } | 189 | } |
154 | 190 | ||
191 | #ifdef CONFIG_64BIT | ||
192 | /** | ||
193 | * ap_queue_interruption_control(): Enable interruption for a specific AP. | ||
194 | * @qid: The AP queue number | ||
195 | * @ind: The notification indicator byte | ||
196 | * | ||
197 | * Returns AP queue status. | ||
198 | */ | ||
199 | static inline struct ap_queue_status | ||
200 | ap_queue_interruption_control(ap_qid_t qid, void *ind) | ||
201 | { | ||
202 | register unsigned long reg0 asm ("0") = qid | 0x03000000UL; | ||
203 | register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC; | ||
204 | register struct ap_queue_status reg1_out asm ("1"); | ||
205 | register void *reg2 asm ("2") = ind; | ||
206 | asm volatile( | ||
207 | ".long 0xb2af0000" /* PQAP(RAPQ) */ | ||
208 | : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2) | ||
209 | : | ||
210 | : "cc" ); | ||
211 | return reg1_out; | ||
212 | } | ||
213 | #endif | ||
214 | |||
215 | /** | ||
216 | * ap_queue_enable_interruption(): Enable interruption on an AP. | ||
217 | * @qid: The AP queue number | ||
218 | * @ind: the notification indicator byte | ||
219 | * | ||
220 | * Enables interruption on AP queue via ap_queue_interruption_control(). Based | ||
221 | * on the return value it waits a while and tests the AP queue if interrupts | ||
222 | * have been switched on using ap_test_queue(). | ||
223 | */ | ||
224 | static int ap_queue_enable_interruption(ap_qid_t qid, void *ind) | ||
225 | { | ||
226 | #ifdef CONFIG_64BIT | ||
227 | struct ap_queue_status status; | ||
228 | int t_depth, t_device_type, rc, i; | ||
229 | |||
230 | rc = -EBUSY; | ||
231 | status = ap_queue_interruption_control(qid, ind); | ||
232 | |||
233 | for (i = 0; i < AP_MAX_RESET; i++) { | ||
234 | switch (status.response_code) { | ||
235 | case AP_RESPONSE_NORMAL: | ||
236 | if (status.int_enabled) | ||
237 | return 0; | ||
238 | break; | ||
239 | case AP_RESPONSE_RESET_IN_PROGRESS: | ||
240 | case AP_RESPONSE_BUSY: | ||
241 | break; | ||
242 | case AP_RESPONSE_Q_NOT_AVAIL: | ||
243 | case AP_RESPONSE_DECONFIGURED: | ||
244 | case AP_RESPONSE_CHECKSTOPPED: | ||
245 | case AP_RESPONSE_INVALID_ADDRESS: | ||
246 | return -ENODEV; | ||
247 | case AP_RESPONSE_OTHERWISE_CHANGED: | ||
248 | if (status.int_enabled) | ||
249 | return 0; | ||
250 | break; | ||
251 | default: | ||
252 | break; | ||
253 | } | ||
254 | if (i < AP_MAX_RESET - 1) { | ||
255 | udelay(5); | ||
256 | status = ap_test_queue(qid, &t_depth, &t_device_type); | ||
257 | } | ||
258 | } | ||
259 | return rc; | ||
260 | #else | ||
261 | return -EINVAL; | ||
262 | #endif | ||
263 | } | ||
264 | |||
155 | /** | 265 | /** |
156 | * __ap_send(): Send message to adjunct processor queue. | 266 | * __ap_send(): Send message to adjunct processor queue. |
157 | * @qid: The AP queue number | 267 | * @qid: The AP queue number |
@@ -295,6 +405,11 @@ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type) | |||
295 | case AP_RESPONSE_CHECKSTOPPED: | 405 | case AP_RESPONSE_CHECKSTOPPED: |
296 | rc = -ENODEV; | 406 | rc = -ENODEV; |
297 | break; | 407 | break; |
408 | case AP_RESPONSE_INVALID_ADDRESS: | ||
409 | rc = -ENODEV; | ||
410 | break; | ||
411 | case AP_RESPONSE_OTHERWISE_CHANGED: | ||
412 | break; | ||
298 | case AP_RESPONSE_BUSY: | 413 | case AP_RESPONSE_BUSY: |
299 | break; | 414 | break; |
300 | default: | 415 | default: |
@@ -345,6 +460,15 @@ static int ap_init_queue(ap_qid_t qid) | |||
345 | status = ap_test_queue(qid, &dummy, &dummy); | 460 | status = ap_test_queue(qid, &dummy, &dummy); |
346 | } | 461 | } |
347 | } | 462 | } |
463 | if (rc == 0 && ap_using_interrupts()) { | ||
464 | rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator); | ||
465 | /* If interruption mode is supported by the machine, | ||
466 | * but an AP can not be enabled for interruption then | ||
467 | * the AP will be discarded. */ | ||
468 | if (rc) | ||
469 | pr_err("Registering adapter interrupts for " | ||
470 | "AP %d failed\n", AP_QID_DEVICE(qid)); | ||
471 | } | ||
348 | return rc; | 472 | return rc; |
349 | } | 473 | } |
350 | 474 | ||
@@ -397,16 +521,16 @@ static ssize_t ap_hwtype_show(struct device *dev, | |||
397 | struct ap_device *ap_dev = to_ap_dev(dev); | 521 | struct ap_device *ap_dev = to_ap_dev(dev); |
398 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type); | 522 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type); |
399 | } | 523 | } |
400 | static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL); | ||
401 | 524 | ||
525 | static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL); | ||
402 | static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr, | 526 | static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr, |
403 | char *buf) | 527 | char *buf) |
404 | { | 528 | { |
405 | struct ap_device *ap_dev = to_ap_dev(dev); | 529 | struct ap_device *ap_dev = to_ap_dev(dev); |
406 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth); | 530 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth); |
407 | } | 531 | } |
408 | static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL); | ||
409 | 532 | ||
533 | static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL); | ||
410 | static ssize_t ap_request_count_show(struct device *dev, | 534 | static ssize_t ap_request_count_show(struct device *dev, |
411 | struct device_attribute *attr, | 535 | struct device_attribute *attr, |
412 | char *buf) | 536 | char *buf) |
@@ -509,9 +633,9 @@ static int ap_device_probe(struct device *dev) | |||
509 | ap_dev->drv = ap_drv; | 633 | ap_dev->drv = ap_drv; |
510 | rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV; | 634 | rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV; |
511 | if (!rc) { | 635 | if (!rc) { |
512 | spin_lock_bh(&ap_device_lock); | 636 | spin_lock_bh(&ap_device_list_lock); |
513 | list_add(&ap_dev->list, &ap_device_list); | 637 | list_add(&ap_dev->list, &ap_device_list); |
514 | spin_unlock_bh(&ap_device_lock); | 638 | spin_unlock_bh(&ap_device_list_lock); |
515 | } | 639 | } |
516 | return rc; | 640 | return rc; |
517 | } | 641 | } |
@@ -553,9 +677,9 @@ static int ap_device_remove(struct device *dev) | |||
553 | 677 | ||
554 | ap_flush_queue(ap_dev); | 678 | ap_flush_queue(ap_dev); |
555 | del_timer_sync(&ap_dev->timeout); | 679 | del_timer_sync(&ap_dev->timeout); |
556 | spin_lock_bh(&ap_device_lock); | 680 | spin_lock_bh(&ap_device_list_lock); |
557 | list_del_init(&ap_dev->list); | 681 | list_del_init(&ap_dev->list); |
558 | spin_unlock_bh(&ap_device_lock); | 682 | spin_unlock_bh(&ap_device_list_lock); |
559 | if (ap_drv->remove) | 683 | if (ap_drv->remove) |
560 | ap_drv->remove(ap_dev); | 684 | ap_drv->remove(ap_dev); |
561 | spin_lock_bh(&ap_dev->lock); | 685 | spin_lock_bh(&ap_dev->lock); |
@@ -599,6 +723,14 @@ static ssize_t ap_config_time_show(struct bus_type *bus, char *buf) | |||
599 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); | 723 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); |
600 | } | 724 | } |
601 | 725 | ||
726 | static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf) | ||
727 | { | ||
728 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
729 | ap_using_interrupts() ? 1 : 0); | ||
730 | } | ||
731 | |||
732 | static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL); | ||
733 | |||
602 | static ssize_t ap_config_time_store(struct bus_type *bus, | 734 | static ssize_t ap_config_time_store(struct bus_type *bus, |
603 | const char *buf, size_t count) | 735 | const char *buf, size_t count) |
604 | { | 736 | { |
@@ -653,7 +785,8 @@ static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf, | |||
653 | ktime_t hr_time; | 785 | ktime_t hr_time; |
654 | 786 | ||
655 | /* 120 seconds = maximum poll interval */ | 787 | /* 120 seconds = maximum poll interval */ |
656 | if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 || time > 120000000000) | 788 | if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 || |
789 | time > 120000000000ULL) | ||
657 | return -EINVAL; | 790 | return -EINVAL; |
658 | poll_timeout = time; | 791 | poll_timeout = time; |
659 | hr_time = ktime_set(0, poll_timeout); | 792 | hr_time = ktime_set(0, poll_timeout); |
@@ -672,6 +805,7 @@ static struct bus_attribute *const ap_bus_attrs[] = { | |||
672 | &bus_attr_ap_domain, | 805 | &bus_attr_ap_domain, |
673 | &bus_attr_config_time, | 806 | &bus_attr_config_time, |
674 | &bus_attr_poll_thread, | 807 | &bus_attr_poll_thread, |
808 | &bus_attr_ap_interrupts, | ||
675 | &bus_attr_poll_timeout, | 809 | &bus_attr_poll_timeout, |
676 | NULL, | 810 | NULL, |
677 | }; | 811 | }; |
@@ -814,6 +948,11 @@ out: | |||
814 | return rc; | 948 | return rc; |
815 | } | 949 | } |
816 | 950 | ||
951 | static void ap_interrupt_handler(void *unused1, void *unused2) | ||
952 | { | ||
953 | tasklet_schedule(&ap_tasklet); | ||
954 | } | ||
955 | |||
817 | /** | 956 | /** |
818 | * __ap_scan_bus(): Scan the AP bus. | 957 | * __ap_scan_bus(): Scan the AP bus. |
819 | * @dev: Pointer to device | 958 | * @dev: Pointer to device |
@@ -928,6 +1067,8 @@ ap_config_timeout(unsigned long ptr) | |||
928 | */ | 1067 | */ |
929 | static inline void ap_schedule_poll_timer(void) | 1068 | static inline void ap_schedule_poll_timer(void) |
930 | { | 1069 | { |
1070 | if (ap_using_interrupts()) | ||
1071 | return; | ||
931 | if (hrtimer_is_queued(&ap_poll_timer)) | 1072 | if (hrtimer_is_queued(&ap_poll_timer)) |
932 | return; | 1073 | return; |
933 | hrtimer_start(&ap_poll_timer, ktime_set(0, poll_timeout), | 1074 | hrtimer_start(&ap_poll_timer, ktime_set(0, poll_timeout), |
@@ -1181,7 +1322,7 @@ static void ap_reset(struct ap_device *ap_dev) | |||
1181 | ap_dev->unregistered = 1; | 1322 | ap_dev->unregistered = 1; |
1182 | } | 1323 | } |
1183 | 1324 | ||
1184 | static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags) | 1325 | static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags) |
1185 | { | 1326 | { |
1186 | spin_lock(&ap_dev->lock); | 1327 | spin_lock(&ap_dev->lock); |
1187 | if (!ap_dev->unregistered) { | 1328 | if (!ap_dev->unregistered) { |
@@ -1207,13 +1348,19 @@ static void ap_poll_all(unsigned long dummy) | |||
1207 | unsigned long flags; | 1348 | unsigned long flags; |
1208 | struct ap_device *ap_dev; | 1349 | struct ap_device *ap_dev; |
1209 | 1350 | ||
1351 | /* Reset the indicator if interrupts are used. Thus new interrupts can | ||
1352 | * be received. Doing it in the beginning of the tasklet is therefor | ||
1353 | * important that no requests on any AP get lost. | ||
1354 | */ | ||
1355 | if (ap_using_interrupts()) | ||
1356 | xchg((u8 *)ap_interrupt_indicator, 0); | ||
1210 | do { | 1357 | do { |
1211 | flags = 0; | 1358 | flags = 0; |
1212 | spin_lock(&ap_device_lock); | 1359 | spin_lock(&ap_device_list_lock); |
1213 | list_for_each_entry(ap_dev, &ap_device_list, list) { | 1360 | list_for_each_entry(ap_dev, &ap_device_list, list) { |
1214 | __ap_poll_all(ap_dev, &flags); | 1361 | __ap_poll_device(ap_dev, &flags); |
1215 | } | 1362 | } |
1216 | spin_unlock(&ap_device_lock); | 1363 | spin_unlock(&ap_device_list_lock); |
1217 | } while (flags & 1); | 1364 | } while (flags & 1); |
1218 | if (flags & 2) | 1365 | if (flags & 2) |
1219 | ap_schedule_poll_timer(); | 1366 | ap_schedule_poll_timer(); |
@@ -1253,11 +1400,11 @@ static int ap_poll_thread(void *data) | |||
1253 | remove_wait_queue(&ap_poll_wait, &wait); | 1400 | remove_wait_queue(&ap_poll_wait, &wait); |
1254 | 1401 | ||
1255 | flags = 0; | 1402 | flags = 0; |
1256 | spin_lock_bh(&ap_device_lock); | 1403 | spin_lock_bh(&ap_device_list_lock); |
1257 | list_for_each_entry(ap_dev, &ap_device_list, list) { | 1404 | list_for_each_entry(ap_dev, &ap_device_list, list) { |
1258 | __ap_poll_all(ap_dev, &flags); | 1405 | __ap_poll_device(ap_dev, &flags); |
1259 | } | 1406 | } |
1260 | spin_unlock_bh(&ap_device_lock); | 1407 | spin_unlock_bh(&ap_device_list_lock); |
1261 | } | 1408 | } |
1262 | set_current_state(TASK_RUNNING); | 1409 | set_current_state(TASK_RUNNING); |
1263 | remove_wait_queue(&ap_poll_wait, &wait); | 1410 | remove_wait_queue(&ap_poll_wait, &wait); |
@@ -1268,6 +1415,8 @@ static int ap_poll_thread_start(void) | |||
1268 | { | 1415 | { |
1269 | int rc; | 1416 | int rc; |
1270 | 1417 | ||
1418 | if (ap_using_interrupts()) | ||
1419 | return 0; | ||
1271 | mutex_lock(&ap_poll_thread_mutex); | 1420 | mutex_lock(&ap_poll_thread_mutex); |
1272 | if (!ap_poll_kthread) { | 1421 | if (!ap_poll_kthread) { |
1273 | ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll"); | 1422 | ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll"); |
@@ -1301,8 +1450,12 @@ static void ap_request_timeout(unsigned long data) | |||
1301 | { | 1450 | { |
1302 | struct ap_device *ap_dev = (struct ap_device *) data; | 1451 | struct ap_device *ap_dev = (struct ap_device *) data; |
1303 | 1452 | ||
1304 | if (ap_dev->reset == AP_RESET_ARMED) | 1453 | if (ap_dev->reset == AP_RESET_ARMED) { |
1305 | ap_dev->reset = AP_RESET_DO; | 1454 | ap_dev->reset = AP_RESET_DO; |
1455 | |||
1456 | if (ap_using_interrupts()) | ||
1457 | tasklet_schedule(&ap_tasklet); | ||
1458 | } | ||
1306 | } | 1459 | } |
1307 | 1460 | ||
1308 | static void ap_reset_domain(void) | 1461 | static void ap_reset_domain(void) |
@@ -1337,14 +1490,25 @@ int __init ap_module_init(void) | |||
1337 | int rc, i; | 1490 | int rc, i; |
1338 | 1491 | ||
1339 | if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) { | 1492 | if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) { |
1340 | printk(KERN_WARNING "Invalid param: domain = %d. " | 1493 | pr_warning("%d is not a valid cryptographic domain\n", |
1341 | " Not loading.\n", ap_domain_index); | 1494 | ap_domain_index); |
1342 | return -EINVAL; | 1495 | return -EINVAL; |
1343 | } | 1496 | } |
1344 | if (ap_instructions_available() != 0) { | 1497 | if (ap_instructions_available() != 0) { |
1345 | printk(KERN_WARNING "AP instructions not installed.\n"); | 1498 | pr_warning("The hardware system does not support " |
1499 | "AP instructions\n"); | ||
1346 | return -ENODEV; | 1500 | return -ENODEV; |
1347 | } | 1501 | } |
1502 | if (ap_interrupts_available()) { | ||
1503 | isc_register(AP_ISC); | ||
1504 | ap_interrupt_indicator = s390_register_adapter_interrupt( | ||
1505 | &ap_interrupt_handler, NULL, AP_ISC); | ||
1506 | if (IS_ERR(ap_interrupt_indicator)) { | ||
1507 | ap_interrupt_indicator = NULL; | ||
1508 | isc_unregister(AP_ISC); | ||
1509 | } | ||
1510 | } | ||
1511 | |||
1348 | register_reset_call(&ap_reset_call); | 1512 | register_reset_call(&ap_reset_call); |
1349 | 1513 | ||
1350 | /* Create /sys/bus/ap. */ | 1514 | /* Create /sys/bus/ap. */ |
@@ -1408,6 +1572,10 @@ out_bus: | |||
1408 | bus_unregister(&ap_bus_type); | 1572 | bus_unregister(&ap_bus_type); |
1409 | out: | 1573 | out: |
1410 | unregister_reset_call(&ap_reset_call); | 1574 | unregister_reset_call(&ap_reset_call); |
1575 | if (ap_using_interrupts()) { | ||
1576 | s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC); | ||
1577 | isc_unregister(AP_ISC); | ||
1578 | } | ||
1411 | return rc; | 1579 | return rc; |
1412 | } | 1580 | } |
1413 | 1581 | ||
@@ -1443,6 +1611,10 @@ void ap_module_exit(void) | |||
1443 | bus_remove_file(&ap_bus_type, ap_bus_attrs[i]); | 1611 | bus_remove_file(&ap_bus_type, ap_bus_attrs[i]); |
1444 | bus_unregister(&ap_bus_type); | 1612 | bus_unregister(&ap_bus_type); |
1445 | unregister_reset_call(&ap_reset_call); | 1613 | unregister_reset_call(&ap_reset_call); |
1614 | if (ap_using_interrupts()) { | ||
1615 | s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC); | ||
1616 | isc_unregister(AP_ISC); | ||
1617 | } | ||
1446 | } | 1618 | } |
1447 | 1619 | ||
1448 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | 1620 | #ifndef CONFIG_ZCRYPT_MONOLITHIC |
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 446378b308fc..a35362241805 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h | |||
@@ -5,6 +5,7 @@ | |||
5 | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> | 5 | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> |
6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
7 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | 7 | * Ralph Wuerthner <rwuerthn@de.ibm.com> |
8 | * Felix Beck <felix.beck@de.ibm.com> | ||
8 | * | 9 | * |
9 | * Adjunct processor bus header file. | 10 | * Adjunct processor bus header file. |
10 | * | 11 | * |
@@ -67,7 +68,8 @@ struct ap_queue_status { | |||
67 | unsigned int queue_empty : 1; | 68 | unsigned int queue_empty : 1; |
68 | unsigned int replies_waiting : 1; | 69 | unsigned int replies_waiting : 1; |
69 | unsigned int queue_full : 1; | 70 | unsigned int queue_full : 1; |
70 | unsigned int pad1 : 5; | 71 | unsigned int pad1 : 4; |
72 | unsigned int int_enabled : 1; | ||
71 | unsigned int response_code : 8; | 73 | unsigned int response_code : 8; |
72 | unsigned int pad2 : 16; | 74 | unsigned int pad2 : 16; |
73 | }; | 75 | }; |
@@ -78,6 +80,8 @@ struct ap_queue_status { | |||
78 | #define AP_RESPONSE_DECONFIGURED 0x03 | 80 | #define AP_RESPONSE_DECONFIGURED 0x03 |
79 | #define AP_RESPONSE_CHECKSTOPPED 0x04 | 81 | #define AP_RESPONSE_CHECKSTOPPED 0x04 |
80 | #define AP_RESPONSE_BUSY 0x05 | 82 | #define AP_RESPONSE_BUSY 0x05 |
83 | #define AP_RESPONSE_INVALID_ADDRESS 0x06 | ||
84 | #define AP_RESPONSE_OTHERWISE_CHANGED 0x07 | ||
81 | #define AP_RESPONSE_Q_FULL 0x10 | 85 | #define AP_RESPONSE_Q_FULL 0x10 |
82 | #define AP_RESPONSE_NO_PENDING_REPLY 0x10 | 86 | #define AP_RESPONSE_NO_PENDING_REPLY 0x10 |
83 | #define AP_RESPONSE_INDEX_TOO_BIG 0x11 | 87 | #define AP_RESPONSE_INDEX_TOO_BIG 0x11 |
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c index 54f4cbc3be9e..326ea08f67c9 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.c +++ b/drivers/s390/crypto/zcrypt_cex2a.c | |||
@@ -264,17 +264,21 @@ static void zcrypt_cex2a_receive(struct ap_device *ap_dev, | |||
264 | .type = TYPE82_RSP_CODE, | 264 | .type = TYPE82_RSP_CODE, |
265 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | 265 | .reply_code = REP82_ERROR_MACHINE_FAILURE, |
266 | }; | 266 | }; |
267 | struct type80_hdr *t80h = reply->message; | 267 | struct type80_hdr *t80h; |
268 | int length; | 268 | int length; |
269 | 269 | ||
270 | /* Copy the reply message to the request message buffer. */ | 270 | /* Copy the reply message to the request message buffer. */ |
271 | if (IS_ERR(reply)) | 271 | if (IS_ERR(reply)) { |
272 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | 272 | memcpy(msg->message, &error_reply, sizeof(error_reply)); |
273 | else if (t80h->type == TYPE80_RSP_CODE) { | 273 | goto out; |
274 | } | ||
275 | t80h = reply->message; | ||
276 | if (t80h->type == TYPE80_RSP_CODE) { | ||
274 | length = min(CEX2A_MAX_RESPONSE_SIZE, (int) t80h->len); | 277 | length = min(CEX2A_MAX_RESPONSE_SIZE, (int) t80h->len); |
275 | memcpy(msg->message, reply->message, length); | 278 | memcpy(msg->message, reply->message, length); |
276 | } else | 279 | } else |
277 | memcpy(msg->message, reply->message, sizeof error_reply); | 280 | memcpy(msg->message, reply->message, sizeof error_reply); |
281 | out: | ||
278 | complete((struct completion *) msg->private); | 282 | complete((struct completion *) msg->private); |
279 | } | 283 | } |
280 | 284 | ||
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c index 12da4815ba8e..17ba81b58c78 100644 --- a/drivers/s390/crypto/zcrypt_pcica.c +++ b/drivers/s390/crypto/zcrypt_pcica.c | |||
@@ -247,17 +247,21 @@ static void zcrypt_pcica_receive(struct ap_device *ap_dev, | |||
247 | .type = TYPE82_RSP_CODE, | 247 | .type = TYPE82_RSP_CODE, |
248 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | 248 | .reply_code = REP82_ERROR_MACHINE_FAILURE, |
249 | }; | 249 | }; |
250 | struct type84_hdr *t84h = reply->message; | 250 | struct type84_hdr *t84h; |
251 | int length; | 251 | int length; |
252 | 252 | ||
253 | /* Copy the reply message to the request message buffer. */ | 253 | /* Copy the reply message to the request message buffer. */ |
254 | if (IS_ERR(reply)) | 254 | if (IS_ERR(reply)) { |
255 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | 255 | memcpy(msg->message, &error_reply, sizeof(error_reply)); |
256 | else if (t84h->code == TYPE84_RSP_CODE) { | 256 | goto out; |
257 | } | ||
258 | t84h = reply->message; | ||
259 | if (t84h->code == TYPE84_RSP_CODE) { | ||
257 | length = min(PCICA_MAX_RESPONSE_SIZE, (int) t84h->len); | 260 | length = min(PCICA_MAX_RESPONSE_SIZE, (int) t84h->len); |
258 | memcpy(msg->message, reply->message, length); | 261 | memcpy(msg->message, reply->message, length); |
259 | } else | 262 | } else |
260 | memcpy(msg->message, reply->message, sizeof error_reply); | 263 | memcpy(msg->message, reply->message, sizeof error_reply); |
264 | out: | ||
261 | complete((struct completion *) msg->private); | 265 | complete((struct completion *) msg->private); |
262 | } | 266 | } |
263 | 267 | ||
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c index 779952cb19fc..f4b0c4795434 100644 --- a/drivers/s390/crypto/zcrypt_pcicc.c +++ b/drivers/s390/crypto/zcrypt_pcicc.c | |||
@@ -447,19 +447,23 @@ static void zcrypt_pcicc_receive(struct ap_device *ap_dev, | |||
447 | .type = TYPE82_RSP_CODE, | 447 | .type = TYPE82_RSP_CODE, |
448 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | 448 | .reply_code = REP82_ERROR_MACHINE_FAILURE, |
449 | }; | 449 | }; |
450 | struct type86_reply *t86r = reply->message; | 450 | struct type86_reply *t86r; |
451 | int length; | 451 | int length; |
452 | 452 | ||
453 | /* Copy the reply message to the request message buffer. */ | 453 | /* Copy the reply message to the request message buffer. */ |
454 | if (IS_ERR(reply)) | 454 | if (IS_ERR(reply)) { |
455 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | 455 | memcpy(msg->message, &error_reply, sizeof(error_reply)); |
456 | else if (t86r->hdr.type == TYPE86_RSP_CODE && | 456 | goto out; |
457 | } | ||
458 | t86r = reply->message; | ||
459 | if (t86r->hdr.type == TYPE86_RSP_CODE && | ||
457 | t86r->cprb.cprb_ver_id == 0x01) { | 460 | t86r->cprb.cprb_ver_id == 0x01) { |
458 | length = sizeof(struct type86_reply) + t86r->length - 2; | 461 | length = sizeof(struct type86_reply) + t86r->length - 2; |
459 | length = min(PCICC_MAX_RESPONSE_SIZE, length); | 462 | length = min(PCICC_MAX_RESPONSE_SIZE, length); |
460 | memcpy(msg->message, reply->message, length); | 463 | memcpy(msg->message, reply->message, length); |
461 | } else | 464 | } else |
462 | memcpy(msg->message, reply->message, sizeof error_reply); | 465 | memcpy(msg->message, reply->message, sizeof error_reply); |
466 | out: | ||
463 | complete((struct completion *) msg->private); | 467 | complete((struct completion *) msg->private); |
464 | } | 468 | } |
465 | 469 | ||
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index d8ad36f81540..e7a1e22e77ac 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c | |||
@@ -635,13 +635,16 @@ static void zcrypt_pcixcc_receive(struct ap_device *ap_dev, | |||
635 | }; | 635 | }; |
636 | struct response_type *resp_type = | 636 | struct response_type *resp_type = |
637 | (struct response_type *) msg->private; | 637 | (struct response_type *) msg->private; |
638 | struct type86x_reply *t86r = reply->message; | 638 | struct type86x_reply *t86r; |
639 | int length; | 639 | int length; |
640 | 640 | ||
641 | /* Copy the reply message to the request message buffer. */ | 641 | /* Copy the reply message to the request message buffer. */ |
642 | if (IS_ERR(reply)) | 642 | if (IS_ERR(reply)) { |
643 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | 643 | memcpy(msg->message, &error_reply, sizeof(error_reply)); |
644 | else if (t86r->hdr.type == TYPE86_RSP_CODE && | 644 | goto out; |
645 | } | ||
646 | t86r = reply->message; | ||
647 | if (t86r->hdr.type == TYPE86_RSP_CODE && | ||
645 | t86r->cprbx.cprb_ver_id == 0x02) { | 648 | t86r->cprbx.cprb_ver_id == 0x02) { |
646 | switch (resp_type->type) { | 649 | switch (resp_type->type) { |
647 | case PCIXCC_RESPONSE_TYPE_ICA: | 650 | case PCIXCC_RESPONSE_TYPE_ICA: |
@@ -660,6 +663,7 @@ static void zcrypt_pcixcc_receive(struct ap_device *ap_dev, | |||
660 | } | 663 | } |
661 | } else | 664 | } else |
662 | memcpy(msg->message, reply->message, sizeof error_reply); | 665 | memcpy(msg->message, reply->message, sizeof error_reply); |
666 | out: | ||
663 | complete(&(resp_type->work)); | 667 | complete(&(resp_type->work)); |
664 | } | 668 | } |
665 | 669 | ||