Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-drm-fsl-dcu.git] / kernel / sys.c
index c7675c1bfdf24e8c9d45b22e67da5c5679ba662b..e1024383314de0428e4739e0f9c782330ecd63d5 100644 (file)
@@ -215,7 +215,7 @@ EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
  *     This routine uses RCU to synchronize with changes to the chain.
  *
  *     If the return value of the notifier can be and'ed
- *     with %NOTIFY_STOP_MASK then atomic_notifier_call_chain
+ *     with %NOTIFY_STOP_MASK then atomic_notifier_call_chain()
  *     will return immediately, with the return value of
  *     the notifier function which halted execution.
  *     Otherwise the return value is the return value
@@ -313,7 +313,7 @@ EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
  *     run in a process context, so they are allowed to block.
  *
  *     If the return value of the notifier can be and'ed
- *     with %NOTIFY_STOP_MASK then blocking_notifier_call_chain
+ *     with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
  *     will return immediately, with the return value of
  *     the notifier function which halted execution.
  *     Otherwise the return value is the return value
@@ -323,11 +323,18 @@ EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
 int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
                unsigned long val, void *v)
 {
-       int ret;
+       int ret = NOTIFY_DONE;
 
-       down_read(&nh->rwsem);
-       ret = notifier_call_chain(&nh->head, val, v);
-       up_read(&nh->rwsem);
+       /*
+        * We check the head outside the lock, but if this access is
+        * racy then it does not matter what the result of the test
+        * is, we re-check the list after having taken the lock anyway:
+        */
+       if (rcu_dereference(nh->head)) {
+               down_read(&nh->rwsem);
+               ret = notifier_call_chain(&nh->head, val, v);
+               up_read(&nh->rwsem);
+       }
        return ret;
 }
 
@@ -386,7 +393,7 @@ EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
  *     All locking must be provided by the caller.
  *
  *     If the return value of the notifier can be and'ed
- *     with %NOTIFY_STOP_MASK then raw_notifier_call_chain
+ *     with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
  *     will return immediately, with the return value of
  *     the notifier function which halted execution.
  *     Otherwise the return value is the return value
@@ -480,7 +487,7 @@ EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
  *     run in a process context, so they are allowed to block.
  *
  *     If the return value of the notifier can be and'ed
- *     with %NOTIFY_STOP_MASK then srcu_notifier_call_chain
+ *     with %NOTIFY_STOP_MASK then srcu_notifier_call_chain()
  *     will return immediately, with the return value of
  *     the notifier function which halted execution.
  *     Otherwise the return value is the return value
@@ -531,7 +538,7 @@ EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
  *     Registers a function with the list of functions
  *     to be called at reboot time.
  *
- *     Currently always returns zero, as blocking_notifier_chain_register
+ *     Currently always returns zero, as blocking_notifier_chain_register()
  *     always returns zero.
  */