phy: rockchip-inno-mipi-dphy: export PLL clock
[firefly-linux-kernel-4.4.55.git] / kernel / kthread.c
index 9ff173dca1aef5e09fd640dc6757fee99c7a956c..698b8dec30741ca633435b4659b39d5c6aab50e4 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/freezer.h>
 #include <linux/ptrace.h>
 #include <linux/uaccess.h>
+#include <linux/cgroup.h>
 #include <trace/events/sched.h>
 
 static DEFINE_SPINLOCK(kthread_create_lock);
@@ -205,6 +206,7 @@ static int kthread(void *_create)
        ret = -EINTR;
 
        if (!test_bit(KTHREAD_SHOULD_STOP, &self.flags)) {
+               cgroup_kthread_ready();
                __kthread_parkme(&self);
                ret = threadfn(data);
        }
@@ -510,6 +512,7 @@ int kthreadd(void *unused)
        set_mems_allowed(node_states[N_MEMORY]);
 
        current->flags |= PF_NOFREEZE;
+       cgroup_init_kthreadd();
 
        for (;;) {
                set_current_state(TASK_INTERRUPTIBLE);
@@ -601,6 +604,19 @@ repeat:
 }
 EXPORT_SYMBOL_GPL(kthread_worker_fn);
 
+/*
+ * Returns true when the work could not be queued at the moment.
+ * It happens when it is already pending in a worker list
+ * or when it is being cancelled.
+ */
+static inline bool queuing_blocked(struct kthread_worker *worker,
+                                  struct kthread_work *work)
+{
+       lockdep_assert_held(&worker->lock);
+
+       return !list_empty(&work->node) || work->canceling;
+}
+
 /* insert @work before @pos in @worker */
 static void insert_kthread_work(struct kthread_worker *worker,
                               struct kthread_work *work,
@@ -630,7 +646,7 @@ bool queue_kthread_work(struct kthread_worker *worker,
        unsigned long flags;
 
        spin_lock_irqsave(&worker->lock, flags);
-       if (list_empty(&work->node)) {
+       if (!queuing_blocked(worker, work)) {
                insert_kthread_work(worker, work, &worker->work_list);
                ret = true;
        }
@@ -691,6 +707,87 @@ retry:
 }
 EXPORT_SYMBOL_GPL(flush_kthread_work);
 
+/*
+ * This function removes the work from the worker queue. Also it makes sure
+ * that it won't get queued later via the delayed work's timer.
+ *
+ * The work might still be in use when this function finishes. See the
+ * current_work proceed by the worker.
+ *
+ * Return: %true if @work was pending and successfully canceled,
+ *     %false if @work was not pending
+ */
+static bool __kthread_cancel_work(struct kthread_work *work,
+                                 unsigned long *flags)
+{
+       /*
+        * Try to remove the work from a worker list. It might either
+        * be from worker->work_list or from worker->delayed_work_list.
+        */
+       if (!list_empty(&work->node)) {
+               list_del_init(&work->node);
+               return true;
+       }
+
+       return false;
+}
+
+static bool __kthread_cancel_work_sync(struct kthread_work *work)
+{
+       struct kthread_worker *worker = work->worker;
+       unsigned long flags;
+       int ret = false;
+
+       if (!worker)
+               goto out;
+
+       spin_lock_irqsave(&worker->lock, flags);
+       /* Work must not be used with >1 worker, see kthread_queue_work(). */
+       WARN_ON_ONCE(work->worker != worker);
+
+       ret = __kthread_cancel_work(work, &flags);
+
+       if (worker->current_work != work)
+               goto out_fast;
+
+       /*
+        * The work is in progress and we need to wait with the lock released.
+        * In the meantime, block any queuing by setting the canceling counter.
+        */
+       work->canceling++;
+       spin_unlock_irqrestore(&worker->lock, flags);
+       flush_kthread_work(work);
+       spin_lock_irqsave(&worker->lock, flags);
+       work->canceling--;
+
+out_fast:
+       spin_unlock_irqrestore(&worker->lock, flags);
+out:
+       return ret;
+}
+
+/**
+ * kthread_cancel_work_sync - cancel a kthread work and wait for it to finish
+ * @work: the kthread work to cancel
+ *
+ * Cancel @work and wait for its execution to finish.  This function
+ * can be used even if the work re-queues itself. On return from this
+ * function, @work is guaranteed to be not pending or executing on any CPU.
+ *
+ * kthread_cancel_work_sync(&delayed_work->work) must not be used for
+ * delayed_work's. Use kthread_cancel_delayed_work_sync() instead.
+ *
+ * The caller must ensure that the worker on which @work was last
+ * queued can't be destroyed before this function returns.
+ *
+ * Return: %true if @work was pending, %false otherwise.
+ */
+bool kthread_cancel_work_sync(struct kthread_work *work)
+{
+       return __kthread_cancel_work_sync(work);
+}
+EXPORT_SYMBOL_GPL(kthread_cancel_work_sync);
+
 /**
  * flush_kthread_worker - flush all current works on a kthread_worker
  * @worker: worker to flush