diff options
Diffstat (limited to 'drivers/s390/crypto/ap_bus.c')
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 1294876bf7b4..91c6028d7b74 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/err.h> | 33 | #include <linux/err.h> |
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
36 | #include <linux/slab.h> | ||
36 | #include <linux/notifier.h> | 37 | #include <linux/notifier.h> |
37 | #include <linux/kthread.h> | 38 | #include <linux/kthread.h> |
38 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
@@ -102,6 +103,7 @@ static atomic_t ap_poll_requests = ATOMIC_INIT(0); | |||
102 | static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait); | 103 | static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait); |
103 | static struct task_struct *ap_poll_kthread = NULL; | 104 | static struct task_struct *ap_poll_kthread = NULL; |
104 | static DEFINE_MUTEX(ap_poll_thread_mutex); | 105 | static DEFINE_MUTEX(ap_poll_thread_mutex); |
106 | static DEFINE_SPINLOCK(ap_poll_timer_lock); | ||
105 | static void *ap_interrupt_indicator; | 107 | static void *ap_interrupt_indicator; |
106 | static struct hrtimer ap_poll_timer; | 108 | static struct hrtimer ap_poll_timer; |
107 | /* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds. | 109 | /* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds. |
@@ -282,6 +284,7 @@ static int ap_queue_enable_interruption(ap_qid_t qid, void *ind) | |||
282 | * @psmid: The program supplied message identifier | 284 | * @psmid: The program supplied message identifier |
283 | * @msg: The message text | 285 | * @msg: The message text |
284 | * @length: The message length | 286 | * @length: The message length |
287 | * @special: Special Bit | ||
285 | * | 288 | * |
286 | * Returns AP queue status structure. | 289 | * Returns AP queue status structure. |
287 | * Condition code 1 on NQAP can't happen because the L bit is 1. | 290 | * Condition code 1 on NQAP can't happen because the L bit is 1. |
@@ -289,7 +292,8 @@ static int ap_queue_enable_interruption(ap_qid_t qid, void *ind) | |||
289 | * because a segment boundary was reached. The NQAP is repeated. | 292 | * because a segment boundary was reached. The NQAP is repeated. |
290 | */ | 293 | */ |
291 | static inline struct ap_queue_status | 294 | static inline struct ap_queue_status |
292 | __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length) | 295 | __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length, |
296 | unsigned int special) | ||
293 | { | 297 | { |
294 | typedef struct { char _[length]; } msgblock; | 298 | typedef struct { char _[length]; } msgblock; |
295 | register unsigned long reg0 asm ("0") = qid | 0x40000000UL; | 299 | register unsigned long reg0 asm ("0") = qid | 0x40000000UL; |
@@ -299,6 +303,9 @@ __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length) | |||
299 | register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32); | 303 | register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32); |
300 | register unsigned long reg5 asm ("5") = (unsigned int) psmid; | 304 | register unsigned long reg5 asm ("5") = (unsigned int) psmid; |
301 | 305 | ||
306 | if (special == 1) | ||
307 | reg0 |= 0x400000UL; | ||
308 | |||
302 | asm volatile ( | 309 | asm volatile ( |
303 | "0: .long 0xb2ad0042\n" /* DQAP */ | 310 | "0: .long 0xb2ad0042\n" /* DQAP */ |
304 | " brc 2,0b" | 311 | " brc 2,0b" |
@@ -312,13 +319,15 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length) | |||
312 | { | 319 | { |
313 | struct ap_queue_status status; | 320 | struct ap_queue_status status; |
314 | 321 | ||
315 | status = __ap_send(qid, psmid, msg, length); | 322 | status = __ap_send(qid, psmid, msg, length, 0); |
316 | switch (status.response_code) { | 323 | switch (status.response_code) { |
317 | case AP_RESPONSE_NORMAL: | 324 | case AP_RESPONSE_NORMAL: |
318 | return 0; | 325 | return 0; |
319 | case AP_RESPONSE_Q_FULL: | 326 | case AP_RESPONSE_Q_FULL: |
320 | case AP_RESPONSE_RESET_IN_PROGRESS: | 327 | case AP_RESPONSE_RESET_IN_PROGRESS: |
321 | return -EBUSY; | 328 | return -EBUSY; |
329 | case AP_RESPONSE_REQ_FAC_NOT_INST: | ||
330 | return -EINVAL; | ||
322 | default: /* Device is gone. */ | 331 | default: /* Device is gone. */ |
323 | return -ENODEV; | 332 | return -ENODEV; |
324 | } | 333 | } |
@@ -1008,7 +1017,7 @@ static int ap_probe_device_type(struct ap_device *ap_dev) | |||
1008 | } | 1017 | } |
1009 | 1018 | ||
1010 | status = __ap_send(ap_dev->qid, 0x0102030405060708ULL, | 1019 | status = __ap_send(ap_dev->qid, 0x0102030405060708ULL, |
1011 | msg, sizeof(msg)); | 1020 | msg, sizeof(msg), 0); |
1012 | if (status.response_code != AP_RESPONSE_NORMAL) { | 1021 | if (status.response_code != AP_RESPONSE_NORMAL) { |
1013 | rc = -ENODEV; | 1022 | rc = -ENODEV; |
1014 | goto out_free; | 1023 | goto out_free; |
@@ -1163,16 +1172,19 @@ ap_config_timeout(unsigned long ptr) | |||
1163 | static inline void ap_schedule_poll_timer(void) | 1172 | static inline void ap_schedule_poll_timer(void) |
1164 | { | 1173 | { |
1165 | ktime_t hr_time; | 1174 | ktime_t hr_time; |
1175 | |||
1176 | spin_lock_bh(&ap_poll_timer_lock); | ||
1166 | if (ap_using_interrupts() || ap_suspend_flag) | 1177 | if (ap_using_interrupts() || ap_suspend_flag) |
1167 | return; | 1178 | goto out; |
1168 | if (hrtimer_is_queued(&ap_poll_timer)) | 1179 | if (hrtimer_is_queued(&ap_poll_timer)) |
1169 | return; | 1180 | goto out; |
1170 | if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) { | 1181 | if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) { |
1171 | hr_time = ktime_set(0, poll_timeout); | 1182 | hr_time = ktime_set(0, poll_timeout); |
1172 | hrtimer_forward_now(&ap_poll_timer, hr_time); | 1183 | hrtimer_forward_now(&ap_poll_timer, hr_time); |
1173 | hrtimer_restart(&ap_poll_timer); | 1184 | hrtimer_restart(&ap_poll_timer); |
1174 | } | 1185 | } |
1175 | return; | 1186 | out: |
1187 | spin_unlock_bh(&ap_poll_timer_lock); | ||
1176 | } | 1188 | } |
1177 | 1189 | ||
1178 | /** | 1190 | /** |
@@ -1243,7 +1255,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) | |||
1243 | /* Start the next request on the queue. */ | 1255 | /* Start the next request on the queue. */ |
1244 | ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list); | 1256 | ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list); |
1245 | status = __ap_send(ap_dev->qid, ap_msg->psmid, | 1257 | status = __ap_send(ap_dev->qid, ap_msg->psmid, |
1246 | ap_msg->message, ap_msg->length); | 1258 | ap_msg->message, ap_msg->length, ap_msg->special); |
1247 | switch (status.response_code) { | 1259 | switch (status.response_code) { |
1248 | case AP_RESPONSE_NORMAL: | 1260 | case AP_RESPONSE_NORMAL: |
1249 | atomic_inc(&ap_poll_requests); | 1261 | atomic_inc(&ap_poll_requests); |
@@ -1261,6 +1273,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) | |||
1261 | *flags |= 2; | 1273 | *flags |= 2; |
1262 | break; | 1274 | break; |
1263 | case AP_RESPONSE_MESSAGE_TOO_BIG: | 1275 | case AP_RESPONSE_MESSAGE_TOO_BIG: |
1276 | case AP_RESPONSE_REQ_FAC_NOT_INST: | ||
1264 | return -EINVAL; | 1277 | return -EINVAL; |
1265 | default: | 1278 | default: |
1266 | return -ENODEV; | 1279 | return -ENODEV; |
@@ -1302,7 +1315,8 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms | |||
1302 | if (list_empty(&ap_dev->requestq) && | 1315 | if (list_empty(&ap_dev->requestq) && |
1303 | ap_dev->queue_count < ap_dev->queue_depth) { | 1316 | ap_dev->queue_count < ap_dev->queue_depth) { |
1304 | status = __ap_send(ap_dev->qid, ap_msg->psmid, | 1317 | status = __ap_send(ap_dev->qid, ap_msg->psmid, |
1305 | ap_msg->message, ap_msg->length); | 1318 | ap_msg->message, ap_msg->length, |
1319 | ap_msg->special); | ||
1306 | switch (status.response_code) { | 1320 | switch (status.response_code) { |
1307 | case AP_RESPONSE_NORMAL: | 1321 | case AP_RESPONSE_NORMAL: |
1308 | list_add_tail(&ap_msg->list, &ap_dev->pendingq); | 1322 | list_add_tail(&ap_msg->list, &ap_dev->pendingq); |
@@ -1317,6 +1331,7 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms | |||
1317 | ap_dev->requestq_count++; | 1331 | ap_dev->requestq_count++; |
1318 | ap_dev->total_request_count++; | 1332 | ap_dev->total_request_count++; |
1319 | return -EBUSY; | 1333 | return -EBUSY; |
1334 | case AP_RESPONSE_REQ_FAC_NOT_INST: | ||
1320 | case AP_RESPONSE_MESSAGE_TOO_BIG: | 1335 | case AP_RESPONSE_MESSAGE_TOO_BIG: |
1321 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL)); | 1336 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL)); |
1322 | return -EINVAL; | 1337 | return -EINVAL; |
@@ -1658,6 +1673,7 @@ int __init ap_module_init(void) | |||
1658 | */ | 1673 | */ |
1659 | if (MACHINE_IS_VM) | 1674 | if (MACHINE_IS_VM) |
1660 | poll_timeout = 1500000; | 1675 | poll_timeout = 1500000; |
1676 | spin_lock_init(&ap_poll_timer_lock); | ||
1661 | hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 1677 | hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
1662 | ap_poll_timer.function = ap_poll_timeout; | 1678 | ap_poll_timer.function = ap_poll_timeout; |
1663 | 1679 | ||