rk3228: add dts file for sdk
[firefly-linux-kernel-4.4.55.git] / lib / rwsem-spinlock.c
index 7542afbb22b368c9c693408b9233421b6a89746b..9be8a9144978685b4c7eae4762d559f9896675a4 100644 (file)
@@ -9,12 +9,15 @@
 #include <linux/sched.h>
 #include <linux/export.h>
 
+enum rwsem_waiter_type {
+       RWSEM_WAITING_FOR_WRITE,
+       RWSEM_WAITING_FOR_READ
+};
+
 struct rwsem_waiter {
        struct list_head list;
        struct task_struct *task;
-       unsigned int flags;
-#define RWSEM_WAITING_FOR_READ 0x00000001
-#define RWSEM_WAITING_FOR_WRITE        0x00000002
+       enum rwsem_waiter_type type;
 };
 
 int rwsem_is_locked(struct rw_semaphore *sem)
@@ -67,26 +70,17 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
 
        waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
 
-       if (!wakewrite) {
-               if (waiter->flags & RWSEM_WAITING_FOR_WRITE)
-                       goto out;
-               goto dont_wake_writers;
-       }
-
-       /*
-        * as we support write lock stealing, we can't set sem->activity
-        * to -1 here to indicate we get the lock. Instead, we wake it up
-        * to let it go get it again.
-        */
-       if (waiter->flags & RWSEM_WAITING_FOR_WRITE) {
-               wake_up_process(waiter->task);
+       if (waiter->type == RWSEM_WAITING_FOR_WRITE) {
+               if (wakewrite)
+                       /* Wake up a writer. Note that we do not grant it the
+                        * lock - it will have to acquire it when it runs. */
+                       wake_up_process(waiter->task);
                goto out;
        }
 
        /* grant an infinite number of read locks to the front of the queue */
- dont_wake_writers:
        woken = 0;
-       while (waiter->flags & RWSEM_WAITING_FOR_READ) {
+       do {
                struct list_head *next = waiter->list.next;
 
                list_del(&waiter->list);
@@ -96,10 +90,10 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
                wake_up_process(tsk);
                put_task_struct(tsk);
                woken++;
-               if (list_empty(&sem->wait_list))
+               if (next == &sem->wait_list)
                        break;
                waiter = list_entry(next, struct rwsem_waiter, list);
-       }
+       } while (waiter->type != RWSEM_WAITING_FOR_WRITE);
 
        sem->activity += woken;
 
@@ -144,7 +138,7 @@ void __sched __down_read(struct rw_semaphore *sem)
 
        /* set up my own style of waitqueue */
        waiter.task = tsk;
-       waiter.flags = RWSEM_WAITING_FOR_READ;
+       waiter.type = RWSEM_WAITING_FOR_READ;
        get_task_struct(tsk);
 
        list_add_tail(&waiter.list, &sem->wait_list);
@@ -201,7 +195,7 @@ void __sched __down_write_nested(struct rw_semaphore *sem, int subclass)
        /* set up my own style of waitqueue */
        tsk = current;
        waiter.task = tsk;
-       waiter.flags = RWSEM_WAITING_FOR_WRITE;
+       waiter.type = RWSEM_WAITING_FOR_WRITE;
        list_add_tail(&waiter.list, &sem->wait_list);
 
        /* wait for someone to release the lock */