Howdy All,
First time poster, so please excuse any stupidity.
I'm working on porting a custom CPLD driver on a linux kernel built for an MPC83xx from 2.6.22 to 2.6.26, and am receiving an unexpected Oops. The driver works fine for the .22 kernel, but the .26 kernel chokes on my call to request_irq. Does anybody know why there was a change in behavior, or better yet, what I need to do to resolve it?
I've tracked down the source of the Oops to a call to kernel/irq/manage.c, where desc->chip->enable(irq) is called in setup_irq(), and it looks like the function pointer to enable is being cleared in a call to ipic_set_irq_type() in arch/powerpc/sysdev/ipic.c. Unfortunately, I have no clue why.
I've included both the Oops and a sample kernel modules that replicates the issue.
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 beating my head on this for several days now, and am open to any suggestions.