Nvme协议第三章 Controller Registers

控制器寄存器位于MLBAR/MUBAR寄存器(PCI BAR0和BAR1)中,该寄存器应映射到支持有序访问和可变访问宽度的内存空间。host主机通过访问虚拟内存的方式访问该部分寄存器。

注:访问过程只能一次访问一个寄存器,不能多个访问。

寄存器如下:

 1 Offset 00h:CAP

 注意type类型以及bit位。MPSMAX和MPSMIN只是设置一个最大最小范围,具体实际的配置还是需要使用CC.MPS设置。(下图是nvme驱动code(Linux-6.8.8)调用read接口读bar空间 cap信息)

 

 全局搜索了下code,用到ctrl->cap的地方:

 nvme disable controller时候,等待CSTS_RDY状态变化,cap有一项timeout项,需要读取timeout时间,此时间可以理解为一个上限时间,不能超过此时间。通常是以500ms为一个单位。

 /**********************************************************************************************************/

 

 在驱动nvme enable ctrl内:

1 首先读取bar空间CAP,写入到本地ctrl->cap

2 获取dev page min;

3 CSS支持情况,协议定义如下:

 4 关于ctrl->ctrl_config配置,放到后面详细说明。这里配置了ctrl_config,然后写入到nvme register。

 5 重新读取cc reg,然后cap reg重读一次(这里暂时没理解到为什么cc写入一次,会影响到cap)

 6 超时判断,如果&NVME_CAP_CRMS_CRWMS为真,那么需要读取Controller Ready timeout

   定义:NVME_REG_CRTO  = 0x0068,   /* Controller Ready Timeouts */

7 开启cc enable

8 超时等待,等待NVME_CSTS_RDY状态转变。

 /**********************************************************************************************************/

 此函数是mps转换sector。

 /**********************************************************************************************************/

 当admin命令queue create完成,执行nvme_init_ctrl_finish函数。

1 读取SSD FW版本,即:

2  读取admin queue entry size:表明单个queue支持的最大entry个数。

3 读取NSSRS:是否支持子系统

 4 identify和configuration设置。(后序再详细解析)

/**********************************************************************************************************/

 扫描NS信息。NVME_CAP_CRMS_CRIMS

nvme协议上对59bit和60bit是reserved,但是nvme驱动里面代表什么含义?

Offset 08h: VS – Version

当admin AQA等信息全部设置完成,可以create admin命令后,执行nvme_init_ctrl_finish函数,读取SSD 版本信息。

Offset 14h: CC – Controller Configuration

3.1 CC.EN 

 在CC.EN =1之前,host应该设置:CC.AMS 、CC.MPS、CC.CSS。

