aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/irq/manage.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index e3336d904f64..facfecfc543c 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -204,6 +204,39 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
204 return ret; 204 return ret;
205} 205}
206 206
207#ifdef CONFIG_GENERIC_PENDING_IRQ
208static inline int irq_set_affinity_pending(struct irq_data *data,
209 const struct cpumask *dest)
210{
211 struct irq_desc *desc = irq_data_to_desc(data);
212
213 irqd_set_move_pending(data);
214 irq_copy_pending(desc, dest);
215 return 0;
216}
217#else
218static inline int irq_set_affinity_pending(struct irq_data *data,
219 const struct cpumask *dest)
220{
221 return -EBUSY;
222}
223#endif
224
225static int irq_try_set_affinity(struct irq_data *data,
226 const struct cpumask *dest, bool force)
227{
228 int ret = irq_do_set_affinity(data, dest, force);
229
230 /*
231 * In case that the underlying vector management is busy and the
232 * architecture supports the generic pending mechanism then utilize
233 * this to avoid returning an error to user space.
234 */
235 if (ret == -EBUSY && !force)
236 ret = irq_set_affinity_pending(data, dest);
237 return ret;
238}
239
207int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask, 240int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
208 bool force) 241 bool force)
209{ 242{
@@ -214,8 +247,8 @@ int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
214 if (!chip || !chip->irq_set_affinity) 247 if (!chip || !chip->irq_set_affinity)
215 return -EINVAL; 248 return -EINVAL;
216 249
217 if (irq_can_move_pcntxt(data)) { 250 if (irq_can_move_pcntxt(data) && !irqd_is_setaffinity_pending(data)) {
218 ret = irq_do_set_affinity(data, mask, force); 251 ret = irq_try_set_affinity(data, mask, force);
219 } else { 252 } else {
220 irqd_set_move_pending(data); 253 irqd_set_move_pending(data);
221 irq_copy_pending(desc, mask); 254 irq_copy_pending(desc, mask);