2014-06-18 125 views
0

我正在嘗試編寫一個內核模塊來處理PCIe設備的MSI中斷。我爲我的驅動程序寫了一個簡單的骨架輪廓,當我嘗試調用'pci_disable_msi(dev)'時,我得到無法處理內核NULL指針解除引用錯誤。我完全按照/Documentation/PCI/MSI-HOWTO.txt中的描述進行操作,在我看來,我不應該得到這個錯誤。這是一個錯誤還是我的設置不正確?根據發生的最後一次打印判斷,當我調用pci_disable_msi()時,我確信它發生在fpga_remove()處。 (顯然,這occures當我移動模塊),pci_disable_msi糟糕問題

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; 
} 

回答

1

你可能不應該使用在request_irq(...)struct pci_dev作爲void *dev_id參數和free_irq(...)功能。使用正確且唯一的中斷參數dev_id來調用它們非常重要。這樣做不會導致內核恐慌在pci_disable_msi()刪除模塊。

在這裏閱讀更多: What is dev_id parameter in request_irq?

+0

而且不要忘記調用'pci_disable_device()'在fpga_remove()。 – passerby