diff options
| -rw-r--r-- | kernel/irq/manage.c | 37 |
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 | ||
| 208 | static 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 | ||
| 218 | static inline int irq_set_affinity_pending(struct irq_data *data, | ||
| 219 | const struct cpumask *dest) | ||
| 220 | { | ||
| 221 | return -EBUSY; | ||
| 222 | } | ||
| 223 | #endif | ||
| 224 | |||
| 225 | static 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 | |||
| 207 | int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask, | 240 | int 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); |
