Commit f3cc2494 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'irq-urgent-2020-02-22' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq fixes from Thomas Gleixner:
 "Two fixes for the irq core code which are follow ups to the recent MSI
  fixes:

   - The WARN_ON which was put into the MSI setaffinity callback for
     paranoia reasons actually triggered via a callchain which escaped
     when all the possible ways to reach that code were analyzed.

     The proc/irq/$N/*affinity interfaces have a quirk which came in
     when ALPHA moved to the generic interface: In case that the written
     affinity mask does not contain any online CPU it calls into ALPHAs
     magic auto affinity setting code.

     A few years later this mechanism was also made available to x86 for
     no good reasons and in a way which circumvents all sanity checks
     for interrupts which cannot have their affinity set from process
     context on X86 due to the way the X86 interrupt delivery works.

     It would be possible to make this work properly, but there is no
     point in doing so. If the interrupt is not yet started then the
     affinity setting has no effect and if it is started already then it
     is already assigned to an online CPU so there is no point to
     randomly move it to some other CPU. Just return EINVAL as the code
     has done before that change forever.

   - The new MSI quirk bit in the irq domain flags turned out to be
     already occupied, which escaped the author and the reviewers
     because the already in use bits were 0,6,2,3,4,5 listed in that
     order.

     That bit 6 was simply overlooked because the ordering was straight
     forward linear otherwise. So the new bit ended up being a
     duplicate.

     Fix it up by switching the oddball 6 to the obvious 1"

* tag 'irq-urgent-2020-02-22' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  genirq/irqdomain: Make sure all irq domain flags are distinct
  genirq/proc: Reject invalid affinity masks (again)
parents fca10378 2546287c
...@@ -192,7 +192,7 @@ enum { ...@@ -192,7 +192,7 @@ enum {
IRQ_DOMAIN_FLAG_HIERARCHY = (1 << 0), IRQ_DOMAIN_FLAG_HIERARCHY = (1 << 0),
/* Irq domain name was allocated in __irq_domain_add() */ /* Irq domain name was allocated in __irq_domain_add() */
IRQ_DOMAIN_NAME_ALLOCATED = (1 << 6), IRQ_DOMAIN_NAME_ALLOCATED = (1 << 1),
/* Irq domain is an IPI domain with virq per cpu */ /* Irq domain is an IPI domain with virq per cpu */
IRQ_DOMAIN_FLAG_IPI_PER_CPU = (1 << 2), IRQ_DOMAIN_FLAG_IPI_PER_CPU = (1 << 2),
......
...@@ -128,8 +128,6 @@ static inline void unregister_handler_proc(unsigned int irq, ...@@ -128,8 +128,6 @@ static inline void unregister_handler_proc(unsigned int irq,
extern bool irq_can_set_affinity_usr(unsigned int irq); extern bool irq_can_set_affinity_usr(unsigned int irq);
extern int irq_select_affinity_usr(unsigned int irq);
extern void irq_set_thread_affinity(struct irq_desc *desc); extern void irq_set_thread_affinity(struct irq_desc *desc);
extern int irq_do_set_affinity(struct irq_data *data, extern int irq_do_set_affinity(struct irq_data *data,
......
...@@ -481,23 +481,9 @@ int irq_setup_affinity(struct irq_desc *desc) ...@@ -481,23 +481,9 @@ int irq_setup_affinity(struct irq_desc *desc)
{ {
return irq_select_affinity(irq_desc_get_irq(desc)); return irq_select_affinity(irq_desc_get_irq(desc));
} }
#endif #endif /* CONFIG_AUTO_IRQ_AFFINITY */
#endif /* CONFIG_SMP */
/*
* Called when a bogus affinity is set via /proc/irq
*/
int irq_select_affinity_usr(unsigned int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
unsigned long flags;
int ret;
raw_spin_lock_irqsave(&desc->lock, flags);
ret = irq_setup_affinity(desc);
raw_spin_unlock_irqrestore(&desc->lock, flags);
return ret;
}
#endif
/** /**
* irq_set_vcpu_affinity - Set vcpu affinity for the interrupt * irq_set_vcpu_affinity - Set vcpu affinity for the interrupt
......
...@@ -111,6 +111,28 @@ static int irq_affinity_list_proc_show(struct seq_file *m, void *v) ...@@ -111,6 +111,28 @@ static int irq_affinity_list_proc_show(struct seq_file *m, void *v)
return show_irq_affinity(AFFINITY_LIST, m); return show_irq_affinity(AFFINITY_LIST, m);
} }
#ifndef CONFIG_AUTO_IRQ_AFFINITY
static inline int irq_select_affinity_usr(unsigned int irq)
{
/*
* If the interrupt is started up already then this fails. The
* interrupt is assigned to an online CPU already. There is no
* point to move it around randomly. Tell user space that the
* selected mask is bogus.
*
* If not then any change to the affinity is pointless because the
* startup code invokes irq_setup_affinity() which will select
* a online CPU anyway.
*/
return -EINVAL;
}
#else
/* ALPHA magic affinity auto selector. Keep it for historical reasons. */
static inline int irq_select_affinity_usr(unsigned int irq)
{
return irq_select_affinity(irq);
}
#endif
static ssize_t write_irq_affinity(int type, struct file *file, static ssize_t write_irq_affinity(int type, struct file *file,
const char __user *buffer, size_t count, loff_t *pos) const char __user *buffer, size_t count, loff_t *pos)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment