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

drivers/irqchip: xtensa-mx: fix mask and unmask

xtensa_irq_mask and xtensa_irq_unmask don't do the right thing when
called for the first two external IRQs. Treat these IRQs as per-CPU
IRQs.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>

+20 -14
+20 -14
drivers/irqchip/irq-xtensa-mx.c
··· 71 71 unsigned int mask = 1u << d->hwirq; 72 72 73 73 if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE | 74 - XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) { 75 - set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) - 76 - HW_IRQ_MX_BASE), MIENG); 77 - } else { 78 - mask = __this_cpu_read(cached_irq_mask) & ~mask; 79 - __this_cpu_write(cached_irq_mask, mask); 80 - xtensa_set_sr(mask, intenable); 74 + XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) { 75 + unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq); 76 + 77 + if (ext_irq >= HW_IRQ_MX_BASE) { 78 + set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENG); 79 + return; 80 + } 81 81 } 82 + mask = __this_cpu_read(cached_irq_mask) & ~mask; 83 + __this_cpu_write(cached_irq_mask, mask); 84 + xtensa_set_sr(mask, intenable); 82 85 } 83 86 84 87 static void xtensa_mx_irq_unmask(struct irq_data *d) ··· 89 86 unsigned int mask = 1u << d->hwirq; 90 87 91 88 if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE | 92 - XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) { 93 - set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) - 94 - HW_IRQ_MX_BASE), MIENGSET); 95 - } else { 96 - mask |= __this_cpu_read(cached_irq_mask); 97 - __this_cpu_write(cached_irq_mask, mask); 98 - xtensa_set_sr(mask, intenable); 89 + XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) { 90 + unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq); 91 + 92 + if (ext_irq >= HW_IRQ_MX_BASE) { 93 + set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENGSET); 94 + return; 95 + } 99 96 } 97 + mask |= __this_cpu_read(cached_irq_mask); 98 + __this_cpu_write(cached_irq_mask, mask); 99 + xtensa_set_sr(mask, intenable); 100 100 } 101 101 102 102 static void xtensa_mx_irq_enable(struct irq_data *d)