0、热插拔
热插拔分为两种,一是通知式热插拔,一个是暴力热插拔,所谓通知式热插拔就是先通知driver卸载驱动,停止IO,然后再拔出。所谓暴力热插拔就是带着IO拔出
1、 SFF-8639
SFF-8639也叫U.2,物理结构可以兼容SAS/SATA/SATA Express/NVMe。SFF-8639详细的引脚定义可以参考PCI Express SFF-8639 Module specification。
其中比较重要的sideband信号有PWRDIS、IfDet#、PERST#、DualPortEn。
PWDIS:该信号assert时,disable SFF-8639电路的供电。
IfDet#:长针信号,是SFF-8639的detect信号,当NVMe盘插入拔插时,作为presence信号会被拉低拉高。
PERST#:PCIe的reset信号,PCIe Spec规定电源、时钟和PESRT#信号的时序。
DualPortEn:双端口盘(一般存储上会用双端口盘)该信号需要assert,如果是单端口盘则该信号de-assert。
2、 连接框图
整个热插拔最关键的是如何把带外信号(power ctrl、presence或者button press)和PCIe 配置空间的slot status reg关联起来。热插拔涉及到systemBIOS预留资源、linux driver中的pciehp service/Endpoint driver、芯片设计(需要root port或者switch有hotplug controller)、芯片firmware、单板硬件,是一个系统工程,不太好调试。
其中CPLD模拟的PCA9555可以由真正的PCA9555芯片代替,使用CPLD模拟PCA9555完全是基于成本考虑。
(1)当SSD被插入,IfDet#信号就被拉低,SFF8639后的IO端口改变,GPIO中断到FW,FW通过IIC接口读取SFF8639后的IO端口,然后和已经保存的IO端口状态对比,发现某个slot的IfDet#信号改变。
(2)FW更改芯片配置空间的presence status和presence change status寄存器。presence change change中断(MSI中断)到CPU,CPU调用hotplug service注册的中断服务函数。
(3)中断服务函数起线程或者工作队列读取配置控制的presence change status,presence status、power status,FW把配置空间的转换成IIC读取SFF8639对应的IO端口。
(4)线程或者工作队列根据presence change status,presence status、power status来判断是否要热插拔,如果满足热插拔条件,则写配置空间的power ctrl把slot上电,然后等待PCIe链路linkup。
(5)FW通过IIC写把配置空间的power ctrl写到SFF8639对应的IIO端口,NVMe SSD被上电,#PERST释放,PCIe链路link up。
(6)线程或者工作队列等待PCIe链路linkup后,扫描NVMe,调用NVMe注册的probe。
(7)NVMe driver配置芯片返回probe流程,热插入完毕。
3、 Nvme盘的热拔插
SFF-8639 spec定义的在位信号和PCIe的定义是有冲突的。SFF-8639规定PRSNT#和IfDet#这两个带外信号都是frist-to-mate and last-to-break的,也就是说SFF-8639规定的PRSNT#和IfDet#比PCIe带内信号要长,而PCIe specification规定的恰好相反。
下面是PCIe SFF8639 Module Specification的原话:
The SFF-8639 interface includes the PRSNT# and IfDet# signals, as an out of band presence detect mechanism, to detect the presence of the SFF-8639 module. Since PRSNT# and IfDet# are not in the last-to-mate and first-to-break group, another vendor-specific mechanism is required to provide warning of module removal。
由于历史原因(SAS盘上是没有button按钮)导致的客户操作习惯(客户换盘都是暴力拔出的),Nvme盘需要支持暴力热插拔而不是通知式热插拔。
暴力热插拔是指不提前通知驱动停IO的情况下,就把PCIe设备从系统中拔出,这样会导致存在未完成的IO。
支持暴力热插拔要求switch或者RP(如果SSD接在switch下或RP下)可以协助处理这些未完成的请求,或者host有类似的机制,针对未完成的Non posted请求,返回completion包(PCIe协议要求Non posted请求需要completion包),从而阻止host等待未完成的请求导致的超时(超时可以能导致系统crash)。这就要用到PCIe 3.1协议新增的一个重要的capability:DPC。
4、 DPC是什么
DPC全称Downstream Port Containment,这个capability是PCIe 3.1协议针对root port和switch downstream port新增的。其作用是当检查到下行口本身出现错误(什么等级的错误会触发DPC是可以配置的)或则下行口下面的设备上报错误message(什么等级的error message会触发DPC也是可以配的)可以关闭对应端口(让该端口的LSTTM进入disable状态),把PCIe traffic 拦截在该端口之下,从而阻止错误扩散。
针对未完成的Non posted的请求,root port或者switch downstream port根据DPC的设置返回completion包,completion包的状态是UR或者CA。对应Non posted的请求,在completion没有返回前,CPU认为该指令是未完成的。
DPC这种机制就为系统恢复错误提供了机会,因此,可以用来实现Nvme盘的暴力热插拔的需求。
5、 实现Nvme暴力拔插的准备工作
(1) BIOS
a. 为每个端口预留资源
由于PCIe设备的枚举是遵从深度优先的原则,如果系统启动时没有带盘启动,BIOS枚举时不会为RP或者switch下行口预留资源(bus资源、memory资源、prefetchable memory资源)。后面再插入Nvme盘,由于端口资源不足,盘无法枚举进系统,除非软件重新调整资源后再枚举(这样会影响其他盘的IO)。
如果是要做整机系统卖给客户,BIOS必须要为支持热插拔的端口预留资源(按照系统支持的EndPoint需要的最大资源预留)。如果仅仅是验证芯片功能,可以让系统带着Nvme盘或接口卡启动,确保在枚举时为支持热插拔的端口分配了资源。
b. PCI Express 配置空间设置
由于PCIe配置空间有些reg是HwInit的,驱动是无法访问的,如果要支持Nvme盘的暴力热插拔,需要BIOS或者Firmware初始化一些HwInit的reg。
如果PCI Express Capabilities中的slot implemented没有实现,将会导致slot capability 无法实现。因此,PCI Express Capabilities中的slot implemented必须为1。
Link Capabitlities reg中的surprise down error report capable必须要为1,否则无法把surprise down的错误转换成DPC(如果接Nvme盘的端口不支持surprise down,则不需要修改该bit)。
Data link layer link active reporting capable最好实现,这样可以通过带内linkup和linkdown方式辅助定位Nvme是否被拔出。
Slot capabilities reg中的power controllerpresent最好能实现,这样软件可以控制槽位电源。
Hot-plug surprise必须为0(如果接Nvme盘的端口不支持surprise down的错误可以不关注该bit),hot-plug surprise是DPC实现之前传统的surprise down handling机制,其实有点掩耳盗铃的意思。由于在某些,平台上,RC收到uncorrectable error的message会导致系统crash,因此在支持热插拔时就增加了hot-plug surprise bit,当出现surprise down error时,不向host报告错误,从而阻止系统crash。这个bit只能阻止surprise down error的上报,不能处理暴力拔出时未完成的IO的导致的CPU等待超时问题,并且会影响DPC功能,属于历史遗留问题。
针对这一点PCIe spec也有详细的描述:
关于slot cap中的hot plug surprise bit,intel的介绍的背景更多一些,不过原理上和spec上解释的是一致的。
Hot-plug capable需要为1,否则无法支持热插拔的各种中断。
(2) 软件
当slot 有对应的能力时,软件需要打开slot ctrl capabilities对应的bit。并且根据系统要求设置DPC ctrl。
6、 Nvme暴力拔插的软件流程流程
从流程上可以看出,其实所谓的surprise add和正常的通知式热插拔的hot add没有太大区别,只是把button press中断换成了presence detect change中断。
Surprise remove流程由于没有按按钮通知Nvme驱动停止IO,将会导致有没完成的IO,这将用到DPC特性来处理这些完成的IO。