Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f05c315 authored by Se Wang (Patrick) Oh's avatar Se Wang (Patrick) Oh
Browse files

workqueue: Fix workqueue stall issue after cpu down failure



When the hotplug notifier call chain with CPU_DOWN_PREPARE
is broken before reaching workqueue_cpu_down_callback(),
rebind_workers() adds WORKER_REBOUND flag for running workers.
Hence, the nr_running of the pool is not increased when scheduler
wakes up the worker. The fix is skipping adding WORKER_REBOUND
flag when the worker doesn't have WORKER_UNBOUND flag in
CPU_DOWN_FAILED path.

Change-Id: I2528e9154f4913d9ec14b63adbcbcd1eaa8a8452
Signed-off-by: default avatarSe Wang (Patrick) Oh <sewango@codeaurora.org>
parent 75d530af
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -4494,10 +4494,13 @@ static void wq_unbind_fn(struct work_struct *work)
/**
 * rebind_workers - rebind all workers of a pool to the associated CPU
 * @pool: pool of interest
 * @force: if it is true, replace WORKER_UNBOUND with WORKER_REBOUND
 * irrespective of flags of workers. Otherwise, replace the flags only
 * when workers have WORKER_UNBOUND flag.
 *
 * @pool->cpu is coming online.  Rebind all workers to the CPU.
 */
static void rebind_workers(struct worker_pool *pool)
static void rebind_workers(struct worker_pool *pool, bool force)
{
	struct worker *worker;

@@ -4546,11 +4549,13 @@ static void rebind_workers(struct worker_pool *pool)
		 * fail incorrectly leading to premature concurrency
		 * management operations.
		 */
		if (force || (worker_flags & WORKER_UNBOUND)) {
			WARN_ON_ONCE(!(worker_flags & WORKER_UNBOUND));
			worker_flags |= WORKER_REBOUND;
			worker_flags &= ~WORKER_UNBOUND;
			ACCESS_ONCE(worker->flags) = worker_flags;
		}
	}

	spin_unlock_irq(&pool->lock);
}
@@ -4618,7 +4623,9 @@ static int workqueue_cpu_up_callback(struct notifier_block *nfb,
			mutex_lock(&pool->attach_mutex);

			if (pool->cpu == cpu)
				rebind_workers(pool);
				rebind_workers(pool,
					(action & ~CPU_TASKS_FROZEN)
						!= CPU_DOWN_FAILED);
			else if (pool->cpu < 0)
				restore_unbound_workers_cpumask(pool, cpu);