• 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有一些相差。

  • 相关阅读:
    如何衡量个人成长?超越数字:探寻个人成长的三个维度
    吃透Chisel语言.30.Chisel进阶之通信状态机(二)——FSMD:以Popcount为例
    elementPlus Pagination 分页怎样变中文
    精准诊断,精确治疗,智芯传感ZXPA侵入式压力传感器为心血管疾病患者带来福音
    拓端tecdat|r语言中对LASSO回归,Ridge岭回归和Elastic Net模型实现
    redis哨兵模式(Redis Sentinel)
    mysql binlog
    快速解决 Resource not accessible by integration
    基于Springboot实现体质测试数据分析平台管理系统项目【项目源码+论文说明】计算机毕业设计
    掌握可扩展和可维护应用程序:12-Factor应用程序开发的全面指南
  • 原文地址:https://www.cnblogs.com/10087622blog/p/17495643.html