TQ2440开发板request_irq中断注册失败(-22)原因分析(一)

一.驱动代码

        uiVal = readl(S3C2410_EXTINT0);
        uiVal &= ~(0x1<<18);
//      uiVal |= (0x1<<18);
        uiVal |= (0x1<<17);
        writel(uiVal, S3C2410_EXTINT0);
        ret = request_irq(IRQ_EINT4t7, kobox_gpio_irq_handle, IRQF_SHARED, "key2", (void *)&nouse);
        if(ret)
        {
                printk("[func:%s][line:%d] request_irq failed, ret:%d!\n", __FUNCTION__,__LINE__,ret);
        }


二.执行结果
[\u@\h \W]# insmod key.ko 
#####enter key_drv_init!
#####[func:request_threaded_irq][line:1504]
[func:request_irq_for_gpio][line:282] request_irq failed, ret:-22!
#####key_drv_init ok!

三. 原因分析

(1)dm9000.c中有irq 20的注册

#####[func:request_threaded_irq][line:1493], irq:55
CPU: 0 PID: 985 Comm: ifconfig Not tainted 3.16.1-svn57 #27
[<c011b1a8>] (unwind_backtrace) from [<c0118a38>] (show_stack+0x10/0x14)
[<c0118a38>] (show_stack) from [<c0152ff0>] (irq_to_desc+0x2c/0x54)
[<c0152ff0>] (irq_to_desc) from [<c015596c>] (irq_get_irq_data+0x8/0xc)
[<c015596c>] (irq_get_irq_data) from [<c02dbb88>] (s3c_irq_unmask+0x44/0x74)
[<c02dbb88>] (s3c_irq_unmask) from [<c01556b4>] (irq_enable+0x44/0x54)
[<c01556b4>] (irq_enable) from [<c0156170>] (irq_startup+0x64/0x68)
[<c0156170>] (irq_startup) from [<c01543fc>] (__setup_irq+0x1f8/0x4fc)
[<c01543fc>] (__setup_irq) from [<c0154940>] (request_threaded_irq+0xf4/0x1e4)
[<c0154940>] (request_threaded_irq) from [<c0385684>] (dm9000_open+0x70/0x134)


[<c0385684>] (dm9000_open) from [<c0430ae0>] (__dev_open+0xb8/0x114)//看来这里调用了中断


[<c0430ae0>] (__dev_open) from [<c04308b0>] (__dev_change_flags+0x90/0x16c)
[<c04308b0>] (__dev_change_flags) from [<c04309ac>] (dev_change_flags+0x18/0x48)
[<c04309ac>] (dev_change_flags) from [<c048cf88>] (devinet_ioctl+0x6d0/0x778)
[<c048cf88>] (devinet_ioctl) from [<c041d130>] (sock_ioctl+0x68/0x298)
[<c041d130>] (sock_ioctl) from [<c01b41bc>] (do_vfs_ioctl+0x7c/0x5f4)
[<c01b41bc>] (do_vfs_ioctl) from [<c01b476c>] (SyS_ioctl+0x38/0x5c)
[<c01b476c>] (SyS_ioctl) from [<c0115840>] (ret_fast_syscall+0x0/0x2c)
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
dm9000 dm9000 eth0: link down




(2)不只是上面的dm9000有注册irq 20,将dm9000.c中的中断注册注掉,仍然有irq 20的注册
S3C2440: IRQ Support
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
irq: clearing pending status 00080000
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111

#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111


下面就是要搜出,这些是哪里打印的:
root@ubuntu:/mnt/shared/linux-3.16.1/drivers# grep "IRQ Support" ./ -r   
Binary file ./built-in.o matches
Binary file ./irqchip/built-in.o matches
Binary file ./irqchip/irq-s3c24xx.o matches
./irqchip/irq-s3c24xx.c:        pr_info("S3C2412: IRQ Support\n");
./irqchip/irq-s3c24xx.c:        pr_info("S3C2416: IRQ Support\n");
./irqchip/irq-s3c24xx.c:        pr_info("S3C2440: IRQ Support\n");
./irqchip/irq-s3c24xx.c:        pr_info("S3C2442: IRQ Support\n");
./irqchip/irq-s3c24xx.c:        pr_info("S3C2443: IRQ Support\n");
root@ubuntu:/mnt/shared/linux-3.16.1/drivers# 


打印:
NR_IRQS:111
S3C2440: IRQ Support
####################################[s3c2440_init_irq][980]
####################################[s3c2440_init_irq][986]
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
####################################[s3c2440_init_irq][995]
irq: clearing pending status 00080000
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
#####[func:irq_to_desc][line:279], [irq==20] NR_IRQS:111
####################################[s3c2440_init_irq][999]
irq: clearing pending status 00000003
irq: clearing pending status 00000002
####################################[s3c2440_init_irq][1004]


