diff options
Diffstat (limited to 'kernel/padata.c')
-rw-r--r-- | kernel/padata.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/kernel/padata.c b/kernel/padata.c index 58728cd7f40c..9a17922ec436 100644 --- a/kernel/padata.c +++ b/kernel/padata.c | |||
@@ -94,17 +94,19 @@ static void padata_parallel_worker(struct work_struct *parallel_work) | |||
94 | * | 94 | * |
95 | * @pinst: padata instance | 95 | * @pinst: padata instance |
96 | * @padata: object to be parallelized | 96 | * @padata: object to be parallelized |
97 | * @cb_cpu: cpu the serialization callback function will run on, | 97 | * @cb_cpu: pointer to the CPU that the serialization callback function should |
98 | * must be in the serial cpumask of padata(i.e. cpumask.cbcpu). | 98 | * run on. If it's not in the serial cpumask of @pinst |
99 | * (i.e. cpumask.cbcpu), this function selects a fallback CPU and if | ||
100 | * none found, returns -EINVAL. | ||
99 | * | 101 | * |
100 | * The parallelization callback function will run with BHs off. | 102 | * The parallelization callback function will run with BHs off. |
101 | * Note: Every object which is parallelized by padata_do_parallel | 103 | * Note: Every object which is parallelized by padata_do_parallel |
102 | * must be seen by padata_do_serial. | 104 | * must be seen by padata_do_serial. |
103 | */ | 105 | */ |
104 | int padata_do_parallel(struct padata_instance *pinst, | 106 | int padata_do_parallel(struct padata_instance *pinst, |
105 | struct padata_priv *padata, int cb_cpu) | 107 | struct padata_priv *padata, int *cb_cpu) |
106 | { | 108 | { |
107 | int target_cpu, err; | 109 | int i, cpu, cpu_index, target_cpu, err; |
108 | struct padata_parallel_queue *queue; | 110 | struct padata_parallel_queue *queue; |
109 | struct parallel_data *pd; | 111 | struct parallel_data *pd; |
110 | 112 | ||
@@ -116,8 +118,19 @@ int padata_do_parallel(struct padata_instance *pinst, | |||
116 | if (!(pinst->flags & PADATA_INIT) || pinst->flags & PADATA_INVALID) | 118 | if (!(pinst->flags & PADATA_INIT) || pinst->flags & PADATA_INVALID) |
117 | goto out; | 119 | goto out; |
118 | 120 | ||
119 | if (!cpumask_test_cpu(cb_cpu, pd->cpumask.cbcpu)) | 121 | if (!cpumask_test_cpu(*cb_cpu, pd->cpumask.cbcpu)) { |
120 | goto out; | 122 | if (!cpumask_weight(pd->cpumask.cbcpu)) |
123 | goto out; | ||
124 | |||
125 | /* Select an alternate fallback CPU and notify the caller. */ | ||
126 | cpu_index = *cb_cpu % cpumask_weight(pd->cpumask.cbcpu); | ||
127 | |||
128 | cpu = cpumask_first(pd->cpumask.cbcpu); | ||
129 | for (i = 0; i < cpu_index; i++) | ||
130 | cpu = cpumask_next(cpu, pd->cpumask.cbcpu); | ||
131 | |||
132 | *cb_cpu = cpu; | ||
133 | } | ||
121 | 134 | ||
122 | err = -EBUSY; | 135 | err = -EBUSY; |
123 | if ((pinst->flags & PADATA_RESET)) | 136 | if ((pinst->flags & PADATA_RESET)) |
@@ -129,7 +142,7 @@ int padata_do_parallel(struct padata_instance *pinst, | |||
129 | err = 0; | 142 | err = 0; |
130 | atomic_inc(&pd->refcnt); | 143 | atomic_inc(&pd->refcnt); |
131 | padata->pd = pd; | 144 | padata->pd = pd; |
132 | padata->cb_cpu = cb_cpu; | 145 | padata->cb_cpu = *cb_cpu; |
133 | 146 | ||
134 | target_cpu = padata_cpu_hash(pd); | 147 | target_cpu = padata_cpu_hash(pd); |
135 | padata->cpu = target_cpu; | 148 | padata->cpu = target_cpu; |