【发布时间】:2019-10-08 07:41:47
【问题描述】:
我正在 Linux 中为在 Xilinx UltrascaleMPSoC FPGA 部件上实现的 PCIe 端点编写设备驱动程序。我已经正确实现了删除功能。我使用适配器将我的设备连接到我的电脑,打开设备,启用其端点,然后打开电脑,一切正常。但是,当我尝试使用 rmmod 命令卸载驱动程序模块时,进程挂起。
我浏览了 Linux 文档和 pci_disable_device() documentation,它说
请注意,直到 pci_enable_device() 的所有调用者都调用了 pci_disable_device(),我们才真正禁用设备。
这是否意味着,我的驱动程序必须等到 linux 中的所有其他 pcie 驱动程序调用 pci_disable_device() 之后才会禁用设备?我真的很怀疑这一点:(
我尝试使用 modprobe -r 并使用“lsmod”列出了模块使用计数。 lsmod 将使用计数显示为“0”。但是我仍然无法卸载模块:(我还添加了打印语句。
void remove(struct pci_dev pdev)
{
pci_unmap_single(pdev, privdata->dma_mem,
PAGE_SIZE * (1 << memorder),
PCI_DMA_FROMDEVICE);
printk(KERN_INFO"unmap_single() complete\n");
free_pages ((unsigned long) privdata->mem, memorder);
printk(KERN_INFO"free_pages() complete\n");
free_irq(pdev->irq, privdata);
printk(KERN_INFO"free_irq() complete\n");
pci_disable_msi(pdev);
printk(KERN_INFO"MSI disable complete\n");
pci_clear_master(pdev); /* Nobody seems to do this */
printk(KERN_INFO"clear_master() complete\n");
pci_iounmap(pdev, privdata->registers);
printk(KERN_INFO"iounmap() complete\n");
pci_disable_device(pdev);
printk(KERN_INFO"disable_device() complete\n");
pci_release_regions(pdev);
printk(KERN_INFO"release_regions() complete\n");
}
预期:设备必须被禁用。我无法得出结论。当我在另一个终端中执行 dmesg 时,我得到打印 till "disable_device() complete" 并且终端挂起。此外,我检查了文件:/proc/iomem 和/proc/interrupts-> 当我卸载模块时,我的设备的相应条目在我的两个文件中都被删除了!我只完成了 pci_disable_device() 的执行,进程挂起。
注意:只有 rmmod 进程挂起,我不能使用当前终端,但我可以打开另一个终端,做所有事情。
最后,当重新启动时,系统再次挂起,每次,我都通过按住电源按钮 10-15 秒来强制重启。 检查这个reboot_hang
为什么 pci_release_regions() 挂起我的系统,即使 lsmod 显示我的模块使用计数为“0”。
在此先感谢 :)
另外,我应该在上面的代码中交换pci_disable_device() 和pci_release_regions() 方法吗? -> 我也试过这个,但后来我得到打印直到 release_regions() 完成,但 disable_device complete 没有打印。并且进程挂起:(
请帮忙
【问题讨论】:
-
您是否调试过它挂在哪里/为什么挂起?你检查过其他司机是怎么做的吗?我建议您在 LKML 中提出此类问题,这是适合此问题的论坛。
标签: c linux-kernel linux-device-driver pci-e