diff options
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 58 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.h | 1 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_api.c | 12 |
3 files changed, 46 insertions, 25 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index c7d1355237b6..bf37cdf43fae 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -65,6 +65,8 @@ module_param_named(poll_thread, ap_thread_flag, int, 0000); | |||
65 | MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 1 (on)."); | 65 | MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 1 (on)."); |
66 | 66 | ||
67 | static struct device *ap_root_device = NULL; | 67 | static struct device *ap_root_device = NULL; |
68 | static DEFINE_SPINLOCK(ap_device_lock); | ||
69 | static LIST_HEAD(ap_device_list); | ||
68 | 70 | ||
69 | /** | 71 | /** |
70 | * Workqueue & timer for bus rescan. | 72 | * Workqueue & timer for bus rescan. |
@@ -457,6 +459,9 @@ static int ap_device_probe(struct device *dev) | |||
457 | int rc; | 459 | int rc; |
458 | 460 | ||
459 | ap_dev->drv = ap_drv; | 461 | ap_dev->drv = ap_drv; |
462 | spin_lock_bh(&ap_device_lock); | ||
463 | list_add(&ap_dev->list, &ap_device_list); | ||
464 | spin_unlock_bh(&ap_device_lock); | ||
460 | rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV; | 465 | rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV; |
461 | return rc; | 466 | return rc; |
462 | } | 467 | } |
@@ -497,6 +502,12 @@ static int ap_device_remove(struct device *dev) | |||
497 | ap_flush_queue(ap_dev); | 502 | ap_flush_queue(ap_dev); |
498 | if (ap_drv->remove) | 503 | if (ap_drv->remove) |
499 | ap_drv->remove(ap_dev); | 504 | ap_drv->remove(ap_dev); |
505 | spin_lock_bh(&ap_device_lock); | ||
506 | list_del_init(&ap_dev->list); | ||
507 | spin_unlock_bh(&ap_device_lock); | ||
508 | spin_lock_bh(&ap_dev->lock); | ||
509 | atomic_sub(ap_dev->queue_count, &ap_poll_requests); | ||
510 | spin_unlock_bh(&ap_dev->lock); | ||
500 | return 0; | 511 | return 0; |
501 | } | 512 | } |
502 | 513 | ||
@@ -749,10 +760,16 @@ static void ap_scan_bus(struct work_struct *unused) | |||
749 | (void *)(unsigned long)qid, | 760 | (void *)(unsigned long)qid, |
750 | __ap_scan_bus); | 761 | __ap_scan_bus); |
751 | rc = ap_query_queue(qid, &queue_depth, &device_type); | 762 | rc = ap_query_queue(qid, &queue_depth, &device_type); |
752 | if (dev && rc) { | 763 | if (dev) { |
753 | put_device(dev); | 764 | ap_dev = to_ap_dev(dev); |
754 | device_unregister(dev); | 765 | spin_lock_bh(&ap_dev->lock); |
755 | continue; | 766 | if (rc || ap_dev->unregistered) { |
767 | spin_unlock_bh(&ap_dev->lock); | ||
768 | put_device(dev); | ||
769 | device_unregister(dev); | ||
770 | continue; | ||
771 | } else | ||
772 | spin_unlock_bh(&ap_dev->lock); | ||
756 | } | 773 | } |
757 | if (dev) { | 774 | if (dev) { |
758 | put_device(dev); | 775 | put_device(dev); |
@@ -772,6 +789,7 @@ static void ap_scan_bus(struct work_struct *unused) | |||
772 | spin_lock_init(&ap_dev->lock); | 789 | spin_lock_init(&ap_dev->lock); |
773 | INIT_LIST_HEAD(&ap_dev->pendingq); | 790 | INIT_LIST_HEAD(&ap_dev->pendingq); |
774 | INIT_LIST_HEAD(&ap_dev->requestq); | 791 | INIT_LIST_HEAD(&ap_dev->requestq); |
792 | INIT_LIST_HEAD(&ap_dev->list); | ||
775 | if (device_type == 0) | 793 | if (device_type == 0) |
776 | ap_probe_device_type(ap_dev); | 794 | ap_probe_device_type(ap_dev); |
777 | else | 795 | else |
@@ -852,6 +870,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) | |||
852 | case AP_RESPONSE_NO_PENDING_REPLY: | 870 | case AP_RESPONSE_NO_PENDING_REPLY: |
853 | if (status.queue_empty) { | 871 | if (status.queue_empty) { |
854 | /* The card shouldn't forget requests but who knows. */ | 872 | /* The card shouldn't forget requests but who knows. */ |
873 | atomic_sub(ap_dev->queue_count, &ap_poll_requests); | ||
855 | ap_dev->queue_count = 0; | 874 | ap_dev->queue_count = 0; |
856 | list_splice_init(&ap_dev->pendingq, &ap_dev->requestq); | 875 | list_splice_init(&ap_dev->pendingq, &ap_dev->requestq); |
857 | ap_dev->requestq_count += ap_dev->pendingq_count; | 876 | ap_dev->requestq_count += ap_dev->pendingq_count; |
@@ -985,7 +1004,7 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg) | |||
985 | ap_dev->unregistered = 1; | 1004 | ap_dev->unregistered = 1; |
986 | } else { | 1005 | } else { |
987 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); | 1006 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); |
988 | rc = 0; | 1007 | rc = -ENODEV; |
989 | } | 1008 | } |
990 | spin_unlock_bh(&ap_dev->lock); | 1009 | spin_unlock_bh(&ap_dev->lock); |
991 | if (rc == -ENODEV) | 1010 | if (rc == -ENODEV) |
@@ -1033,31 +1052,29 @@ static void ap_poll_timeout(unsigned long unused) | |||
1033 | * polling until bit 2^0 of the control flags is not set. If bit 2^1 | 1052 | * polling until bit 2^0 of the control flags is not set. If bit 2^1 |
1034 | * of the control flags has been set arm the poll timer. | 1053 | * of the control flags has been set arm the poll timer. |
1035 | */ | 1054 | */ |
1036 | static int __ap_poll_all(struct device *dev, void *data) | 1055 | static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags) |
1037 | { | 1056 | { |
1038 | struct ap_device *ap_dev = to_ap_dev(dev); | ||
1039 | int rc; | ||
1040 | |||
1041 | spin_lock(&ap_dev->lock); | 1057 | spin_lock(&ap_dev->lock); |
1042 | if (!ap_dev->unregistered) { | 1058 | if (!ap_dev->unregistered) { |
1043 | rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data); | 1059 | if (ap_poll_queue(ap_dev, flags)) |
1044 | if (rc) | ||
1045 | ap_dev->unregistered = 1; | 1060 | ap_dev->unregistered = 1; |
1046 | } else | 1061 | } |
1047 | rc = 0; | ||
1048 | spin_unlock(&ap_dev->lock); | 1062 | spin_unlock(&ap_dev->lock); |
1049 | if (rc) | ||
1050 | device_unregister(&ap_dev->device); | ||
1051 | return 0; | 1063 | return 0; |
1052 | } | 1064 | } |
1053 | 1065 | ||
1054 | static void ap_poll_all(unsigned long dummy) | 1066 | static void ap_poll_all(unsigned long dummy) |
1055 | { | 1067 | { |
1056 | unsigned long flags; | 1068 | unsigned long flags; |
1069 | struct ap_device *ap_dev; | ||
1057 | 1070 | ||
1058 | do { | 1071 | do { |
1059 | flags = 0; | 1072 | flags = 0; |
1060 | bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all); | 1073 | spin_lock(&ap_device_lock); |
1074 | list_for_each_entry(ap_dev, &ap_device_list, list) { | ||
1075 | __ap_poll_all(ap_dev, &flags); | ||
1076 | } | ||
1077 | spin_unlock(&ap_device_lock); | ||
1061 | } while (flags & 1); | 1078 | } while (flags & 1); |
1062 | if (flags & 2) | 1079 | if (flags & 2) |
1063 | ap_schedule_poll_timer(); | 1080 | ap_schedule_poll_timer(); |
@@ -1075,6 +1092,7 @@ static int ap_poll_thread(void *data) | |||
1075 | DECLARE_WAITQUEUE(wait, current); | 1092 | DECLARE_WAITQUEUE(wait, current); |
1076 | unsigned long flags; | 1093 | unsigned long flags; |
1077 | int requests; | 1094 | int requests; |
1095 | struct ap_device *ap_dev; | ||
1078 | 1096 | ||
1079 | set_user_nice(current, 19); | 1097 | set_user_nice(current, 19); |
1080 | while (1) { | 1098 | while (1) { |
@@ -1092,10 +1110,12 @@ static int ap_poll_thread(void *data) | |||
1092 | set_current_state(TASK_RUNNING); | 1110 | set_current_state(TASK_RUNNING); |
1093 | remove_wait_queue(&ap_poll_wait, &wait); | 1111 | remove_wait_queue(&ap_poll_wait, &wait); |
1094 | 1112 | ||
1095 | local_bh_disable(); | ||
1096 | flags = 0; | 1113 | flags = 0; |
1097 | bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all); | 1114 | spin_lock_bh(&ap_device_lock); |
1098 | local_bh_enable(); | 1115 | list_for_each_entry(ap_dev, &ap_device_list, list) { |
1116 | __ap_poll_all(ap_dev, &flags); | ||
1117 | } | ||
1118 | spin_unlock_bh(&ap_device_lock); | ||
1099 | } | 1119 | } |
1100 | set_current_state(TASK_RUNNING); | 1120 | set_current_state(TASK_RUNNING); |
1101 | remove_wait_queue(&ap_poll_wait, &wait); | 1121 | remove_wait_queue(&ap_poll_wait, &wait); |
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 83b69c01cd6e..008559ea742b 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h | |||
@@ -106,6 +106,7 @@ struct ap_device { | |||
106 | struct device device; | 106 | struct device device; |
107 | struct ap_driver *drv; /* Pointer to AP device driver. */ | 107 | struct ap_driver *drv; /* Pointer to AP device driver. */ |
108 | spinlock_t lock; /* Per device lock. */ | 108 | spinlock_t lock; /* Per device lock. */ |
109 | struct list_head list; /* private list of all AP devices. */ | ||
109 | 110 | ||
110 | ap_qid_t qid; /* AP queue id. */ | 111 | ap_qid_t qid; /* AP queue id. */ |
111 | int queue_depth; /* AP queue depth.*/ | 112 | int queue_depth; /* AP queue depth.*/ |
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 99761391f340..e3625a47a596 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
@@ -298,14 +298,14 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex) | |||
298 | get_device(&zdev->ap_dev->device); | 298 | get_device(&zdev->ap_dev->device); |
299 | zdev->request_count++; | 299 | zdev->request_count++; |
300 | __zcrypt_decrease_preference(zdev); | 300 | __zcrypt_decrease_preference(zdev); |
301 | spin_unlock_bh(&zcrypt_device_lock); | ||
302 | if (try_module_get(zdev->ap_dev->drv->driver.owner)) { | 301 | if (try_module_get(zdev->ap_dev->drv->driver.owner)) { |
302 | spin_unlock_bh(&zcrypt_device_lock); | ||
303 | rc = zdev->ops->rsa_modexpo(zdev, mex); | 303 | rc = zdev->ops->rsa_modexpo(zdev, mex); |
304 | spin_lock_bh(&zcrypt_device_lock); | ||
304 | module_put(zdev->ap_dev->drv->driver.owner); | 305 | module_put(zdev->ap_dev->drv->driver.owner); |
305 | } | 306 | } |
306 | else | 307 | else |
307 | rc = -EAGAIN; | 308 | rc = -EAGAIN; |
308 | spin_lock_bh(&zcrypt_device_lock); | ||
309 | zdev->request_count--; | 309 | zdev->request_count--; |
310 | __zcrypt_increase_preference(zdev); | 310 | __zcrypt_increase_preference(zdev); |
311 | put_device(&zdev->ap_dev->device); | 311 | put_device(&zdev->ap_dev->device); |
@@ -373,14 +373,14 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) | |||
373 | get_device(&zdev->ap_dev->device); | 373 | get_device(&zdev->ap_dev->device); |
374 | zdev->request_count++; | 374 | zdev->request_count++; |
375 | __zcrypt_decrease_preference(zdev); | 375 | __zcrypt_decrease_preference(zdev); |
376 | spin_unlock_bh(&zcrypt_device_lock); | ||
377 | if (try_module_get(zdev->ap_dev->drv->driver.owner)) { | 376 | if (try_module_get(zdev->ap_dev->drv->driver.owner)) { |
377 | spin_unlock_bh(&zcrypt_device_lock); | ||
378 | rc = zdev->ops->rsa_modexpo_crt(zdev, crt); | 378 | rc = zdev->ops->rsa_modexpo_crt(zdev, crt); |
379 | spin_lock_bh(&zcrypt_device_lock); | ||
379 | module_put(zdev->ap_dev->drv->driver.owner); | 380 | module_put(zdev->ap_dev->drv->driver.owner); |
380 | } | 381 | } |
381 | else | 382 | else |
382 | rc = -EAGAIN; | 383 | rc = -EAGAIN; |
383 | spin_lock_bh(&zcrypt_device_lock); | ||
384 | zdev->request_count--; | 384 | zdev->request_count--; |
385 | __zcrypt_increase_preference(zdev); | 385 | __zcrypt_increase_preference(zdev); |
386 | put_device(&zdev->ap_dev->device); | 386 | put_device(&zdev->ap_dev->device); |
@@ -408,14 +408,14 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) | |||
408 | get_device(&zdev->ap_dev->device); | 408 | get_device(&zdev->ap_dev->device); |
409 | zdev->request_count++; | 409 | zdev->request_count++; |
410 | __zcrypt_decrease_preference(zdev); | 410 | __zcrypt_decrease_preference(zdev); |
411 | spin_unlock_bh(&zcrypt_device_lock); | ||
412 | if (try_module_get(zdev->ap_dev->drv->driver.owner)) { | 411 | if (try_module_get(zdev->ap_dev->drv->driver.owner)) { |
412 | spin_unlock_bh(&zcrypt_device_lock); | ||
413 | rc = zdev->ops->send_cprb(zdev, xcRB); | 413 | rc = zdev->ops->send_cprb(zdev, xcRB); |
414 | spin_lock_bh(&zcrypt_device_lock); | ||
414 | module_put(zdev->ap_dev->drv->driver.owner); | 415 | module_put(zdev->ap_dev->drv->driver.owner); |
415 | } | 416 | } |
416 | else | 417 | else |
417 | rc = -EAGAIN; | 418 | rc = -EAGAIN; |
418 | spin_lock_bh(&zcrypt_device_lock); | ||
419 | zdev->request_count--; | 419 | zdev->request_count--; |
420 | __zcrypt_increase_preference(zdev); | 420 | __zcrypt_increase_preference(zdev); |
421 | put_device(&zdev->ap_dev->device); | 421 | put_device(&zdev->ap_dev->device); |