SIOCGIFMAP获取到错误的网络设备中断号

网卡驱动 专栏收录该内容
14 篇文章 0 订阅

内核的ioctl(SIOCGIFMAP)处理函数如下,其由net_device结构的irq成员获取中断号。

static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd)
{
    switch (cmd) {
    case SIOCGIFMAP:
        ifr->ifr_map.mem_start = dev->mem_start;
        ifr->ifr_map.mem_end   = dev->mem_end;

        ifr->ifr_map.irq       = dev->irq;
        return 0;
    }
}

以下以intel网卡驱动e1000e为例,追踪以下网络设备的irq中断号的赋值。首先,在probe阶段,网络设备的irq初始化为PCI设备pdev的中断号。

static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
    struct net_device *netdev;
    struct e1000_adapter *adapter;

    netdev = alloc_etherdev(sizeof(struct e1000_adapter));

    netdev->irq = pdev->irq;

	err = e1000_sw_init(adapter);
}

其次在函数e1000_sw_init中,中断能力初始化函数e1000e_set_interrupt_capability,依据PCI设备的中断模式(MSIX、MSI和传统的中断线三种模式)进行初始化,并且重新分配中断号。优先初始化MSIX中断,如果不成功,初始化MSI中断,最后如果MSI初始化失败,使用系统默认的传统中断模式(无须初始化)。

void e1000e_set_interrupt_capability(struct e1000_adapter *adapter)
{
    switch (adapter->int_mode) {
    case E1000E_INT_MODE_MSIX:
	    if (adapter->flags & FLAG_HAS_MSIX) {
            ...
	    }
	    adapter->int_mode = E1000E_INT_MODE_MSI;
    case E1000E_INT_MODE_MSI:
        if (!pci_enable_msi(adapter->pdev)) {
            adapter->flags |= FLAG_MSI_ENABLED;
        } else {
            adapter->int_mode = E1000E_INT_MODE_LEGACY;
            e_err("Failed to initialize MSI interrupts.  Falling back to legacy interrupts.\n");
        }
    case E1000E_INT_MODE_LEGACY:
        break;
    }
}

以MSI中断为例,其使用函数msi_capability_init进行初始化。arch_setup_msi_irqs函数为PCI设备重新分配新的中断号,并最终赋值的PCI设备结构的irq成员字段。

static int msi_capability_init(struct pci_dev *dev, int nvec)
{
    ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);

    dev->msi_enabled = 1;
    dev->irq = entry->irq;
}

由于在probe过程中,新分配的网络设备使用的是PCI设备的旧中断号,PCI设备更新中断号之后,并没有更新网络设备结构成员中irq的值,导致其irq为不正确的值。对于传统的中断线模式来说,PCI设备没有更新中断号(见函数e1000e_set_interrupt_capability),ioctl(SIOCGIFMAP)可以取得正确的网络设备irq。但是对于MSIX和MSI中的模式来说,ioctl取得的irq值会不正确。

 

内核版本

Linux-4.15

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值