Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=c6a48264739e3486f66e5b21a543c9573b713621
Commit:     c6a48264739e3486f66e5b21a543c9573b713621
Parent:     25c61a1fe8c97d1352a2dc0eda25128b3be0db27
Author:     Ralph Wuerthner <[EMAIL PROTECTED]>
AuthorDate: Mon Mar 26 20:42:42 2007 +0200
Committer:  Heiko Carstens <[EMAIL PROTECTED]>
CommitDate: Mon Mar 26 20:43:47 2007 +0200

    [S390] zcrypt: Fix possible dead lock in AP bus module.
    
    If a AP device is unconfigured __ap_poll_all() will call
    device_unregister() in software interrupt context which can cause
    dead locks. To fix this the device will be only marked as unconfigured
    and the device_unregister() call will be done later by either
    ap_scan_bus() or ap_queue_message() in process context.
    
    Cc: Martin Schwidefsky <[EMAIL PROTECTED]>
    Signed-off-by: Ralph Wuerthner <[EMAIL PROTECTED]>
    Signed-off-by: Heiko Carstens <[EMAIL PROTECTED]>
---
 drivers/s390/crypto/ap_bus.c |   26 +++++++++++++-------------
 1 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 181b517..a817dad 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -757,10 +757,16 @@ static void ap_scan_bus(struct work_struct *unused)
                                      (void *)(unsigned long)qid,
                                      __ap_scan_bus);
                rc = ap_query_queue(qid, &queue_depth, &device_type);
-               if (dev && rc) {
-                       put_device(dev);
-                       device_unregister(dev);
-                       continue;
+               if (dev) {
+                       ap_dev = to_ap_dev(dev);
+                       spin_lock_bh(&ap_dev->lock);
+                       if (rc || ap_dev->unregistered) {
+                               spin_unlock_bh(&ap_dev->lock);
+                               put_device(dev);
+                               device_unregister(dev);
+                               continue;
+                       } else
+                               spin_unlock_bh(&ap_dev->lock);
                }
                if (dev) {
                        put_device(dev);
@@ -994,7 +1000,7 @@ void ap_queue_message(struct ap_device *ap_dev, struct 
ap_message *ap_msg)
                        ap_dev->unregistered = 1;
        } else {
                ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
-               rc = 0;
+               rc = -ENODEV;
        }
        spin_unlock_bh(&ap_dev->lock);
        if (rc == -ENODEV)
@@ -1044,18 +1050,12 @@ static void ap_poll_timeout(unsigned long unused)
  */
 static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
 {
-       int rc;
-
        spin_lock(&ap_dev->lock);
        if (!ap_dev->unregistered) {
-               rc = ap_poll_queue(ap_dev, flags);
-               if (rc)
+               if (ap_poll_queue(ap_dev, flags))
                        ap_dev->unregistered = 1;
-       } else
-               rc = 0;
+       }
        spin_unlock(&ap_dev->lock);
-       if (rc)
-               device_unregister(&ap_dev->device);
        return 0;
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to