patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / s390 / cio / airq.c
index 71c03c8..3720e77 100644 (file)
@@ -2,7 +2,7 @@
  *  drivers/s390/cio/airq.c
  *   S/390 common I/O routines -- support for adapter interruptions
  *
- *   $Revision: 1.11 $
+ *   $Revision: 1.12 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *                           IBM Corporation
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 
 #include "cio_debug.h"
 #include "airq.h"
 
-static spinlock_t adapter_lock = SPIN_LOCK_UNLOCKED;
 static adapter_int_handler_t adapter_handler;
 
 /*
@@ -40,23 +40,17 @@ s390_register_adapter_interrupt (adapter_int_handler_t handler)
 
        CIO_TRACE_EVENT (4, "rgaint");
 
-       spin_lock (&adapter_lock);
-
        if (handler == NULL)
                ret = -EINVAL;
-       else if (adapter_handler)
-               ret = -EBUSY;
-       else {
-               adapter_handler = handler;
-               ret = 0;
-       }
-
-       spin_unlock (&adapter_lock);
+       else
+               ret = (cmpxchg(&adapter_handler, NULL, handler) ? -EBUSY : 0);
+       if (!ret)
+               synchronize_kernel();
 
        sprintf (dbf_txt, "ret:%d", ret);
        CIO_TRACE_EVENT (4, dbf_txt);
 
-       return (ret);
+       return ret;
 }
 
 int
@@ -67,38 +61,26 @@ s390_unregister_adapter_interrupt (adapter_int_handler_t handler)
 
        CIO_TRACE_EVENT (4, "urgaint");
 
-       spin_lock (&adapter_lock);
-
        if (handler == NULL)
                ret = -EINVAL;
-       else if (handler != adapter_handler)
-               ret = -EINVAL;
        else {
                adapter_handler = NULL;
+               synchronize_kernel();
                ret = 0;
        }
-
-       spin_unlock (&adapter_lock);
-
        sprintf (dbf_txt, "ret:%d", ret);
        CIO_TRACE_EVENT (4, dbf_txt);
 
-       return (ret);
+       return ret;
 }
 
 void
 do_adapter_IO (void)
 {
-       CIO_TRACE_EVENT (4, "doaio");
-
-       spin_lock (&adapter_lock);
+       CIO_TRACE_EVENT (6, "doaio");
 
        if (adapter_handler)
                (*adapter_handler) ();
-
-       spin_unlock (&adapter_lock);
-
-       return;
 }
 
 EXPORT_SYMBOL (s390_register_adapter_interrupt);