如果在初始化CC.IOCQES和(CC.IOSQES之前去创建IO queue,那么会造成controller去终止创建IO CQ和IO SQ,并返回一个无效状态(status code of Invalid Queue Size)。

当SQ doorbell tail写入成功后,EN应该设置为1。 

当EN被清空为“0”时,控制器不得处理命令,也不得将CQ entry写入到CQ queue里面。

当EN状态从1->0时候,controller被重启。删除所有的IO queue(SQ和CQ),复位Admin SQ和CQ queue,硬件处于idle状态。controller级别重启并不影响到PCI寄存器设定和AQA ASQ ACQ的设定。但是其他相关联的,在bar空间(本章节就是bar空间寄存器定义,应该可以这样理解)恢复成默认状态。

controller应该确保在重启操作之前,已经发送到nvme设备的命令,数据没有丢失(需要SSD PLP掉电保护机制来保证),并收到cpl msg到CQ。

当EN被清空为0时候,一旦controller准备好重新启用,CSTS.RDY 被controller清空为0;

当EN=1时候,如果controller准备好处理命令,CSTS.RDY 被controller设置为1。

以下两个情况导致未定义结果

CSTS.RDY=1时,EN状态从0->1过程中;

CSTS.RDY=0时,EN状态从1->0过程中;

另外:AQA ASQ和ACQ只能在EN=0情况下进行修改

查看Linux内核code,驱动中关于CC.EN设置:

nvme_disable_ctrl函数内部,设置EN=0,用于shutdown流程。

/**********************************************************************************************************/

nvme_enable_ctrl函数如上CAP的描述,设置EN=1。

/**********************************************************************************************************/

 函数是表面此刻continue是否正在处理cmd。必须在EN=1才有效。

 3.2 CC.CSS

 

CC.CSS是为了IO SQ选择使用的命令集。host应该选择一个支持的命令集,并且只能在CC.EN =0情况下修改,这个改动应该适用于正在使用的所有IO SQ。(主要关注nvme命令)

  3.3 CC.MPS

MPS是设置host page size,但是范围只能在[CAP.MPSMIN,CAP.MPSMAX]。

 关于CC.AMS、CC.SHN、CC.IOSQES、CC.IOCQES如上,依然写入到ctrl->ctrl_config。

  3.4 CC.AMS

 选择仲裁机制,也需要在EN=0情况下设置。

3.5 CC.SHN

用于设置 shutdown notification。host应该在PCI power management state改变或者下电发生前进行设置。

发生warm reboot时候,需要重新配置(关于reboot类型 如cold warm等,可以单独分析);

特别注意:当SHN改变成01b或者10b时候,其他位域可能会改变。

3.6 CC.IOSQES

用于定义IO命令集可以保存多少个SQ entry。

3.7 CC.IOCQES

用于定义IO命令集可以保存多少个CQ entry 。

驱动内部定义CC IOSQES= 6 << 16 =  0x60000;IOCQES= 4 << 20 = 0x400000。

Offset 1Ch: CSTS – Controller Status

定义controller state相关信息。

4.1 RDY

 CC.EN =1被设置后,controller准备接收SQ tail doorbell的写入,RDY被设置为1。

如果CC.EN被清空为0,那么RDY应该也为0;

CC.EN = 1,然后RDY=1后,命令才可以被提交;

CC.EN从初始0变化到1,Host应该等待CAP.TO的最小值,使得RDY=1;(CAP TO是最小时间?)

4.2 CFS

发生了一个致命的控制器错误,无法在对应的CQ中进行通信,CFS会被置1;如果没有发送错误,那么一直为0;

controller初始化阶段如果发生fatal controller error,那么重启后该值会被置1;

4.3 SHST

 SHST和CC.SHN关联,表示shutdown过程状态,需要主机设置CC.SHN。

shutdown操作后(即SHST->10b),需要CC.EN=0,然后开始执行命令(和shutdown相关的)。

如果host提交reset命令给controller,但是controller并没有reset,该行为未被定义。

4.4 NSSRO

如果在向NVM子系统供电时上次出现NVM子系统重置,则此字段的初始值为“1”。

由于对NVM子系统供电,在NVM子系统重置后,该字段的初始值为“0”。

CAP.NSSRS= 1,controller支持NVM Subsystem Reset feature,NSSRO才有效;

如果NVM子系统重置导致了新固件映像的激活,则此字段的重置值为“0”。

判断是否可以reset

 

 配置Admin queue时候,把NSSRO写入到CSTS register。

4.5 PP

CC.EN =1时候生效;

PP表示控制器是否在处理命令。PP=0表示controller正常处理命令;如果此位设置为“1”,则控制器已暂时停止处理命令以处理事件。

Offset 20h: NSSR – NVM Subsystem Reset  

 为主机软件提供了启动NVM子系统重置的能力,是可选项(不是必须的),NSSR是否支持取决于CAP.NSSRS的值。但是位域空间必须占。

host往NSSR中写入0x4E564D65,表示初始化NVME subsystem Reset;其余值都不会产生效果。如果读取该寄存器,返回为0。

 6 Offset 24h: AQA – Admin Queue Attributes

此寄存器定义了admin CQ和SQ的属性。admin SQ和CQ的队列标识符为0h;admin SQ的优先级由所选的仲裁机制决定(参考第4.11节)。admin SQ和CQ要求必须在连续的物理内存中。 

ASQS和ACQS分别定义了admin SQ entry size和admin CQ entry size;

在清除此字段为0时候,启用控制器会产生未定义的结果。

CQ和SQ entry的最小是2,最大值为4096。这是一个0 base的值。

 nvme_pci_configure_admin_queue配置AQA。

Offset 28h: ASQ – Admin Submission Queue Base Address

表示admin SQ base address,这个需要根据CC.MPS值确定对齐边界。

 dma_alloc_coherent函数分配sq dma address。

Offset 30h: ACQ – Admin Completion Queue Base Address

表示admin CQ base address,这个需要根据CC.MPS值确定对齐边界。 

 驱动使用dma_alloc_coherent函数分配cq dma address。

9  Offset (1000h + ((2y) * (4 << CAP.DSTRD))): SQyTDBL – Submission Queue y Tail Doorbell

 定义SQ doorbell tail指针。host有cmd需要执行,需要往tail指针+1,host不可读取tail指针,需要SSDread指针,获取cmd信息。

 

 

 驱动是通过nvme_dev_map映射bar+dbs。

  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值