将如下部分注掉后,key.ko中注册正常: s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
函数代码:
void __init s3c2440_init_irq(void)
{
pr_info("S3C2440: IRQ Support\n");


printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);


#ifdef CONFIG_FIQ
init_FIQ(FIQ_START);
#endif


printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);
#if 1
s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL,
0x4a000000);
if (IS_ERR(s3c_intc[0])) {
pr_err("irq: could not create main interrupt controller\n");
return;
}

printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);
#if 0
s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
#endif
printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);


s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2440subint[0],
s3c_intc[0], 0x4a000018);
#endif
printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);
}
#endif


但是会出现如下打印:


s3c-sdi s3c2440-sdi: can't get card detect irq.
------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at kernel/irq/manage.c:1325 __free_irq+0x108/0x178()
Trying to free already-free IRQ 64
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 3.16.1-svn57 #35
[<c011b1a8>] (unwind_backtrace) from [<c0118a38>] (show_stack+0x10/0x14)
[<c0118a38>] (show_stack) from [<c0124f24>] (warn_slowpath_common+0x60/0x80)
[<c0124f24>] (warn_slowpath_common) from [<c0124fd8>] (warn_slowpath_fmt+0x30/0x40)
[<c0124fd8>] (warn_slowpath_fmt) from [<c0154de4>] (__free_irq+0x108/0x178)
[<c0154de4>] (__free_irq) from [<c0154e98>] (free_irq+0x44/0x80)
[<c0154e98>] (free_irq) from [<c03dfa84>] (s3cmci_probe+0x250/0x57c)
[<c03dfa84>] (s3cmci_probe) from [<c03234fc>] (platform_drv_probe+0x1c/0x4c)
[<c03234fc>] (platform_drv_probe) from [<c0321e0c>] (driver_probe_device+0x88/0x224)
[<c0321e0c>] (driver_probe_device) from [<c0322034>] (__driver_attach+0x8c/0x90)
[<c0322034>] (__driver_attach) from [<c03209ac>] (bus_for_each_dev+0x78/0x9c)
[<c03209ac>] (bus_for_each_dev) from [<c0321014>] (bus_add_driver+0xe4/0x1d4)
[<c0321014>] (bus_add_driver) from [<c03225b8>] (driver_register+0x58/0xf8)
[<c03225b8>] (driver_register) from [<c01089f8>] (do_one_initcall+0x84/0x1e4)
[<c01089f8>] (do_one_initcall) from [<c06165c8>] (kernel_init_freeable+0xf4/0x1bc)
[<c06165c8>] (kernel_init_freeable) from [<c04d5000>] (kernel_init+0x8/0x10c)
[<c04d5000>] (kernel_init) from [<c01158d0>] (ret_from_fork+0x14/0x24)
---[ end trace 31de2d25f8e2a307 ]---
s3c-sdi: probe of s3c2440-sdi failed with error -2
TCP: cubic registered
NET: Registered protocol family 17


将如下内容打开: s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);


void __init s3c2440_init_irq(void)
{
pr_info("S3C2440: IRQ Support\n");


printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);


#ifdef CONFIG_FIQ
init_FIQ(FIQ_START);
#endif


printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);
#if 1
s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL,
0x4a000000);
if (IS_ERR(s3c_intc[0])) {
pr_err("irq: could not create main interrupt controller\n");
return;
}

printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);
#if 1
s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
#endif

printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);


s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2440subint[0],
s3c_intc[0], 0x4a000018);
#endif
printk("####################################[%s][%d]\n", __FUNCTION__, __LINE__);
}
#endif


而将 struct s3c_irq_data init_eint[32] 做如下修改:
原因:注册EINT0\1\2都是正常的,但是注册EINT4-7失败,而这里没有0\1\2\3,这就是和EINT4-7的差异




static struct s3c_irq_data init_eint[32] = {
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
#if 0
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
#else
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
#endif
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
};


果然是可以注册成功的



综上所述,tq2440中request_irq注册20号中断(EINT4-7)失败的直接原因是:
init_eint[32] 中对其进行了初始化


但是如果将dm9000.c中注掉的代码打开,在insmod key.ko后,再ifconfig eth0,会出现eth0 open失败的情况:


[\u@\h \W]# ifconfig eth0 up
####################################[dm9000_open][1331]
#####[func:request_threaded_irq][line:1493], irq:55
ifconfig: SIOCSIFFLAGS: Resource temporarily unavailable


这说明:
dm9000.c中对20号中断的注册,和key.ko中的注册,还是有冲突的
为什么有冲突呢?共享中断如何共享、如何注册呢?后面进一步分析。

你可能感兴趣的:(linux,kernel,驱动包,TQ2440)