Linux 6.9-rc1
[linux-2.6-microblaze.git] / kernel / padata.c
index e5819bb..e3f639f 100644 (file)
@@ -83,8 +83,16 @@ static struct padata_work *padata_work_alloc(void)
        return pw;
 }
 
-static void padata_work_init(struct padata_work *pw, work_func_t work_fn,
-                            void *data, int flags)
+/*
+ * This function is marked __ref because this function may be optimized in such
+ * a way that it directly refers to work_fn's address, which causes modpost to
+ * complain when work_fn is marked __init. This scenario was observed with clang
+ * LTO, where padata_work_init() was optimized to refer directly to
+ * padata_mt_helper() because the calls to padata_work_init() with other work_fn
+ * values were eliminated or inlined.
+ */
+static void __ref padata_work_init(struct padata_work *pw, work_func_t work_fn,
+                                  void *data, int flags)
 {
        if (flags & PADATA_WORK_ONSTACK)
                INIT_WORK_ONSTACK(&pw->pw_work, work_fn);
@@ -194,7 +202,7 @@ int padata_do_parallel(struct padata_shell *ps,
                *cb_cpu = cpu;
        }
 
-       err =  -EBUSY;
+       err = -EBUSY;
        if ((pinst->flags & PADATA_RESET))
                goto out;
 
@@ -207,14 +215,16 @@ int padata_do_parallel(struct padata_shell *ps,
        pw = padata_work_alloc();
        spin_unlock(&padata_works_lock);
 
+       if (!pw) {
+               /* Maximum works limit exceeded, run in the current task. */
+               padata->parallel(padata);
+       }
+
        rcu_read_unlock_bh();
 
        if (pw) {
                padata_work_init(pw, padata_parallel_worker, padata, 0);
                queue_work(pinst->parallel_wq, &pw->pw_work);
-       } else {
-               /* Maximum works limit exceeded, run in the current task. */
-               padata->parallel(padata);
        }
 
        return 0;
@@ -388,13 +398,16 @@ void padata_do_serial(struct padata_priv *padata)
        int hashed_cpu = padata_cpu_hash(pd, padata->seq_nr);
        struct padata_list *reorder = per_cpu_ptr(pd->reorder_list, hashed_cpu);
        struct padata_priv *cur;
+       struct list_head *pos;
 
        spin_lock(&reorder->lock);
        /* Sort in ascending order of sequence number. */
-       list_for_each_entry_reverse(cur, &reorder->list, list)
+       list_for_each_prev(pos, &reorder->list) {
+               cur = list_entry(pos, struct padata_priv, list);
                if (cur->seq_nr < padata->seq_nr)
                        break;
-       list_add(&padata->list, &cur->list);
+       }
+       list_add(&padata->list, pos);
        spin_unlock(&reorder->lock);
 
        /*
@@ -472,13 +485,14 @@ void __init padata_do_multithreaded(struct padata_mt_job *job)
        struct padata_work my_work, *pw;
        struct padata_mt_job_state ps;
        LIST_HEAD(works);
-       int nworks;
+       int nworks, nid;
+       static atomic_t last_used_nid __initdata;
 
        if (job->size == 0)
                return;
 
        /* Ensure at least one thread when size < min_chunk. */
-       nworks = max(job->size / job->min_chunk, 1ul);
+       nworks = max(job->size / max(job->min_chunk, job->align), 1ul);
        nworks = min(nworks, job->max_threads);
 
        if (nworks == 1) {
@@ -504,7 +518,16 @@ void __init padata_do_multithreaded(struct padata_mt_job *job)
        ps.chunk_size = roundup(ps.chunk_size, job->align);
 
        list_for_each_entry(pw, &works, pw_list)
-               queue_work(system_unbound_wq, &pw->pw_work);
+               if (job->numa_aware) {
+                       int old_node = atomic_read(&last_used_nid);
+
+                       do {
+                               nid = next_node_in(old_node, node_states[N_CPU]);
+                       } while (!atomic_try_cmpxchg(&last_used_nid, &old_node, nid));
+                       queue_work_node(nid, system_unbound_wq, &pw->pw_work);
+               } else {
+                       queue_work(system_unbound_wq, &pw->pw_work);
+               }
 
        /* Use the current thread, which saves starting a workqueue worker. */
        padata_work_init(&my_work, padata_mt_helper, &ps, PADATA_WORK_ONSTACK);
@@ -954,7 +977,7 @@ static const struct sysfs_ops padata_sysfs_ops = {
        .store = padata_sysfs_store,
 };
 
-static struct kobj_type padata_attr_type = {
+static const struct kobj_type padata_attr_type = {
        .sysfs_ops = &padata_sysfs_ops,
        .default_groups = padata_default_groups,
        .release = padata_sysfs_release,
@@ -1089,12 +1112,16 @@ EXPORT_SYMBOL(padata_alloc_shell);
  */
 void padata_free_shell(struct padata_shell *ps)
 {
+       struct parallel_data *pd;
+
        if (!ps)
                return;
 
        mutex_lock(&ps->pinst->lock);
        list_del(&ps->list);
-       padata_free_pd(rcu_dereference_protected(ps->pd, 1));
+       pd = rcu_dereference_protected(ps->pd, 1);
+       if (refcount_dec_and_test(&pd->refcnt))
+               padata_free_pd(pd);
        mutex_unlock(&ps->pinst->lock);
 
        kfree(ps);