|
@@ -616,6 +616,22 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_HARDIRQS_SW_RESEND
|
|
|
+int irq_set_parent(int irq, int parent_irq)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
|
|
|
+
|
|
|
+ if (!desc)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ desc->parent_irq = parent_irq;
|
|
|
+
|
|
|
+ irq_put_desc_unlock(desc, flags);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* Default primary interrupt handler for threaded interrupts. Is
|
|
|
* assigned as primary handler when request_threaded_irq is called
|
|
@@ -716,6 +732,7 @@ static void
|
|
|
irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
|
|
|
{
|
|
|
cpumask_var_t mask;
|
|
|
+ bool valid = true;
|
|
|
|
|
|
if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags))
|
|
|
return;
|
|
@@ -730,10 +747,18 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
|
|
|
}
|
|
|
|
|
|
raw_spin_lock_irq(&desc->lock);
|
|
|
- cpumask_copy(mask, desc->irq_data.affinity);
|
|
|
+ /*
|
|
|
+ * This code is triggered unconditionally. Check the affinity
|
|
|
+ * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out.
|
|
|
+ */
|
|
|
+ if (desc->irq_data.affinity)
|
|
|
+ cpumask_copy(mask, desc->irq_data.affinity);
|
|
|
+ else
|
|
|
+ valid = false;
|
|
|
raw_spin_unlock_irq(&desc->lock);
|
|
|
|
|
|
- set_cpus_allowed_ptr(current, mask);
|
|
|
+ if (valid)
|
|
|
+ set_cpus_allowed_ptr(current, mask);
|
|
|
free_cpumask_var(mask);
|
|
|
}
|
|
|
#else
|
|
@@ -833,6 +858,8 @@ static int irq_thread(void *data)
|
|
|
init_task_work(&on_exit_work, irq_thread_dtor);
|
|
|
task_work_add(current, &on_exit_work, false);
|
|
|
|
|
|
+ irq_thread_check_affinity(desc, action);
|
|
|
+
|
|
|
while (!irq_wait_for_interrupt(action)) {
|
|
|
irqreturn_t action_ret;
|
|
|
|
|
@@ -936,6 +963,16 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
|
|
*/
|
|
|
get_task_struct(t);
|
|
|
new->thread = t;
|
|
|
+ /*
|
|
|
+ * Tell the thread to set its affinity. This is
|
|
|
+ * important for shared interrupt handlers as we do
|
|
|
+ * not invoke setup_affinity() for the secondary
|
|
|
+ * handlers as everything is already set up. Even for
|
|
|
+ * interrupts marked with IRQF_NO_BALANCE this is
|
|
|
+ * correct as we want the thread to move to the cpu(s)
|
|
|
+ * on which the requesting code placed the interrupt.
|
|
|
+ */
|
|
|
+ set_bit(IRQTF_AFFINITY, &new->thread_flags);
|
|
|
}
|
|
|
|
|
|
if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
|