免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 15582 | 回复: 12
打印 上一主题 下一主题

再问PCIe中断问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-02-11 20:23 |只看该作者 |倒序浏览
在软件中有没有办法区分中断是MSI触发的还是INTx触发的?现在用的Xilinx V5的板子发中断是通过它的IP Core发的,导致遇到的问题不好定位。

另外规范中感觉有些含糊(也有可能是没看到位,毕竟太多了),MSI中断如果全能,最终映射到软件应该也是一个IRQ号吧,它是不是也是Configuration Register中的Interrupt Pin的值?

还有一个问题是规范中简单提了一下Level-Triggerd和Edge-Trigger,并且规定MSI只能是Edge-Trigger的,但INTx好像都可以,这两者在操作系统层面有没有什么区别?

论坛徽章:
0
2 [报告]
发表于 2009-02-12 12:42 |只看该作者
>在软件中有没有办法区分中断是MSI触发的还是INTx触发的?现在用的Xilinx V5的板子发中断是通过它的IP Core发的,导致遇到的问题不好定位。

注册中断的时候区分。 实际发生中断的时候,就走到你注册的handler里去了。  再说,PCIE设备是不直接支持INTx的,它只是用MSI方式emulate了INTx中断,以便软件可以向后兼容。

>另外规范中感觉有些含糊(也有可能是没看到位,毕竟太多了),MSI中断如果全能,最终映射到软件应该也是一个IRQ号吧,它是不是也是Configuration Register中的Interrupt Pin的值?

是有个irq号,不过这个号没多少意义。 和Interupt PIN、Interrupt LINE寄存器更是没关系。

> 还有一个问题是规范中简单提了一下Level-Triggerd和Edge-Trigger,并且规定MSI只能是Edge-Trigger的,但INTx好像都可以,这两者在操作系统层面有没有什么区别?

应该说是有点区别的。 MSI之所以应该被当成一个Edge-triggered,是因为它只是一个消息写到系统总线上,并不维护什么状态。 而INTx必须是Level-Triggered,它是有PCI设备的PIN(也就是INTA/INTB/INTC/INTD这些),经过主板上chipset的路由,间接“插到” IO-APIC的输入引脚上的。  发生了中断后,电平一直有效,直到IOAPIC给它撤销掉——这期间相当于维护了一个状态。

论坛徽章:
0
3 [报告]
发表于 2009-02-12 13:24 |只看该作者

回复 #2 albcamus 的帖子

1. 注册中断时如何区分?我只知道用reqeust_irq来注册,这个显然是和中断号绑定的吧,如果用MSI的话是不是另有专门的注册接口?不过用CONFIG_PCI_MSI搜索内核代码好像没看到中断处理上有什么特殊的区别。
2. 如果MSI和Interrupt Line没有关系,它是如何和中断处理的handler联系到一起的?

V5的板子现在测试的结果感觉是用了INTx模拟发送的,但奇怪的是它会一直产生中断,或者某种错误状态导致内核认为中断错过一个使APIC重新产生(但这种情况好像多核才会出现)。目前没办法确定是不是板子产生的,具体发送是IP Core做的,不清楚具体如何实现的。

同样的板子,通过/proc/interrupts查看在一台HP工作站上看时发现V5的板子中断是IO-APIC-level,而在AMD的一个台式机上却是IO-APIC-fastio,不知道两者是不是一样的?另外在工作站上发现两个集成的网卡(应该也是PCIe总线上)的中断是MSI,但插在PCIe x16上的独立显卡却是IO-APIC-level,这个是如何确定出来的?因为PCIe是强制支持MSI的,那么显卡本身应该是支持的,但为什么系统配置它使用传统的INTx模拟呢?
在工作站上更奇怪的是如果我不挂自己的中断处理函数,它产生中断过多之后会使一个USB的中断被Disable掉,实在是很奇怪。

论坛徽章:
0
4 [报告]
发表于 2009-02-12 17:23 |只看该作者
自己顶一下。看了一下Linux的代码,发现它的中断号是用另外的机制产生的:
static int msi_capability_init(struct pci_dev *dev)
{
    struct msi_desc *entry;
    int pos, ret;
    u16 control;

    msi_set_enable(dev, 0);    /* Ensure msi is disabled as I set it up */

       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
    pci_read_config_word(dev, msi_control_reg(pos), &control);
    /* MSI Entry Initialization */
    entry = alloc_msi_entry();
    if (!entry)
        return -ENOMEM;

    entry->msi_attrib.type = PCI_CAP_ID_MSI;
    entry->msi_attrib.is_64 = is_64bit_address(control);
    entry->msi_attrib.entry_nr = 0;
    entry->msi_attrib.maskbit = is_mask_bit_support(control);
    entry->msi_attrib.masked = 1;
    entry->msi_attrib.default_irq = dev->irq;    /* Save IOAPIC IRQ */
    entry->msi_attrib.pos = pos;
    if (is_mask_bit_support(control)) {
        entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
                is_64bit_address(control));
    }
    entry->dev = dev;
    if (entry->msi_attrib.maskbit) {
        unsigned int maskbits, temp;
        /* All MSIs are unmasked by default, Mask them all */
        pci_read_config_dword(dev,
            msi_mask_bits_reg(pos, is_64bit_address(control)),
            &maskbits);
        temp = (1 << multi_msi_capable(control));
        temp = ((temp - 1) & ~temp);
        maskbits |= temp;
        pci_write_config_dword(dev,
            msi_mask_bits_reg(pos, is_64bit_address(control)),
            maskbits);
    }
    list_add_tail(&entry->list, &dev->msi_list);

    /* Configure MSI capability structure */
    ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI);
    if (ret) {
        msi_free_irqs(dev);
        return ret;
    }

    /* Set MSI enabled bits     */
    pci_intx(dev, 0);        /* disable intx */
    msi_set_enable(dev, 1);
    dev->msi_enabled = 1;

    dev->irq = entry->irq;
    return 0;
}

