nvme Linux driver 学习之二pcie设备枚举原理

首先任何Linux 驱动的加载入口都是xxx_init() 接口,卸载入口是xxx_exit(). 对于nvme驱动同样,它的驱动加载入口是nvme_init()接口。
其内部实现的一个关键的地方在于使用pci_register_driver()接口和它的接口参数来注册其支持的设备的pcie设备。
其参数是nvme_driver,其取值如下:
static struct pci_driver nvme_driver = {
.name = "nvme",
.id_table = nvme_id_table,
.probe = nvme_probe,
.remove = nvme_remove,
.shutdown = nvme_shutdown,
.driver = {
.pm = &nvme_dev_pm_ops,
},
};
其中nvme_driver中的id_table 取值如下
static const struct pci_device_id nvme_id_table[] = {
{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
{ 0, }
};
其中PCI_DEVICE_CLASS宏用于创建一个struct pci_device_id类型的实例,这个实例只需要匹配指定的pci class,这个指定的匹配PCI_CLASS_STORAGE_EXPRESS的类型,想vendor id, device id, subvendor id, subdevice id 都不care,只要匹配上PCI_CLASS_STORAGE_EXPRESS,就可以。
需要说明几点
(1)每个pci设备都通过struct pci_device_id中的vender id, device id 和class node的一个实例唯一标志.
(2)每一个pci设备通过struct pci_device类型的实例表示。
(3)每个pci驱动通过struct pci_driver类型的实例标识,它包含该支持该驱动的pci设备pci_device_id表,device driver设备驱动,和probe, remove 等函数指针。

搞清楚了关键的参数含义,我们就可以开始pci device 和pci driver的绑定过程
(1)第一步,首先系统启动的时候,pci bus 会scan 所有在这条总线的所有设备,为每一个pci设备创建一个struct pci_device 类型的实例,而struct pci_device类型包含device的成员,正是通过这个成员,pci bus 将所有在总线上得所有设备连接起来,通过pci bus的总线描述符的设备链表可以遍历所有的设备。
(2)第二步,当pci driver加载的时候,pci driver 会初始化,并且会调用driver_register()来pci driver加到总线的驱动链表上.这样支持该驱动设备插上去的时候,该通过什么pci driver 来驱动这个设备。在pci driver 注册的过程中,系统会检查pci 驱动的id_table ,看在总线的device list 里面设备有没有该pci driver 支持的,如果支持,就把这个设备加到这个pci driver的device list 里面,并开始probe 过程。

你可能感兴趣的:(nvme Linux driver 学习之二pcie设备枚举原理)