Linux kernel 运行Debian linux的CompactPCI系统:lspci显示不正确的IRQ,导致gen_IRQ标志不匹配和IRQ冲突

Linux kernel 运行Debian linux的CompactPCI系统:lspci显示不正确的IRQ,导致gen_IRQ标志不匹配和IRQ冲突,linux-kernel,linux-device-driver,Linux Kernel,Linux Device Driver,我正在使用3U compactPCI系统,该系统带有Advantec MIC3325处理器和多个插件卡,其中一个是8端口串行卡。此串行卡公开2个Oxford OX16PCI954,每个模拟4个16C950 我正在从Linux4.9.4源代码构建一个内核,但我描述的问题与Debian8安装(内核3.16)中的问题相同 通过手动配置LinuxTTY串行8250驱动程序,我可以让所有8个端口都工作,但我需要解决两个问题才能做到这一点 第一个问题是检测IRQ。在过去,我使用lspci并解析输出。然而,我

我正在使用3U compactPCI系统,该系统带有Advantec MIC3325处理器和多个插件卡,其中一个是8端口串行卡。此串行卡公开2个Oxford OX16PCI954,每个模拟4个16C950

我正在从Linux4.9.4源代码构建一个内核,但我描述的问题与Debian8安装(内核3.16)中的问题相同

通过手动配置LinuxTTY串行8250驱动程序,我可以让所有8个端口都工作,但我需要解决两个问题才能做到这一点

第一个问题是检测IRQ。在过去,我使用lspci并解析输出。然而,我发现这个IRQ并不总是正确的。例如:

05:0c.0 Serial controller: Tenta Technology Device 0800 (prog-if 06 [16950])
 Interrupt: pin A routed to IRQ 18
 Region 0: I/O ports at ec00 [size=32]
05:0c.1 Bridge: Tenta Technology Device a801
 Interrupt: pin B routed to IRQ 10
 Region 0: I/O ports at e800 [size=32]
我曾尝试过关闭APIC、按内核选项和直接在BIOS中关闭,并尝试过ACPI配置的所有组合,虽然IRQ在某些情况下发生了更改,但它仍然不可靠地正确,通常在这两种情况下我都会遇到更糟糕的问题。我没有使用设备树,当MSIX打开时,这个设备不支持MSI,所以这看起来不相关。该电路板可以处理轮询中断,但我丢失了串行线路上的数据,因此这不是一个解决方案

我读过很多关于中断路由如何工作以及从PCI引脚号到IRQ号的链接如何发生的讨论,但是我找不到任何关于如何更改或调试配置的文档。例如,由于第一个芯片充当到第二个芯片的PCI桥,可能会有额外的旋转,但我不知道如何深入挖掘

在代码中使用pci_dev结构并通过导航虚拟文件系统/proc/bus/pci,可以找到相同的(不正确的IRQ)。此问题发生在其他插槽和不同机箱(背板)中的其他cPCI插件卡上

在这一点上,你可能想知道我怎么知道IRQ是不正确的。我有两种情况,一种是另一个设备使用正确的IRQ,另一种是没有。第二种情况最简单,端口根本不工作

在第一种情况下,当在端口接收数据时,最终在dmesg中,我将看到:

[57.301692] irq 19: nobody cared
...
[57.302684] Disabling IRQ #19
使用cat/proc/interrupts,我看到IRQ19注册到某个USB端口

19:      24987      25004      25000      25009   IO-APIC  19-fasteoi   uhci_hcd:usb2
我使用setserial/dev/ttyS6端口exe800 irq19autoconfig强制串行端口使用irq 19,而不是lspci中显示的irq 10

这导致了第二个问题,即:

[40.875178] genirq: Flags mismatch irq 19. 00000000 (serial) vs. 00000080 (uhci_hcd:usb2)
我设法在BIOS中禁用USB端口,并使串行端口在IRQ 19上正常工作。我知道它在工作,因为当数据在端口中发送(和接收)时,/proc/interrupts中的IRQ19中断数量增加

我检查了8250_core.c中的代码并交叉引用了我的内核编译标志,似乎驱动程序被设置为共享中断:

CONFIG_SERIAL_8250_SHARE_IRQ=y
ret = request_irq(up->port.irq, serial8250_interrupt,
                              IRQF_SHARED, "serial", i);
作为最后手段,我入侵了8250_core.c,以强制始终使用共享中断:

CONFIG_SERIAL_8250_SHARE_IRQ=y
ret = request_irq(up->port.irq, serial8250_interrupt,
                              IRQF_SHARED, "serial", i);
这实际上解决了genirq标志不匹配的问题。但是我不明白为什么现有的代码没有在 使用setserial手动配置端口时,uart_port.port.flags

因此,总结一下我的问题,有谁能帮助我:

1) 为什么lspci显示不正确的IRQ?(就我而言是10而不是19)


2) 为什么8250内核驱动程序在手动配置端口时不设置UPD_SHARE_IRQ标志,并且有没有一种方法可以在不破解驱动程序代码的情况下实现这一点?

vanilla——来自Linus的树,stock——来自发行版。根据您上面描述的,您应该只有两个驱动程序实例,但是8250端口的8个实例。所以,就我所知,基本上你的设备应该每4个端口共用2条线路。@0安德烈,很抱歉,我是说库存。你所说的例子是什么意思?我可能遗漏了一些关于模块工作原理的基本信息。理想的解决方案是修改8250Āpci驱动程序以支持两个pci设备中的每一个。尽管图中显示了2个OX16PCI954设备,但我认为这是不正确的。OX16PCI954是一款双功能PCI设备。功能0具有四个UART,功能1可以通过各种方式进行配置,但在这种情况下,功能1作为8位本地总线的桥接器,I/O区域映射到附加UART上。这两个函数中的每一个在Linux中都显示为单独的PCI设备,从lspci输出中可以看出。