diff options
Diffstat (limited to 'usr.sbin/nvmfd/controller.c')
-rw-r--r-- | usr.sbin/nvmfd/controller.c | 244 |
1 files changed, 0 insertions, 244 deletions
diff --git a/usr.sbin/nvmfd/controller.c b/usr.sbin/nvmfd/controller.c deleted file mode 100644 index e9435bce69da..000000000000 --- a/usr.sbin/nvmfd/controller.c +++ /dev/null @@ -1,244 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2023-2024 Chelsio Communications, Inc. - * Written by: John Baldwin <jhb@FreeBSD.org> - */ - -#include <err.h> -#include <errno.h> -#include <libnvmf.h> -#include <stdlib.h> - -#include "internal.h" - -struct controller { - struct nvmf_qpair *qp; - - uint64_t cap; - uint32_t vs; - uint32_t cc; - uint32_t csts; - - bool shutdown; - - struct nvme_controller_data cdata; -}; - -static bool -update_cc(struct controller *c, uint32_t new_cc) -{ - uint32_t changes; - - if (c->shutdown) - return (false); - if (!nvmf_validate_cc(c->qp, c->cap, c->cc, new_cc)) - return (false); - - changes = c->cc ^ new_cc; - c->cc = new_cc; - - /* Handle shutdown requests. */ - if (NVMEV(NVME_CC_REG_SHN, changes) != 0 && - NVMEV(NVME_CC_REG_SHN, new_cc) != 0) { - c->csts &= ~NVMEM(NVME_CSTS_REG_SHST); - c->csts |= NVMEF(NVME_CSTS_REG_SHST, NVME_SHST_COMPLETE); - c->shutdown = true; - } - - if (NVMEV(NVME_CC_REG_EN, changes) != 0) { - if (NVMEV(NVME_CC_REG_EN, new_cc) == 0) { - /* Controller reset. */ - c->csts = 0; - c->shutdown = true; - } else - c->csts |= NVMEF(NVME_CSTS_REG_RDY, 1); - } - return (true); -} - -static void -handle_property_get(const struct controller *c, const struct nvmf_capsule *nc, - const struct nvmf_fabric_prop_get_cmd *pget) -{ - struct nvmf_fabric_prop_get_rsp rsp; - - nvmf_init_cqe(&rsp, nc, 0); - - switch (le32toh(pget->ofst)) { - case NVMF_PROP_CAP: - if (pget->attrib.size != NVMF_PROP_SIZE_8) - goto error; - rsp.value.u64 = htole64(c->cap); - break; - case NVMF_PROP_VS: - if (pget->attrib.size != NVMF_PROP_SIZE_4) - goto error; - rsp.value.u32.low = htole32(c->vs); - break; - case NVMF_PROP_CC: - if (pget->attrib.size != NVMF_PROP_SIZE_4) - goto error; - rsp.value.u32.low = htole32(c->cc); - break; - case NVMF_PROP_CSTS: - if (pget->attrib.size != NVMF_PROP_SIZE_4) - goto error; - rsp.value.u32.low = htole32(c->csts); - break; - default: - goto error; - } - - nvmf_send_response(nc, &rsp); - return; -error: - nvmf_send_generic_error(nc, NVME_SC_INVALID_FIELD); -} - -static void -handle_property_set(struct controller *c, const struct nvmf_capsule *nc, - const struct nvmf_fabric_prop_set_cmd *pset) -{ - switch (le32toh(pset->ofst)) { - case NVMF_PROP_CC: - if (pset->attrib.size != NVMF_PROP_SIZE_4) - goto error; - if (!update_cc(c, le32toh(pset->value.u32.low))) - goto error; - break; - default: - goto error; - } - - nvmf_send_success(nc); - return; -error: - nvmf_send_generic_error(nc, NVME_SC_INVALID_FIELD); -} - -static void -handle_fabrics_command(struct controller *c, - const struct nvmf_capsule *nc, const struct nvmf_fabric_cmd *fc) -{ - switch (fc->fctype) { - case NVMF_FABRIC_COMMAND_PROPERTY_GET: - handle_property_get(c, nc, - (const struct nvmf_fabric_prop_get_cmd *)fc); - break; - case NVMF_FABRIC_COMMAND_PROPERTY_SET: - handle_property_set(c, nc, - (const struct nvmf_fabric_prop_set_cmd *)fc); - break; - case NVMF_FABRIC_COMMAND_CONNECT: - warnx("CONNECT command on connected queue"); - nvmf_send_generic_error(nc, NVME_SC_COMMAND_SEQUENCE_ERROR); - break; - case NVMF_FABRIC_COMMAND_DISCONNECT: - warnx("DISCONNECT command on admin queue"); - nvmf_send_error(nc, NVME_SCT_COMMAND_SPECIFIC, - NVMF_FABRIC_SC_INVALID_QUEUE_TYPE); - break; - default: - warnx("Unsupported fabrics command %#x", fc->fctype); - nvmf_send_generic_error(nc, NVME_SC_INVALID_OPCODE); - break; - } -} - -static void -handle_identify_command(const struct controller *c, - const struct nvmf_capsule *nc, const struct nvme_command *cmd) -{ - uint8_t cns; - - cns = le32toh(cmd->cdw10) & 0xFF; - switch (cns) { - case 1: - break; - default: - warnx("Unsupported CNS %#x for IDENTIFY", cns); - goto error; - } - - nvmf_send_controller_data(nc, &c->cdata, sizeof(c->cdata)); - return; -error: - nvmf_send_generic_error(nc, NVME_SC_INVALID_FIELD); -} - -void -controller_handle_admin_commands(struct controller *c, handle_command *cb, - void *cb_arg) -{ - struct nvmf_qpair *qp = c->qp; - const struct nvme_command *cmd; - struct nvmf_capsule *nc; - int error; - - for (;;) { - error = nvmf_controller_receive_capsule(qp, &nc); - if (error != 0) { - if (error != ECONNRESET) - warnc(error, "Failed to read command capsule"); - break; - } - - cmd = nvmf_capsule_sqe(nc); - - /* - * Only permit Fabrics commands while a controller is - * disabled. - */ - if (NVMEV(NVME_CC_REG_EN, c->cc) == 0 && - cmd->opc != NVME_OPC_FABRICS_COMMANDS) { - warnx("Unsupported admin opcode %#x while disabled\n", - cmd->opc); - nvmf_send_generic_error(nc, - NVME_SC_COMMAND_SEQUENCE_ERROR); - nvmf_free_capsule(nc); - continue; - } - - if (cb(nc, cmd, cb_arg)) { - nvmf_free_capsule(nc); - continue; - } - - switch (cmd->opc) { - case NVME_OPC_FABRICS_COMMANDS: - handle_fabrics_command(c, nc, - (const struct nvmf_fabric_cmd *)cmd); - break; - case NVME_OPC_IDENTIFY: - handle_identify_command(c, nc, cmd); - break; - default: - warnx("Unsupported admin opcode %#x", cmd->opc); - nvmf_send_generic_error(nc, NVME_SC_INVALID_OPCODE); - break; - } - nvmf_free_capsule(nc); - } -} - -struct controller * -init_controller(struct nvmf_qpair *qp, - const struct nvme_controller_data *cdata) -{ - struct controller *c; - - c = calloc(1, sizeof(*c)); - c->qp = qp; - c->cap = nvmf_controller_cap(c->qp); - c->vs = cdata->ver; - c->cdata = *cdata; - - return (c); -} - -void -free_controller(struct controller *c) -{ - free(c); -} |