diff options
Diffstat (limited to 'drivers/nvme/target/core.c')
| -rw-r--r-- | drivers/nvme/target/core.c | 50 | 
1 files changed, 31 insertions, 19 deletions
| diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index be6fcdaf51a7..25cc2ee8de3f 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -864,10 +864,9 @@ static inline u16 nvmet_io_cmd_check_access(struct nvmet_req *req)  static u16 nvmet_parse_io_cmd(struct nvmet_req *req)  { -	struct nvme_command *cmd = req->cmd;  	u16 ret; -	ret = nvmet_check_ctrl_status(req, cmd); +	ret = nvmet_check_ctrl_status(req);  	if (unlikely(ret))  		return ret; @@ -1118,9 +1117,20 @@ static void nvmet_start_ctrl(struct nvmet_ctrl *ctrl)  {  	lockdep_assert_held(&ctrl->lock); -	if (nvmet_cc_iosqes(ctrl->cc) != NVME_NVM_IOSQES || -	    nvmet_cc_iocqes(ctrl->cc) != NVME_NVM_IOCQES || -	    nvmet_cc_mps(ctrl->cc) != 0 || +	/* +	 * Only I/O controllers should verify iosqes,iocqes. +	 * Strictly speaking, the spec says a discovery controller +	 * should verify iosqes,iocqes are zeroed, however that +	 * would break backwards compatibility, so don't enforce it. +	 */ +	if (ctrl->subsys->type != NVME_NQN_DISC && +	    (nvmet_cc_iosqes(ctrl->cc) != NVME_NVM_IOSQES || +	     nvmet_cc_iocqes(ctrl->cc) != NVME_NVM_IOCQES)) { +		ctrl->csts = NVME_CSTS_CFS; +		return; +	} + +	if (nvmet_cc_mps(ctrl->cc) != 0 ||  	    nvmet_cc_ams(ctrl->cc) != 0 ||  	    nvmet_cc_css(ctrl->cc) != 0) {  		ctrl->csts = NVME_CSTS_CFS; @@ -1179,19 +1189,19 @@ static void nvmet_init_cap(struct nvmet_ctrl *ctrl)  	ctrl->cap |= NVMET_QUEUE_SIZE - 1;  } -u16 nvmet_ctrl_find_get(const char *subsysnqn, const char *hostnqn, u16 cntlid, -		struct nvmet_req *req, struct nvmet_ctrl **ret) +struct nvmet_ctrl *nvmet_ctrl_find_get(const char *subsysnqn, +				       const char *hostnqn, u16 cntlid, +				       struct nvmet_req *req)  { +	struct nvmet_ctrl *ctrl = NULL;  	struct nvmet_subsys *subsys; -	struct nvmet_ctrl *ctrl; -	u16 status = 0;  	subsys = nvmet_find_get_subsys(req->port, subsysnqn);  	if (!subsys) {  		pr_warn("connect request for invalid subsystem %s!\n",  			subsysnqn);  		req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(subsysnqn); -		return NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR; +		goto out;  	}  	mutex_lock(&subsys->lock); @@ -1204,33 +1214,34 @@ u16 nvmet_ctrl_find_get(const char *subsysnqn, const char *hostnqn, u16 cntlid,  			if (!kref_get_unless_zero(&ctrl->ref))  				continue; -			*ret = ctrl; -			goto out; +			/* ctrl found */ +			goto found;  		}  	} +	ctrl = NULL; /* ctrl not found */  	pr_warn("could not find controller %d for subsys %s / host %s\n",  		cntlid, subsysnqn, hostnqn);  	req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(cntlid); -	status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR; -out: +found:  	mutex_unlock(&subsys->lock);  	nvmet_subsys_put(subsys); -	return status; +out: +	return ctrl;  } -u16 nvmet_check_ctrl_status(struct nvmet_req *req, struct nvme_command *cmd) +u16 nvmet_check_ctrl_status(struct nvmet_req *req)  {  	if (unlikely(!(req->sq->ctrl->cc & NVME_CC_ENABLE))) {  		pr_err("got cmd %d while CC.EN == 0 on qid = %d\n", -		       cmd->common.opcode, req->sq->qid); +		       req->cmd->common.opcode, req->sq->qid);  		return NVME_SC_CMD_SEQ_ERROR | NVME_SC_DNR;  	}  	if (unlikely(!(req->sq->ctrl->csts & NVME_CSTS_RDY))) {  		pr_err("got cmd %d while CSTS.RDY == 0 on qid = %d\n", -		       cmd->common.opcode, req->sq->qid); +		       req->cmd->common.opcode, req->sq->qid);  		return NVME_SC_CMD_SEQ_ERROR | NVME_SC_DNR;  	}  	return 0; @@ -1311,10 +1322,10 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,  		pr_warn("connect request for invalid subsystem %s!\n",  			subsysnqn);  		req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(subsysnqn); +		req->error_loc = offsetof(struct nvme_common_command, dptr);  		goto out;  	} -	status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;  	down_read(&nvmet_config_sem);  	if (!nvmet_host_allowed(subsys, hostnqn)) {  		pr_info("connect by host %s for subsystem %s not allowed\n", @@ -1322,6 +1333,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,  		req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(hostnqn);  		up_read(&nvmet_config_sem);  		status = NVME_SC_CONNECT_INVALID_HOST | NVME_SC_DNR; +		req->error_loc = offsetof(struct nvme_common_command, dptr);  		goto out_put_subsystem;  	}  	up_read(&nvmet_config_sem); | 
