【NVMe 专题详解 probe 之 reset - nvme_reset_work】

目录

概述 nvme_reset_work

 1.nvem_reset_work 处理流程

2 NVMe 控制寄存器状态分类  

 3.nvme_reset_work  代码部分

4.主要功能讲解

小结


概述 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 启动控制器:启动控制器使其处于活动状态。

小结

后续补充

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值