request_irq失败,因为没有irq描述符

问题描述 投票:0回答:1

我有一个要连接到定制硬件的Linux系统。 (具体来说,这是具有FPGA的SoC)。

我正在尝试编写一个内核模块,该模块将响应来自设备的中断。它包含对request_irq的调用,但这是通过对uio_register_device的调用来完成的。当我运行insmod时,它失败并显示“无效参数”。

经过一段时间的浏览,我最终将这些行添加到了模块的初始化函数中:

struct irq_desc *p;
p = irq_to_desc(89);
if (!p) {
    printk(KERN_ALERT "No descriptor allocated for IRQ number 89!!\n");
}
p = irq_to_desc(121);
if (!p) {
    printk(KERN_ALERT "No descriptor allocated for IRQ number 121!!\n");
}

当然,我在dmesg中看到了这些消息。

在这种情况下我该怎么办?

linux-device-driver interrupt
1个回答
0
投票
map转换为硬件IRQ编号。当然,硬件IRQ编号不是唯一的。例如,两个中断控制器的硬件IRQ编号可能为0。所以我的意思是必须将虚拟IRQ编号与irq_domain

combination和硬件IRQ编号相关联。

还有一点点:irq_domain与中断控制器不一对一对应。一个控制器可以有多个域。 因此,让我们精确定义“映射” IRQ的含义:

每个虚拟IRQ都有一个struct irq_desc。该结构的某些字段被映射为指向由中断控制器驱动程序实现的功能。 (我不确定在执行任何映射之前,Linux收到中断时会做什么)

    每个中断控制器可以提供一定数量的struct irq_domain。这些实质上是对硬件IRQ编号到虚拟IRQ编号之间的映射进行编码,并具有用于驱动程序查找编号的API。
  1. irq_domain结构还包含指向由中断控制器驱动程序实现的回调的指针。创建新映射时,将触发这些回调之一。我认为这是配置硬件以生成特定虚拟IRQ的方式。
  • 当您请求中断时,您的ISR将被添加到actionsirq_desc列表中,前提是irq_desc已正确初始化。
  • 无论如何,我发现在给定硬件IRQ编号的情况下获取虚拟IRQ编号的方法(并在必要时创建新映射)如下:

    #include <linux/irqdomain.h> //For irq_domain struct #include <linux/of.h> //For device tree struct types #include <linux/irq.h> //Needed by other interrupt-related code struct device_node *dn; struct irq_domain *dom; struct irq_fwspec dummy_fwspec = { .param_count = 3, .param = {0, 89, 4} }; int virq; //Find the Linux irq number dn = of_find_node_by_name(NULL, "interrupt-controller"); if (!dn) { printk(KERN_ERR "Could not find device node for \"interrupt-controller\"\n"); goto /*error_handler*/; } dom = irq_find_host(dn); if (!dom) { printk(KERN_ERR "Could not find irq domain\n"); goto /*error_handler*/; } dummy_fwspec.fwnode = dom->fwnode; virq = irq_create_fwspec_mapping(&dummy_fwspec);

    irq_create_fwspec_mapping将返回一个现有的(映射的)虚拟IRQ编号,或映射一个新的。 struct irq_fwspec包含执行映射所需的所有信息。 fwnode字段必须指向您正在使用的中断控制器。就我而言,我使用设备树API找到了正确的值(可能有更好的方法,但是我不知道它是什么!)

    此示例专门针对MPSoC,我碰巧知道它使用this驱动程序(drivers / irqchip / irq-gic.c)。我查看了驱动程序的源代码,以确定在irq_fwspec结构的其他部分中需要什么。具体来说,每个控制器驱动程序都将填充struct irq_domain_ops,因此使用CTRL-F可以找到您需要满足的回调函数。

    在我的特定示例中,我知道gic_irq_domain_alloc将被调用,并且它也将被称为gic_irq_domain_translate。这告诉我第二个数字是硬件IRQ编号,但是出于某种原因会在其中添加32。因为我想要硬件IRQ号121,所以我在第二号插入了89。第一个和第三个数字是基于我看到其他人在做的事情的一种猜测。

    如果有人知道更简单的方法,请告诉我

  • © www.soinside.com 2019 - 2024. All rights reserved.