目录
概述 nvme_reset_work
在NVMe 在初始化完控制器后会使用nvme_reset_ctrl 中的queue_work(nvme_reset_wq, &ctrl->reset_work); 来调度工作队列中新work及执行nvme_reset_work
1.nvem_reset_work 处理流程
2 NVMe 控制寄存器状态分类
NVMe 控制器处于以下7 种状态 来区别控制器是否可以可以访问
3.nvme_reset_work 代码部分
static void nvme_reset_work(struct work_struct *work)
{
struct nvme_dev *dev =
container_of(work, struct nvme_dev, ctrl.reset_work);
bool was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL);
int result;
if (dev->ctrl.state != NVME_CTRL_RESETTING) {
dev_warn(dev->ctrl.device, "ctrl state %d is not RESETTING\n",
dev->ctrl.state);
result = -ENODEV;
goto out;
}
/*
* If we're called to reset a live controller first shut it down before
* moving on.
*/
if (dev->ctrl.ctrl_config & NVME_CC_ENABLE)
nvme_dev_disable(dev, false);
nvme_sync_queues(&dev->ctrl);
mutex_lock(&dev->shutdown_lock);
result = nvme_pci_enable(dev);
if (result)
goto out_unlock;
result = nvme_pci_configure_admin_queue(dev);
if (result)
goto out_unlock;
result = nvme_alloc_admin_tags(dev);
if (result)
goto out_unlock;
dma_set_min_align_mask(dev->dev, NVME_CTRL_PAGE_SIZE - 1);
/*
* Limit the max command size to prevent iod->sg allocations going
* over a single page.
*/
dev->ctrl.max_hw_sectors = min_t(u32,
NVME_MAX_KB_SZ << 1, dma_max_mapping_size(dev->dev) >> 9);
dev->ctrl.max_segments = NVME_MAX_SEGS;
/*
* Don't limit the IOMMU merged segment size.
*/
dma_set_max_seg_size(dev->dev, 0xffffffff);
mutex_unlock(&dev->shutdown_lock);
/*
* Introduce CONNECTING state from nvme-fc/rdma transports to mark the
* initializing procedure here.
*/
if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) {
dev_warn(dev->ctrl.device,
"failed to mark controller CONNECTING\n");
result = -EBUSY;
goto out;
}
/*
* We do not support an SGL for metadata (yet), so we are limited to a
* single integrity segment for the separate metadata pointer.
*/
dev->ctrl.max_integrity_segments = 1;
result = nvme_init_identify(&dev->ctrl);
if (result)
goto out;
if (dev->ctrl.oacs & NVME_CTRL_OACS_SEC_SUPP) {
if (!dev->ctrl.opal_dev)
dev->ctrl.opal_dev =
init_opal_dev(&dev->ctrl, &nvme_sec_submit);
else if (was_suspend)
opal_unlock_from_suspend(dev->ctrl.opal_dev);
} else {
free_opal_dev(dev->ctrl.opal_dev);
dev->ctrl.opal_dev = NULL;
}
if (dev->ctrl.oacs & NVME_CTRL_OACS_DBBUF_SUPP) {
result = nvme_dbbuf_dma_alloc(dev);
if (result)
dev_warn(dev->dev,
"unable to allocate dma for dbbuf\n");
}
if (dev->ctrl.hmpre) {
result = nvme_setup_host_mem(dev);
if (result < 0)
goto out;
}
result = nvme_setup_io_queues(dev);
if (result)
goto out;
/*
* Keep the controller around but remove all namespaces if we don't have
* any working I/O queue.
*/
if (dev->online_queues < 2) {
dev_warn(dev->ctrl.device, "IO queues not created\n");
nvme_kill_queues(&dev->ctrl);
nvme_remove_namespaces(&dev->ctrl);
nvme_free_tagset(dev);
} else {
nvme_start_queues(&dev->ctrl);
nvme_wait_freeze(&dev->ctrl);
nvme_dev_add(dev);
nvme_unfreeze(&dev->ctrl);
}
/*
* If only admin queue live, keep it to do further investigation or
* recovery.
*/
if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_LIVE)) {
dev_warn(dev->ctrl.device,
"failed to mark controller live state\n");
result = -ENODEV;
goto out;
}
nvme_start_ctrl(&dev->ctrl);
return;
out_unlock:
mutex_unlock(&dev->shutdown_lock);
out:
if (result)
dev_warn(dev->ctrl.device,
"Removing after probe failure status: %d\n", result);
nvme_remove_dead_ctrl(dev);
}
4.主要功能讲解
1.校验状态:检查控制器的状态是否为正在重置状态(NVME_CTRL_RESETTING),如果不是,则发出警告并返回错误码。
2.nvme_dev_disable 禁用控制器:如果控制器是启用的(NVME_CC_ENABLE 标志),则先禁用控制器。
3.nvme_sync_queues同步队列:同步控制器队列以确保未完成的请求完成并清空。
锁定:锁定设备的关闭锁(shutdown_lock),以确保在初始化过程中不会发生竞态条件。
4.nvme_pci_enablel启用控制器:尝试启用 NVMe 控制器,并在失败时跳转到解锁步骤。
5.nvme_pci_configure_admin_queue 配置admin queue管理队列:配置管理队列,用于执行控制器管理命令。
6.nvme_alloc_admin_tags分配管理标签:为管理队列分配标签(tag)。
7.dma_set_min_align_mask设置 DMA 对齐:设置 DMA 的最小对齐大小。
8.dev->ctrl.max_hw_sectors = min_t(u32,NVME_MAX_KB_SZ << 1, dma_max_mapping_size(dev->dev) >> 9)设置最大命令大小:根据硬件和配置,限制最大命令大小。
9.dma_set_max_seg_size(dev->dev, 0xffffffff);设置最大段数量:限制 I/O 请求中段的最大数量。
10.解锁:解锁关闭锁,以便初始化过程中的其他操作可以继续。
11.nvme_change_ctrl_state 进入 CONNECTING 状态:将控制器状态设置为连接中(NVME_CTRL_CONNECTING)状态,表示初始化过程正在进行中。
12.nvme_init_identify 初始化identify数据: nvme_ctrl 结构中初始化identify和各种控制器寄存器的缓存副本。在管理队列完全启动并运行后尽快调用。
13.nvme_sec_submit 处理安全特性:根据支持的安全特性初始化相关设置。Optional Admin Command Support (OACS)
14.nvme_dbbuf_dma_alloc分配 DBBUF:分配用于数据库缓冲区的 DMA 内存。
15.nvme_setup_host_mem 设置主机内存:根据控制器配置设置主机内存。
16.nvme_setup_io_queues 设置 I/O 队列:配置并初始化 I/O 队列。
17.nvme_remove_namespaces 根据队列数决定控制器状态:如果在线队列少于 2 个,则表示 I/O 队列未创建,执行相关清理操作;否则,启动 I/O 队列并.添加控制器。nvme_dev_add
18.nvme_change_ctrl_state 标记控制器为“LIVE”:将控制器状态标记为“LIVE”。
19.nvme_start_ctrl 启动控制器:启动控制器使其处于活动状态。
小结
后续补充