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

Commit 2b73b07a authored by Steffen Klassert's avatar Steffen Klassert Committed by Herbert Xu
Browse files

padata: Flush the padata queues actively



yield was used to wait until all references of the internal control
structure in use are dropped before it is freed. This patch implements
padata_flush_queues which actively flushes the padata percpu queues
in this case.

Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent d46a5ac7
Loading
Loading
Loading
Loading
+25 −8
Original line number Diff line number Diff line
@@ -417,6 +417,29 @@ static void padata_free_pd(struct parallel_data *pd)
	kfree(pd);
}

static void padata_flush_queues(struct parallel_data *pd)
{
	int cpu;
	struct padata_queue *queue;

	for_each_cpu(cpu, pd->cpumask) {
		queue = per_cpu_ptr(pd->queue, cpu);
		flush_work(&queue->pwork);
	}

	del_timer_sync(&pd->timer);

	if (atomic_read(&pd->reorder_objects))
		padata_reorder(pd);

	for_each_cpu(cpu, pd->cpumask) {
		queue = per_cpu_ptr(pd->queue, cpu);
		flush_work(&queue->swork);
	}

	BUG_ON(atomic_read(&pd->refcnt) != 0);
}

static void padata_replace(struct padata_instance *pinst,
			   struct parallel_data *pd_new)
{
@@ -428,11 +451,7 @@ static void padata_replace(struct padata_instance *pinst,

	synchronize_rcu();

	while (atomic_read(&pd_old->refcnt) != 0)
		yield();

	flush_workqueue(pinst->wq);

	padata_flush_queues(pd_old);
	padata_free_pd(pd_old);

	pinst->flags &= ~PADATA_RESET;
@@ -695,12 +714,10 @@ void padata_free(struct padata_instance *pinst)

	synchronize_rcu();

	while (atomic_read(&pinst->pd->refcnt) != 0)
		yield();

#ifdef CONFIG_HOTPLUG_CPU
	unregister_hotcpu_notifier(&pinst->cpu_notifier);
#endif
	padata_flush_queues(pinst->pd);
	padata_free_pd(pinst->pd);
	free_cpumask_var(pinst->cpumask);
	kfree(pinst);