LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 07-16-2008, 11:45 AM   #1
bshan85
LQ Newbie
 
Registered: Jan 2008
Posts: 4

Rep: Reputation: 0
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
 
Old 07-16-2008, 12:02 PM   #2
resetreset
Senior Member
 
Registered: Mar 2008
Location: Cyberspace
Distribution: Dynebolic, Ubuntu 10.10
Posts: 1,340

Rep: Reputation: 62
which interrupt?
 
Old 07-16-2008, 01:27 PM   #3
rjlee
Senior Member
 
Registered: Jul 2004
Distribution: Ubuntu 7.04
Posts: 1,994

Rep: Reputation: 76
Quote:
Originally Posted by bshan85 View Post
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.
 
Old 07-17-2008, 11:27 AM   #4
bshan85
LQ Newbie
 
Registered: Jan 2008
Posts: 4

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by rjlee View Post
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);
 
Old 07-26-2008, 08:33 AM   #5
rjlee
Senior Member
 
Registered: Jul 2004
Distribution: Ubuntu 7.04
Posts: 1,994

Rep: Reputation: 76
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
 
Old 07-27-2008, 01:51 PM   #6
bshan85
LQ Newbie
 
Registered: Jan 2008
Posts: 4

Original Poster
Rep: Reputation: 0
Thank you

Quote:
Originally Posted by rjlee View Post
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...
 
Old 07-27-2008, 02:01 PM   #7
rjlee
Senior Member
 
Registered: Jul 2004
Distribution: Ubuntu 7.04
Posts: 1,994

Rep: Reputation: 76
Quote:
Originally Posted by bshan85 View Post
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
 
Old 06-03-2009, 09:21 AM   #8
bshan85
LQ Newbie
 
Registered: Jan 2008
Posts: 4

Original Poster
Rep: Reputation: 0
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.......
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
lowest level of interrupt handling in kernel ashok449 Linux - Kernel 6 07-28-2008 08:44 AM
interrupt handling... culin Programming 2 02-12-2007 11:35 PM
Interrupt handling in C vkmgeek Programming 4 02-28-2006 01:42 AM
interrupt handling mp4-10 Programming 5 02-14-2005 06:13 AM
Interrupt handling in gcc? captainstorm Programming 13 07-16-2003 05:57 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 09:08 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration