diff options
Diffstat (limited to 'kernel/irq/migration.c')
-rw-r--r-- | kernel/irq/migration.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index 86ae0eb80b53..8b8cecd18cce 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c | |||
@@ -38,17 +38,18 @@ bool irq_fixup_move_pending(struct irq_desc *desc, bool force_clear) | |||
38 | void irq_move_masked_irq(struct irq_data *idata) | 38 | void irq_move_masked_irq(struct irq_data *idata) |
39 | { | 39 | { |
40 | struct irq_desc *desc = irq_data_to_desc(idata); | 40 | struct irq_desc *desc = irq_data_to_desc(idata); |
41 | struct irq_chip *chip = desc->irq_data.chip; | 41 | struct irq_data *data = &desc->irq_data; |
42 | struct irq_chip *chip = data->chip; | ||
42 | 43 | ||
43 | if (likely(!irqd_is_setaffinity_pending(&desc->irq_data))) | 44 | if (likely(!irqd_is_setaffinity_pending(data))) |
44 | return; | 45 | return; |
45 | 46 | ||
46 | irqd_clr_move_pending(&desc->irq_data); | 47 | irqd_clr_move_pending(data); |
47 | 48 | ||
48 | /* | 49 | /* |
49 | * Paranoia: cpu-local interrupts shouldn't be calling in here anyway. | 50 | * Paranoia: cpu-local interrupts shouldn't be calling in here anyway. |
50 | */ | 51 | */ |
51 | if (irqd_is_per_cpu(&desc->irq_data)) { | 52 | if (irqd_is_per_cpu(data)) { |
52 | WARN_ON(1); | 53 | WARN_ON(1); |
53 | return; | 54 | return; |
54 | } | 55 | } |
@@ -73,9 +74,20 @@ void irq_move_masked_irq(struct irq_data *idata) | |||
73 | * For correct operation this depends on the caller | 74 | * For correct operation this depends on the caller |
74 | * masking the irqs. | 75 | * masking the irqs. |
75 | */ | 76 | */ |
76 | if (cpumask_any_and(desc->pending_mask, cpu_online_mask) < nr_cpu_ids) | 77 | if (cpumask_any_and(desc->pending_mask, cpu_online_mask) < nr_cpu_ids) { |
77 | irq_do_set_affinity(&desc->irq_data, desc->pending_mask, false); | 78 | int ret; |
78 | 79 | ||
80 | ret = irq_do_set_affinity(data, desc->pending_mask, false); | ||
81 | /* | ||
82 | * If the there is a cleanup pending in the underlying | ||
83 | * vector management, reschedule the move for the next | ||
84 | * interrupt. Leave desc->pending_mask intact. | ||
85 | */ | ||
86 | if (ret == -EBUSY) { | ||
87 | irqd_set_move_pending(data); | ||
88 | return; | ||
89 | } | ||
90 | } | ||
79 | cpumask_clear(desc->pending_mask); | 91 | cpumask_clear(desc->pending_mask); |
80 | } | 92 | } |
81 | 93 | ||