不过前面的arch_setup_msi_irqs函数没找到i368的实现,所以不清楚具体是怎么操作的。

不过通过实际系统中PCIe设备的配置空间查看还是有些奇怪:
1. 对于使能了MSI的网卡,msi_capability_init->pci_intx(dev, 0);应该是把command register中的Disable INTx置1了,但我读到的网卡配置空间的这一寄存器的对应bit却是清0了的。
2. 对于没有使能的显卡,Interrupt Line并不是/proc/interrupts中的中断号,难道虚拟的INTx并不使用这一寄存器?范围中没看到相关说明。

pci_msi_check_device函数中的注释说明需要设备本身和其上面的总线都支持MSI才返回0,显卡的配置空间显示它本身是支持MSI的,难道是总线的某一级不支持?

还有一点不确认的是fastio和MSI或level-triggered是什么关系?不知道是不同版本显示不一样(一个是RHEL5.1,还有一个是Fedora 8),还是Intel和ADM系统中有所区别?

论坛徽章:
0
5 [报告]
发表于 2009-02-13 10:27 |只看该作者
有些问题自己搞清楚了:
Linux不会自动使能MSI/MSI-X的,需要驱动在调用request_irq之前调用pci_enable_msi/msix()。以前看PCI规范中写设置MSI Control Register只能是系统软件,不能在驱动中处理,所以一直以为是系统自动处理的。
今天测试了一下,发现用MSI方式是OK的,不清楚V5的IP Core怎么做的,只能发MSI或根据配置情况自动选择?INTx方式有缺陷或我们的使用方式不对?这个Core也并非很稳定,去年用新版本它上面映射上来的RAM写正常,读几次之后就挂了,整个系统崩溃,换了个旧的就OK了。
不过发现Linux中的pci.txt的描述对于PCIe并不一定完全适用,它里面讲到MSI的两个好处之一是避免DMA/IRQ race conditions,但对于PCIe,DMA和MSI如果使用不同的TC/VC的话还是会存在问题的。

现在还有一个很迷惑的问题是Interrupt Line寄存器到底是干啥用的?按LLD3中的说法,根本可以直接读出来做IRQ号使用于request_irq,但昨天我发现用INTx的PCIe设备都对不上,于是特地在一台带了PCI无线网卡的机器上查看,结果发现/proc/interrupts中的中断号和这一寄存器还是对不上。不过在Linux代码中看到在pci_setup_device()->pci_read_irq()中是直接读的寄存器:
static void pci_read_irq(struct pci_dev *dev)
{
    unsigned char irq;

    pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq);
    dev->pin = irq;
    if (irq)
        pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
    dev->irq = irq;
}

但后面有没有再调整这一值在相关的代码中没有看到。

论坛徽章:
0
6 [报告]
发表于 2009-02-13 10:44 |只看该作者
>> 按LLD3中的说法,根本可以直接读出来做IRQ号使用于request_irq

ldd3的说法是错的。  driver应该用pdev->irq,而不是读INTERRUPT LINE寄存器。

论坛徽章:
0
7 [报告]
发表于 2009-02-13 11:04 |只看该作者
感觉有点儿象是在pcibios_fixup_irqs中重新调整了dev->irq,但从内核代码看出现这种情况它应该在/var/log/messages中打印一个“PCI->APIC IRQ transform: ...”,但实际上却找不到。

先告一段落了,至少现在中断调通可以正常使用了。LLD3对于PCI设备驱动的描述实在是太少了,而且它里面的配置空间讲得都是很老的了,连Capability List入口都写成保留字节了。

论坛徽章:
0
8 [报告]
发表于 2009-02-18 20:39 |只看该作者
原帖由 albcamus 于 2009-2-13 10:44 发表
>> 按LLD3中的说法,根本可以直接读出来做IRQ号使用于request_irq

ldd3的说法是错的。  driver应该用pdev->irq,而不是读INTERRUPT LINE寄存器。


对pci来说这两个值应该是一致的吧?

drivers/pci/setup-irq.c->pdev_fixup_irq()

论坛徽章:
0
9 [报告]
发表于 2009-02-19 10:25 |只看该作者

回复 #8 Roemer 的帖子

你可以在写个module,

for each pci dev, 读一下其pdev->irq和INTERRUPT LINE寄存器, 比较一下就知道是否一样了。

注意kernel不要太老的版本

论坛徽章:
0
10 [报告]
发表于 2009-02-19 22:12 |只看该作者

回复 #9 albcamus 的帖子

那INTERRUPT LINE寄存器里面得值是什么意思呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP