From: Julia Cartwright <ju...@ni.com>

commit 5c8919eed1cfcad5da452047bd4ab088837afc41 in linux-rt-devel.

In order to enable the queuing of kthread work items from hardirq
context even when PREEMPT_RT_FULL is enabled, convert the worker
spin_lock to a raw_spin_lock.

This is only acceptable to do because the work performed under the lock
is well-bounded and minimal.

Cc: Sebastian Andrzej Siewior <bige...@linutronix.de>
Cc: Guenter Roeck <li...@roeck-us.net>
Reported-and-tested-by: Steffen Trumtrar <s.trumt...@pengutronix.de>
Reported-by: Tim Sander <t...@krieglstein.org>
Signed-off-by: Julia Cartwright <ju...@ni.com>
Signed-off-by: Sebastian Andrzej Siewior <bige...@linutronix.de>
Signed-off-by: Paul Gortmaker <paul.gortma...@windriver.com>
---
 include/linux/kthread.h |  2 +-
 kernel/kthread.c        | 42 +++++++++++++++++++++---------------------
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index c1961761311d..ad292898f7f2 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -85,7 +85,7 @@ enum {
 
 struct kthread_worker {
        unsigned int            flags;
-       spinlock_t              lock;
+       raw_spinlock_t          lock;
        struct list_head        work_list;
        struct list_head        delayed_work_list;
        struct task_struct      *task;
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 486dedbd9af5..c1d9ee6671c6 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -597,7 +597,7 @@ void __kthread_init_worker(struct kthread_worker *worker,
                                struct lock_class_key *key)
 {
        memset(worker, 0, sizeof(struct kthread_worker));
-       spin_lock_init(&worker->lock);
+       raw_spin_lock_init(&worker->lock);
        lockdep_set_class_and_name(&worker->lock, key, name);
        INIT_LIST_HEAD(&worker->work_list);
        INIT_LIST_HEAD(&worker->delayed_work_list);
@@ -639,21 +639,21 @@ int kthread_worker_fn(void *worker_ptr)
 
        if (kthread_should_stop()) {
                __set_current_state(TASK_RUNNING);
-               spin_lock_irq(&worker->lock);
+               raw_spin_lock_irq(&worker->lock);
                worker->task = NULL;
-               spin_unlock_irq(&worker->lock);
+               raw_spin_unlock_irq(&worker->lock);
                return 0;
        }
 
        work = NULL;
-       spin_lock_irq(&worker->lock);
+       raw_spin_lock_irq(&worker->lock);
        if (!list_empty(&worker->work_list)) {
                work = list_first_entry(&worker->work_list,
                                        struct kthread_work, node);
                list_del_init(&work->node);
        }
        worker->current_work = work;
-       spin_unlock_irq(&worker->lock);
+       raw_spin_unlock_irq(&worker->lock);
 
        if (work) {
                __set_current_state(TASK_RUNNING);
@@ -810,12 +810,12 @@ bool kthread_queue_work(struct kthread_worker *worker,
        bool ret = false;
        unsigned long flags;
 
-       spin_lock_irqsave(&worker->lock, flags);
+       raw_spin_lock_irqsave(&worker->lock, flags);
        if (!queuing_blocked(worker, work)) {
                kthread_insert_work(worker, work, &worker->work_list);
                ret = true;
        }
-       spin_unlock_irqrestore(&worker->lock, flags);
+       raw_spin_unlock_irqrestore(&worker->lock, flags);
        return ret;
 }
 EXPORT_SYMBOL_GPL(kthread_queue_work);
@@ -841,7 +841,7 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
        if (WARN_ON_ONCE(!worker))
                return;
 
-       spin_lock(&worker->lock);
+       raw_spin_lock(&worker->lock);
        /* Work must not be used with >1 worker, see kthread_queue_work(). */
        WARN_ON_ONCE(work->worker != worker);
 
@@ -850,7 +850,7 @@ void kthread_delayed_work_timer_fn(struct timer_list *t)
        list_del_init(&work->node);
        kthread_insert_work(worker, work, &worker->work_list);
 
-       spin_unlock(&worker->lock);
+       raw_spin_unlock(&worker->lock);
 }
 EXPORT_SYMBOL(kthread_delayed_work_timer_fn);
 
@@ -906,14 +906,14 @@ bool kthread_queue_delayed_work(struct kthread_worker 
*worker,
        unsigned long flags;
        bool ret = false;
 
-       spin_lock_irqsave(&worker->lock, flags);
+       raw_spin_lock_irqsave(&worker->lock, flags);
 
        if (!queuing_blocked(worker, work)) {
                __kthread_queue_delayed_work(worker, dwork, delay);
                ret = true;
        }
 
-       spin_unlock_irqrestore(&worker->lock, flags);
+       raw_spin_unlock_irqrestore(&worker->lock, flags);
        return ret;
 }
 EXPORT_SYMBOL_GPL(kthread_queue_delayed_work);
@@ -949,7 +949,7 @@ void kthread_flush_work(struct kthread_work *work)
        if (!worker)
                return;
 
-       spin_lock_irq(&worker->lock);
+       raw_spin_lock_irq(&worker->lock);
        /* Work must not be used with >1 worker, see kthread_queue_work(). */
        WARN_ON_ONCE(work->worker != worker);
 
@@ -961,7 +961,7 @@ void kthread_flush_work(struct kthread_work *work)
        else
                noop = true;
 
-       spin_unlock_irq(&worker->lock);
+       raw_spin_unlock_irq(&worker->lock);
 
        if (!noop)
                wait_for_completion(&fwork.done);
@@ -994,9 +994,9 @@ static bool __kthread_cancel_work(struct kthread_work 
*work, bool is_dwork,
                 * any queuing is blocked by setting the canceling counter.
                 */
                work->canceling++;
-               spin_unlock_irqrestore(&worker->lock, *flags);
+               raw_spin_unlock_irqrestore(&worker->lock, *flags);
                del_timer_sync(&dwork->timer);
-               spin_lock_irqsave(&worker->lock, *flags);
+               raw_spin_lock_irqsave(&worker->lock, *flags);
                work->canceling--;
        }
 
@@ -1043,7 +1043,7 @@ bool kthread_mod_delayed_work(struct kthread_worker 
*worker,
        unsigned long flags;
        int ret = false;
 
-       spin_lock_irqsave(&worker->lock, flags);
+       raw_spin_lock_irqsave(&worker->lock, flags);
 
        /* Do not bother with canceling when never queued. */
        if (!work->worker)
@@ -1060,7 +1060,7 @@ bool kthread_mod_delayed_work(struct kthread_worker 
*worker,
 fast_queue:
        __kthread_queue_delayed_work(worker, dwork, delay);
 out:
-       spin_unlock_irqrestore(&worker->lock, flags);
+       raw_spin_unlock_irqrestore(&worker->lock, flags);
        return ret;
 }
 EXPORT_SYMBOL_GPL(kthread_mod_delayed_work);
@@ -1074,7 +1074,7 @@ static bool __kthread_cancel_work_sync(struct 
kthread_work *work, bool is_dwork)
        if (!worker)
                goto out;
 
-       spin_lock_irqsave(&worker->lock, flags);
+       raw_spin_lock_irqsave(&worker->lock, flags);
        /* Work must not be used with >1 worker, see kthread_queue_work(). */
        WARN_ON_ONCE(work->worker != worker);
 
@@ -1088,13 +1088,13 @@ static bool __kthread_cancel_work_sync(struct 
kthread_work *work, bool is_dwork)
         * In the meantime, block any queuing by setting the canceling counter.
         */
        work->canceling++;
-       spin_unlock_irqrestore(&worker->lock, flags);
+       raw_spin_unlock_irqrestore(&worker->lock, flags);
        kthread_flush_work(work);
-       spin_lock_irqsave(&worker->lock, flags);
+       raw_spin_lock_irqsave(&worker->lock, flags);
        work->canceling--;
 
 out_fast:
-       spin_unlock_irqrestore(&worker->lock, flags);
+       raw_spin_unlock_irqrestore(&worker->lock, flags);
 out:
        return ret;
 }
-- 
2.15.0

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to