IRQ interrupt is not get triggered - linux

My Driver Code :
static irqreturn_t pwm_cnt_interrupt(int irq, void *data)
{
printk("==> %s\r\n", __func__);
return IRQ_HANDLED;
}
static int ecap_cnt_probe(struct platform_device *pdev)
{
pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
if (!pc)
return -ENOMEM;
clk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(clk)) {
if (of_device_is_compatible(np, "ti,counter-ecap")) {
dev_warn(&pdev->dev, "Binding is obsolete.\n");
clk = devm_clk_get(pdev->dev.parent, "fck");
}
}
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
return PTR_ERR(clk);
}
pc->clk_rate = clk_get_rate(clk);
if (!pc->clk_rate) {
dev_err(&pdev->dev, "failed to get clock rate\n");
return -EINVAL;
}
/* Get PWM IRQ number */
ecapirq = platform_get_irq(pdev, 0);
if (ecapirq < 0) {
printk(KERN_ERR "Could not get IRQ");
return -EINVAL;
}
printk(KERN_DEBUG "irq = %d\n", ecapirq);
oreore_dentry = debugfs_create_file("counter", 0666, NULL, &value, &fops);
if(request_irq(ecapirq, pwm_cnt_interrupt, IRQF_SHARED,
"counter", (void *)&counter)) {
printk(KERN_ERR "pwm counter: Can't allocate irq %d\n",
ecapirq);
return -EBUSY;
}
enable_irq(ecapirq);
return 0;
}
My Interrupt got registed in /proc/interrupts
But, Its not get triggered.
I have connected UART with my pwm interrupt pin. I m sending data using uart port. my irq handler is not get called at that time.
Need help on this.

Related

c - Can't subscribe to new signal handler in Linux

I'm trying to subscribe to a new signal handler in my current signal handler but nothing happens. No output from usr1b is printed in terminal, output from usr1a is printed in terminal.
Code:
#include<signal.h>
#include<stdio.h>
#include<unistd.h>
static int counter = 0;
void usr1b(int sig1) {
printf("usr1b\n");
counter++;
printf("current count: %d", counter);
}
void usr1a(int sig) {
printf("usr1a\n");
if( signal(SIGUSR1, usr1b) == SIG_ERR) {
printf("ERROR\n"); // subscribe usr1b to SIGUSR1
}
}
int main(void) {
if(signal(SIGINT, SIG_IGN)==SIG_ERR)
printf("ERROR"); // ignore SIGINT
if(signal(SIGUSR1, usr1a)==SIG_ERR)
printf("ERROR"); // subscribe usr1a to SIGUSR1
printf("Send some signal to process %d\n", getpid());
while (1) {
sleep(1);
}
return 0;
}
Try this...
static void usr1b(int signo) {
if (signo == SIGUSR1) {
cnt++;
printf("SIGUSR1 count: %d\n", cnt);
}
}

Linux Device Driver open error

I am new with Linux.
I have made a USB skeleton driver and one application program which open and close skeleton.
But it gives error can't open device.
Can anyone tell me the possible reason why this may happen?
This simple driver programs needs any device attached with usb port ?
Here is my application programs
int main()
/* no memory-swapping for this programm */
ret = mlockall(MCL_CURRENT | MCL_FUTURE);
if (ret) {
perror("ERROR : mlockall has failled");
exit(1);
}
/*
* Turn the NRTcurrent task into a RT-task.
* */
ret = rt_task_shadow(&rt_task_desc, NULL, 1, 0);
if (ret)
{
fprintf(stderr, "ERROR : rt_task_shadow: %s\n",
strerror(-ret));
exit(1);
}
/* open the device */
device = rt_dev_open(DEVICE_NAME, 0);
if (device < 0) {
printf("ERROR : can't open device %s (%s)\n",
DEVICE_NAME, strerror(-device));
exit(1);
}
/*
* If an argument was given on the command line, write it to the device,
* otherwise, read from the device.
*/
/* close the device */
ret = rt_dev_close(device);
if (ret < 0) {
printf("ERROR : can't close device %s (%s)\n",
DEVICE_NAME, strerror(-ret));
exit(1);
}
return 0;
}
Here is a my driver open function
static int skel_open(struct inode *inode, struct file *file)
{
struct usb_skel *dev;
struct usb_interface *interface;
int subminor;
int retval = 0;
subminor = iminor(inode);
interface = usb_find_interface(&skel_driver, subminor);
if (!interface) {
pr_err("%s - error, can't find device for minor %d\n",
__func__, subminor);
retval = -ENODEV;
goto exit;
}
dev = usb_get_intfdata(interface);
if (!dev) {
retval = -ENODEV;
goto exit;
}
/* increment our usage count for the device */
kref_get(&dev->kref);
/* lock the device to allow correctly handling errors
* in resumption */
mutex_lock(&dev->io_mutex);
retval = usb_autopm_get_interface(interface);
if (retval)
goto out_err;
/* save our object in the file's private structure */
file->private_data = dev;
mutex_unlock(&dev->io_mutex);
exit:
return retval;
}

