\-[0000:00]+-01.4-[03]--+-00.0 Intel Corporation I350 Gigabit Network Connection
| \-00.1 Intel Corporation I350 Gigabit Network Connection
1、手動remove一個pci設備(bus:device.function 3:0.0和3.0.1)
echo 1 > /sys/bus/pci/devices/0000\:03\:00.0/remove
echo 1 > /sys/bus/pci/devices/0000\:03\:00.1/remove
2、手動掃描pci設備
echo 1 > /sys/bus/pci/rescan
當然如果想更精確一點,可以使用父設備下的recan來掃描子設備,兩者唯一的區別就是通過bus節點掃描會調用pci_find_next_bus把系統中的所有設備都rescan一遍。
echo 1 >/sys/bus/pci/devices/0000\:00\:01.4/rescan
3、源碼到底是怎麼實現呢?
https://elixir.bootlin.com/linux/v5.3/source/drivers/pci/pci-sysfs.c
sys文件系統的函數裏面有3個節點device的remove、bus的rescan和devcie的rescan,當你往文件系統寫1時就回調attribute的store函數指針:
/* interface for exporting device attributes */
struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
};
remove主要是卸載資源和調用driver的remove
下面是通過kprobe打印出來的remove調用棧
<...>-4114 [059] .... 73835.573048: myprobe: (pci_remove_bus_device+0x0/0x100)
bash-4114 [059] .... 73835.573066: <stack trace>
=> pci_remove_bus_device
=> pci_stop_and_remove_bus_device_locked
=> remove_store------------------入口
=> kernfs_fop_write
=> vfs_write
=> ksys_write
=> do_syscall_64
=> entry_SYSCALL_64_after_hwframe
rescan主要幹兩件事
(1)分配資源
(2)調用probe
kprobe打印的分配資源的調用棧
bash-1596 [026] .... 56128.977294: myprobe: (pci_assign_resource+0x0/0x200)
bash-1596 [026] .... 56128.977296: <stack trace>
=> pci_assign_resource
=> assign_requested_resources_sorted
=> __assign_resources_sorted
=> __pci_bus_assign_resources
=> __pci_bus_assign_resources
=> pci_assign_unassigned_bus_resources
=> pci_rescan_bus
=> rescan_store--------------------入口
=> kernfs_fop_write
=> vfs_write
=> ksys_write
=> do_syscall_64
=> entry_SYSCALL_64_after_hwframe
pci_assign_resource函數調用_pci_assign_resource分配設備需要的resource
分配完畢打印資源情況:pci_info(dev, "BAR %d: assigned %pR\n", resno, res);打印出就是下面的格式
具體實現原理見
https://blog.csdn.net/tiantao2012/article/details/68483118
[72131.692082] pci 0000:03:00.0: BAR 0: assigned [mem 0xef600000-0xef61ffff]
[72131.692087] pci 0000:03:00.1: BAR 0: assigned [mem 0xef620000-0xef63ffff]
[72131.692092] pci 0000:03:00.0: BAR 3: assigned [mem 0xef640000-0xef643fff]
[72131.692097] pci 0000:03:00.0: BAR 7: assigned [mem 0x323a0000000-0x323a001ffff 64bit pref]
[72131.692103] pci 0000:03:00.0: BAR 10: assigned [mem 0x323a0020000-0x323a003ffff 64bit pref]
[72131.692108] pci 0000:03:00.1: BAR 3: assigned [mem 0xef644000-0xef647fff]
[72131.692112] pci 0000:03:00.1: BAR 7: assigned [mem 0x323a0040000-0x323a005ffff 64bit pref]
[72131.692118] pci 0000:03:00.1: BAR 10: assigned [mem 0x323a0060000-0x323a007ffff 64bit pref]
[72131.692123] pci 0000:03:00.0: BAR 2: assigned [io 0x1000-0x101f]
[72131.692128] pci 0000:03:00.1: BAR 2: assigned [io 0x1020-0x103f]
kworker/0:2-336 [000] .... 4201.787205: myprobe: (pci_enable_resources+0x0/0x170)
kworker/0:2-336 [000] .... 4201.787228: <stack trace>
=> pci_enable_resources
=> pcibios_enable_device
=> do_pci_enable_device
=> pci_enable_device_flags
=> igb_probe
=> local_pci_probe
=> work_for_cpu_fn
=> process_one_work
=> worker_thread
=> kthread
=> ret_from_fork
kworker/0:2-336 [000] .... 4201.825660: myprobe: (pci_enable_resources+0x0/0x170)
kworker/0:2-336 [000] .... 4201.825671: <stack trace>
=> pci_enable_resources
=> pcibios_enable_device
=> do_pci_enable_device
=> pci_enable_device_flags
=> igb_probe
=> local_pci_probe
=> work_for_cpu_fn
=> process_one_work
=> worker_thread
=> kthread
=> ret_from_fork
起worker來調用driver probe。
bash-4872 [026] .... 90924.365341: myprobe: (pci_device_probe+0x0/0x1c0)
bash-4872 [026] .... 90924.365355: <stack trace>
=> pci_device_probe
=> really_probe
=> driver_probe_device
=> bus_for_each_drv
=> __device_attach
=> pci_bus_add_device
=> pci_bus_add_devices
=> pci_bus_add_devices
=> pci_rescan_bus
=> rescan_store--------------------入口
=> kernfs_fop_write
=> vfs_write
=> ksys_write
=> do_syscall_64
=> entry_SYSCALL_64_after_hwframe