Commit 6b43537f authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge tag 'nvme-6.11-2024-07-08' of git://git.infradead.org/nvme into for-6.11/block

Pull NVMe updates from Keith:

"nvme updates for Linux 6.11

 - Device initialization memory leak fixes (Keith)
 - More constants defined (Weiwen)
 - Target debugfs support (Hannes)
 - PCIe subsystem reset enhancements (Keith)
 - Queue-depth multipath policy (Redhat and PureStorage)
 - Implement get_unique_id (Christoph)
 - Authentication error fixes (Gaosheng)"

* tag 'nvme-6.11-2024-07-08' of git://git.infradead.org/nvme: (21 commits)
  nvmet-auth: fix nvmet_auth hash error handling
  nvme: implement ->get_unique_id
  nvme-multipath: implement "queue-depth" iopolicy
  nvme-multipath: prepare for "queue-depth" iopolicy
  nvme-pci: do not directly handle subsys reset fallout
  lpfc_nvmet: implement 'host_traddr'
  nvme-fcloop: implement 'host_traddr'
  nvmet-fc: implement host_traddr()
  nvmet-rdma: implement host_traddr()
  nvmet-tcp: implement host_traddr()
  nvmet: add 'host_traddr' callback for debugfs
  nvmet: add debugfs support
  mailmap: add entry for Weiwen Hu
  nvme: rename CDR/MORE/DNR to NVME_STATUS_*
  nvme: fix status magic numbers
  nvme: rename nvme_sc_to_pr_err to nvme_status_to_pr_err
  nvme: split device add from initialization
  nvme: fc: split controller bringup handling
  nvme: rdma: split controller bringup handling
  nvme: tcp: split controller bringup handling
  ...
parents 09595e0c 89f58f96
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -685,6 +685,7 @@ Vivien Didelot <vivien.didelot@gmail.com> <vivien.didelot@savoirfairelinux.com>
Vlad Dogaru <ddvlad@gmail.com> <vlad.dogaru@intel.com>
Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@parallels.com>
Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@virtuozzo.com>
Weiwen Hu <huweiwen@linux.alibaba.com> <sehuww@mail.scut.edu.cn>
WeiXiong Liao <gmpy.liaowx@gmail.com> <liaoweixiong@allwinnertech.com>
Wen Gong <quic_wgong@quicinc.com> <wgong@codeaurora.org>
Wesley Cheng <quic_wcheng@quicinc.com> <wcheng@codeaurora.org>
+27 −5
Original line number Diff line number Diff line
@@ -1388,7 +1388,7 @@ static void devm_apple_nvme_mempool_destroy(void *data)
	mempool_destroy(data);
}

static int apple_nvme_probe(struct platform_device *pdev)
static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct apple_nvme *anv;
@@ -1396,7 +1396,7 @@ static int apple_nvme_probe(struct platform_device *pdev)

	anv = devm_kzalloc(dev, sizeof(*anv), GFP_KERNEL);
	if (!anv)
		return -ENOMEM;
		return ERR_PTR(-ENOMEM);

	anv->dev = get_device(dev);
	anv->adminq.is_adminq = true;
@@ -1516,10 +1516,30 @@ static int apple_nvme_probe(struct platform_device *pdev)
		goto put_dev;
	}

	return anv;
put_dev:
	put_device(anv->dev);
	return ERR_PTR(ret);
}

static int apple_nvme_probe(struct platform_device *pdev)
{
	struct apple_nvme *anv;
	int ret;

	anv = apple_nvme_alloc(pdev);
	if (IS_ERR(anv))
		return PTR_ERR(anv);

	ret = nvme_add_ctrl(&anv->ctrl);
	if (ret)
		goto out_put_ctrl;

	anv->ctrl.admin_q = blk_mq_alloc_queue(&anv->admin_tagset, NULL, NULL);
	if (IS_ERR(anv->ctrl.admin_q)) {
		ret = -ENOMEM;
		goto put_dev;
		anv->ctrl.admin_q = NULL;
		goto out_uninit_ctrl;
	}

	nvme_reset_ctrl(&anv->ctrl);
@@ -1527,8 +1547,10 @@ static int apple_nvme_probe(struct platform_device *pdev)

	return 0;

put_dev:
	put_device(anv->dev);
out_uninit_ctrl:
	nvme_uninit_ctrl(&anv->ctrl);
out_put_ctrl:
	nvme_put_ctrl(&anv->ctrl);
	return ret;
}

+1 −1
Original line number Diff line number Diff line
@@ -173,7 +173,7 @@ static const char * const nvme_statuses[] = {

const char *nvme_get_error_status_str(u16 status)
{
	status &= 0x7ff;
	status &= NVME_SCT_SC_MASK;
	if (status < ARRAY_SIZE(nvme_statuses) && nvme_statuses[status])
		return nvme_statuses[status];
	return "Unknown";
+83 −44
Original line number Diff line number Diff line
@@ -110,7 +110,7 @@ struct workqueue_struct *nvme_delete_wq;
EXPORT_SYMBOL_GPL(nvme_delete_wq);

static LIST_HEAD(nvme_subsystems);
static DEFINE_MUTEX(nvme_subsystems_lock);
DEFINE_MUTEX(nvme_subsystems_lock);

static DEFINE_IDA(nvme_instance_ida);
static dev_t nvme_ctrl_base_chr_devt;
@@ -261,7 +261,7 @@ void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl)

static blk_status_t nvme_error_status(u16 status)
{
	switch (status & 0x7ff) {
	switch (status & NVME_SCT_SC_MASK) {
	case NVME_SC_SUCCESS:
		return BLK_STS_OK;
	case NVME_SC_CAP_EXCEEDED:
@@ -307,7 +307,7 @@ static void nvme_retry_req(struct request *req)
	u16 crd;

	/* The mask and shift result must be <= 3 */
	crd = (nvme_req(req)->status & NVME_SC_CRD) >> 11;
	crd = (nvme_req(req)->status & NVME_STATUS_CRD) >> 11;
	if (crd)
		delay = nvme_req(req)->ctrl->crdt[crd - 1] * 100;

@@ -329,10 +329,10 @@ static void nvme_log_error(struct request *req)
		       nvme_sect_to_lba(ns->head, blk_rq_pos(req)),
		       blk_rq_bytes(req) >> ns->head->lba_shift,
		       nvme_get_error_status_str(nr->status),
		       nr->status >> 8 & 7,	/* Status Code Type */
		       nr->status & 0xff,	/* Status Code */
		       nr->status & NVME_SC_MORE ? "MORE " : "",
		       nr->status & NVME_SC_DNR  ? "DNR "  : "");
		       NVME_SCT(nr->status),		/* Status Code Type */
		       nr->status & NVME_SC_MASK,	/* Status Code */
		       nr->status & NVME_STATUS_MORE ? "MORE " : "",
		       nr->status & NVME_STATUS_DNR  ? "DNR "  : "");
		return;
	}

@@ -341,10 +341,10 @@ static void nvme_log_error(struct request *req)
			   nvme_get_admin_opcode_str(nr->cmd->common.opcode),
			   nr->cmd->common.opcode,
			   nvme_get_error_status_str(nr->status),
			   nr->status >> 8 & 7,	/* Status Code Type */
			   nr->status & 0xff,	/* Status Code */
			   nr->status & NVME_SC_MORE ? "MORE " : "",
			   nr->status & NVME_SC_DNR  ? "DNR "  : "");
			   NVME_SCT(nr->status),	/* Status Code Type */
			   nr->status & NVME_SC_MASK,	/* Status Code */
			   nr->status & NVME_STATUS_MORE ? "MORE " : "",
			   nr->status & NVME_STATUS_DNR  ? "DNR "  : "");
}

static void nvme_log_err_passthru(struct request *req)
@@ -359,10 +359,10 @@ static void nvme_log_err_passthru(struct request *req)
		     nvme_get_admin_opcode_str(nr->cmd->common.opcode),
		nr->cmd->common.opcode,
		nvme_get_error_status_str(nr->status),
		nr->status >> 8 & 7,	/* Status Code Type */
		nr->status & 0xff,	/* Status Code */
		nr->status & NVME_SC_MORE ? "MORE " : "",
		nr->status & NVME_SC_DNR  ? "DNR "  : "",
		NVME_SCT(nr->status),		/* Status Code Type */
		nr->status & NVME_SC_MASK,	/* Status Code */
		nr->status & NVME_STATUS_MORE ? "MORE " : "",
		nr->status & NVME_STATUS_DNR  ? "DNR "  : "",
		nr->cmd->common.cdw10,
		nr->cmd->common.cdw11,
		nr->cmd->common.cdw12,
