0、Power Mangement的两种方式

     PCIe spec定义的两种power management方式,一种是针对device的(其实是针对function的)Device Power Mangement State即D-state。一种是针对Link的Link Power Management Sates即L-States。其中红色的状态是必须实现的,黑色的状态是可选的。

一句话说就是:Link的状态由下游设备的D-state决定。

    针对Power Management有两种管理机制,其中ASPM是在D0状态下进入低功耗模式的管理机制。PCI-PM是软件写function的配置空间的Power Management Control/Status Register来让function进入某种D state。而ASPM是硬件行为,软件只能写function配置空间Link Control Register的ASPM Control比特来disable和允许进入某种L state。

    进入低功耗模式容易,出来就难了,需要链路两端设备都发EIEOS的TS序列进行交互,从低功耗状态出来会出现各种各样的问题,可能出现PCIe错误或者会出现MCE等,一般会把低功耗模式关闭,cmdline关闭的方式如下:

pcie_aspm=off,pcie_port_pm =off

       pcie_aspm=      [PCIE] Forcibly enable or disable PCIe Active State Power
                        Management.
                off     Disable ASPM.
                force   Enable ASPM even on devices that claim not to support it.
                        WARNING: Forcing ASPM on may cause system lockups.
       pcie_port_pm=   [PCIE] PCIe port power management handling:
                off     Disable power management of all PCIe ports
                force   Forcibly enable power management of all PCIe ports

1、什么是PME    

     PCIe PME机制与PCI Bus Power Management Interface spec定义兼容的PME机制。Power management events由需要产生PM state变化的function发出。Power management events典型应用就是让系统或者某个function从lower power state恢复。

    PME(power management events)是一种特殊的post TLP(message),它起源于PCIe EP、PCI Express Legacy Endpoints或者RP并且路由到RC。PME message中的requestid字段代表出现PM state变化的设备。

   PCIe主要支持下面有些power management message

    由于RP下面有很多设备,但是root status寄存器的requestid只有一个,RC里有一个buffer来存储这些PME message,由于buffer是有限的,这样就可以导致backpressure问题(也就是RC的buffer的容量存不下Root Port下面的设备发过来的PME message)。

   为了保证PME message不丢失,所有能产生PME message的设备必须有PME 服务超时机制当超时后,设备的PME status没有被清除的话,设备需要重发PME message。这一点非常重要,因为linux PME driver是依赖于requestid的,虽然linux这么做有点不合理

    RP收到下游设备的PME message后会设置Root Status reg的PME status状态,如果root control reg的PME interrupt enable为1的话,RP还可发起中断

    从上面这些描述可以看出,PME和AER比较类似,设备发出message,然后路由到RC,如果RP对应的ctrl reg是使能的,则产生中断,并且message中都有一个叫做requestid的字段来表征是哪个设备发出的message。

2、linux PME driver流程   

    linux PME driver流程主要分为下面几个方面

2.1 pme probe流程

    这个流程中主要是申请这个资源,清理PME status reg,使能PME 中断。

2.2 pme中断服务流程

    和所有的中断服务函数一样,pme的中断服务函数只是确认下是否产生了PME中断,然后马上转中断下半部处理。

    

2.3 work处理流程

2.3.0 work处理框架  

 work中先确认是否收到了PME message,然后循环处理PME request,这里的重点就是处理requestid的流程。

2.3.1处理requestid

    这个流程完全依赖requestid来处理PME message,不仅写的异常啰嗦,而且依赖硬件按照协议实现,弄出5个场景,其实一个walk bus,从RP一直往下处理就可以,根本不需要依赖requestid。

    从上面流程可以看出,linux PME driver处理完全依赖requestid的更新,由于requestid仅仅代表最后的PME requester,这就PME pending和硬件重新set PME status并更新requestid字段。如果超时后,设备的PME status还没有清零,依赖PME 重发机制。简单说,linux PME driver完全按照协议来写的,从理论上来说没啥问题。但是理想很美好,现实很残酷,没有没bug的芯片,linux PME driver这套代码放在工程上会被吊打。合理的做法是不依赖requestid字段,只要RP收到中断,肯定是RP或者RP下面设备发出来的PME message,只需要walk bus按深度遍历RP本身和RP下游设备的PME ctrl and status reg,然后按照2.4的处理流程处理就可以了,直到满足2.3.0的跳出循环条件为止。

2.4 检查对应设备是否发出了PME message

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