ARC linux uses 2 distribution modes for common interrupts: round robin mode (IDU_M_DISTRI_RR) and a simple destination mode (IDU_M_DISTRI_DEST). The first one is used when more than 1 cores may handle a common interrupt and the second one is used when only 1 core may handle a common interrupt. However idu_irq_set_affinity() always sets IDU_M_DISTRI_RR for all affinity values. But there is no sense in setting of such mode if only 1 core must handle a common interrupt.
Unified · Split
| @@ -181,6 +181,8 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask, · 180 unmodified lines | ||
| 181 | 181 | { |
| 182 | 182 | unsigned long flags; |
| 183 | 183 | cpumask_t online; |
| 184 | + unsigned int destination_bits; | |
| 185 | + unsigned int distribution_mode; | |
| 184 | 186 | |
| 185 | 187 | /* errout if no online cpu per @cpumask */ |
| 186 | 188 | if (!cpumask_and(&online, cpumask, cpu_online_mask)) |
| @@ -188,8 +190,15 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask, · 1 unmodified line | ||
| 188 | 190 | |
| 189 | 191 | raw_spin_lock_irqsave(&mcip_lock, flags); |
| 190 | 192 | |
| 191 | − idu_set_dest(data->hwirq, cpumask_bits(&online)[0]); | |
| 192 | − idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR); | |
| 193 | + destination_bits = cpumask_bits(&online)[0]; | |
| 194 | + idu_set_dest(data->hwirq, destination_bits); | |
| 195 | + | |
| 196 | + if (ffs(destination_bits) == fls(destination_bits)) | |
| 197 | + distribution_mode = IDU_M_DISTRI_DEST; | |
| 198 | + else | |
| 199 | + distribution_mode = IDU_M_DISTRI_RR; | |
| 200 | + | |
| 201 | + idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, distribution_mode); | |
| 193 | 202 | |
| 194 | 203 | raw_spin_unlock_irqrestore(&mcip_lock, flags); |
| 195 | 204 | |