处理字符设备中的中断

Handling interrupt in character device

我正在尝试在用户界面的内核中正确注册中断。

令人惊讶的是,我没有在内核中找到很多这样的例子。

irq 处理程序

static irqreturn_t irq_handler(int irq, void *dev_id)
{
   struct el_irq_dev *el_irq = &el_irq_devices[0];
    printk("irq in\n");

    spin_lock(&el->my_lock,flags);

    clear_interrupt() 

    some_buffer[buf_wr] = ch;
    el_irq->buf_wr++;
    if (el_irqbuf_wr >= 16)
        el_irqbuf_wr = 0;


     spin_unlock(&el->my_lock,flags);
     wake_up_interruptible(&el->pollw);



return IRQ_HANDLED;

}

ioctl 用于等待中断

static long el_device_ioctl( struct file *filp, 
         unsigned int ioctl_num, 
         unsigned long ioctl_param)
{
    struct el_irq_dev *el_irq = &el_irq_devices[0];
switch (ioctl_num) {
case IOCTL_WAIT_IRQ:      <<<---- using ioctl (no poll) to wait on interrupt
    wait_event_interruptible(el_irq->pollw, &el_irq->buf_wr != &el_irq->buf_rd) ;
    spin_lock(&el_irq->my_lock);
    if (el_irq->buf_wr != &el_irq->buf_rd)
    {
        my_value=some_buffer[el_irq->buf_rd];
        el_irq->buf_rd++;
        if (el_irq->buf_rd >= 16)
            el_irq->buf_rd = 0;
    }

    spin_unlock(&el_irq->my_lock);
    copy_to_user(ioctl_param,&my_value,sizeof(my_value));

default:
        break;
    }
    return 0;
}

我的问题是:

  1. 我们是否应该将fpga中的中断清除(clear_interrupt())放在中断中 在 wake_up 之前还是之后?我们能否将清除中断事件放在用户空间处理程序 (IOCTL_WAIT_IRQ) 中,而不是在 中断处理程序 ?
  2. 如您在代码中所见,我使用循环缓冲区来处理用户空间处理程序缺少中断的情况。这真的是必需的,还是我们可以假设没有遗漏? 换句话说,假设永远不会错过中断是否合理?这样 ioctl 调用就永远不会看到超过 1 个等待中断?如果是 - 也许我不需要中断处理程序和 ioctl 处理程序之间的缓冲机制。

谢谢, 运行

简答。

  1. 我认为清除 user-space 处理程序中的中断似乎是合理的。在完成所有工作之后,尽可能晚地进行是有道理的,只要您在清除后再次检查确实没有剩下的工作要做(可能在清除之前还有一些工作已经到达)。
  2. user-space 处理程序可能确实错过了中断,例如如果在调用 IOCTL_WAIT_IRQ 之间有几个到达。如果在清除中断之前有几项工作到达,中断在某种意义上也可能会得到 "missed"。堆栈(硬件和软件)的设计应确保这不是问题。中断应该只发出有工作要做的信号,user-space 处理程序应该能够在返回之前完成所有未完成的工作。
  3. 您可能应该在 IOCtl 代码中使用 spin_lock_irqsave()[1]。

[1] http://www.makelinux.net/ldd3/chp-5-sect-5