ARM char device driver initialization isn't creating /dev/ file

I am writing a driver for the GPIO pins on an ARM platform.
My driver works correctly and I've avoided the problem until
now by manually mknod'ing a device file.
my initialization code:
static int __init gpio_init (void)
{
void *ptr_error;
if (register_chrdev(249, "gpio_device", &fops) < 0){
printk(KERN_INFO "Registering device failed\n");
return -EINVAL;
}
if ((device_class = class_create(THIS_MODULE, "gpio_device"))
== NULL){
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Class creation failed\n");
return -EINVAL;
}
ptr_error = device_create(device_class, NULL, DEV_T, NULL, "gpio_device");
if (IS_ERR(ptr_error)){
class_destroy(device_class);
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Device creation failed\n");
return -EINVAL;
}
cdev_init(&c_dev, &fops);
if (cdev_add(&c_dev, DEV_T, 1)){
device_destroy(device_class, DEV_T);
class_destroy(device_class);
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Cdev add failed\n");
return -EINVAL;
}
printk(KERN_INFO "Guten tag, GPIO driver initialized\n");
return SUCCESS;
}
This runs with no errors, except no file "gpio_device" is created in /dev.
I'm cross compiling for ARM onto kernel 2.6.39.4. (using arm-linux-gcc)
As I understand it, device_create should be creating the /dev file.
I tried running your code and found a few mistakes:
When you register with register_chrdev(), you should unregister with unregister_chrdev(). unregister_chrdev_region() is used to unregister a registration done with alloc_chrdev_region() or register_chrdev_region().
A call to register_chrdev() registers minor numbers 0-255 for the given major, and sets up a default cdev structure for each, therefore, you do not need to deal with the cdev_init() & cdev_add().
You should check the error using IS_ERR & PTR_ERR for class_create() & device_create() as PTR_ERR will turn the return pointer to the error code with a cast.
You can read more here: Char Device Registration.
After applying the modification I mentioned, the /dev/gpio_device is created without mknod:
int init_module(void)
{
void *ptr_error;
struct cdev* c_dev;
int result=0;
/* register_chrdev */
result=register_chrdev(my_major, "gpio_device", &fops);
if (result < 0)
{
printk(KERN_INFO "Registering device failed\n");
return result;
}
DEV_T = MKDEV(my_major, my_minor);
/* class_create */
device_class = class_create(THIS_MODULE, "gpio_device");
if (IS_ERR(device_class))
{
unregister_chrdev(my_major, "gpio_device");
printk(KERN_INFO "Class creation failed\n");
return PTR_ERR(device_class);
}
/* device_create */
ptr_error = device_create(device_class, NULL, DEV_T, NULL, "gpio_device");
if (IS_ERR(ptr_error))
{
class_destroy(device_class);
unregister_chrdev(my_major, "gpio_device");
printk(KERN_INFO "Device creation failed\n");
return PTR_ERR(ptr_error);
}
/* //removed
cdev_init(&c_dev, &fops);
if (cdev_add(&c_dev, DEV_T, 1)){
device_destroy(device_class, DEV_T);
class_destroy(device_class);
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Cdev add failed\n");
return -EINVAL;
}*/
printk(KERN_INFO "Guten tag, GPIO driver initialized\n");
return SUCCESS;
}
I just figured out what was going on here.
We are using BuildRoot to create our custom
linux, and the it turns out we had compiled
out the udev device file management system.
So that's why this doesn't work.

How to soft reboot from a non-monolithic kernel module in an IRQ scope?

