Why can't I register interrupts with interrupts in Linux 2.6.26?
The first poster, so please excuse any nonsense.
I am working on porting a custom CPLD driver in Linux kernel built for MPC83xx from 2.6.22 to 2.6.26 and am getting unexpected Oops. The driver works fine for the .22 kernel, but the .26 kernel clamps my request_irq call. Does anyone have any idea why the behavior change occurred, or better yet, what should I do to fix this issue?
I tracked down the Oops source for calling kernel / irq / manage.c where it desc->chip->enable(irq)
is called in setup_irq()
, and it looks like the function pointer that is allowed is cleared in the call ipic_set_irq_type()
in arch / powerpc / sysdev / ipic.c. Unfortunately, I don't know why.
I have included Oops and sample kernel modules that replicate the problem.
Oops -
Unable to handle kernel paging request for instruction fetch
Faulting instruction address: 0x00000000
Oops: Kernel access of bad area, sig: 11 [#1]
PREEMPT SCPA-G2
Modules linked in: cpld(+)
NIP: 00000000 LR: c004b930 CTR: 00000000
REGS: df8b5df0 TRAP: 0400 Not tainted (2.6.26-twacs-100.0.0)
MSR: 20001032 <ME,IR,DR> CR: 24022422 XER: 20000000
TASK = dfbcfc00[488] 'insmod' THREAD: df8b4000
GPR00: 00000000 df8b5ea0 dfbcfc00 00000017 00000001 00000001 00000000 c02d1fb4
GPR08: 00002268 00000000 00000000 00000000 44022484 10073f68 1ffcb000 007ffeb0
GPR16: 00000000 00000000 00800000 00000000 bffff7f0 00000000 1006e3dc 00000000
GPR24: 00000002 00000000 00000000 00009032 df9d04c0 00000017 df8b4000 c02d40e4
NIP [00000000] 0x0
LR [c004b930] setup_irq+0x404/0x430
Call Trace:
[df8b5ea0] [c004b8ec] setup_irq+0x3c0/0x430 (unreliable)
[df8b5ed0] [c004bbd8] request_irq+0xe0/0x130
[df8b5f00] [e1078054] cpld_init+0x54/0xd0 [cpld]
[df8b5f10] [c0048ba0] sys_init_module+0x14c/0x1d8
[df8b5f40] [c0010008] ret_from_syscall+0x0/0x38
--- Exception: c01 at 0xff27bb0
LR = 0x10019ca8
Instruction dump:
XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Kernel panic - not syncing: Fatal exception
Module -
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
static unsigned int cpld_virq = NO_IRQ;
unsigned value = 0xdeadbeef;
static irqreturn_t cpld_isr(int irq, void *dev_id) {
return IRQ_HANDLED;
}
void __exit cpld_cleanup(void) {
free_irq(cpld_interrupt, &value);
irq_dispose_mapping(cpld_virq);
return;
}
int __init cpld_init(void) {
int retval;
unsigned long cpld_interrupt = 23;
cpld_virq = irq_create_mapping(NULL, cpld_interrupt);
if (cpld_virq == NO_IRQ) {
return -EBUSY;
}
retval = request_irq(cpld_virq, cpld_isr,
IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_FALLING,
"CPLD", &value);
if (retval) {
irq_dispose_mapping(cpld_virq);
return retval;
}
return 0;
}
module_init(cpld_init);
module_exit(cpld_cleanup);
MODULE_LICENSE("Dual BSD/GPL");
Thanks for the help. I've been bashing my head about this for several days now, and I'm open to any suggestions.
source to share
Aa. It looks like JayM was close, although not for the reason he thought he was. I just saw a patch look at the linuxppc-dev mailing list stating that the edge supported interrupts were broken. http://lkml.org/lkml/2010/5/3/363
This may not be the root cause, but indicates a problem that I am not going to fix.
source to share
My copy of the 2.6.26 kernel does ipic_set_irq_type()
nothing with the pointer enable()
. However, it has the following comments, which were not specified in 2.6.22:
/* ipic only supports low assertion and high-to-low change senses
*/
and
/* ipic supports only edge mode on external interrupts */
It looks like what you were doing on 2.6.22 was not supported by the hardware.
source to share