Linux设备驱动程序处理多个中断源/向量

时间:2011-03-21 15:18:25

标签: linux device-driver linux-device-driver interrupt

我正在编写一个设备驱动程序来处理PCIe卡的中断,该卡目前适用于IRQ线上产生的任何中断向量。

但它有一些可以引发的类型,由Vector寄存器标记。所以现在我需要阅读矢量信息并且有点聪明......
那么,我: -

1 /每个中断类型都有单独的开发节点/dev/int1/dev/int2等,只有int1用于矢量类型A等的文档?
1.1 /因为每个文件/ char设备都有自己的minor号码,打开时我会知道哪个是哪个。 我想。
1.2 / ldd3似乎演示了这种方法。

2 /有一个节点/dev/int (就像我现在这样做)并且有多个进程挂起了相同的read方法吗? 听起来更棒?!
2.1 /然后只唤醒正确的过程...?
2.2 /我是否使用单独的wait_queue_head_t wait_queue?或者不同的flag /测试条件?

read方法中: -

    wait_event_interruptible(wait_queue, flag);

在处理程序中不是真正的代码!: -

    int vector = read_vector();
    if vector = A then 
        wake_up_interruptible(wait_queue, flag)
        return IRQ_HANDLED;
    else
        return IRQ_NONE/IRQ_RETVAL?

编辑:各国人民的评论: - 1)我的用户空间代码mmap的所有PCIe固件寄存器
2)用户空间代码有几个线程,每个线程在设备驱动程序设备节点上执行阻塞read,然后在发生中断时从固件返回数据。我需要根据中断类型唤醒正确的线程。

3 个答案:

答案 0 :(得分:2)

我不确定我是否理解你对Vector寄存器的意思(指向某些文档的指针可以帮助我精确处理你的情况)。

无论如何,任何PCI设备都会获得一个唯一的中断号(由BIOS或其他架构上的某些固件提供,而不是x86)。您只需在驱动程序中注册此中断即可。

priv->name = DRV_NAME;
err = request_irq(pdev->irq, your_irqhandler, IRQF_SHARED, priv->name,
          pdev);
if (err) {
    dev_err(&pdev->dev, "cannot request IRQ\n");
    goto err_out_unmap;
}

另一件我不太了解的事情是你将中断导出为dev节点的原因:中断肯定需要保留在你的驱动程序/内核代码中。但我想在这里你要导出一个然后在用户空间中访问的设备。我发现 / dev / int 不是一个很好的命名。

关于多个dev节点的问题:如果你的不同中断源提供对不同硬件资源的访问(即使在同一个PCI板上),我会选择1),每个设备都有wait_queue。否则,我会选择2)

由于您的中断来自同一个物理设备,如果您选择了选项1)或选项2),则必须共享中断线,您必须阅读中的向量中断处理程序,用于定义哪个硬件资源引发了中断。

对于选项1),它将是这样的:

static irqreturn_t pex_irqhandler(int irq, void *dev) {
    struct pci_dev *pdev = dev;
    int result;

    result = pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &myirq);

    if (result) {
         int vector = read_vector();
         if (vector == A) {
                set_flagA(flag);
         } else if (vector == B) {
                set_flagB(flag);
         }
         wake_up_interruptible(wait_queue, flag);
         return IRQ_HANDLED;
    } else {
         return IRQ_NONE;
}

对于选项2,它将是类似的,但是在每个不同的中断处理程序中,您将只为每个节点请求一个if子句(对于相应的向量值)。

答案 1 :(得分:1)

如果你有read()来自不同的chanel,那么你肯定应该使用不同的次要号码。想象一下,你有一个带四个串口的卡,你肯定想要四个/dev/ttySx 但是你的设备适合这种型号吗?

答案 2 :(得分:1)

首先,我假设您没有尝试将代码放入主线内核。如果您是,请期待有关最佳方法的激烈讨论。如果您正在为一张主要由用户空间mmap驱动的卡写一个简单的中断处理驱动程序,那么有很多方法可以解决这个问题。

如果使用多个设备节点(选项1),还可以实现poll,以便单个应用程序可以打开多个设备节点并等待选择中断。次要数字足以告诉他们。如果每个向量都有一个唤醒队列,则只能唤醒相关的侦听器。成功poll后,您需要锁定向量,以确保read成功。

如果使用单个设备节点(选项2),则需要添加一些额外的魔法,以便线程可以注册他们对特定中断向量的兴趣。您可以使用ioctl执行此操作,或者让线程write成为设备的中断向量。每个线程都应该打开设备节点以获取自己的文件描述符。然后,您可以将请求的向量列表与每个打开的文件描述符相关联。作为奖励,你可以让应用程序read来自设备的中断向量,因此它知道发生了哪一个。

您需要考虑如何清除中断。中断处理程序需要删除中断,然后存储结果,以便将其传递给用户空间。您可能会发现kfifo对此有用而不是等待队列。如果每个打开的文件描述符都有一个fifo,则可以将中断通知分发给每个侦听应用程序。