/*****************************************************************************
* Author : Elvins Fu [email protected]
*
* Info : xxx Inc,(C) 2018-01-11, All rights revseved.
*
* Description : This document is summed up by the author for that the company of xxxs
* R&D debug interrupt on the android platform driver。
*
* This context describes that sd card problem and methods to analysis.
****************************************************************************/
1.先補充點理論知識enable_irq & enable_irq_wake
一、Unbalanced enable for IRQ XX
使能中斷不平衡,主要原因是在申請中斷時已經調用了一次enable_irq()。所以在申請中斷成功後,使用enable_irq()之前需要先調用一次disable_irq()。
如果產生不平衡,則會報出dump_stack(),如上的Unbalanced enable for IRQ XX。
同樣的,如果連續調用同一個中斷的enable_irq()或者disable_irq(),也會產生dump_stack(),不能連續使能,這個就靠代碼邏輯了。
二、enable_irq & enable_irq_wake
enable_irq():用於使能中斷,只在系統正常運行狀態下產生的IRQ會上報。
enable_irq_wake():用於使能中斷,不僅在系統正常運行狀態下產生的IRQ會上報,同時在系統休眠的情況下產生的IRQ會上報。
2.irq導致的unbalance實例分析和修改
1)串口信息
[ 51.932842] ------------[ cut here ]------------
[ 51.936438] WARNING: CPU: 0 PID: 3039 at /home/fujw/fujw/Android8.0/QT4004/LINUX/android/kernel/msm-3.18/kernel/irq/manage.c:543 irq_set_irq_wake+0x88/0xec()
[ 51.950494] Unbalanced IRQ 119 wake disable
[ 51.954654] Modules linked in:
[ 51.957696] CPU: 0 PID: 3039 Comm: NonUiTaskBuilde Not tainted 3.18.71-svn2976 #5
[ 51.965172] [<c010e384>] (unwind_backtrace) from [<c010b3f8>] (show_stack+0x10/0x14)
[ 51.972901] [<c010b3f8>] (show_stack) from [<c0c6eadc>] (dump_stack+0x78/0x98)
[ 51.980109] [<c0c6eadc>] (dump_stack) from [<c011d3ec>] (warn_slowpath_common+0x64/0x88)
[ 51.988182] [<c011d3ec>] (warn_slowpath_common) from [<c011d43c>] (warn_slowpath_fmt+0x2c/0x3c)
[ 51.996863] [<c011d43c>] (warn_slowpath_fmt) from [<c016dc30>] (irq_set_irq_wake+0x88/0xec)
[ 52.005198] [<c016dc30>] (irq_set_irq_wake) from [<c0604e30>] (pn544_disable_irq+0x40/0x58)
[ 52.013525] [<c0604e30>] (pn544_disable_irq) from [<c0605338>] (pn544_dev_irq_handler+0x14/0x80)
[ 52.022284] [<c0605338>] (pn544_dev_irq_handler) from [<c016d630>] (handle_irq_event_percpu+0xa4/0x294)
[ 52.031655] [<c016d630>] (handle_irq_event_percpu) from [<c016d85c>] (handle_irq_event+0x3c/0x5c)
[ 52.040511] [<c016d85c>] (handle_irq_event) from [<c0170580>] (handle_level_irq+0xdc/0x120)
[ 52.048844] [<c0170580>] (handle_level_irq) from [<c016cd68>] (generic_handle_irq+0x20/0x2c)
[ 52.057265] [<c016cd68>] (generic_handle_irq) from [<c040a5ec>] (msm_gpio_irq_handler+0x100/0x158)
[ 52.066205] [<c040a5ec>] (msm_gpio_irq_handler) from [<c016cd68>] (generic_handle_irq+0x20/0x2c)
[ 52.074972] [<c016cd68>] (generic_handle_irq) from [<c016d040>] (__handle_domain_irq+0x94/0xd0)
[ 52.083652] [<c016d040>] (__handle_domain_irq) from [<c010071c>] (gic_handle_irq+0x48/0x7c)
[ 52.091986] [<c010071c>] (gic_handle_irq) from [<c0c7ad50>] (__irq_usr+0x50/0x80)
[ 52.099445] Exception stack(0xdcd89fb0 to 0xdcd89ff8)
[ 52.104484] 9fa0: a7cb2c30 000003b8 00000001 00000180
[ 52.112645] 9fc0: b09808c0 a6a7a408 a7ca5e60 a7c80000 b0980040 a6a7a408 12c12128 13ac0160
[ 52.120803] 9fe0: b369162c 988fc708 b365d517 b365d536 20070030 ffffffff
[ 52.127397] ---[ end trace e7065b488e5a0a12 ]---
[ 52.134735] CPU2: shutdown
2)中斷代碼出錯分析
int irq_set_irq_wake(unsigned int irq, unsigned int on)
{
unsigned long flags;
struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
int ret = 0;
if (!desc)
return -EINVAL;
/* wakeup-capable irqs can be shared between drivers that
* don't need to have the same sleep mode behaviors.
*/
if (on) {
if (desc->wake_depth++ == 0) {
ret = set_irq_wake_real(irq, on);
if (ret)
desc->wake_depth = 0;
else
irqd_set(&desc->irq_data, IRQD_WAKEUP_STATE);
}
} else {
if (desc->wake_depth == 0) {
WARN(1, "Unbalanced IRQ %d wake disable\n", irq);
} else if (--desc->wake_depth == 0) {
ret = set_irq_wake_real(irq, on);
if (ret)
desc->wake_depth = 1;
else
irqd_clear(&desc->irq_data, IRQD_WAKEUP_STATE);
}
}
irq_put_desc_busunlock(desc, flags);
return ret;
}
3)分析原因及其修改
根據一個做++操作,一個做–操作。可以得出disable_irq與enable_irq需要成對的使用。屏蔽掉irq_wake做測試即可。
Index: kernel/msm-3.18/drivers/nfc/pn544/pn54x.c
===================================================================
--- kernel/msm-3.18/drivers/nfc/pn544/pn54x.c (revision 3020)
+++ kernel/msm-3.18/drivers/nfc/pn544/pn54x.c (working copy)
@@ -99,7 +99,7 @@
spin_lock_irqsave(&pn544_dev->irq_enabled_lock, flags);
if (pn544_dev->irq_enabled) {
disable_irq_nosync(pn544_dev->client->irq);
- disable_irq_wake(pn544_dev->client->irq);
+ // disable_irq_wake(pn544_dev->client->irq);
pn544_dev->irq_enabled = false;
}
spin_unlock_irqrestore(&pn544_dev->irq_enabled_lock, flags);
@@ -146,7 +146,7 @@
while (1) {
pn544_dev->irq_enabled = true;
enable_irq(pn544_dev->client->irq);
- enable_irq_wake(pn544_dev->client->irq);
+// enable_irq_wake(pn544_dev->client->irq);
ret = wait_event_interruptible(
pn544_dev->read_wq,
!pn544_dev->irq_enabled);
@@ -741,7 +741,7 @@
unsigned long tempJ = msecs_to_jiffies(timeout);
if(down_timeout(&ese_access_sema, tempJ) != 0)
{
- printk("get_ese_lock: timeout p61_current_state = %d\n", p61_current_state);
+ pr_info("get_ese_lock: timeout p61_current_state = %d\n", p61_current_state); //printk ----> pr_info
return -EBUSY;
}
return 0;
@@ -930,7 +930,7 @@
goto err_request_irq_failed;
}
pr_info("%s : Enabling IRQ Wake\n", __func__);
- enable_irq_wake(pn544_dev->client->irq);
+// enable_irq_wake(pn544_dev->client->irq);
pn544_disable_irq(pn544_dev);
i2c_set_clientdata(client, pn544_dev);
3.推薦兩篇比較全面和專業的博客
1.irq balance詳解:https://blog.csdn.net/whrszzc/article/details/50533866
2.linux request irq詳解 :https://blog.csdn.net/wealoong/article/details/7566546