arm: dts: bcm2711-rpi-4-b: Adds respeaker 4mic nodes
[platform/kernel/linux-rpi.git] / kernel / workqueue.c
index 1b3eb1e..f5fa7be 100644 (file)
@@ -867,8 +867,17 @@ void wq_worker_running(struct task_struct *task)
 
        if (!worker->sleeping)
                return;
+
+       /*
+        * If preempted by unbind_workers() between the WORKER_NOT_RUNNING check
+        * and the nr_running increment below, we may ruin the nr_running reset
+        * and leave with an unexpected pool->nr_running == 1 on the newly unbound
+        * pool. Protect against such race.
+        */
+       preempt_disable();
        if (!(worker->flags & WORKER_NOT_RUNNING))
                atomic_inc(&worker->pool->nr_running);
+       preempt_enable();
        worker->sleeping = 0;
 }
 
@@ -3074,10 +3083,8 @@ static bool __flush_work(struct work_struct *work, bool from_cancel)
        if (WARN_ON(!work->func))
                return false;
 
-       if (!from_cancel) {
-               lock_map_acquire(&work->lockdep_map);
-               lock_map_release(&work->lockdep_map);
-       }
+       lock_map_acquire(&work->lockdep_map);
+       lock_map_release(&work->lockdep_map);
 
        if (start_flush_work(work, &barr, from_cancel)) {
                wait_for_completion(&barr.done);
@@ -5384,9 +5391,6 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask)
        int ret = -EINVAL;
        cpumask_var_t saved_cpumask;
 
-       if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL))
-               return -ENOMEM;
-
        /*
         * Not excluding isolated cpus on purpose.
         * If the user wishes to include them, we allow that.
@@ -5394,6 +5398,15 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask)
        cpumask_and(cpumask, cpumask, cpu_possible_mask);
        if (!cpumask_empty(cpumask)) {
                apply_wqattrs_lock();
+               if (cpumask_equal(cpumask, wq_unbound_cpumask)) {
+                       ret = 0;
+                       goto out_unlock;
+               }
+
+               if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL)) {
+                       ret = -ENOMEM;
+                       goto out_unlock;
+               }
 
                /* save the old wq_unbound_cpumask. */
                cpumask_copy(saved_cpumask, wq_unbound_cpumask);
@@ -5406,10 +5419,11 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask)
                if (ret < 0)
                        cpumask_copy(wq_unbound_cpumask, saved_cpumask);
 
+               free_cpumask_var(saved_cpumask);
+out_unlock:
                apply_wqattrs_unlock();
        }
 
-       free_cpumask_var(saved_cpumask);
        return ret;
 }