@@ -384,11 +384,11 @@ static inline enum nvme_disposition nvme_decide_disposition(struct request *req)
		return COMPLETE;

	if (blk_noretry_request(req) ||
	    (nvme_req(req)->status & NVME_SC_DNR) ||
	    (nvme_req(req)->status & NVME_STATUS_DNR) ||
	    nvme_req(req)->retries >= nvme_max_retries)
		return COMPLETE;

	if ((nvme_req(req)->status & 0x7ff) == NVME_SC_AUTH_REQUIRED)
	if ((nvme_req(req)->status & NVME_SCT_SC_MASK) == NVME_SC_AUTH_REQUIRED)
		return AUTHENTICATE;

	if (req->cmd_flags & REQ_NVME_MPATH) {
@@ -2286,6 +2286,32 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info)
	return ret;
}

int nvme_ns_get_unique_id(struct nvme_ns *ns, u8 id[16],
		enum blk_unique_id type)
{
	struct nvme_ns_ids *ids = &ns->head->ids;

	if (type != BLK_UID_EUI64)
		return -EINVAL;

	if (memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) {
		memcpy(id, &ids->nguid, sizeof(ids->nguid));
		return sizeof(ids->nguid);
	}
	if (memchr_inv(ids->eui64, 0, sizeof(ids->eui64))) {
		memcpy(id, &ids->eui64, sizeof(ids->eui64));
		return sizeof(ids->eui64);
	}

	return -EINVAL;
}

static int nvme_get_unique_id(struct gendisk *disk, u8 id[16],
		enum blk_unique_id type)
{
	return nvme_ns_get_unique_id(disk->private_data, id, type);
}

#ifdef CONFIG_BLK_SED_OPAL
static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len,
		bool send)
@@ -2341,6 +2367,7 @@ const struct block_device_operations nvme_bdev_ops = {
	.open		= nvme_open,
	.release	= nvme_release,
	.getgeo		= nvme_getgeo,
	.get_unique_id	= nvme_get_unique_id,
	.report_zones	= nvme_report_zones,
	.pr_ops		= &nvme_pr_ops,
};
@@ -3941,7 +3968,7 @@ static void nvme_ns_remove_by_nsid(struct nvme_ctrl *ctrl, u32 nsid)

static void nvme_validate_ns(struct nvme_ns *ns, struct nvme_ns_info *info)
{
	int ret = NVME_SC_INVALID_NS | NVME_SC_DNR;
	int ret = NVME_SC_INVALID_NS | NVME_STATUS_DNR;

	if (!nvme_ns_ids_equal(&ns->head->ids, &info->ids)) {
		dev_err(ns->ctrl->device,
@@ -3957,7 +3984,7 @@ static void nvme_validate_ns(struct nvme_ns *ns, struct nvme_ns_info *info)
	 *
	 * TODO: we should probably schedule a delayed retry here.
	 */
	if (ret > 0 && (ret & NVME_SC_DNR))
	if (ret > 0 && (ret & NVME_STATUS_DNR))
		nvme_ns_remove(ns);
}

@@ -4148,7 +4175,7 @@ static void nvme_scan_work(struct work_struct *work)
		 * they report) but don't actually support it.
		 */
		ret = nvme_scan_ns_list(ctrl);
		if (ret > 0 && ret & NVME_SC_DNR)
		if (ret > 0 && ret & NVME_STATUS_DNR)
			nvme_scan_ns_sequential(ctrl);
	}
	mutex_unlock(&ctrl->scan_lock);
@@ -4668,6 +4695,9 @@ static void nvme_free_ctrl(struct device *dev)
 * Initialize a NVMe controller structures.  This needs to be called during
 * earliest initialization so that we have the initialized structured around
 * during probing.
 *
 * On success, the caller must use the nvme_put_ctrl() to release this when
 * needed, which also invokes the ops->free_ctrl() callback.
 */
int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
		const struct nvme_ctrl_ops *ops, unsigned long quirks)
@@ -4716,6 +4746,12 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
		goto out;
	ctrl->instance = ret;

	ret = nvme_auth_init_ctrl(ctrl);
	if (ret)
		goto out_release_instance;

	nvme_mpath_init_ctrl(ctrl);

	device_initialize(&ctrl->ctrl_device);
	ctrl->device = &ctrl->ctrl_device;
	ctrl->device->devt = MKDEV(MAJOR(nvme_ctrl_base_chr_devt),
@@ -4728,16 +4764,36 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
		ctrl->device->groups = nvme_dev_attr_groups;
	ctrl->device->release = nvme_free_ctrl;
	dev_set_drvdata(ctrl->device, ctrl);

	return ret;

out_release_instance:
	ida_free(&nvme_instance_ida, ctrl->instance);
out:
	if (ctrl->discard_page)
		__free_page(ctrl->discard_page);
	cleanup_srcu_struct(&ctrl->srcu);
	return ret;
}
EXPORT_SYMBOL_GPL(nvme_init_ctrl);

