Skip to content

Commit 1ad8630

Browse files
damien-lemoalkeithbusch
authored andcommitted
nvmet: Do not require SGL for PCI target controller commands
Support for SGL is optional for the PCI transport. Modify nvmet_req_init() to not require the NVME_CMD_SGL_METABUF command flag to be set if the target controller transport type is NVMF_TRTYPE_PCI. In addition to this, the NVMe base specification v2.1 mandate that all admin commands use PRP, that is, have CDW0.PSDT cleared to 0. Modify nvmet_parse_admin_cmd() to check this. Finally, modify nvmet_check_transfer_len() and nvmet_check_data_len_lte() to return the appropriate error status depending on the command using SGL or PRP. Since for fabrics nvmet_req_init() checks that a command uses SGL, always, this change affects only PCI target controllers. Signed-off-by: Damien Le Moal <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Tested-by: Rick Wertenbroek <[email protected]> Tested-by: Manivannan Sadhasivam <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent 60d3cd8 commit 1ad8630

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

drivers/nvme/target/admin-cmd.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,11 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req)
14781478
if (unlikely(ret))
14791479
return ret;
14801480

1481+
/* For PCI controllers, admin commands shall not use SGL. */
1482+
if (nvmet_is_pci_ctrl(req->sq->ctrl) && !req->sq->qid &&
1483+
cmd->common.flags & NVME_CMD_SGL_ALL)
1484+
return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
1485+
14811486
if (nvmet_is_passthru_req(req))
14821487
return nvmet_parse_passthru_admin_cmd(req);
14831488

drivers/nvme/target/core.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,12 +1122,15 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
11221122
/*
11231123
* For fabrics, PSDT field shall describe metadata pointer (MPTR) that
11241124
* contains an address of a single contiguous physical buffer that is
1125-
* byte aligned.
1125+
* byte aligned. For PCI controllers, this is optional so not enforced.
11261126
*/
11271127
if (unlikely((flags & NVME_CMD_SGL_ALL) != NVME_CMD_SGL_METABUF)) {
1128-
req->error_loc = offsetof(struct nvme_common_command, flags);
1129-
status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
1130-
goto fail;
1128+
if (!req->sq->ctrl || !nvmet_is_pci_ctrl(req->sq->ctrl)) {
1129+
req->error_loc =
1130+
offsetof(struct nvme_common_command, flags);
1131+
status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
1132+
goto fail;
1133+
}
11311134
}
11321135

11331136
if (unlikely(!req->sq->ctrl))
@@ -1182,8 +1185,14 @@ EXPORT_SYMBOL_GPL(nvmet_req_transfer_len);
11821185
bool nvmet_check_transfer_len(struct nvmet_req *req, size_t len)
11831186
{
11841187
if (unlikely(len != req->transfer_len)) {
1188+
u16 status;
1189+
11851190
req->error_loc = offsetof(struct nvme_common_command, dptr);
1186-
nvmet_req_complete(req, NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR);
1191+
if (req->cmd->common.flags & NVME_CMD_SGL_ALL)
1192+
status = NVME_SC_SGL_INVALID_DATA;
1193+
else
1194+
status = NVME_SC_INVALID_FIELD;
1195+
nvmet_req_complete(req, status | NVME_STATUS_DNR);
11871196
return false;
11881197
}
11891198

@@ -1194,8 +1203,14 @@ EXPORT_SYMBOL_GPL(nvmet_check_transfer_len);
11941203
bool nvmet_check_data_len_lte(struct nvmet_req *req, size_t data_len)
11951204
{
11961205
if (unlikely(data_len > req->transfer_len)) {
1206+
u16 status;
1207+
11971208
req->error_loc = offsetof(struct nvme_common_command, dptr);
1198-
nvmet_req_complete(req, NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR);
1209+
if (req->cmd->common.flags & NVME_CMD_SGL_ALL)
1210+
status = NVME_SC_SGL_INVALID_DATA;
1211+
else
1212+
status = NVME_SC_INVALID_FIELD;
1213+
nvmet_req_complete(req, status | NVME_STATUS_DNR);
11991214
return false;
12001215
}
12011216

0 commit comments

Comments
 (0)