diff options
author | lei.zhang8 <lei.zhang8@transsion.com> | 2024-05-07 11:37:20 +0800 |
---|---|---|
committer | Lee Jones <joneslee@google.com> | 2024-05-20 08:07:30 +0000 |
commit | f6d1a01fac51edd2f594f5d3236f60494fdcdc20 (patch) | |
tree | 05795bd09585726a17ea21f3361a2beb389efd80 | |
parent | fd07886c72df4e66fb98593141d2db2b5b6f1f0e (diff) | |
download | hikey-linaro-mirror-android13-5.10.tar.gz |
ANDROID: irq: put irq_resolve_mapping under protection of __irq_enter_rawmirror-android13-5.10
With commit 3f9d45d8021df4739103db8f902f588782c4f81b
("ANDROID: genirq: Allow an interrupt to be marked
as 'raw'"), irq_find_mapping was moved out of scope between
irq_enter() and irq_exit(). This result in
el1_irq->__handle_domain_irq->
irq_find_mapping->rcu_read_unlock->rcu_read_unlock_special->
irq_work_queue_on->el1_irq because ir_irq() return false.
Now one RCU stall issue was observed due to IPI_IRQ_WORK irq storm.
IPI_IRQ_WORK irq was triggered from handle_domain_irq->...->
rcu_read_unlock_special->irq_work_queue_on again and again unexpectedly
due to in_irq() return false even it is in IRQ context.
This patch fix its side effect without reverting commit
3f9d45d8021df4739103db8f902f588782c4f81b.
During call path "handle_domain_irq->irq_find_mapping->...->
rcu_read_unlock_special()" with use_softirq is true.
1)before this patch, in_irq() is false
This will result in IPI_IRQ_WORK irq storm due to next IPI_IRQ_WORK
irq
will be triggered under IRQ context again and again.
2)after this patch,in_irq() will be true
RCU_SOFTIRQ will be raised(but not next IPI_IRQ_WORK irq) under IRQ
context.
Bug: 339061905
Fixes: 3f9d45d8021d ("FROMLIST: genirq: Allow an interrupt to be marked as 'raw'")
Change-Id: I27caeaf6817e42b3c15effe8b750cb83af90aeb3
Signed-off-by: lei.zhang8 <lei.zhang8@transsion.com>
-rw-r--r-- | kernel/irq/irqdesc.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 67d73af06cfe..74df0289409a 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -676,8 +676,11 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, int ret = 0; #ifdef CONFIG_IRQ_DOMAIN - if (lookup) + if (lookup) { + __irq_enter_raw(); irq = irq_find_mapping(domain, hwirq); + __irq_exit_raw(); + } #endif /* |