diff --git a/plugins/microchip/switchtec-nvme-device.c b/plugins/microchip/switchtec-nvme-device.c index efb2f9b..a1d9488 100644 --- a/plugins/microchip/switchtec-nvme-device.c +++ b/plugins/microchip/switchtec-nvme-device.c @@ -54,13 +54,12 @@ struct switchtec_device_manage_nvme_rsp struct switchtec_admin_passthru_nvme_req { uint32_t nvme_sqe[16]; - uint8_t nvme_data[SWITCHTEC_NVME_ADMIN_PASSTHRU_MAX_DATA_LEN - - (16 * 4)]; + uint8_t nvme_data[]; }; struct switchtec_admin_passthru_nvme_rsp { uint32_t nvme_cqe[4]; - uint8_t nvme_data[4096]; + uint8_t nvme_data[]; }; int pax_nvme_submit_admin_passthru_1k_rsp(int fd, @@ -114,56 +113,57 @@ int pax_nvme_submit_admin_passthru_1k_rsp(int fd, return status; } -int pax_nvme_submit_admin_passthru_4k_rsp(int fd, - struct nvme_passthru_cmd *cmd) +int pax_nvme_submit_admin_passthru_var_rsp(int fd, + struct nvme_passthru_cmd *cmd) { int ret; struct pax_nvme_device *pax; - struct switchtec_admin_passthru_nvme_req req; - struct switchtec_admin_passthru_nvme_rsp rsp; - size_t data_len = 0; + struct switchtec_admin_passthru_nvme_req *req; + struct switchtec_admin_passthru_nvme_rsp *rsp; + size_t req_len = 16 * 4; size_t rsp_len; int status; - memset(&req, 0, sizeof(req)); - memset(&rsp, 0, sizeof(rsp)); pax = to_pax_nvme_device(global_device); - memcpy(&req.nvme_sqe, cmd, 16 * 4); + if (cmd->opcode & 0x1) + req_len += cmd->data_len; + req = (struct switchtec_admin_passthru_nvme_req *) malloc(req_len); + memset(req, 0, req_len); + memcpy(req->nvme_sqe, cmd, 16 * 4); /* sqe[9] should be 0 per spec */ - req.nvme_sqe[9] = 0; - - if (cmd->opcode & 0x1) { - if (cmd->data_len > sizeof(req.nvme_data)) - data_len = sizeof(req.nvme_data); - else - data_len = cmd->data_len; - - memcpy(req.nvme_data, (void *)cmd->addr, data_len); - } + req->nvme_sqe[9] = 0; - data_len = data_len + 16 * 4; + if (cmd->opcode & 0x1) + memcpy(req->nvme_data, (void *)cmd->addr, cmd->data_len); - rsp_len = (sizeof(rsp.nvme_cqe) + cmd->data_len); + rsp_len = (sizeof(rsp->nvme_cqe) + cmd->data_len); + rsp = (struct switchtec_admin_passthru_nvme_rsp*) malloc(rsp_len); + memset(rsp, 0, rsp_len); ret = switchtec_nvme_admin_passthru(pax->dev, pax->pdfid, - data_len, &req, - &rsp_len, &rsp); - if (ret) + req_len, req, + &rsp_len, rsp); + if (ret) { + free(req); + free(rsp); return ret; + } - status = (rsp.nvme_cqe[3] & 0xfffe0000) >> 17; + status = (rsp->nvme_cqe[3] & 0xfffe0000) >> 17; if (!status) { - cmd->result = rsp.nvme_cqe[0]; + cmd->result = rsp->nvme_cqe[0]; if (cmd->addr) { memcpy((uint64_t *)cmd->addr, - rsp.nvme_data, + rsp->nvme_data, rsp_len - 4 * 4); } } + free(req); + free(rsp); return status; } @@ -171,7 +171,7 @@ int pax_nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd) { int ret; - ret = pax_nvme_submit_admin_passthru_4k_rsp(fd, cmd); + ret = pax_nvme_submit_admin_passthru_var_rsp(fd, cmd); if (ret && errno == INVALID_MRPC_CMD) ret = pax_nvme_submit_admin_passthru_1k_rsp(fd, cmd);