5

pcie reset系列之 内核框架 - _备忘录

 1 year ago
source link: https://www.cnblogs.com/10087622blog/p/17495643.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

pcie reset系列之 内核框架

FLR是pci reset的一种。

关于FLR的寄存器操作比较简单, 相关的寄存器有:
配置空间里device cap里的FLR capability bit, 这个表示设备是否支持FLR。
配置空间里device control里的BCR_FLR bit, 写这个bit可以触发FLR。

调用函数检测是否支持FLR:

/* drivers/pci/pci.c */
pcie_has_flr(struct pci_dev *dev)

Linux kernel里pcie_flr会被下面的函数调用到, 触发FLR

/* drivers/pci/pci.c: below tree functions will call __pci_reset_function_locked */
pci_reset_function(struct pci_dev *dev)
pci_reset_function_locked(struct pci_dev *dev)
pci_try_reset_function(struct pci_dev *dev)
    => __pci_reset_function_locked(struct pci_dev *dev)
        -> pcie_flr(struct pci_dev *dev)

执行 __pci_reset_function_locked 的时候,6.2内核提供的reset方法有:

/* dev->reset_methods[] is a 0-terminated list of indices into this array */
static const struct pci_reset_fn_method pci_reset_fn_methods[] = {
    { },
    { pci_dev_specific_reset, .name = "device_specific" },
    { pci_dev_acpi_reset, .name = "acpi" },
    { pcie_reset_flr, .name = "flr" },
    { pci_af_flr, .name = "af_flr" },
    { pci_pm_reset, .name = "pm" },
    { pci_reset_bus_function, .name = "bus" },
};

那么这些reset的优先级,是从数组下标小的,优先级就高。在4.19的内核中,并没有做成table,但顺序是一样的。
且前面reset只要返回不是 -ENOTTY,则不会执行后面的reset。

首先,暴露给用户态的接口,通过这个设备的sysfs接口可以触发FLR:

/* drivers/pci/pci-sysfs.c */
reset_store
    -> pci_reset_function(struct pci_dev *dev)

另外,vfio里也提供的接口,可以供给用户态触发FLR。这些接口包括,vfio设备的enable,
disable, 以及一个vfio设备相关的ioctl。

/* drivers/vfio/pci/vfio_pci_config.c */
vfio_exp_config_write
    -> pci_try_reset_function

/* drivers/vfio/pci/vfio_pci.c */
vfio_pci_enable
vfio_pci_disable
vfio_pci_ioctl (cmd == VFIO_DEVICE_RESET)
    => pci_try_reset_function(pdev);

单独的FLR操作需要配合整个reset流程工作, 在上面的调用pcie_flr的函数里,他们基本
的处理流程都是, 先做reset_prepare, 再触发FLR,最后做reset后的恢复:

the logic of pci_reset_function and its brother functions are:
	- reset_prepare
	- flr operation if supporting flr
	- reset_done

reset_prepare and reset_done callbacks are stored in pci_driver’s pci_error_handlers,大多数驱动注册了pci_error_handler,但很多没有实现prepare。
these callbacks should be offered by your device driver:

驱动中的函数:

struct pci_driver {
	...
	const struct pci_error_handlers {
		...
		void (*reset_prepare)(struct pci_dev *dev);
		void (*reset_done)(struct pci_dev *dev);
		...
	}
	...
}

从上面的代码分析中可以看出,linux内核中的flr流程并不涉及到软件中设备结构的销毁.包括驱动资源的释放。
所以,只要在发生flr这段时间不去下发硬件请求,如果用lspci看,设备理论上会一直都在。对于使能了sriov的硬件,
在实现flr的时候,如果对pf执行flr,在硬件层面都有pf到vf的通知方式, 包括业务黑洞的设置,这样可以保证在pf flr时候通知到
flr做必要的处理,当pf flr完成后,可以通知vf驱动做必要的硬件配置上的恢复。
如果只是flr 某一个vf,不应该影响到其他vf的业务流。

注意,这个跟pcie g5 spec有一些相差。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK