【问题标题】:pci_disable_msi Oops Bugpci_disable_msi 糟糕的错误
【发布时间】:2014-06-18 16:48:41
【问题描述】:

我正在尝试编写一个内核模块来处理 PCIe 设备的 MSI 中断。我目前为我的驱动程序编写了一个简单的框架大纲,每当我尝试调用“pci_disable_msi(dev)”时,我都会遇到无法处理内核 NULL 指针取消引用错误。我完全按照 /Documentation/PCI/MSI-HOWTO.txt 中的描述进行操作,在我看来,我不应该收到此错误。这是一个错误还是我的设置不正确?从发生的最后一次打印来看,当我调用 pci_disable_msi() 时,我很确定它发生在 fpga_remove() 上。 (很明显,当我移除模块时会发生这种情况)

static struct pci_driver fpga_driver = {
        .name       = "PCIe_test",
        .id_table   = fpga_dev_table,
        .probe      = fpga_probe,
        .remove     = fpga_remove,
        .suspend    = fpga_suspend,
        .resume     = fpga_resume,
};

static irqreturn_t fpga_isr(int irq, struct pci_dev *dev)
{

    printk(KERN_NOTICE "THIS is the ISR\n");

    return IRQ_HANDLED;
}


static int setup_MSI_interrupt(struct pci_dev *dev, int num_msi)
{

    int result;
    result = pci_enable_msi(dev);
    if(result)
    {
        printk(KERN_WARNING "Could not enable MSI\n");
        return result;

    }
    printk(KERN_NOTICE "MSI has been enabled\n");
    printk(KERN_NOTICE "dev->irq line is %d", dev->irq);

    result = request_irq(dev->irq, fpga_isr, IRQF_SHARED, fpga_driver.name, dev);
    printk(KERN_NOTICE "Using IRQ num %d\n", dev->irq);

    if (result) {
        dev_err(&dev->dev, "Failed to allocate irq %d: %d\n", dev->irq, result);
        goto exit1;
    }
        dev_info(&dev->dev, "FPGA using PCIe Interrupt\n");

    return 0;
exit1:
    return -1;
}

static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
    printk(KERN_NOTICE "Probing driver\n");
    switch(dev->vendor) {
    case VENDOR://0x1708:
        printk(KERN_NOTICE "Xilinx device found\n");
        break;
    default:
        printk(KERN_NOTICE "Device found that does not match id: id = 0x%04X\n", dev->device);
    };

    int err = pci_enable_device(dev);
    if (err) {
        dev_err(&dev->dev, "Failed to enable FPGA PCI device (%d)\n", err);
        goto exit;
    }

    err = setup_MSI_interrupt(dev, NUM_MSI);

    if(err)
        goto exit;

    return 0;

exit:
    return -1;
}

static void fpga_remove(struct pci_dev *dev)
{
    printk(KERN_NOTICE "REMOVING IRQ # %d\n", dev->irq);

    free_irq(dev->irq, dev);
    printk(KERN_NOTICE "IRQ has been freed\n");
    pci_disable_msi(dev);                                               // This causes a NUll Pointer to be dereferenced but needs to be added
    printk(KERN_NOTICE "MSI has been disabled\n");
}

static int __init fpga_init(void)
{
    printk(KERN_NOTICE "Registering Driver\n");
    return pci_register_driver(&fpga_driver);
    return 0;
}

【问题讨论】:

    标签: linux-device-driver kernel-module pci-e


    【解决方案1】:

    您可能不应该在request_irq(...)free_irq(...) 函数中使用struct pci_dev 作为void *dev_id 参数。使用正确且相同的唯一dev_id 参数调用它们非常重要。不这样做可能会在删除模块时导致pci_disable_msi() 的内核崩溃。

    在这里阅读更多: What is dev_id parameter in request_irq?

    【讨论】:

    • 别忘了在 fpga_remove() 中调用pci_disable_device()
    猜你喜欢
    • 1970-01-01
    • 2014-09-07
    • 2019-11-13
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 2022-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多