nvme_pcie驱动

linux kernel version: 5.15.x

关键结构体

nvme_dev

字段 说明
unsigned int nr_write_queues Number of queues to use for writes. If not set, reads and writes will share a queue set.
可以通过nvme.ko加载参数指定,默认为0
unsigned int nr_poll_queues Number of queues to use for polled IO
可以通过nvme.ko加载参数指定,默认为0
unsigned int nr_allocated_queues num_possible_cpus() + nr_write_queues + nr_poll_queues + 1
struct nvme_queue* queues 保存nvme_dev中的所有的sq和cq的队列信息的数组,index为0保存的时admin QP的信息
数组中的元素为struct nvme_queue结构体
数组的个数为nr_allocated_queues
unsigned online_queues 有效的队列数
unsigned long bar_mapped_size bar空间ioremap的大小
void __iomem* bar bar空间地址,内容为映射的ctrl的寄存器数据
void __iomem* dbs 队列的门铃寄存器的基地址,为bar空间地址+0x1000偏移地址
struct dma_pool* prp_page_pool prp page页面管理结构体数组,元素为4K大小,地址要求4K对齐
struct dma_pool* prp_small_pool prp small管理结构体数组,元素为256bytes大小,地址要求256bytes对齐
mempool_t* iod_mempool

nvme_ctrl

nvme_queue

nvme_queue结构体对应一个QP(SQ + CQ)。

字段 说明
u16 qid 队列id,admin的队列id为0
u32 q_depth 队列深度,admin队列为32,io队列的值等于nvme_dev->q_depth,通常情况下,SQ和CQ的深度时一样的
驱动会将该信息同步到ctrl的AQA寄存器
u32 __iomem* q_db 队列对应doorbell的地址,按照顺序分别存放SQ Tail Doorbell和CQ Head Doorbell,均为4bytes大小
nvme_dev->dbs[qid 2 nvme_dev->db_stride]
u8 sqes 提交队列中命令(sqe)结构体的大小
admin的SQ队列为6,io的SQ队列的值等于nvme_dev->sqes(通常也是6),实际大小为2^6=64 bytes
void* sq_cmds sqe的数组,保存了q_depth个sqes大小的元素
采用dma_alloc_coherent函数申请资源
dma_addr_t sq_dma_addr sq的dma地址,,驱动会将该地址信息同步给ctrl的ASQ寄存器
u16 sq_tail sq队列的尾指针位置
u16 last_sq_tail
struct nvme_completion* cqes cqe的数组,保存了q_depth个nvme_completion结构体
使用dma_alloc_coherent函数申请资源
dma_addr_t cq_dma_addr cq的dma地址,驱动会将该地址信息同步给ctrl的ACQ寄存器
u16 cq_head cq队列的头指针位置
u8 cq_phase 通过该字段与cqe中的phase bit进行对比来判定当前cqe是否时有效的cqe
u16 cq_vector 队列对应的中断向量号