点击上方蓝字【囧囧妹】一起学习,一起成长!
一,pcie设备关闭流程
在卸载 PCI 设备驱动程序时,需要执行以下步骤:
禁止设备生成 IRQ
释放 IRQ (
free_irq()
)停止所有 DMA
释放 DMA 缓冲区(流式和一致性)
从其他子系统(例如 scsi 或 netdev)注销
禁止设备,不再响应 MMIO/IO 端口地址使用
释放 MMIO/IO 端口资源
下面来看看每一步都具体做了些什么。
停止设备irq
如果irq不进行注销,当IRQ 与另一个设备共享时,它就会打开“screaming interrupt”。
当共享 IRQ 被设置为“unhooked”时,使用相同 IRQ 线的其余设备仍需要启用 IRQ,因此,如果“unhooked”设备断言 IRQ 线,系统将响应假设它是其余设备之一断言 IRQ 线,由于没有其他设备将处理 IRQ,系统将被挂起,直到它决定不处理 IRQ 并屏蔽 IRQ(100,000 次迭代之后)。一旦共享 IRQ 被屏蔽,其余设备将停止正常运行。
这是使用 MSI 或 MSI-X(如果可用)的另一个原因,MSI 和 MSI-X 被定义为独占中断,因此不易受到“screaming interrupt”的影响。
释放irq
停止所有的dma
在尝试解除分配 DMA 控制数据之前需要停止所有 DMA 操作,不这样做可能会导致内存损坏、挂起,并且在某些芯片组上会发生硬崩溃。
在停止 IRQ 后停止 DMA 可以避免 IRQ 处理程序可能重新启动 DMA 引擎的竞争。
释放dma缓冲区
停止 DMA 后,首先清理流式 DMA,即取消映射数据缓冲区并将缓冲区返回给“上游”所有者,然后清理包含控制数据的相关缓冲区。关于取消映射的接口会在dma节来介绍。
从其它子系统注销
大多数低级 PCI 设备驱动程序支持一些其他子系统,如 USB、ALSA、SCSI、NetDev、Infiniband 等,所以要确保pci驱动程序不会丢失其他子系统的资源,一旦发生这种情况,当子系统尝试调用已卸载的驱动程序时会出现 Oops。
禁止设备,不再响应 MMIO/IO 端口地址使用
通过io_unmap()来解映射MMIO 或 IO 端口资源,然后调用pci_disable_device(),这个与pci_enable_device()对应。调用pci_disable_device()之后就不可以再访问寄存器了。
释放 MMIO/IO 端口资源
调用pci_release_region()以将 MMIO 或 IO 端口范围标记为可用,不这样做会导致无法重新加载驱动程序。
这样pci设备初始化和关闭的步骤就说完了,下面来看看linux如何访问pci的配置空间。




