Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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)

+25 -19
+1 -1
include/linux/irqdomain.h
··· 192 192 IRQ_DOMAIN_FLAG_HIERARCHY = (1 << 0), 193 193 194 194 /* Irq domain name was allocated in __irq_domain_add() */ 195 - IRQ_DOMAIN_NAME_ALLOCATED = (1 << 6), 195 + IRQ_DOMAIN_NAME_ALLOCATED = (1 << 1), 196 196 197 197 /* Irq domain is an IPI domain with virq per cpu */ 198 198 IRQ_DOMAIN_FLAG_IPI_PER_CPU = (1 << 2),
-2
kernel/irq/internals.h
··· 128 128 129 129 extern bool irq_can_set_affinity_usr(unsigned int irq); 130 130 131 - extern int irq_select_affinity_usr(unsigned int irq); 132 - 133 131 extern void irq_set_thread_affinity(struct irq_desc *desc); 134 132 135 133 extern int irq_do_set_affinity(struct irq_data *data,
+2 -16
kernel/irq/manage.c
··· 481 481 { 482 482 return irq_select_affinity(irq_desc_get_irq(desc)); 483 483 } 484 - #endif 484 + #endif /* CONFIG_AUTO_IRQ_AFFINITY */ 485 + #endif /* CONFIG_SMP */ 485 486 486 - /* 487 - * Called when a bogus affinity is set via /proc/irq 488 - */ 489 - int irq_select_affinity_usr(unsigned int irq) 490 - { 491 - struct irq_desc *desc = irq_to_desc(irq); 492 - unsigned long flags; 493 - int ret; 494 - 495 - raw_spin_lock_irqsave(&desc->lock, flags); 496 - ret = irq_setup_affinity(desc); 497 - raw_spin_unlock_irqrestore(&desc->lock, flags); 498 - return ret; 499 - } 500 - #endif 501 487 502 488 /** 503 489 * irq_set_vcpu_affinity - Set vcpu affinity for the interrupt
+22
kernel/irq/proc.c
··· 111 111 return show_irq_affinity(AFFINITY_LIST, m); 112 112 } 113 113 114 + #ifndef CONFIG_AUTO_IRQ_AFFINITY 115 + static inline int irq_select_affinity_usr(unsigned int irq) 116 + { 117 + /* 118 + * If the interrupt is started up already then this fails. The 119 + * interrupt is assigned to an online CPU already. There is no 120 + * point to move it around randomly. Tell user space that the 121 + * selected mask is bogus. 122 + * 123 + * If not then any change to the affinity is pointless because the 124 + * startup code invokes irq_setup_affinity() which will select 125 + * a online CPU anyway. 126 + */ 127 + return -EINVAL; 128 + } 129 + #else 130 + /* ALPHA magic affinity auto selector. Keep it for historical reasons. */ 131 + static inline int irq_select_affinity_usr(unsigned int irq) 132 + { 133 + return irq_select_affinity(irq); 134 + } 135 + #endif 114 136 115 137 static ssize_t write_irq_affinity(int type, struct file *file, 116 138 const char __user *buffer, size_t count, loff_t *pos)