I need to reboot upon handling an IRQ in kernel land.
I want to call the /sbin/reboot binary, but I have got limitations due to the IRQ scope.
Code follows :
#define MY_IRQ_ID 42
void __init rebootmodule_init(void) {
request_any_context_irq(MY_IRQ_ID, rebootmodule_irq_handler, IRQF_TRIGGER_FALLING, "irq-name", NULL);
}
irqreturn_t rebootmodule_irq_handler(int irq, void *dev_id) {
my_reboot();
return IRQ_HANDLED;
}
void my_reboot(void) {
int ret;
char *argv[2], *envp[4];
argv[0] = "/sbin/reboot";
argv[1] = NULL;
envp[0] = "HOME=/";
envp[1] = "PWD=/";
envp[2] = "PATH=/sbin";
envp[3] = NULL;
ret = call_usermodehelper(argv[0], argv, envp, 0);
printk(KERN_INFO "trying to reboot (ret = %d)", ret);
}
I can see the printk(...) when the IRQ is triggered but I have some errors, even if I replace /sbin/reboot by /bin/rm /tmp/its-not-working.
I tested other way to do reboot like mvBoardReset(), machine_halt(), arm_pm_restart(), pm_power_off(), kill(1, SIGTSTP), reboot(), handle_sysrq('b'), I always have errors that I don't have outside the IRQ scope.
I really want to call /sbin/reboot, since it does clean soft reset.
Thank you for your time.
Just an idea: you can start kernel thread by kthread_run(), put it to sleep by wait_event(), wake it up in the IRQ handler by wake_up(), do your stuff (run /sbin/reboot or whatever you want) in the kernel thread. Something like this (completely untested):
#define MY_IRQ_ID 42
static DECLARE_WAIT_QUEUE_HEAD(wq);
static volatile int showtime = 0;
void my_reboot(void) {
int ret;
char *argv[2], *envp[4];
argv[0] = "/sbin/reboot";
argv[1] = NULL;
envp[0] = "HOME=/";
envp[1] = "PWD=/";
envp[2] = "PATH=/sbin";
envp[3] = NULL;
ret = call_usermodehelper(argv[0], argv, envp, 0);
printk(KERN_INFO "trying to reboot (ret = %d)", ret);
}
static int my_thread(void *arg) {
wait_event(&wq, showtime);
my_reboot();
return 0;
}
irqreturn_t rebootmodule_irq_handler(int irq, void *dev_id) {
showtime = 1;
wake_up(&wq);
return IRQ_HANDLED;
}
void __init rebootmodule_init(void) {
kthread_run(my_thread, NULL, "my_module");
request_any_context_irq(MY_IRQ_ID, rebootmodule_irq_handler, IRQF_TRIGGER_FALLING, "irq-name", NULL);
}
Don't forget to handle module __exit and the case when interrupt has come before the kernel thread was sent to sleep.

Problem with netlink socket: kernel freeze

I'm trying to use netlink sockets to exchange messages between user-space and kernel space...i send a message from user-space to kernel-space and all works well but when i try to reply from kernel-space, system freezes. In particular i schedule with a workqueue a function that create the message and send to user-space using netlink_unicast function...here some kernel code:
void wq_func(struct work_queue *wq)
{
struct sk_buff *resp = alloc_skb(NLMSG_LENGTH(100), GFP_KERNEL);
if (!resp)
{
printk(KERN_INFO "alloc_skb failed");
return;
}
struct nlmsghdr *nlh = (struct nlmsghdr *)skb_put(resp, NLMSG_LENGTH(100));
memset(nlh, 0, NLMSG_LENGTH(100));
nlh->nlmsg_len = NLMSG_LENGTH(100);
nlh->nlmsg_pid = 0;
nlh->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nlh), "From kernel: Yes i'm here!");
NETLINK_CB(resp).pid = 0;
NETLINK_CB(resp).dst_group = 0;
printk(KERN_INFO "Trying to send a netlink message to pid %d", pid);
int err = netlink_unicast(s, resp, pid, MSG_DONTWAIT);
if (err < 0)
printk(KERN_ALERT "Error sending message to user-space");
kfree_skb(resp);
}
DECLARE_WORK(wq, wq_func);
static void input_nl(struct sk_buff *buff)
{
printk(KERN_INFO "Received message socket NETLINK_TEST");
if (buff == NULL)
{
printk(KERN_ALERT "NULL sk_buff!");
return;
}
struct nlmsghdr *nlh = (struct nlmsghdr *)buff->data;
printk(KERN_INFO "Received netlink message from pid %d: %s", nlh->nlmsg_pid, NLMSG_DATA(nlh));
pid = nlh->nlmsg_pid;
schedule_work(&wq);
}
int __init knl_init()
{
printk(KERN_INFO "knl module loaded");
s = netlink_kernel_create(&init_net, NETLINK_TEST, 0, input_nl, NULL, THIS_MODULE);
if (s == NULL)
return -1;
return 0;
}
If i try to comment the call to netlink_unicast kernel doesn't freeze. From user-space i can send a message correctly. I remember that the same code worked well in the past and i 'm very surprised about this strange error now.
Any idea?
Thank you all!
I tried to remove kfree_skb call after netlink_unicast call and all works...so, why the system hangs with that call? Where should i free allocated sk_buff?
netlink_unicast() takes ownership of the skb and frees it itself.
After calling netlink_unicast you cannot free struct sk_buff

Resources