| From foo@baz Mon Apr 9 17:09:24 CEST 2018 |
| From: MaJun <majun258@huawei.com> |
| Date: Fri, 12 May 2017 11:55:28 +0800 |
| Subject: irqchip/mbigen: Fix the clear register offset calculation |
| |
| From: MaJun <majun258@huawei.com> |
| |
| |
| [ Upstream commit 9459a04b6a5a09967eec94a1b66f0a74312819d9 ] |
| |
| The register array offset for clearing an interrupt is calculated by: |
| |
| offset = (hwirq - RESERVED_IRQ_PER_MBIGEN_CHIP) / 32; |
| |
| This is wrong because the clear register array includes the reserved |
| interrupts. So the clear operation ends up in the wrong register. |
| |
| This went unnoticed so far, because the hardware clears the real bit |
| through a timeout mechanism when the hardware is configured in debug |
| mode. That debug mode was enabled on early generations of the hardware, so |
| the problem was papered over. |
| |
| On newer hardware with updated firmware the debug mode was disabled, so the |
| bits did not get cleared which causes the system to malfunction. |
| |
| Remove the subtraction of RESERVED_IRQ_PER_MBIGEN_CHIP, so the correct |
| register is accessed. |
| |
| [ tglx: Rewrote changelog ] |
| |
| Fixes: a6c2f87b8820 ("irqchip/mbigen: Implement the mbigen irq chip operation functions") |
| Signed-off-by: MaJun <majun258@huawei.com> |
| Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> |
| Acked-by: Marc Zyngier <marc.zyngier@arm.com> |
| Cc: Kefeng Wang <wangkefeng.wang@huawei.com> |
| Cc: linuxarm@huawei.com |
| Cc: Wei Yongjun <weiyongjun1@huawei.com> |
| Link: http://lkml.kernel.org/r/1494561328-39514-4-git-send-email-guohanjun@huawei.com |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/irqchip/irq-mbigen.c | 5 +---- |
| 1 file changed, 1 insertion(+), 4 deletions(-) |
| |
| --- a/drivers/irqchip/irq-mbigen.c |
| +++ b/drivers/irqchip/irq-mbigen.c |
| @@ -105,10 +105,7 @@ static inline void get_mbigen_type_reg(i |
| static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq, |
| u32 *mask, u32 *addr) |
| { |
| - unsigned int ofst; |
| - |
| - hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP; |
| - ofst = hwirq / 32 * 4; |
| + unsigned int ofst = (hwirq / 32) * 4; |
| |
| *mask = 1 << (hwirq % 32); |
| *addr = ofst + REG_MBIGEN_CLEAR_OFFSET; |