Linux内核驱动与单个PCI设备的绑定和解绑定

一、前言在linux内核2.6.13-rc3以前,驱动和设备之间的绑定和解绑只能通过insmod(modprobe)和rmmod来实现,但是这种实现方法有一个弊端,就是一旦绑定或者解绑定都是针对驱动与其所支持的所有设备之间进行,无法实现驱动单独绑定或者解绑定一个设备。然而,在linux内核2.6.13-rc3以后,提供了在用户空间动态的绑定和解绑定驱动与设备之间关系的功能,这样就解决了前面提到的无法实现驱动单独绑定或者解绑定一个设备的问题。
二、pci总线pci(peripheral component interconnect,外围设备互联)总线由pci host bridge(pci主桥)或者pci bus bridge(pci桥)管理,用来连接各类pci设备,如声卡、网卡和pci桥等。在一个处理器系统中,可以通过pci桥扩展pci总线,形成pci总线树型结构,如下图:bus0上的device2是一个pci桥,由该桥拓展出bus1。
在处理器系统中有几个host主桥,就有几棵pci总线树,而每一棵pci总线树都与一个pci domain(pci总线域)对应,上图就是一个总线域。每个pci设备都有一个vendor id(供应商号)和device id(设备号)。
lspci用来显示所有的pci总线和连接在pci总线上的设备,在一台linux设备上敲一敲lspci,通常得到类似如下信息:
[root@localhost ~]# lspci00:00.0 host bridge: advanced micro devices, inc. [amd] starship/matisse root complex00:00.2 iommu: advanced micro devices, inc. [amd] starship/matisse iommu00:01.0 host bridge: advanced micro devices, inc. [amd] starship/matisse pcie dummy host bridge00:01.1 pci bridge: advanced micro devices, inc. [amd] starship/matisse gpp bridge00:02.0 host bridge: advanced micro devices, inc. [amd] starship/matisse pcie dummy host bridge00:03.0 host bridge: advanced micro devices, inc. [amd] starship/matisse pcie dummy host bridge00:04.0 host bridge: advanced micro devices, inc. [amd] starship/matisse pcie dummy host bridge00:05.0 host bridge: advanced micro devices, inc. [amd] starship/matisse pcie dummy host bridge00:07.0 host bridge: advanced micro devices, inc. [amd] starship/matisse pcie dummy host bridge00:07.1 pci bridge: advanced micro devices, inc. [amd] starship/matisse internal pcie gpp bridge 0 to bus[e:b]00:08.0 host bridge: advanced micro devices, inc. [amd] starship/matisse pcie dummy host bridge00:08.1 pci bridge: advanced micro devices, inc. [amd] starship/matisse internal pcie gpp bridge 0 to bus[e:b]00:14.0 smbus: advanced micro devices, inc. [amd] fch smbus controller (rev 61)00:14.3 isa bridge: advanced micro devices, inc. [amd] fch lpc bridge (rev 51)00:18.0 host bridge: advanced micro devices, inc. [amd] starship device 24; function 000:18.1 host bridge: advanced micro devices, inc. [amd] starship device 24; function 100:18.2 host bridge: advanced micro devices, inc. [amd] starship device 24; function 200:18.3 host bridge: advanced micro devices, inc. [amd] starship device 24; function 300:18.4 host bridge: advanced micro devices, inc. [amd] starship device 24; function 400:18.5 host bridge: advanced micro devices, inc. [amd] starship device 24; function 500:18.6 host bridge: advanced micro devices, inc. [amd] starship device 24; function 600:18.7 host bridge: advanced micro devices, inc. [amd] starship device 24; function 700:19.0 host bridge: advanced micro devices, inc. [amd] starship device 24; function 000:19.1 host bridge: advanced micro devices, inc. [amd] starship device 24; function 100:19.2 host bridge: advanced micro devices, inc. [amd] starship device 24; function 200:19.3 host bridge: advanced micro devices, inc. [amd] starship device 24; function 300:19.4 host bridge: advanced micro devices, inc. [amd] starship device 24; function 400:19.5 host bridge: advanced micro devices, inc. [amd] starship device 24; function 500:19.6 host bridge: advanced micro devices, inc. [amd] starship device 24; function 600:19.7 host bridge: advanced micro devices, inc. [amd] starship device 24; function 701:00.0 ethernet controller: corigine, inc. device 4000......用其中最常见的以太网卡信息来剖析下各个参数的含义:
01:00.0 ethernet controller: corigine, inc. device 400001:00.0 :表示pci总线域为0000,bus总线号为02,槽位号为01,功能号为0(lspci默认省略总线域0000,可以加参数-d显示)。ethernet controller :指设备类型,设备类型包括device classes,device subclasses,program interfaces(一般省略),通过加参数 -nn 可以看到ethernet controller对应的设备类型号为0200,其中02指device classes,00指device subclasses,通过the pci id repository(http://pci-ids.ucw.cz/read/pd/02/00)在线网站也可以查看。[root@localhost ~]# lspci -nn -d -s 01:00.00000:01:00.0 ethernet controller [0200]: corigine, inc. device [1da8:4000]corigine, inc. :表示corigine公司,如上面所示,对应了供应商号1da8和设备号4000,可通过如下方式查看,也可以通过device hunt``(https://devicehunt.com/)在线网站查看。[root@localhost ~]# lspci -nvmms 01:00.0slot: 01:00.0class: 0200vendor: 1da8device: 4000svendor: 1da8sdevice: 0bf9physlot: 2numanode: 0iommugroup: 13注意 :在 linux中,pci设备的设备名称(device name)通常以 domain:bus:slot:function 的形式来表示,如图所示:
其中冒号分隔开的各个数字具有以下含义:
domain :表示pci设备所在的pci总线域(domain),通常为一个 16 位的十六进制数,用于区分不同的 pci 总线域。在大多数情况下,这个值为 0000。bus :表示 pci 设备所在的总线(bus),通常为一个 8 位的十六进制数,用于区分不同的总线。一个系统可以具有多个总线。slot :表示 pci 设备所在的插槽(slot),通常为一个 5 位的十六进制数,用于区分不同的插槽。一个总线上可以有多个插槽。function :表示 pci 设备的功能(function),通常为一个 3 位的十六进制数,用于区分同一插槽上的不同功能。一个插槽上可以有多个功能。一个pci物理设备可以实现多个功能设备,且逻辑功能相互独立,其实就是 硬件虚拟化 。通过这种编号方式,可以唯一标识一个 pci 设备的位置信息。在上述示例中,0000:01:00.0 表示该设备位于 pci 总线域 0000,总线 01,插槽 00,功能 0 。
请注意,这些数字可能会因系统配置而有所不同,具体取决于你的系统和相应的 pci 设备。
三、驱动与单个pci设备的绑定和解绑定此处,我们以pci总线的corigine网卡设备及其驱动为例,讲述网卡设备及其驱动的绑定和解绑定过程。首先,执行lspci显示所用机器上的所有网卡设备:
[root@localhost ~]# lspci | grep eth01:00.0 ethernet controller: corigine, inc. device 400021:00.0 ethernet controller: corigine, inc. network flow processor 380041:00.0 ethernet controller: intel corporation i350 gigabit network connection (rev 01)41:00.1 ethernet controller: intel corporation i350 gigabit network connection (rev 01)41:00.2 ethernet controller: intel corporation i350 gigabit network connection (rev 01)41:00.3 ethernet controller: intel corporation i350 gigabit network connection (rev 01)对于所有的corigine网卡设备,都可以在nfp驱动下看到。其中,bind和unbind文件就是涉及到绑定和解绑的关键文件。
[root@localhost ~]# ls -l /sys/bus/pci/drivers/nfptotal 0lrwxrwxrwx 1 root root 0 nov 14 05:17 0000:01:00.0 - > ../../../../devices/pci0000:00/0000:00:01.1/0000:01:00.0lrwxrwxrwx 1 root root 0 nov 14 05:17 0000:21:00.0 - > ../../../../devices/pci0000:20/0000:20:03.2/0000:21:00.0--w------- 1 root root 4096 nov 14 05:17 bindlrwxrwxrwx 1 root root 0 jun 28 07:58 module - > ../../../../module/nfp--w------- 1 root root 4096 nov 14 05:17 new_id--w------- 1 root root 4096 nov 14 05:17 remove_id--w------- 1 root root 4096 jun 8 17:34 uevent--w------- 1 root root 4096 nov 14 05:17 unbind1、解绑定这里我们以pci总线bdf号为01:00.0的corigine网卡为例,解绑该设备,只需将设备的带pci总线域的bdf号写入/sys/bus/pci/drivers/nfp/unbind(不同的设备,驱动不同,即这里的nfp)即可:
[root@localhost ~]# echo 0000:01:00.0 > /sys/bus/pci/drivers/nfp/unbind# 解除绑定成功,再查看目录下文件,该驱动下不再有对应的设备。[root@localhost ~]# ls -l /sys/bus/pci/drivers/nfptotal 0lrwxrwxrwx 1 root root 0 nov 14 05:17 0000:21:00.0 - > ../../../../devices/pci0000:20/0000:20:03.2/0000:21:00.0--w------- 1 root root 4096 nov 14 05:17 bindlrwxrwxrwx 1 root root 0 jun 28 07:58 module - > ../../../../module/nfp--w------- 1 root root 4096 nov 14 05:17 new_id--w------- 1 root root 4096 nov 14 05:17 remove_id--w------- 1 root root 4096 jun 8 17:34 uevent--w------- 1 root root 4096 nov 14 05:23 unbind执行解绑定操作以后,我们可以通过lshw命令查看pci设备:
[root@localhost ~]# lshw -c network -businfobus info device class description=======================================================pci@0000:01:00.0 /dev/fb0 network corigine, inc.pci@0000:21:00.0 ens1np0 network corigine, inc.pci@0000:41:00.0 eno1 network i350 gigabit network connectionpci@0000:41:00.1 ens16f1 network i350 gigabit network connectionpci@0000:41:00.2 ens16f2 network i350 gigabit network connectionpci@0000:41:00.3 ens16f3 network i350 gigabit network connectionpci@0000:21:00.0 ens1np1 network ethernet interface通过上述结果可知,bdf号为01:00.0的设备,在解绑定nfp驱动和该设备以后,该设备接口名称已无法正常显示,而同样使用nfp 驱动的其他pci设备,如上面bdf号为21:00.0的设备,则接口名称正常显示,说明驱动和该设备正常绑定。另外,也可通过如下方式对比两个pci设备此时的区别:
[root@localhost ~]# echo 0000:01:00.0 > /sys/bus/pci/drivers/nfp/unbind[root@localhost ~]# lspci -s 01:00.0 -v01:00.0 ethernet controller: corigine, inc. device 4000 subsystem: corigine, inc. device 0bf9 physical slot: 2 flags: fast devsel, irq 117, numa node 0, iommu group 13 memory at 340a0000000 (64-bit, prefetchable) [size=128m] memory at 340a8000000 (64-bit, prefetchable) [size=64m] memory at 340ac000000 (64-bit, prefetchable) [size=16m] expansion rom at f5000000 [disabled] [size=16m] capabilities: [80] power management version 3 capabilities: [b0] msi-x: enable- count=256 masked- capabilities: [c0] express endpoint, msi 00 capabilities: [100] advanced error reporting capabilities: [140] alternative routing-id interpretation (ari) capabilities: [150] device serial number 88-3c-c5-a0-18-6d-10-ff capabilities: [200] single root i/o virtualization (sr-iov) capabilities: [300] secondary pci express kernel modules: nfp [root@localhost ~]# lspci -s 21:00.0 -v21:00.0 ethernet controller: corigine, inc. network flow processor 3800 subsystem: corigine, inc. device 7feb physical slot: 1 flags: bus master, fast devsel, latency 0, irq 213, numa node 0, iommu group 29 memory at 2c070000000 (64-bit, prefetchable) [size=128m] memory at 2c078000000 (64-bit, prefetchable) [size=64m] memory at 2c07c000000 (64-bit, prefetchable) [size=16m] expansion rom at b0000000 [disabled] [size=16m] capabilities: [88] power management version 3 capabilities: [b0] msi-x: enable+ count=64 masked- capabilities: [c0] express endpoint, msi 00 capabilities: [100] advanced error reporting capabilities: [140] alternative routing-id interpretation (ari) capabilities: [150] device serial number 88-3c-c5-a0-32-1e-10-ff capabilities: [160] power budgeting capabilities: [1b8] latency tolerance reporting capabilities: [200] single root i/o virtualization (sr-iov) capabilities: [300] secondary pci express capabilities: [400] vendor specific information: id=0001 rev=1 len=010 kernel driver in use: nfp kernel modules: nfp根据上述结果可知,bdf号为01:00.0的pci设备较bdf号为21:00.0的pci设备明显少了一行kernel driver in use: nfp,说明bdf号为01:00.0的pci设备已与nfp驱动解绑定,即nfp驱动未在使用中。而bdf号为21:00.0的pci设备则正在与nfp驱动绑定中,即nfp驱动正在使用中。
2、绑定绑定一个网卡设备,和解绑类似,将设备的带pci总线域的bdf号写入/sys/bus/pci/drivers/nfp/bind(不同的设备,驱动不同,即这里的nfp):
[root@localhost ~]# echo 0000:01:00.0 > /sys/bus/pci/drivers/nfp/bind[root@localhost ~]# ls -l /sys/bus/pci/drivers/nfptotal 0lrwxrwxrwx 1 root root 0 nov 14 05:28 0000:01:00.0 - > ../../../../devices/pci0000:00/0000:00:01.1/0000:01:00.0lrwxrwxrwx 1 root root 0 nov 14 05:17 0000:21:00.0 - > ../../../../devices/pci0000:20/0000:20:03.2/0000:21:00.0--w------- 1 root root 4096 nov 14 05:27 bindlrwxrwxrwx 1 root root 0 jun 28 07:58 module - > ../../../../module/nfp--w------- 1 root root 4096 nov 14 05:17 new_id--w------- 1 root root 4096 nov 14 05:17 remove_id--w------- 1 root root 4096 jun 8 17:34 uevent--w------- 1 root root 4096 nov 14 05:23 unbind执行绑定操作以后,我们可以通过lshw命令查看pci设备:
[root@localhost ~]# lshw -c network -businfobus info device class description=======================================================pci@0000:01:00.0 ens2np0 network corigine, inc.pci@0000:21:00.0 ens1np0 network corigine, inc.pci@0000:41:00.0 eno1 network i350 gigabit network connectionpci@0000:41:00.1 ens16f1 network i350 gigabit network connectionpci@0000:41:00.2 ens16f2 network i350 gigabit network connectionpci@0000:41:00.3 ens16f3 network i350 gigabit network connectionpci@0000:21:00.0 ens1np1 network ethernet interfacepci@0000:01:00.0 ens2np1 network ethernet interface通过上述结果可知,bdf号为01:00.0的设备,在绑定nfp驱动和该设备以后,该设备接口名称已正常显示,且使用如下命令时,也显示nfp驱动正在使用中。
[root@localhost ~]# echo 0000:01:00.0 > /sys/bus/pci/drivers/nfp/bind[root@localhost ~]# lspci -s 01:00.0 -v01:00.0 ethernet controller: corigine, inc. device 4000 subsystem: corigine, inc. device 0bf9 physical slot: 2 flags: bus master, fast devsel, latency 0, irq 117, numa node 0, iommu group 13 memory at 340a0000000 (64-bit, prefetchable) [size=128m] memory at 340a8000000 (64-bit, prefetchable) [size=64m] memory at 340ac000000 (64-bit, prefetchable) [size=16m] expansion rom at f5000000 [disabled] [size=16m] capabilities: [80] power management version 3 capabilities: [b0] msi-x: enable+ count=256 masked- capabilities: [c0] express endpoint, msi 00 capabilities: [100] advanced error reporting capabilities: [140] alternative routing-id interpretation (ari) capabilities: [150] device serial number 88-3c-c5-a0-18-6d-10-ff capabilities: [200] single root i/o virtualization (sr-iov) capabilities: [300] secondary pci express kernel driver in use: nfp kernel modules: nfp四、总结bind是pci设备绑定驱动过程中会使用到的文件,unbind 是解绑pci设备与驱动过程中会使用到的文件。具体的绑定与解绑的过程就是向这两个文件中写入规定格式的数据完成的。
对 bind 文件写入每一个接口的 pci 号意味着我们可以将一个网卡上的不同口绑定到不同的驱动上。对unbind 文件写入接口的 pci 号就会解除当前绑定的驱动。一个接口可以不绑定到任何驱动上面,不过我们常常不会这样去做。
这里,我们只讲了bind和unbind文件,其实pci设备接口绑定驱动可能还会与new_id文件有关,new_id主要用于动态的向pci设备驱动中添加一个新的设备id,这种功能允许驱动添加更多的硬件而非仅包含在编译时驱动静态支持设备 id 列表中的硬件。 写入这个文件的格式中,vendor id 与 device id 字段是必须的,其它的字段可以不指定 。格式如下:
[root@localhost ~]# echo 1da8 4000 > /sys/bus/pci/drivers/nfp/new_id成功添加一个设备 id 时,驱动会尝试 probe 系统中匹配到的设备并尝试绑定到它之上。
既然有添加新的pci设备的文件,那一定有移除新的pci设备的文件,即与new_id位于同一目录下的remove_id。
remove_id 的写入格式与 new_id 的写入格式相同。写入 remove_id 可以用来确保内核不会自动 probe 匹配到这个驱动的设备。格式如下:
[root@localhost ~]# echo 1da8 4000 > /sys/bus/pci/drivers/nfp/remove_id至此,关于驱动与单个pci设备的绑定和解绑定就介绍完了。

首届高校未来汽车人机交互设计大赛启动 促进学科创新和人才培养
AR发帖好神奇!寻找身边的那个ta
专为RTS游戏打造 新贵GX1
世界十强芯片制造商有哪些
透烟成像、多目标跟踪和高速成像, SWIR相机在安防领域一枝独秀
Linux内核驱动与单个PCI设备的绑定和解绑定
2023CPSE安博会圆满落幕,英码科技展位吸引众多国内外客户关注!
红外热像仪与热电偶的对照试验
智能家居安全系统是怎样的一套系统
日本JEITA预测全球电子设备产值将突破3万亿美元
OLED拼接屏制作技术要点解析,助力商业展示效果升级
大数据对于工业制造企业的重要性
新大脑智慧停车管理系统的功能及应用优势分析
疑似OPPOR11曝光,颜值在线,或邀200万老婆的迪丽热巴代言
fsu动环监控系统,减少运维成本,提高运行效率
将pA偏置电流放大器与高源阻抗传感器配合使用
嵌入式系统未来将会怎样
搜狗怎么/如何打输入特殊符号
在线密度计的安装说明
Microchip推出首款仪表放大器MCP6N11