/*****************************************************************************
* 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