Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nvmet: Add support for I/O queue management admin commands

The I/O submission queue management admin commands
(nvme_admin_delete_sq, nvme_admin_create_sq, nvme_admin_delete_cq,
and nvme_admin_create_cq) are mandatory admin commands for I/O
controllers using the PCI transport, that is, support for these commands
is mandatory for a a PCI target I/O controller.

Implement support for these commands by adding the functions
nvmet_execute_delete_sq(), nvmet_execute_create_sq(),
nvmet_execute_delete_cq() and nvmet_execute_create_cq() to set as the
execute method of requests for these commands. These functions will
return an invalid opcode error for any controller that is not a PCI
target controller. Support for the I/O queue management commands is also
reported in the command effect log of PCI target controllers (using
nvmet_get_cmd_effects_admin()).

Each management command is backed by a controller fabric operation
that can be defined by a PCI target controller driver to setup I/O
queues using nvmet_sq_create() and nvmet_cq_create() or delete I/O
queues using nvmet_sq_destroy().

As noted in a comment in nvmet_execute_create_sq(), we do not yet
support sharing a single CQ between multiple SQs.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Tested-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>

authored by

Damien Le Moal and committed by
Keith Busch
60d3cd85 1eb380ca

+170 -3
+162 -3
drivers/nvme/target/admin-cmd.c
··· 12 12 #include <linux/unaligned.h> 13 13 #include "nvmet.h" 14 14 15 + static void nvmet_execute_delete_sq(struct nvmet_req *req) 16 + { 17 + struct nvmet_ctrl *ctrl = req->sq->ctrl; 18 + u16 sqid = le16_to_cpu(req->cmd->delete_queue.qid); 19 + u16 status; 20 + 21 + if (!nvmet_is_pci_ctrl(ctrl)) { 22 + status = nvmet_report_invalid_opcode(req); 23 + goto complete; 24 + } 25 + 26 + if (!sqid) { 27 + status = NVME_SC_QID_INVALID | NVME_STATUS_DNR; 28 + goto complete; 29 + } 30 + 31 + status = nvmet_check_sqid(ctrl, sqid, false); 32 + if (status != NVME_SC_SUCCESS) 33 + goto complete; 34 + 35 + status = ctrl->ops->delete_sq(ctrl, sqid); 36 + 37 + complete: 38 + nvmet_req_complete(req, status); 39 + } 40 + 41 + static void nvmet_execute_create_sq(struct nvmet_req *req) 42 + { 43 + struct nvmet_ctrl *ctrl = req->sq->ctrl; 44 + struct nvme_command *cmd = req->cmd; 45 + u16 sqid = le16_to_cpu(cmd->create_sq.sqid); 46 + u16 cqid = le16_to_cpu(cmd->create_sq.cqid); 47 + u16 sq_flags = le16_to_cpu(cmd->create_sq.sq_flags); 48 + u16 qsize = le16_to_cpu(cmd->create_sq.qsize); 49 + u64 prp1 = le64_to_cpu(cmd->create_sq.prp1); 50 + u16 status; 51 + 52 + if (!nvmet_is_pci_ctrl(ctrl)) { 53 + status = nvmet_report_invalid_opcode(req); 54 + goto complete; 55 + } 56 + 57 + if (!sqid) { 58 + status = NVME_SC_QID_INVALID | NVME_STATUS_DNR; 59 + goto complete; 60 + } 61 + 62 + status = nvmet_check_sqid(ctrl, sqid, true); 63 + if (status != NVME_SC_SUCCESS) 64 + goto complete; 65 + 66 + /* 67 + * Note: The NVMe specification allows multiple SQs to use the same CQ. 68 + * However, the target code does not really support that. So for now, 69 + * prevent this and fail the command if sqid and cqid are different. 70 + */ 71 + if (!cqid || cqid != sqid) { 72 + pr_err("SQ %u: Unsupported CQID %u\n", sqid, cqid); 73 + status = NVME_SC_CQ_INVALID | NVME_STATUS_DNR; 74 + goto complete; 75 + } 76 + 77 + if (!qsize || qsize > NVME_CAP_MQES(ctrl->cap)) { 78 + status = NVME_SC_QUEUE_SIZE | NVME_STATUS_DNR; 79 + goto complete; 80 + } 81 + 82 + status = ctrl->ops->create_sq(ctrl, sqid, sq_flags, qsize, prp1); 83 + 84 + complete: 85 + nvmet_req_complete(req, status); 86 + } 87 + 88 + static void nvmet_execute_delete_cq(struct nvmet_req *req) 89 + { 90 + struct nvmet_ctrl *ctrl = req->sq->ctrl; 91 + u16 cqid = le16_to_cpu(req->cmd->delete_queue.qid); 92 + u16 status; 93 + 94 + if (!nvmet_is_pci_ctrl(ctrl)) { 95 + status = nvmet_report_invalid_opcode(req); 96 + goto complete; 97 + } 98 + 99 + if (!cqid) { 100 + status = NVME_SC_QID_INVALID | NVME_STATUS_DNR; 101 + goto complete; 102 + } 103 + 104 + status = nvmet_check_cqid(ctrl, cqid); 105 + if (status != NVME_SC_SUCCESS) 106 + goto complete; 107 + 108 + status = ctrl->ops->delete_cq(ctrl, cqid); 109 + 110 + complete: 111 + nvmet_req_complete(req, status); 112 + } 113 + 114 + static void nvmet_execute_create_cq(struct nvmet_req *req) 115 + { 116 + struct nvmet_ctrl *ctrl = req->sq->ctrl; 117 + struct nvme_command *cmd = req->cmd; 118 + u16 cqid = le16_to_cpu(cmd->create_cq.cqid); 119 + u16 cq_flags = le16_to_cpu(cmd->create_cq.cq_flags); 120 + u16 qsize = le16_to_cpu(cmd->create_cq.qsize); 121 + u16 irq_vector = le16_to_cpu(cmd->create_cq.irq_vector); 122 + u64 prp1 = le64_to_cpu(cmd->create_cq.prp1); 123 + u16 status; 124 + 125 + if (!nvmet_is_pci_ctrl(ctrl)) { 126 + status = nvmet_report_invalid_opcode(req); 127 + goto complete; 128 + } 129 + 130 + if (!cqid) { 131 + status = NVME_SC_QID_INVALID | NVME_STATUS_DNR; 132 + goto complete; 133 + } 134 + 135 + status = nvmet_check_cqid(ctrl, cqid); 136 + if (status != NVME_SC_SUCCESS) 137 + goto complete; 138 + 139 + if (!qsize || qsize > NVME_CAP_MQES(ctrl->cap)) { 140 + status = NVME_SC_QUEUE_SIZE | NVME_STATUS_DNR; 141 + goto complete; 142 + } 143 + 144 + status = ctrl->ops->create_cq(ctrl, cqid, cq_flags, qsize, 145 + prp1, irq_vector); 146 + 147 + complete: 148 + nvmet_req_complete(req, status); 149 + } 150 + 15 151 u32 nvmet_get_log_page_len(struct nvme_command *cmd) 16 152 { 17 153 u32 len = le16_to_cpu(cmd->get_log_page.numdu); ··· 366 230 nvmet_req_complete(req, status); 367 231 } 368 232 369 - static void nvmet_get_cmd_effects_admin(struct nvme_effects_log *log) 233 + static void nvmet_get_cmd_effects_admin(struct nvmet_ctrl *ctrl, 234 + struct nvme_effects_log *log) 370 235 { 236 + /* For a PCI target controller, advertize support for the . */ 237 + if (nvmet_is_pci_ctrl(ctrl)) { 238 + log->acs[nvme_admin_delete_sq] = 239 + log->acs[nvme_admin_create_sq] = 240 + log->acs[nvme_admin_delete_cq] = 241 + log->acs[nvme_admin_create_cq] = 242 + cpu_to_le32(NVME_CMD_EFFECTS_CSUPP); 243 + } 244 + 371 245 log->acs[nvme_admin_get_log_page] = 372 246 log->acs[nvme_admin_identify] = 373 247 log->acs[nvme_admin_abort_cmd] = ··· 414 268 415 269 static void nvmet_execute_get_log_cmd_effects_ns(struct nvmet_req *req) 416 270 { 271 + struct nvmet_ctrl *ctrl = req->sq->ctrl; 417 272 struct nvme_effects_log *log; 418 273 u16 status = NVME_SC_SUCCESS; 419 274 ··· 426 279 427 280 switch (req->cmd->get_log_page.csi) { 428 281 case NVME_CSI_NVM: 429 - nvmet_get_cmd_effects_admin(log); 282 + nvmet_get_cmd_effects_admin(ctrl, log); 430 283 nvmet_get_cmd_effects_nvm(log); 431 284 break; 432 285 case NVME_CSI_ZNS: ··· 434 287 status = NVME_SC_INVALID_IO_CMD_SET; 435 288 goto free; 436 289 } 437 - nvmet_get_cmd_effects_admin(log); 290 + nvmet_get_cmd_effects_admin(ctrl, log); 438 291 nvmet_get_cmd_effects_nvm(log); 439 292 nvmet_get_cmd_effects_zns(log); 440 293 break; ··· 1482 1335 return nvmet_parse_passthru_admin_cmd(req); 1483 1336 1484 1337 switch (cmd->common.opcode) { 1338 + case nvme_admin_delete_sq: 1339 + req->execute = nvmet_execute_delete_sq; 1340 + return 0; 1341 + case nvme_admin_create_sq: 1342 + req->execute = nvmet_execute_create_sq; 1343 + return 0; 1485 1344 case nvme_admin_get_log_page: 1486 1345 req->execute = nvmet_execute_get_log_page; 1346 + return 0; 1347 + case nvme_admin_delete_cq: 1348 + req->execute = nvmet_execute_delete_cq; 1349 + return 0; 1350 + case nvme_admin_create_cq: 1351 + req->execute = nvmet_execute_create_cq; 1487 1352 return 0; 1488 1353 case nvme_admin_identify: 1489 1354 req->execute = nvmet_execute_identify;
+8
drivers/nvme/target/nvmet.h
··· 408 408 void (*discovery_chg)(struct nvmet_port *port); 409 409 u8 (*get_mdts)(const struct nvmet_ctrl *ctrl); 410 410 u16 (*get_max_queue_size)(const struct nvmet_ctrl *ctrl); 411 + 412 + /* Operations mandatory for PCI target controllers */ 413 + u16 (*create_sq)(struct nvmet_ctrl *ctrl, u16 sqid, u16 flags, 414 + u16 qsize, u64 prp1); 415 + u16 (*delete_sq)(struct nvmet_ctrl *ctrl, u16 sqid); 416 + u16 (*create_cq)(struct nvmet_ctrl *ctrl, u16 cqid, u16 flags, 417 + u16 qsize, u64 prp1, u16 irq_vector); 418 + u16 (*delete_cq)(struct nvmet_ctrl *ctrl, u16 cqid); 411 419 }; 412 420 413 421 #define NVMET_MAX_INLINE_BIOVEC 8