diff options
Diffstat (limited to 'drivers/s390/crypto/ap_bus.c')
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 58 |
1 files changed, 39 insertions, 19 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); |