mirror of https://gitee.com/openkylin/linux.git
Merge branch 'irq-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'irq-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: genirq: Delegate irq affinity setting to the irq thread
This commit is contained in:
commit
5b26776bd9
|
@ -64,11 +64,13 @@
|
||||||
* IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
|
* IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
|
||||||
* IRQTF_DIED - handler thread died
|
* IRQTF_DIED - handler thread died
|
||||||
* IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
|
* IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
|
||||||
|
* IRQTF_AFFINITY - irq thread is requested to adjust affinity
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
IRQTF_RUNTHREAD,
|
IRQTF_RUNTHREAD,
|
||||||
IRQTF_DIED,
|
IRQTF_DIED,
|
||||||
IRQTF_WARNED,
|
IRQTF_WARNED,
|
||||||
|
IRQTF_AFFINITY,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef irqreturn_t (*irq_handler_t)(int, void *);
|
typedef irqreturn_t (*irq_handler_t)(int, void *);
|
||||||
|
|
|
@ -42,8 +42,7 @@ static inline void unregister_handler_proc(unsigned int irq,
|
||||||
|
|
||||||
extern int irq_select_affinity_usr(unsigned int irq);
|
extern int irq_select_affinity_usr(unsigned int irq);
|
||||||
|
|
||||||
extern void
|
extern void irq_set_thread_affinity(struct irq_desc *desc);
|
||||||
irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Debugging printout:
|
* Debugging printout:
|
||||||
|
|
|
@ -80,14 +80,22 @@ int irq_can_set_affinity(unsigned int irq)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/**
|
||||||
irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
|
* irq_set_thread_affinity - Notify irq threads to adjust affinity
|
||||||
|
* @desc: irq descriptor which has affitnity changed
|
||||||
|
*
|
||||||
|
* We just set IRQTF_AFFINITY and delegate the affinity setting
|
||||||
|
* to the interrupt thread itself. We can not call
|
||||||
|
* set_cpus_allowed_ptr() here as we hold desc->lock and this
|
||||||
|
* code can be called from hard interrupt context.
|
||||||
|
*/
|
||||||
|
void irq_set_thread_affinity(struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
struct irqaction *action = desc->action;
|
struct irqaction *action = desc->action;
|
||||||
|
|
||||||
while (action) {
|
while (action) {
|
||||||
if (action->thread)
|
if (action->thread)
|
||||||
set_cpus_allowed_ptr(action->thread, cpumask);
|
set_bit(IRQTF_AFFINITY, &action->thread_flags);
|
||||||
action = action->next;
|
action = action->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +120,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||||
if (desc->status & IRQ_MOVE_PCNTXT) {
|
if (desc->status & IRQ_MOVE_PCNTXT) {
|
||||||
if (!desc->chip->set_affinity(irq, cpumask)) {
|
if (!desc->chip->set_affinity(irq, cpumask)) {
|
||||||
cpumask_copy(desc->affinity, cpumask);
|
cpumask_copy(desc->affinity, cpumask);
|
||||||
irq_set_thread_affinity(desc, cpumask);
|
irq_set_thread_affinity(desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -122,7 +130,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||||
#else
|
#else
|
||||||
if (!desc->chip->set_affinity(irq, cpumask)) {
|
if (!desc->chip->set_affinity(irq, cpumask)) {
|
||||||
cpumask_copy(desc->affinity, cpumask);
|
cpumask_copy(desc->affinity, cpumask);
|
||||||
irq_set_thread_affinity(desc, cpumask);
|
irq_set_thread_affinity(desc);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
desc->status |= IRQ_AFFINITY_SET;
|
desc->status |= IRQ_AFFINITY_SET;
|
||||||
|
@ -176,7 +184,7 @@ int irq_select_affinity_usr(unsigned int irq)
|
||||||
spin_lock_irqsave(&desc->lock, flags);
|
spin_lock_irqsave(&desc->lock, flags);
|
||||||
ret = setup_affinity(irq, desc);
|
ret = setup_affinity(irq, desc);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
irq_set_thread_affinity(desc, desc->affinity);
|
irq_set_thread_affinity(desc);
|
||||||
spin_unlock_irqrestore(&desc->lock, flags);
|
spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -443,6 +451,34 @@ static int irq_wait_for_interrupt(struct irqaction *action)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether we need to change the affinity of the interrupt thread.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
|
||||||
|
{
|
||||||
|
cpumask_var_t mask;
|
||||||
|
|
||||||
|
if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case we are out of memory we set IRQTF_AFFINITY again and
|
||||||
|
* try again next time
|
||||||
|
*/
|
||||||
|
if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
|
||||||
|
set_bit(IRQTF_AFFINITY, &action->thread_flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irq(&desc->lock);
|
||||||
|
cpumask_copy(mask, desc->affinity);
|
||||||
|
spin_unlock_irq(&desc->lock);
|
||||||
|
|
||||||
|
set_cpus_allowed_ptr(current, mask);
|
||||||
|
free_cpumask_var(mask);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interrupt handler thread
|
* Interrupt handler thread
|
||||||
*/
|
*/
|
||||||
|
@ -458,6 +494,8 @@ static int irq_thread(void *data)
|
||||||
|
|
||||||
while (!irq_wait_for_interrupt(action)) {
|
while (!irq_wait_for_interrupt(action)) {
|
||||||
|
|
||||||
|
irq_thread_check_affinity(desc, action);
|
||||||
|
|
||||||
atomic_inc(&desc->threads_active);
|
atomic_inc(&desc->threads_active);
|
||||||
|
|
||||||
spin_lock_irq(&desc->lock);
|
spin_lock_irq(&desc->lock);
|
||||||
|
|
|
@ -45,7 +45,7 @@ void move_masked_irq(int irq)
|
||||||
< nr_cpu_ids))
|
< nr_cpu_ids))
|
||||||
if (!desc->chip->set_affinity(irq, desc->pending_mask)) {
|
if (!desc->chip->set_affinity(irq, desc->pending_mask)) {
|
||||||
cpumask_copy(desc->affinity, desc->pending_mask);
|
cpumask_copy(desc->affinity, desc->pending_mask);
|
||||||
irq_set_thread_affinity(desc, desc->pending_mask);
|
irq_set_thread_affinity(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpumask_clear(desc->pending_mask);
|
cpumask_clear(desc->pending_mask);
|
||||||
|
|
Loading…
Reference in New Issue