aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalph Wuerthner <rwuerthn@de.ibm.com>2006-10-04 14:02:05 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-10-04 14:02:05 -0400
commit4e56296d471a827fdd244cfdb6a1e62fc3af7af0 (patch)
tree8532577922b2dfe337701544305c19726c82443f
parentf1ee3281bedbbca70a1f53bc715ea6f27c616052 (diff)
[S390] zcrypt device registration/unregistration race.
Fix a race condition during AP device registration and unregistration. Signed-off-by: Ralph Wuerthner <rwuerthn@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--drivers/s390/crypto/ap_bus.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 6ed0985c0c91..cd30f37fceae 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -449,8 +449,6 @@ static int ap_device_probe(struct device *dev)
449 449
450 ap_dev->drv = ap_drv; 450 ap_dev->drv = ap_drv;
451 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV; 451 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
452 if (rc)
453 ap_dev->unregistered = 1;
454 return rc; 452 return rc;
455} 453}
456 454
@@ -487,14 +485,7 @@ static int ap_device_remove(struct device *dev)
487 struct ap_device *ap_dev = to_ap_dev(dev); 485 struct ap_device *ap_dev = to_ap_dev(dev);
488 struct ap_driver *ap_drv = ap_dev->drv; 486 struct ap_driver *ap_drv = ap_dev->drv;
489 487
490 spin_lock_bh(&ap_dev->lock); 488 ap_flush_queue(ap_dev);
491 __ap_flush_queue(ap_dev);
492 /**
493 * set ->unregistered to 1 while holding the lock. This prevents
494 * new messages to be put on the queue from now on.
495 */
496 ap_dev->unregistered = 1;
497 spin_unlock_bh(&ap_dev->lock);
498 if (ap_drv->remove) 489 if (ap_drv->remove)
499 ap_drv->remove(ap_dev); 490 ap_drv->remove(ap_dev);
500 return 0; 491 return 0;
@@ -763,6 +754,7 @@ static void ap_scan_bus(void *data)
763 break; 754 break;
764 ap_dev->qid = qid; 755 ap_dev->qid = qid;
765 ap_dev->queue_depth = queue_depth; 756 ap_dev->queue_depth = queue_depth;
757 ap_dev->unregistered = 1;
766 spin_lock_init(&ap_dev->lock); 758 spin_lock_init(&ap_dev->lock);
767 INIT_LIST_HEAD(&ap_dev->pendingq); 759 INIT_LIST_HEAD(&ap_dev->pendingq);
768 INIT_LIST_HEAD(&ap_dev->requestq); 760 INIT_LIST_HEAD(&ap_dev->requestq);
@@ -784,7 +776,12 @@ static void ap_scan_bus(void *data)
784 /* Add device attributes. */ 776 /* Add device attributes. */
785 rc = sysfs_create_group(&ap_dev->device.kobj, 777 rc = sysfs_create_group(&ap_dev->device.kobj,
786 &ap_dev_attr_group); 778 &ap_dev_attr_group);
787 if (rc) 779 if (!rc) {
780 spin_lock_bh(&ap_dev->lock);
781 ap_dev->unregistered = 0;
782 spin_unlock_bh(&ap_dev->lock);
783 }
784 else
788 device_unregister(&ap_dev->device); 785 device_unregister(&ap_dev->device);
789 } 786 }
790} 787}
@@ -970,6 +967,8 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
970 rc = __ap_queue_message(ap_dev, ap_msg); 967 rc = __ap_queue_message(ap_dev, ap_msg);
971 if (!rc) 968 if (!rc)
972 wake_up(&ap_poll_wait); 969 wake_up(&ap_poll_wait);
970 if (rc == -ENODEV)
971 ap_dev->unregistered = 1;
973 } else { 972 } else {
974 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); 973 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
975 rc = 0; 974 rc = 0;
@@ -1028,6 +1027,8 @@ static int __ap_poll_all(struct device *dev, void *data)
1028 spin_lock(&ap_dev->lock); 1027 spin_lock(&ap_dev->lock);
1029 if (!ap_dev->unregistered) { 1028 if (!ap_dev->unregistered) {
1030 rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data); 1029 rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data);
1030 if (rc)
1031 ap_dev->unregistered = 1;
1031 } else 1032 } else
1032 rc = 0; 1033 rc = 0;
1033 spin_unlock(&ap_dev->lock); 1034 spin_unlock(&ap_dev->lock);