LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   interrupt handling problem in kernel version 2.6.8.53 (https://www.linuxquestions.org/questions/linux-newbie-8/interrupt-handling-problem-in-kernel-version-2-6-8-53-a-656163/)

bshan85 07-16-2008 11:45 AM

interrupt handling problem in kernel version 2.6.8.53
 
hi to all,
i am writing device driver in RHEL5.1(Kernel 2.6.18.53el).
i am writng driver pci devices..
Irq registeration is being successfully done ..but interrupt is not being generated.Previously i was using Kernel 2.6.9 vesion..its working in this version..Please help me

resetreset 07-16-2008 12:02 PM

which interrupt?

rjlee 07-16-2008 01:27 PM

Quote:

Originally Posted by bshan85 (Post 3216588)
hi to all,
i am writing device driver in RHEL5.1(Kernel 2.6.18.53el).
i am writng driver pci devices..
Irq registeration is being successfully done ..but interrupt is not being generated.Previously i was using Kernel 2.6.9 vesion..its working in this version..Please help me

Can you post the source code?

If it's a kernel version problem, then you might want to take a look at the kernel changes. A somewhat more readable form than the official changelog can be found at http://kernelnewbies.org/Linux26Changes

Incidentally, 2.6.26 is the current version, so you might try upgrading and seeing if that fixes the problem. But, without knowing what the problem is, that's quite a long shot.

bshan85 07-17-2008 11:27 AM

Quote:

Originally Posted by rjlee (Post 3216690)
Can you post the source code?

If it's a kernel version problem, then you might want to take a look at the kernel changes. A somewhat more readable form than the official changelog can be found at http://kernelnewbies.org/Linux26Changes

Incidentally, 2.6.26 is the current version, so you might try upgrading and seeing if that fixes the problem. But, without knowing what the problem is, that's quite a long shot.


#include <linux/pci.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include "park_irigb.h"
MODULE_LICENSE("GPL");
#define DEBUG 1
void* PCM_Mapped_Addr[MAXCARDS];
void *Base_Addr[MAXCARDS];
unsigned short pcm_irq[MAXCARDS];
unsigned long mem_size[MAXCARDS];
UCHAR cardsfound=0;
int cards[MAXCARDS];
pid_t processno;
int Tcrflag[MAXCARDS];
int SignalNo;
int Pid;
Uchar g_PortReg;
Uchar g_LeapReg;



UCHAR bIntFlag[MAXCARDS] ;
UCHAR bD0_D1Flag[MAXCARDS];
UCHAR bD3Flag[MAXCARDS] ;
UCHAR bD7Flag[MAXCARDS] ;
UCHAR bD2Flag[MAXCARDS] ;
UCHAR signalflag=0;


int GetDetails();
int pcm_interrupt_handler(int i,void *v,struct pt_regs *pt_reg);

int pcm_interrupt_handler(int i,void *v,struct pt_regs *pt_reg)
{
/* UCHAR card;
UCHAR intRegister;
card=*(UCHAR*)v;
intRegister = readb((UCHAR *)PCM_Mapped_Addr[0]+STATUS_REG);
if(intRegister != 0x3f)
if(intRegister != 0x3e)
if(intRegister != 0x3c)
if(intRegister != 0x38)

{
#ifdef DEBUG
printk("Interrupt Genarated is from other Device %x\n",card);
#endif
return -1;
}

#ifdef DEBUG
printk("Inside the Interrupt Service Routine Card: %d\n",card);
#endif
// Send Signal
*/
kill_proc ( Pid, SignalNo, 0 );
//Clearing the Timer Interrupt
writeb(0xFF,(UCHAR *)PCM_Mapped_Addr[0]+0x00);
readb((UCHAR *)PCM_Mapped_Addr[0]+0x00);

return IRQ_HANDLED;
}

int GetDetails()
{
unsigned long max,min;
int i,j;
struct pci_dev *de=NULL,*df=NULL;
ULONG k=0;
for(i=0;i<MAXCARDS;i++)
{
while(!(de = pci_find_device(VENDOR,DEVICE,de)))
{
k++;
if(k>256*256)
break;
}
if(k>256*256)
break;
if(i == 0)
{
df=de;
}
else
{
if(df==de)
break;
}
for(j=0;j<(6*4);j+=4)
{
pci_read_config_dword(de,0x10+j,(u32 *)&Base_Addr[i]);
if(Base_Addr[i])
{
// Calculate Size
min=pci_resource_start(de,j/4);
max=pci_resource_end(de,j/4);
mem_size[i]=(max-min)+1;
break;
}
}

pcm_irq[i]=de->irq;
(unsigned long)Base_Addr[i]=((unsigned long)Base_Addr[i])&0xfffffff0;
(void *)PCM_Mapped_Addr[i]=(void *)ioremap((unsigned long)Base_Addr[i],mem_size[i]);
#ifdef DEBUG
printk("<1>device %lx : Irq :%x Size:%lx\n",(u32 *)Base_Addr[i],pcm_irq[i],mem_size[i]);
printk("<1>Mapped Addr : %lx\n",PCM_Mapped_Addr[i]);
#endif

}
return i;
}



static int pcm_open(struct inode *inode, struct file *filp)
{
return 0;

}


static int pcm_close(struct inode *inode, struct file *filp)
{
return 0;
}


ssize_t pcm_read(struct file *filp, char *buff, size_t count, loff_t *offset)
{
return 0;
}


ssize_t pcm_write(struct file *filp, const char *buf, size_t count, loff_t *offset)
{
return 0;
}

int pcm_control(struct inode *inode, struct file *filp, unsigned int command, unsigned long argument)
{
return 0;
}

struct file_operations pcm_fops = {
read : pcm_read,
write : pcm_write,
open : pcm_open,
release : pcm_close,
ioctl : pcm_control,
owner : THIS_MODULE,
};



int pcm_init(void)
{
int major,i=0,q=0;
cardsfound=GetDetails();
if(cardsfound<=0)
return -10;
#ifdef DEBUG
printk("<1>Cards Found : %d\n",cardsfound);
#endif
// Interrupt Handler
for(i=0;i<cardsfound;i++)
{
cards[i]=i;
q=request_irq(pcm_irq[0],pcm_interrupt_handler,SA_INTERRUPT | SA_SHIRQ,"TCR",&cards[0]);
}
printk("int request:%d\n",q);
major = register_chrdev(TCR_MAJOR,"TCR_DEV",&pcm_fops);

return 0;

}

/****************************************************************************
CLOSE OF DRIVER MODULE
*****************************************************************************/

void pcm_cleanup(void)
{
int i=0;
printk("<1> Unloading Driver \n");
unregister_chrdev(TCR_MAJOR,"TCR_DEV");
for(i=0;i<cardsfound;i++)
{
free_irq(pcm_irq[i],&cards[i]);
}
}

module_init(pcm_init);
module_exit(pcm_cleanup);

rjlee 07-26-2008 08:33 AM

Sorry it took me a while to get back to you; I was rather busy with other things and I thought it best to wait until I had time for a proper look at this one.

The first thing that hits me is that GetDetails() isn't called anywhere. This could be an issue since it assigns to your module's variables. But you say that the IRQ is registered correctly; I guess from that that you're seeing the debug output from GetDetails() so you must be calling it somehow yourself? Or are you referring to the IRQ being registered with the PCI interrupt handler itself?

Similarly, you declare and define the pcm_interrupt_handler() method but never do anything with it. In the case of PCI devices, when an interrupt occurs, the PCI interrupt handler goes through the irq_action vector, which contains all the registered interrupt handlers for that interrupt and calls each one in turn, until one of them processes the interrupt. So your interrupt handler must be in that vector for it to work.

Normally, the request_irq() method (linux/interrupt.h) is used to register an interrupt handler. This is probably the most important bit to get right. Something like this:
Code:

  // .... find your device, then:
        pci_enable_device(dev);
        irq = dev->irq;
        result=request_irq(irq, handler, SA_INTERRUPT|SA_SHIRQ,
                          "device name", (void *)parameters);

[cite reference: http://linux.derkeiler.com/Mailing-L...5-03/6066.html]

It is also theoretically possible that your device is sharing an IRQ line with another device, and that that device's driver has some bug that causes it to claim your interrupts as it's own. If so, you may be able to do something about this by changing the BIOS device mappings, or reconfiguring the card to use a different interrupt line.

Is your PCI device listed in /sys/devices? If not, you may need to call register_device to register the PCI device.

There should also be a listing for your driver in /sys/bus/pci/drivers/; if not, you should call driver_register() to create it.

Finally, are you sure that another driver hasn't already claimed the same device?

By the way, you don't need to define dummy methods for pcm_read, pcm_write, etc; if you're not using that operation then you can just set it to null. See http://www.faqs.org/docs/kernel/x571.html.

Yours,

—Robert J Lee

bshan85 07-27-2008 01:51 PM

Thank you
 
Quote:

Originally Posted by rjlee (Post 3226889)
Sorry it took me a while to get back to you; I was rather busy with other things and I thought it best to wait until I had time for a proper look at this one.

The first thing that hits me is that GetDetails() isn't called anywhere. This could be an issue since it assigns to your module's variables. But you say that the IRQ is registered correctly; I guess from that that you're seeing the debug output from GetDetails() so you must be calling it somehow yourself? Or are you referring to the IRQ being registered with the PCI interrupt handler itself?

Similarly, you declare and define the pcm_interrupt_handler() method but never do anything with it. In the case of PCI devices, when an interrupt occurs, the PCI interrupt handler goes through the irq_action vector, which contains all the registered interrupt handlers for that interrupt and calls each one in turn, until one of them processes the interrupt. So your interrupt handler must be in that vector for it to work.

Normally, the request_irq() method (linux/interrupt.h) is used to register an interrupt handler. This is probably the most important bit to get right. Something like this:
Code:

  // .... find your device, then:
        pci_enable_device(dev);
        irq = dev->irq;
        result=request_irq(irq, handler, SA_INTERRUPT|SA_SHIRQ,
                          "device name", (void *)parameters);

[cite reference: http://linux.derkeiler.com/Mailing-L...5-03/6066.html]

It is also theoretically possible that your device is sharing an IRQ line with another device, and that that device's driver has some bug that causes it to claim your interrupts as it's own. If so, you may be able to do something about this by changing the BIOS device mappings, or reconfiguring the card to use a different interrupt line.

Is your PCI device listed in /sys/devices? If not, you may need to call register_device to register the PCI device.

There should also be a listing for your driver in /sys/bus/pci/drivers/; if not, you should call driver_register() to create it.

Finally, are you sure that another driver hasn't already claimed the same device?

By the way, you don't need to define dummy methods for pcm_read, pcm_write, etc; if you're not using that operation then you can just set it to null. See http://www.faqs.org/docs/kernel/x571.html.

Yours,

—Robert J Lee

hi Robert...
Thank u for ur infornation.Now i got it .
Problem was that i was registering the irq handler with irq number which is read from pci configuration space(Physical no).I thing IRQ no is mapped in to some other no which we get from dev->irq.That is what i understood.If i am wrong make me to understand...

rjlee 07-27-2008 02:01 PM

Quote:

Originally Posted by bshan85 (Post 3227834)
hi Robert...
Thank u for ur infornation.Now i got it .
Problem was that i was registering the irq handler with irq number which is read from pci configuration space(Physical no).I thing IRQ no is mapped in to some other no which we get from dev->irq.That is what i understood.If i am wrong make me to understand...

That sounds about right to me. I don't know the exact details off-hand, but IIRC the PCI controller has a set of pins which are mapped in hardware to the IRQ lines. A map in the BIOS (or just in the kernel, depending on the motherboard support) also maps these pins to the IRQ.

I think that the physical number identifies the pin on the PCI controller, which is possibly only useful to module writers if you are debugging with an oscilloscope.

Yours,

—Robert Lee

bshan85 06-03-2009 09:21 AM

Hi Robert,
This is shan.
I am facing one problem in SMP version.
I am using RHEL 2.6.8 version
My system has Atmel two processor.
I have written driver for interrupt based cPci card...
I am getting interrupt when i boot with single core kernel.
But i am not getting any interrupt when i boot with SMP kernel.
i dont thing there will be change in the driver between SMP and single core.if any please assist me.......


All times are GMT -5. The time now is 02:02 AM.