上一篇文章讲述nvme driver 识别找到支持该driver 的nvme pci设备的过程,现在开始讲述nvme driver 识别之后,会调用该struct pci_driver实例中的probe 函数。
probe函数,功能是初始化controller,并为后续的进行IO做准备。
主要以下几个事情:
(1)host 设置pci和pcie 寄存器,这些配置包括创建IO queue前,使用a single interrupt(pin-based ,single-MSI, single MSI-X), 将controller 的pcie Bar 空间映射到host memory当中,这样host 就能直接配置controller的寄存器。需要说明的是,nvme 协议规定pcie的bar空间的最前面一段空间是作为controller的寄存器空间,需要暴露给host;
(2)host 通过check CSTS.RDY 是否为0,以等待上一次的reset完成;
(3)配置admin queue, 设置admin queue attributes(AQA),admin submission queue(ASQ),admin completion queue(ACQ)三个寄存器;
AQA:配置admin cq 和 sq size
ASQ:配置host 存放 admin command的queue的host memory 基地址;
ACQ:配置controller 存放admin command 返回command response 的host memory 基地址;
(3)admin queue 创建好之后,就可以通过admin queue创建IO 的SQ,CQ;
(4)配置controller 以下几个设置:
a. 仲裁机制CC.AMS
b. memory page size设置CC.MPS
c. IO command set 设置CC.CSS
(5)使能controller, 通过CC.EN置
(6)host 需要wait for controller 是否ready,通过check CSTS.RDY是否为1.
(7)host 使用set feature command 并且用number of queue的feature id来确定sq,cq的个数,确定完IO queue的数量之后,我们就知道需要配置MSI和MSI-X的数量了。
(8)host 根据controller支持的数量和system 配置数量,先申请合适数量的IO cq,然后申请合适数量的IO sq;
(9)host 发送第一次identify命令,获取controller 等配置,这些配置信息包括namespace个数;
(10)host 接下来针对每个namespace 发送identify 命令,获取每个namaspace的配置信息,并check是否active, 若active的话,就并发送get feature 命令获取namespace lab format, lba data size,metadata size等信息;
(11)通过add_diak()将每个namespace 加入到块设备层,IO就可以开始对其进行访问。
reference:
(1) nvme spec 1.3a.pdf
(2) Linux 3.18 nvme driver.
网友评论