/*
 * On success, returns with an elevated controller reference and caller must
 * use nvme_uninit_ctrl() to properly free resources associated with the ctrl.
 */
int nvme_add_ctrl(struct nvme_ctrl *ctrl)
{
	int ret;

	ret = dev_set_name(ctrl->device, "nvme%d", ctrl->instance);
	if (ret)
		goto out_release_instance;
		return ret;

	nvme_get_ctrl(ctrl);
	cdev_init(&ctrl->cdev, &nvme_dev_fops);
	ctrl->cdev.owner = ops->module;
	ctrl->cdev.owner = ctrl->ops->module;
	ret = cdev_device_add(&ctrl->cdev, ctrl->device);
	if (ret)
		goto out_free_name;
		return ret;

	/*
	 * Initialize latency tolerance controls.  The sysfs files won't
@@ -4748,28 +4804,11 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
		min(default_ps_max_latency_us, (unsigned long)S32_MAX));

	nvme_fault_inject_init(&ctrl->fault_inject, dev_name(ctrl->device));
	nvme_mpath_init_ctrl(ctrl);
	ret = nvme_auth_init_ctrl(ctrl);
	if (ret)
		goto out_free_cdev;
	nvme_get_ctrl(ctrl);

	return 0;
out_free_cdev:
	nvme_fault_inject_fini(&ctrl->fault_inject);
	dev_pm_qos_hide_latency_tolerance(ctrl->device);
	cdev_device_del(&ctrl->cdev, ctrl->device);
out_free_name:
	nvme_put_ctrl(ctrl);
	kfree_const(ctrl->device->kobj.name);
out_release_instance:
	ida_free(&nvme_instance_ida, ctrl->instance);
out:
	if (ctrl->discard_page)
		__free_page(ctrl->discard_page);
	cleanup_srcu_struct(&ctrl->srcu);
	return ret;
}
EXPORT_SYMBOL_GPL(nvme_init_ctrl);
EXPORT_SYMBOL_GPL(nvme_add_ctrl);

/* let I/O to all namespaces fail in preparation for surprise removal */
void nvme_mark_namespaces_dead(struct nvme_ctrl *ctrl)
+20 −5
Original line number Diff line number Diff line
@@ -187,7 +187,7 @@ int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val)
	if (unlikely(ret != 0))
		dev_err(ctrl->device,
			"Property Get error: %d, offset %#x\n",
			ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
			ret > 0 ? ret & ~NVME_STATUS_DNR : ret, off);

	return ret;
}
@@ -233,7 +233,7 @@ int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val)
	if (unlikely(ret != 0))
		dev_err(ctrl->device,
			"Property Get error: %d, offset %#x\n",
			ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
			ret > 0 ? ret & ~NVME_STATUS_DNR : ret, off);
	return ret;
}
EXPORT_SYMBOL_GPL(nvmf_reg_read64);
@@ -275,11 +275,26 @@ int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val)
	if (unlikely(ret))
		dev_err(ctrl->device,
			"Property Set error: %d, offset %#x\n",
			ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
			ret > 0 ? ret & ~NVME_STATUS_DNR : ret, off);
	return ret;
}
EXPORT_SYMBOL_GPL(nvmf_reg_write32);

int nvmf_subsystem_reset(struct nvme_ctrl *ctrl)
{
	int ret;

	if (!nvme_wait_reset(ctrl))
		return -EBUSY;

	ret = ctrl->ops->reg_write32(ctrl, NVME_REG_NSSR, NVME_SUBSYS_RESET);
	if (ret)
		return ret;

	return nvme_try_sched_reset(ctrl);
}
EXPORT_SYMBOL_GPL(nvmf_subsystem_reset);

/**
 * nvmf_log_connect_error() - Error-parsing-diagnostic print out function for
 * 				connect() errors.
@@ -295,7 +310,7 @@ static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
		int errval, int offset, struct nvme_command *cmd,
		struct nvmf_connect_data *data)
{
	int err_sctype = errval & ~NVME_SC_DNR;
	int err_sctype = errval & ~NVME_STATUS_DNR;

	if (errval < 0) {
		dev_err(ctrl->device,
@@ -573,7 +588,7 @@ EXPORT_SYMBOL_GPL(nvmf_connect_io_queue);
 */
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl, int status)
{
	if (status > 0 && (status & NVME_SC_DNR))
	if (status > 0 && (status & NVME_STATUS_DNR))
		return false;

	if (status == -EKEYREJECTED)
Loading