LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Kernel (https://www.linuxquestions.org/questions/linux-kernel-70/)
-   -   Module Issue (https://www.linuxquestions.org/questions/linux-kernel-70/module-issue-909132/)

humph 10-20-2011 05:17 AM

Module Issue
 
Hi guys. I'm currently trying to test the interrupt line on a PowerPC device. To do this I am creating a module that does a simple printk when the Interrupt is triggered. It cross-compiles without any errors or warnings but the problem I'm encountering is that when I try to do an insmod on the target device there is an error that prevents the module from being loaded. The code for the module is:

Code:

//int_test.c

#include <linux/kernel.h>             
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>




//static irqreturn_t irq_handler(int irq, void *dev_id)
irqreturn_t irq_handler(int irq, void *dev_id)
{
  printk("IRQ5 triggered\n");
  return IRQ_HANDLED;
}


int init_module()
{
       
        printk("testing\n");       
  return request_irq(5, 
              irq_handler, 
              IRQF_SHARED,
              "tst_interrupt",NULL);
        printk("Set up IRQ5\n");
}

/* Cleanup */
void cleanup_module()
{
        free_irq(5, NULL);
}

The Makefile is simply:

Code:

obj-m  :=  int_test.o
When I run it I get the error:
Code:

[root@p1021mds /root]# insmod int_test.ko                                     
int_test: module license 'unspecified' taints kernel.                         
Disabling lock debugging due to kernel taint                                   
testing                                                                       
insmod: error inserting 'int_test.ko': -1 Invalid parameters

dmesg gives:

Code:

PHY: mdio@ffe24000:02 - Link is Up - 1000/Full                                 
testing                                                                       
int_test: module license 'unspecified' taints kernel.                         
Disabling lock debugging due to kernel taint                                   
testing

If anyone has come across this before or thinks they know what the cause might be I'd greatly appreciate the help. If I've left any information out just ask.

Thanks a lot.

EDIT: Forgot to mention that the kernel version is "3.0.4+ #14 SMP" on the target board.

Aquarius_Girl 10-21-2011 12:12 AM

Is the code getting compiled without any errors?
Quote:

Originally Posted by humph (Post 4503294)
The Makefile is simply:
Code:

obj-m  :=  int_test.o

The Makefile of a kernel module usually contains:
Code:

obj-m += hello.o

all:
......make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
......make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Makefile is TAB sensitive. The red dots above need to be replaced
by a TAB.

For getting rid of the Kernel taint message, you need to add the following
to your code.
Code:

MODULE_LICENSE ("GPL");

humph 10-21-2011 04:04 AM

Thanks for the reply. The code is getting compiled error free and with regards to the make file I've omitted that and just enter the Linux directory in the terminal. Found that the reason insmod was not loading the module was due to request_irq() returning an error value and not 0. Apparently one of the parameters is invalid so I'm not trying to hunt down the source code for request_irq() to work out exactly what is going on.

Aquarius_Girl 10-21-2011 04:10 AM

Quote:

Originally Posted by humph (Post 4504109)
Found that the reason insmod was not loading the module was due to request_irq() returning an error value and not 0.

How did you find that request_irq is not returning 0?
AFAIK, for "executing" a kernel module, one has to "insmod" it.
Am I missing a point here?

humph 10-21-2011 07:14 AM

I changed the hi.c code to:

Quote:

static int hi(void)
{
/*printk(KERN_INFO "Hello from hi module.\n");
printk(KERN_INFO "The user space process is '%s'\n", current->comm);
printk(KERN_INFO "The user space PID is %i\n", current->pid);
return 0; // to show a successful load*/
printk("Setting up IRQ5\n");
int error;


struct device dev;


error = request_irq(5,
irq_handl,
0,
"Int Test",&dev);

if(error == 0){
printk("0 error returned\n");
return 0;
}
else{
printk("%d\n",error);
return 0;
}
}

static void bye(void)
{
printk(KERN_INFO "Goodbye from hi module.\n");
}

module_init(hi);
module_exit(bye);

MODULE_AUTHOR("Robert P. J. Day");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION("2:1.0") ;
MODULE_DESCRIPTION("You have to start somewhere.");
So now I can actually see what it is returning. The error number it returns is 22, or an invalid parameter. I am trying to track down where in the Kernel is actually returning this error. So far I know it goes to interrupt.h (http://lxr.free-electrons.com/source...a=powerpc#L129) as I inserted a printk at that point in the code. However I'm still unsuccessful in tracking where it goes after that.

rulingminds 10-22-2011 09:45 AM

Problem is with the irq number. In case of Powerpc, the irq number should be mapped to a virtual irq and that will be passed to the request_irq(). Generally irq will be specified in the device tree and the function of_irq_to_resource() is called to get the virq for the irq that is taken from the device tree.

humph 10-24-2011 04:40 AM

Thanks for the reply. That sounds pretty promising so I'll give it a go.

humph 10-25-2011 08:46 AM

Hi everyone. I had a look through the kernel looking for some examples of virtual IRQs and from that edited my code to the following:
Code:

//IRQF_SHARED
#include <linux/module.h>      // for all modules
#include <linux/init.h>        // for entry/exit macros
#include <linux/kernel.h>      // for printk priority macros
#include <asm/current.h>        // process information, just for fun
#include <linux/sched.h>        // for "struct task_struct"
#include <linux/interrupt.h>
#include <linux/device.h>









static irqreturn_t irq_handl(int irq, void *dev_id)
{       
  printk("IRQ5 triggered\n");
  return IRQ_HANDLED;
}
 



static int hi(void)
{
        /*printk(KERN_INFO "Hello from hi module.\n");
        printk(KERN_INFO "The user space process is '%s'\n", current->comm);
        printk(KERN_INFO "The user space PID is  %i\n", current->pid);
        return 0;      // to show a successful load*/
        printk("Setting up IRQ5\n");
        int error; 
       
        struct device dev;
        int virq;
        unsigned long mapIRQ;
       
        mapIRQ = 5;
       
        virq = irq_create_mapping(NULL,mapIRQ);
 
       
              error = request_irq(virq, 
              irq_handl, 
              0,
              "Int Test",&dev);

        if(error == 0){
                printk("0 error returned\n");               
                return 0;
        }
        else{
                printk("%d\n",error);
                return 0;
        }       
}

static void bye(void)
{
        printk(KERN_INFO "Goodbye from hi module.\n");
}

module_init(hi);
module_exit(bye);

MODULE_AUTHOR("Robert P. J. Day");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION("2:1.0") ;
MODULE_DESCRIPTION("You have to start somewhere.");

So it now compiles and returns what I'm expecting after performing an insmod:
Code:

Setting up IRQ5                                                               
This is before calling the request threaded IRQ                               
0 error returned

I verified that it had been registered by Linux through /proc/interrupts:
Code:

[root@p1021mds /root]# cat /proc/interrupts                                   
          CPU0      CPU1                                                     
 18:          8          0  OpenPIC  Level    phy_interrupt                 
 19:          0          0  OpenPIC  Level    fsl-lbc                       
 22:          0        30  OpenPIC  Level    eth1_g0_rx                   
 23:          0          0  OpenPIC  Edge      Int Test                     
 25:          0        28  OpenPIC  Level    eth1_g1_tx                   
 26:          0          0  OpenPIC  Level    eth1_g1_rx                   
 27:          0          0  OpenPIC  Level    eth1_g1_er                   
 28:        27          0  OpenPIC  Level    ehci_hcd:usb1                 
 31:          1          0  OpenPIC  Level    eth1_g0_tx                   
 33:          0          0  OpenPIC  Level    eth1_g0_er                   
 42:      1066          0  OpenPIC  Level    serial                       
 43:          0          0  OpenPIC  Level    i2c-mpc, i2c-mpc             
 45:          0          0  OpenPIC  Level    talitos                       
 72:          0          0  OpenPIC  Level    mmc0                         
251:          0          0  OpenPIC  Edge      ipi call function             
252:      1568      1887  OpenPIC  Edge      ipi reschedule               
253:        28        14  OpenPIC  Edge      ipi call function single     
LOC:      2179      4191  Local timer interrupts                           
SPU:          1          0  Spurious interrupts                               
CNT:          0          0  Performance monitoring interrupts                 
MCE:          0          0  Machine check exceptions

However, when I'm testing the pin (by putting a pull-up button combination that asserts a low with a button press) I am not getting the "IRQ5 triggered" message. I was just wondering if anyone could verify that what I've done in my code is correct or, more than likely, wrong. Thanks a lot.

humph 10-26-2011 07:53 AM

It turned out to be a problem in hardware and it's working now. Thanks for the help.


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