Make NVMe compatible with the original API

The original NVMe API used bit-fields to represent fields in data
structures defined by the specification (e.g. the op-code in the command
data structure). The implementation targeted x86_64 processors and
defined the bit fields for little endian dwords (i.e. 32 bits).

This approach does not work as-is for big endian architectures and was
changed to use a combination of bit shifts and masks to support PowerPC.
Unfortunately, this changed the NVMe API and forces #ifdef's based on
the OS revision level in user space code.

This change reverts to something that looks like the original API, but
it uses bytes instead of bit-fields inside the packed command structure.
As a bonus, this works as-is for both big and little endian CPU
architectures.

Bump __FreeBSD_version to 1200081 due to API change

Reviewed by: imp, kbowling, smh, mav
Approved by: imp (mentor)
Differential Revision: https://reviews.freebsd.org/D16404
This commit is contained in:
Chuck Tuffli 2018-08-22 04:29:24 +00:00
parent d3878608d7
commit 9544e6dcf1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=338182
17 changed files with 59 additions and 79 deletions

View File

@ -125,7 +125,7 @@ update_firmware(int fd, uint8_t *payload, int32_t payload_size)
memcpy(chunk, payload + off, size); memcpy(chunk, payload + off, size);
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD); pt.cmd.opc = NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
pt.cmd.cdw10 = htole32((size / sizeof(uint32_t)) - 1); pt.cmd.cdw10 = htole32((size / sizeof(uint32_t)) - 1);
pt.cmd.cdw11 = htole32(off / sizeof(uint32_t)); pt.cmd.cdw11 = htole32(off / sizeof(uint32_t));
pt.buf = chunk; pt.buf = chunk;
@ -150,7 +150,7 @@ activate_firmware(int fd, int slot, int activate_action)
uint16_t sct, sc; uint16_t sct, sc;
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_FIRMWARE_ACTIVATE); pt.cmd.opc = NVME_OPC_FIRMWARE_ACTIVATE;
pt.cmd.cdw10 = htole32((activate_action << 3) | slot); pt.cmd.cdw10 = htole32((activate_action << 3) | slot);
pt.is_read = 0; pt.is_read = 0;

View File

@ -172,7 +172,7 @@ format(int argc, char *argv[])
} }
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_FORMAT_NVM); pt.cmd.opc = NVME_OPC_FORMAT_NVM;
pt.cmd.nsid = htole32(nsid); pt.cmd.nsid = htole32(nsid);
pt.cmd.cdw10 = htole32((ses << 9) + (pil << 8) + (pi << 5) + pt.cmd.cdw10 = htole32((ses << 9) + (pil << 8) + (pi << 5) +
(mset << 4) + lbaf); (mset << 4) + lbaf);

View File

@ -107,7 +107,7 @@ read_logpage(int fd, uint8_t log_page, uint32_t nsid, void *payload,
int i, err_pages; int i, err_pages;
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_GET_LOG_PAGE); pt.cmd.opc = NVME_OPC_GET_LOG_PAGE;
pt.cmd.nsid = htole32(nsid); pt.cmd.nsid = htole32(nsid);
pt.cmd.cdw10 = ((payload_size/sizeof(uint32_t)) - 1) << 16; pt.cmd.cdw10 = ((payload_size/sizeof(uint32_t)) - 1) << 16;
pt.cmd.cdw10 |= log_page; pt.cmd.cdw10 |= log_page;

View File

@ -216,7 +216,7 @@ nscreate(int argc, char *argv[])
nvme_namespace_data_swapbytes(&nsdata); nvme_namespace_data_swapbytes(&nsdata);
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_NAMESPACE_MANAGEMENT); pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT;
pt.cmd.cdw10 = 0; /* create */ pt.cmd.cdw10 = 0; /* create */
pt.buf = &nsdata; pt.buf = &nsdata;
@ -267,7 +267,7 @@ nsdelete(int argc, char *argv[])
errx(1, "controller does not support namespace management"); errx(1, "controller does not support namespace management");
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_NAMESPACE_MANAGEMENT); pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT;
pt.cmd.cdw10 = 1; /* delete */ pt.cmd.cdw10 = 1; /* delete */
pt.buf = buf; pt.buf = buf;
pt.len = sizeof(buf); pt.len = sizeof(buf);
@ -343,7 +343,7 @@ nsattach(int argc, char *argv[])
if (ctrlrid == -1) { if (ctrlrid == -1) {
/* Get full list of controllers to attach to. */ /* Get full list of controllers to attach to. */
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY); pt.cmd.opc = NVME_OPC_IDENTIFY;
pt.cmd.cdw10 = htole32(0x13); pt.cmd.cdw10 = htole32(0x13);
pt.buf = clist; pt.buf = clist;
pt.len = sizeof(clist); pt.len = sizeof(clist);
@ -362,7 +362,7 @@ nsattach(int argc, char *argv[])
} }
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_NAMESPACE_ATTACHMENT); pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT;
pt.cmd.cdw10 = 0; /* attach */ pt.cmd.cdw10 = 0; /* attach */
pt.cmd.nsid = (uint32_t)nsid; pt.cmd.nsid = (uint32_t)nsid;
pt.buf = &clist; pt.buf = &clist;
@ -422,7 +422,7 @@ nsdetach(int argc, char *argv[])
if (ctrlrid == -1) { if (ctrlrid == -1) {
/* Get list of controllers this namespace attached to. */ /* Get list of controllers this namespace attached to. */
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY); pt.cmd.opc = NVME_OPC_IDENTIFY;
pt.cmd.nsid = htole32(nsid); pt.cmd.nsid = htole32(nsid);
pt.cmd.cdw10 = htole32(0x12); pt.cmd.cdw10 = htole32(0x12);
pt.buf = clist; pt.buf = clist;
@ -448,7 +448,7 @@ nsdetach(int argc, char *argv[])
} }
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_NAMESPACE_ATTACHMENT); pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT;
pt.cmd.cdw10 = 1; /* detach */ pt.cmd.cdw10 = 1; /* detach */
pt.cmd.nsid = (uint32_t)nsid; pt.cmd.nsid = (uint32_t)nsid;
pt.buf = &clist; pt.buf = &clist;

View File

@ -148,7 +148,7 @@ read_controller_data(int fd, struct nvme_controller_data *cdata)
struct nvme_pt_command pt; struct nvme_pt_command pt;
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY); pt.cmd.opc = NVME_OPC_IDENTIFY;
pt.cmd.cdw10 = htole32(1); pt.cmd.cdw10 = htole32(1);
pt.buf = cdata; pt.buf = cdata;
pt.len = sizeof(*cdata); pt.len = sizeof(*cdata);
@ -170,7 +170,7 @@ read_namespace_data(int fd, uint32_t nsid, struct nvme_namespace_data *nsdata)
struct nvme_pt_command pt; struct nvme_pt_command pt;
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY); pt.cmd.opc = NVME_OPC_IDENTIFY;
pt.cmd.nsid = htole32(nsid); pt.cmd.nsid = htole32(nsid);
pt.buf = nsdata; pt.buf = nsdata;
pt.len = sizeof(*nsdata); pt.len = sizeof(*nsdata);

View File

@ -104,7 +104,7 @@ power_set(int fd, int power_val, int workload, int perm)
p = perm ? (1u << 31) : 0; p = perm ? (1u << 31) : 0;
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_SET_FEATURES); pt.cmd.opc = NVME_OPC_SET_FEATURES;
pt.cmd.cdw10 = htole32(NVME_FEAT_POWER_MANAGEMENT | p); pt.cmd.cdw10 = htole32(NVME_FEAT_POWER_MANAGEMENT | p);
pt.cmd.cdw11 = htole32(power_val | (workload << 5)); pt.cmd.cdw11 = htole32(power_val | (workload << 5));
@ -121,7 +121,7 @@ power_show(int fd)
struct nvme_pt_command pt; struct nvme_pt_command pt;
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_GET_FEATURES); pt.cmd.opc = NVME_OPC_GET_FEATURES;
pt.cmd.cdw10 = htole32(NVME_FEAT_POWER_MANAGEMENT); pt.cmd.cdw10 = htole32(NVME_FEAT_POWER_MANAGEMENT);
if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)

View File

@ -81,7 +81,7 @@ wdc_get_data(int fd, uint32_t opcode, uint32_t len, uint32_t off, uint32_t cmd,
struct nvme_pt_command pt; struct nvme_pt_command pt;
memset(&pt, 0, sizeof(pt)); memset(&pt, 0, sizeof(pt));
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(opcode); pt.cmd.opc = opcode;
pt.cmd.cdw10 = htole32(len / sizeof(uint32_t)); /* - 1 like all the others ??? */ pt.cmd.cdw10 = htole32(len / sizeof(uint32_t)); /* - 1 like all the others ??? */
pt.cmd.cdw11 = htole32(off / sizeof(uint32_t)); pt.cmd.cdw11 = htole32(off / sizeof(uint32_t));
pt.cmd.cdw12 = htole32(cmd); pt.cmd.cdw12 = htole32(cmd);

View File

@ -69,7 +69,7 @@ nvme_ns_cmd(struct ccb_nvmeio *nvmeio, uint8_t cmd, uint32_t nsid,
uint32_t cdw14, uint32_t cdw15) uint32_t cdw14, uint32_t cdw15)
{ {
bzero(&nvmeio->cmd, sizeof(struct nvme_command)); bzero(&nvmeio->cmd, sizeof(struct nvme_command));
nvmeio->cmd.opc_fuse = NVME_CMD_SET_OPC(cmd); nvmeio->cmd.opc = cmd;
nvmeio->cmd.nsid = htole32(nsid); nvmeio->cmd.nsid = htole32(nsid);
nvmeio->cmd.cdw10 = htole32(cdw10); nvmeio->cmd.cdw10 = htole32(cdw10);
nvmeio->cmd.cdw11 = htole32(cdw11); nvmeio->cmd.cdw11 = htole32(cdw11);
@ -117,29 +117,24 @@ nvme_opc2str[] = {
const char * const char *
nvme_op_string(const struct nvme_command *cmd) nvme_op_string(const struct nvme_command *cmd)
{ {
uint8_t opc;
opc = (cmd->opc_fuse >> NVME_CMD_OPC_SHIFT) & NVME_CMD_OPC_MASK; if (cmd->opc >= nitems(nvme_opc2str))
if (opc >= nitems(nvme_opc2str))
return "UNKNOWN"; return "UNKNOWN";
return nvme_opc2str[opc]; return nvme_opc2str[cmd->opc];
} }
const char * const char *
nvme_cmd_string(const struct nvme_command *cmd, char *cmd_string, size_t len) nvme_cmd_string(const struct nvme_command *cmd, char *cmd_string, size_t len)
{ {
uint8_t opc, fuse;
opc = (cmd->opc_fuse >> NVME_CMD_OPC_SHIFT) & NVME_CMD_OPC_MASK;
fuse = (cmd->opc_fuse >> NVME_CMD_FUSE_SHIFT) & NVME_CMD_FUSE_MASK;
/* /*
* cid, rsvd areas and mptr not printed, since they are used * cid, rsvd areas and mptr not printed, since they are used
* only internally by the SIM. * only internally by the SIM.
*/ */
snprintf(cmd_string, len, snprintf(cmd_string, len,
"opc=%x fuse=%x nsid=%x prp1=%llx prp2=%llx cdw=%x %x %x %x %x %x", "opc=%x fuse=%x nsid=%x prp1=%llx prp2=%llx cdw=%x %x %x %x %x %x",
opc, fuse, cmd->nsid, cmd->opc, cmd->fuse, cmd->nsid,
(unsigned long long)cmd->prp1, (unsigned long long)cmd->prp2, (unsigned long long)cmd->prp1, (unsigned long long)cmd->prp2,
cmd->cdw10, cmd->cdw11, cmd->cdw12, cmd->cdw10, cmd->cdw11, cmd->cdw12,
cmd->cdw13, cmd->cdw14, cmd->cdw15); cmd->cdw13, cmd->cdw14, cmd->cdw15);

View File

@ -1840,7 +1840,7 @@ mprsas_build_nvme_unmap(struct mpr_softc *sc, struct mpr_command *cm,
/* Build NVMe DSM command */ /* Build NVMe DSM command */
c = (struct nvme_command *) req->NVMe_Command; c = (struct nvme_command *) req->NVMe_Command;
c->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_DATASET_MANAGEMENT); c->opc = NVME_OPC_DATASET_MANAGEMENT;
c->nsid = htole32(csio->ccb_h.target_lun + 1); c->nsid = htole32(csio->ccb_h.target_lun + 1);
c->cdw10 = htole32(ndesc - 1); c->cdw10 = htole32(ndesc - 1);
c->cdw11 = htole32(NVME_DSM_ATTR_DEALLOCATE); c->cdw11 = htole32(NVME_DSM_ATTR_DEALLOCATE);

View File

@ -222,14 +222,10 @@ nvme_modevent(module_t mod, int type, void *arg)
void void
nvme_dump_command(struct nvme_command *cmd) nvme_dump_command(struct nvme_command *cmd)
{ {
uint8_t opc, fuse;
opc = (cmd->opc_fuse >> NVME_CMD_OPC_SHIFT) & NVME_CMD_OPC_MASK;
fuse = (cmd->opc_fuse >> NVME_CMD_FUSE_SHIFT) & NVME_CMD_FUSE_MASK;
printf( printf(
"opc:%x f:%x cid:%x nsid:%x r2:%x r3:%x mptr:%jx prp1:%jx prp2:%jx cdw:%x %x %x %x %x %x\n", "opc:%x f:%x cid:%x nsid:%x r2:%x r3:%x mptr:%jx prp1:%jx prp2:%jx cdw:%x %x %x %x %x %x\n",
opc, fuse, cmd->cid, le32toh(cmd->nsid), cmd->opc, cmd->fuse, cmd->cid, le32toh(cmd->nsid),
cmd->rsvd2, cmd->rsvd3, cmd->rsvd2, cmd->rsvd3,
(uintmax_t)le64toh(cmd->mptr), (uintmax_t)le64toh(cmd->prp1), (uintmax_t)le64toh(cmd->prp2), (uintmax_t)le64toh(cmd->mptr), (uintmax_t)le64toh(cmd->prp1), (uintmax_t)le64toh(cmd->prp2),
le32toh(cmd->cdw10), le32toh(cmd->cdw11), le32toh(cmd->cdw12), le32toh(cmd->cdw10), le32toh(cmd->cdw11), le32toh(cmd->cdw12),

View File

@ -110,13 +110,9 @@
/* Command field definitions */ /* Command field definitions */
#define NVME_CMD_OPC_SHIFT (0)
#define NVME_CMD_OPC_MASK (0xFF)
#define NVME_CMD_FUSE_SHIFT (8) #define NVME_CMD_FUSE_SHIFT (8)
#define NVME_CMD_FUSE_MASK (0x3) #define NVME_CMD_FUSE_MASK (0x3)
#define NVME_CMD_SET_OPC(opc) (htole16(((uint16_t)(opc) & NVME_CMD_OPC_MASK) << NVME_CMD_OPC_SHIFT))
#define NVME_STATUS_P_SHIFT (0) #define NVME_STATUS_P_SHIFT (0)
#define NVME_STATUS_P_MASK (0x1) #define NVME_STATUS_P_MASK (0x1)
#define NVME_STATUS_SC_SHIFT (1) #define NVME_STATUS_SC_SHIFT (1)
@ -428,7 +424,8 @@ _Static_assert(sizeof(struct nvme_registers) == 0x1008, "bad size for nvme_regis
struct nvme_command struct nvme_command
{ {
/* dword 0 */ /* dword 0 */
uint16_t opc_fuse; /* opcode, fused operation */ uint8_t opc; /* opcode */
uint8_t fuse; /* fused operation */
uint16_t cid; /* command identifier */ uint16_t cid; /* command identifier */
/* dword 1 */ /* dword 1 */
@ -1288,7 +1285,7 @@ static inline
void nvme_ns_flush_cmd(struct nvme_command *cmd, uint32_t nsid) void nvme_ns_flush_cmd(struct nvme_command *cmd, uint32_t nsid)
{ {
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_FLUSH); cmd->opc = NVME_OPC_FLUSH;
cmd->nsid = htole32(nsid); cmd->nsid = htole32(nsid);
} }
@ -1296,7 +1293,7 @@ static inline
void nvme_ns_rw_cmd(struct nvme_command *cmd, uint32_t rwcmd, uint32_t nsid, void nvme_ns_rw_cmd(struct nvme_command *cmd, uint32_t rwcmd, uint32_t nsid,
uint64_t lba, uint32_t count) uint64_t lba, uint32_t count)
{ {
cmd->opc_fuse = NVME_CMD_SET_OPC(rwcmd); cmd->opc = rwcmd;
cmd->nsid = htole32(nsid); cmd->nsid = htole32(nsid);
cmd->cdw10 = htole32(lba & 0xffffffffu); cmd->cdw10 = htole32(lba & 0xffffffffu);
cmd->cdw11 = htole32(lba >> 32); cmd->cdw11 = htole32(lba >> 32);
@ -1321,7 +1318,7 @@ static inline
void nvme_ns_trim_cmd(struct nvme_command *cmd, uint32_t nsid, void nvme_ns_trim_cmd(struct nvme_command *cmd, uint32_t nsid,
uint32_t num_ranges) uint32_t num_ranges)
{ {
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_DATASET_MANAGEMENT); cmd->opc = NVME_OPC_DATASET_MANAGEMENT;
cmd->nsid = htole32(nsid); cmd->nsid = htole32(nsid);
cmd->cdw10 = htole32(num_ranges - 1); cmd->cdw10 = htole32(num_ranges - 1);
cmd->cdw11 = htole32(NVME_DSM_ATTR_DEALLOCATE); cmd->cdw11 = htole32(NVME_DSM_ATTR_DEALLOCATE);

View File

@ -769,7 +769,7 @@ nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr,
* nature never be timed out. * nature never be timed out.
*/ */
req->timeout = FALSE; req->timeout = FALSE;
req->cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_ASYNC_EVENT_REQUEST); req->cmd.opc = NVME_OPC_ASYNC_EVENT_REQUEST;
nvme_ctrlr_submit_admin_request(ctrlr, req); nvme_ctrlr_submit_admin_request(ctrlr, req);
} }
@ -1073,7 +1073,8 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr,
req = nvme_allocate_request_null(nvme_pt_done, pt); req = nvme_allocate_request_null(nvme_pt_done, pt);
/* Assume userspace already converted to little-endian */ /* Assume userspace already converted to little-endian */
req->cmd.opc_fuse = pt->cmd.opc_fuse; req->cmd.opc = pt->cmd.opc;
req->cmd.fuse = pt->cmd.fuse;
req->cmd.cdw10 = pt->cmd.cdw10; req->cmd.cdw10 = pt->cmd.cdw10;
req->cmd.cdw11 = pt->cmd.cdw11; req->cmd.cdw11 = pt->cmd.cdw11;
req->cmd.cdw12 = pt->cmd.cdw12; req->cmd.cdw12 = pt->cmd.cdw12;

View File

@ -42,7 +42,7 @@ nvme_ctrlr_cmd_identify_controller(struct nvme_controller *ctrlr, void *payload,
sizeof(struct nvme_controller_data), cb_fn, cb_arg); sizeof(struct nvme_controller_data), cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY); cmd->opc = NVME_OPC_IDENTIFY;
/* /*
* TODO: create an identify command data structure, which * TODO: create an identify command data structure, which
@ -64,7 +64,7 @@ nvme_ctrlr_cmd_identify_namespace(struct nvme_controller *ctrlr, uint32_t nsid,
sizeof(struct nvme_namespace_data), cb_fn, cb_arg); sizeof(struct nvme_namespace_data), cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY); cmd->opc = NVME_OPC_IDENTIFY;
/* /*
* TODO: create an identify command data structure * TODO: create an identify command data structure
@ -85,7 +85,7 @@ nvme_ctrlr_cmd_create_io_cq(struct nvme_controller *ctrlr,
req = nvme_allocate_request_null(cb_fn, cb_arg); req = nvme_allocate_request_null(cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_CREATE_IO_CQ); cmd->opc = NVME_OPC_CREATE_IO_CQ;
/* /*
* TODO: create a create io completion queue command data * TODO: create a create io completion queue command data
@ -109,7 +109,7 @@ nvme_ctrlr_cmd_create_io_sq(struct nvme_controller *ctrlr,
req = nvme_allocate_request_null(cb_fn, cb_arg); req = nvme_allocate_request_null(cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_CREATE_IO_SQ); cmd->opc = NVME_OPC_CREATE_IO_SQ;
/* /*
* TODO: create a create io submission queue command data * TODO: create a create io submission queue command data
@ -133,7 +133,7 @@ nvme_ctrlr_cmd_delete_io_cq(struct nvme_controller *ctrlr,
req = nvme_allocate_request_null(cb_fn, cb_arg); req = nvme_allocate_request_null(cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_DELETE_IO_CQ); cmd->opc = NVME_OPC_DELETE_IO_CQ;
/* /*
* TODO: create a delete io completion queue command data * TODO: create a delete io completion queue command data
@ -154,7 +154,7 @@ nvme_ctrlr_cmd_delete_io_sq(struct nvme_controller *ctrlr,
req = nvme_allocate_request_null(cb_fn, cb_arg); req = nvme_allocate_request_null(cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_DELETE_IO_SQ); cmd->opc = NVME_OPC_DELETE_IO_SQ;
/* /*
* TODO: create a delete io submission queue command data * TODO: create a delete io submission queue command data
@ -176,7 +176,7 @@ nvme_ctrlr_cmd_set_feature(struct nvme_controller *ctrlr, uint8_t feature,
req = nvme_allocate_request_null(cb_fn, cb_arg); req = nvme_allocate_request_null(cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_SET_FEATURES); cmd->opc = NVME_OPC_SET_FEATURES;
cmd->cdw10 = htole32(feature); cmd->cdw10 = htole32(feature);
cmd->cdw11 = htole32(cdw11); cmd->cdw11 = htole32(cdw11);
@ -194,7 +194,7 @@ nvme_ctrlr_cmd_get_feature(struct nvme_controller *ctrlr, uint8_t feature,
req = nvme_allocate_request_null(cb_fn, cb_arg); req = nvme_allocate_request_null(cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_GET_FEATURES); cmd->opc = NVME_OPC_GET_FEATURES;
cmd->cdw10 = htole32(feature); cmd->cdw10 = htole32(feature);
cmd->cdw11 = htole32(cdw11); cmd->cdw11 = htole32(cdw11);
@ -260,7 +260,7 @@ nvme_ctrlr_cmd_get_log_page(struct nvme_controller *ctrlr, uint8_t log_page,
req = nvme_allocate_request_vaddr(payload, payload_size, cb_fn, cb_arg); req = nvme_allocate_request_vaddr(payload, payload_size, cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_GET_LOG_PAGE); cmd->opc = NVME_OPC_GET_LOG_PAGE;
cmd->nsid = htole32(nsid); cmd->nsid = htole32(nsid);
cmd->cdw10 = ((payload_size/sizeof(uint32_t)) - 1) << 16; cmd->cdw10 = ((payload_size/sizeof(uint32_t)) - 1) << 16;
cmd->cdw10 |= log_page; cmd->cdw10 |= log_page;
@ -320,7 +320,7 @@ nvme_ctrlr_cmd_abort(struct nvme_controller *ctrlr, uint16_t cid,
req = nvme_allocate_request_null(cb_fn, cb_arg); req = nvme_allocate_request_null(cb_fn, cb_arg);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_ABORT); cmd->opc = NVME_OPC_ABORT;
cmd->cdw10 = htole32((cid << 16) | sqid); cmd->cdw10 = htole32((cid << 16) | sqid);
nvme_ctrlr_submit_admin_request(ctrlr, req); nvme_ctrlr_submit_admin_request(ctrlr, req);

View File

@ -126,7 +126,7 @@ nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload,
return (ENOMEM); return (ENOMEM);
cmd = &req->cmd; cmd = &req->cmd;
cmd->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_DATASET_MANAGEMENT); cmd->opc = NVME_OPC_DATASET_MANAGEMENT;
cmd->nsid = htole32(ns->id); cmd->nsid = htole32(ns->id);
/* TODO: create a delete command data structure */ /* TODO: create a delete command data structure */

View File

@ -125,12 +125,10 @@ static void
nvme_admin_qpair_print_command(struct nvme_qpair *qpair, nvme_admin_qpair_print_command(struct nvme_qpair *qpair,
struct nvme_command *cmd) struct nvme_command *cmd)
{ {
uint16_t opc;
opc = le16toh(cmd->opc_fuse) & NVME_CMD_OPC_MASK;
nvme_printf(qpair->ctrlr, "%s (%02x) sqid:%d cid:%d nsid:%x " nvme_printf(qpair->ctrlr, "%s (%02x) sqid:%d cid:%d nsid:%x "
"cdw10:%08x cdw11:%08x\n", "cdw10:%08x cdw11:%08x\n",
get_admin_opcode_string(opc), opc, qpair->id, cmd->cid, get_admin_opcode_string(cmd->opc), cmd->opc, qpair->id, cmd->cid,
le32toh(cmd->nsid), le32toh(cmd->cdw10), le32toh(cmd->cdw11)); le32toh(cmd->nsid), le32toh(cmd->cdw10), le32toh(cmd->cdw11));
} }
@ -138,10 +136,8 @@ static void
nvme_io_qpair_print_command(struct nvme_qpair *qpair, nvme_io_qpair_print_command(struct nvme_qpair *qpair,
struct nvme_command *cmd) struct nvme_command *cmd)
{ {
uint16_t opc;
opc = le16toh(cmd->opc_fuse) & NVME_CMD_OPC_MASK; switch (cmd->opc) {
switch (opc) {
case NVME_OPC_WRITE: case NVME_OPC_WRITE:
case NVME_OPC_READ: case NVME_OPC_READ:
case NVME_OPC_WRITE_UNCORRECTABLE: case NVME_OPC_WRITE_UNCORRECTABLE:
@ -149,7 +145,7 @@ nvme_io_qpair_print_command(struct nvme_qpair *qpair,
case NVME_OPC_WRITE_ZEROES: case NVME_OPC_WRITE_ZEROES:
nvme_printf(qpair->ctrlr, "%s sqid:%d cid:%d nsid:%d " nvme_printf(qpair->ctrlr, "%s sqid:%d cid:%d nsid:%d "
"lba:%llu len:%d\n", "lba:%llu len:%d\n",
get_io_opcode_string(opc), qpair->id, cmd->cid, le32toh(cmd->nsid), get_io_opcode_string(cmd->opc), qpair->id, cmd->cid, le32toh(cmd->nsid),
((unsigned long long)le32toh(cmd->cdw11) << 32) + le32toh(cmd->cdw10), ((unsigned long long)le32toh(cmd->cdw11) << 32) + le32toh(cmd->cdw10),
(le32toh(cmd->cdw12) & 0xFFFF) + 1); (le32toh(cmd->cdw12) & 0xFFFF) + 1);
break; break;
@ -160,11 +156,11 @@ nvme_io_qpair_print_command(struct nvme_qpair *qpair,
case NVME_OPC_RESERVATION_ACQUIRE: case NVME_OPC_RESERVATION_ACQUIRE:
case NVME_OPC_RESERVATION_RELEASE: case NVME_OPC_RESERVATION_RELEASE:
nvme_printf(qpair->ctrlr, "%s sqid:%d cid:%d nsid:%d\n", nvme_printf(qpair->ctrlr, "%s sqid:%d cid:%d nsid:%d\n",
get_io_opcode_string(opc), qpair->id, cmd->cid, le32toh(cmd->nsid)); get_io_opcode_string(cmd->opc), qpair->id, cmd->cid, le32toh(cmd->nsid));
break; break;
default: default:
nvme_printf(qpair->ctrlr, "%s (%02x) sqid:%d cid:%d nsid:%d\n", nvme_printf(qpair->ctrlr, "%s (%02x) sqid:%d cid:%d nsid:%d\n",
get_io_opcode_string(opc), opc, qpair->id, get_io_opcode_string(cmd->opc), cmd->opc, qpair->id,
cmd->cid, le32toh(cmd->nsid)); cmd->cid, le32toh(cmd->nsid));
break; break;
} }
@ -721,7 +717,7 @@ nvme_admin_qpair_abort_aers(struct nvme_qpair *qpair)
tr = TAILQ_FIRST(&qpair->outstanding_tr); tr = TAILQ_FIRST(&qpair->outstanding_tr);
while (tr != NULL) { while (tr != NULL) {
if ((le16toh(tr->req->cmd.opc_fuse) & NVME_CMD_OPC_MASK) == NVME_OPC_ASYNC_EVENT_REQUEST) { if (tr->req->cmd.opc == NVME_OPC_ASYNC_EVENT_REQUEST) {
nvme_qpair_manual_complete_tracker(qpair, tr, nvme_qpair_manual_complete_tracker(qpair, tr,
NVME_SCT_GENERIC, NVME_SC_ABORTED_SQ_DELETION, 0, NVME_SCT_GENERIC, NVME_SC_ABORTED_SQ_DELETION, 0,
FALSE); FALSE);

View File

@ -60,7 +60,7 @@
* in the range 5 to 9. * in the range 5 to 9.
*/ */
#undef __FreeBSD_version #undef __FreeBSD_version
#define __FreeBSD_version 1200080 /* Master, propagated to newvers */ #define __FreeBSD_version 1200081 /* Master, propagated to newvers */
/* /*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

View File

@ -117,9 +117,6 @@ enum nvme_cmd_cdw11 {
NVME_CMD_CDW11_IV = 0xFFFF0000, NVME_CMD_CDW11_IV = 0xFFFF0000,
}; };
#define NVME_CMD_GET_OPC(opc) \
((opc) >> NVME_CMD_OPC_SHIFT & NVME_CMD_OPC_MASK)
#define NVME_CQ_INTEN 0x01 #define NVME_CQ_INTEN 0x01
#define NVME_CQ_INTCOAL 0x02 #define NVME_CQ_INTCOAL 0x02
@ -892,7 +889,7 @@ pci_nvme_handle_admin_cmd(struct pci_nvme_softc* sc, uint64_t value)
cmd = &(sq->qbase)[sqhead]; cmd = &(sq->qbase)[sqhead];
compl.status = 0; compl.status = 0;
switch (NVME_CMD_GET_OPC(cmd->opc_fuse)) { switch (cmd->opc) {
case NVME_OPC_DELETE_IO_SQ: case NVME_OPC_DELETE_IO_SQ:
DPRINTF(("%s command DELETE_IO_SQ\r\n", __func__)); DPRINTF(("%s command DELETE_IO_SQ\r\n", __func__));
do_intr |= nvme_opc_delete_io_sq(sc, cmd, &compl); do_intr |= nvme_opc_delete_io_sq(sc, cmd, &compl);
@ -937,12 +934,11 @@ pci_nvme_handle_admin_cmd(struct pci_nvme_softc* sc, uint64_t value)
break; break;
default: default:
WPRINTF(("0x%x command is not implemented\r\n", WPRINTF(("0x%x command is not implemented\r\n",
NVME_CMD_GET_OPC(cmd->opc_fuse))); cmd->opc));
} }
/* for now skip async event generation */ /* for now skip async event generation */
if (NVME_CMD_GET_OPC(cmd->opc_fuse) != if (cmd->opc != NVME_OPC_ASYNC_EVENT_REQUEST) {
NVME_OPC_ASYNC_EVENT_REQUEST) {
struct nvme_completion *cp; struct nvme_completion *cp;
int phase; int phase;
@ -1211,13 +1207,13 @@ pci_nvme_handle_io_cmd(struct pci_nvme_softc* sc, uint16_t idx)
lba = ((uint64_t)cmd->cdw11 << 32) | cmd->cdw10; lba = ((uint64_t)cmd->cdw11 << 32) | cmd->cdw10;
if (NVME_CMD_GET_OPC(cmd->opc_fuse) == NVME_OPC_FLUSH) { if (cmd->opc == NVME_OPC_FLUSH) {
pci_nvme_status_genc(&status, NVME_SC_SUCCESS); pci_nvme_status_genc(&status, NVME_SC_SUCCESS);
pci_nvme_set_completion(sc, sq, idx, cmd->cid, 0, pci_nvme_set_completion(sc, sq, idx, cmd->cid, 0,
status, 1); status, 1);
continue; continue;
} else if (NVME_CMD_GET_OPC(cmd->opc_fuse) == 0x08) { } else if (cmd->opc == 0x08) {
/* TODO: write zeroes */ /* TODO: write zeroes */
WPRINTF(("%s write zeroes lba 0x%lx blocks %u\r\n", WPRINTF(("%s write zeroes lba 0x%lx blocks %u\r\n",
__func__, lba, cmd->cdw12 & 0xFFFF)); __func__, lba, cmd->cdw12 & 0xFFFF));
@ -1246,7 +1242,7 @@ pci_nvme_handle_io_cmd(struct pci_nvme_softc* sc, uint16_t idx)
DPRINTF(("[h%u:t%u:n%u] %s starting LBA 0x%lx blocks %lu " DPRINTF(("[h%u:t%u:n%u] %s starting LBA 0x%lx blocks %lu "
"(%lu-bytes)\r\n", "(%lu-bytes)\r\n",
sqhead==0 ? sq->size-1 : sqhead-1, sq->tail, sq->size, sqhead==0 ? sq->size-1 : sqhead-1, sq->tail, sq->size,
NVME_CMD_GET_OPC(cmd->opc_fuse) == NVME_OPC_WRITE ? cmd->opc == NVME_OPC_WRITE ?
"WRITE" : "READ", "WRITE" : "READ",
lba, nblocks, bytes)); lba, nblocks, bytes));
@ -1266,13 +1262,13 @@ pci_nvme_handle_io_cmd(struct pci_nvme_softc* sc, uint16_t idx)
if (req != NULL) { if (req != NULL) {
req->io_req.br_offset = ((uint64_t)cmd->cdw11 << 32) | req->io_req.br_offset = ((uint64_t)cmd->cdw11 << 32) |
cmd->cdw10; cmd->cdw10;
req->opc = NVME_CMD_GET_OPC(cmd->opc_fuse); req->opc = cmd->opc;
req->cid = cmd->cid; req->cid = cmd->cid;
req->nsid = cmd->nsid; req->nsid = cmd->nsid;
} }
err = pci_nvme_append_iov_req(sc, req, cmd->prp1, cpsz, err = pci_nvme_append_iov_req(sc, req, cmd->prp1, cpsz,
NVME_CMD_GET_OPC(cmd->opc_fuse) == NVME_OPC_WRITE, lba); cmd->opc == NVME_OPC_WRITE, lba);
lba += cpsz; lba += cpsz;
size -= cpsz; size -= cpsz;
@ -1284,7 +1280,7 @@ pci_nvme_handle_io_cmd(struct pci_nvme_softc* sc, uint16_t idx)
err = pci_nvme_append_iov_req(sc, req, cmd->prp2, err = pci_nvme_append_iov_req(sc, req, cmd->prp2,
size, size,
NVME_CMD_GET_OPC(cmd->opc_fuse) == NVME_OPC_WRITE, cmd->opc == NVME_OPC_WRITE,
lba); lba);
} else { } else {
uint64_t *prp_list; uint64_t *prp_list;
@ -1318,8 +1314,7 @@ pci_nvme_handle_io_cmd(struct pci_nvme_softc* sc, uint16_t idx)
err = pci_nvme_append_iov_req(sc, req, err = pci_nvme_append_iov_req(sc, req,
prp_list[i], cpsz, prp_list[i], cpsz,
NVME_CMD_GET_OPC(cmd->opc_fuse) == cmd->opc == NVME_OPC_WRITE, lba);
NVME_OPC_WRITE, lba);
if (err) if (err)
break; break;
@ -1350,7 +1345,7 @@ pci_nvme_handle_io_cmd(struct pci_nvme_softc* sc, uint16_t idx)
req->io_req.br_callback = pci_nvme_io_done; req->io_req.br_callback = pci_nvme_io_done;
err = 0; err = 0;
switch (NVME_CMD_GET_OPC(cmd->opc_fuse)) { switch (cmd->opc) {
case NVME_OPC_READ: case NVME_OPC_READ:
err = blockif_read(sc->nvstore.ctx, &req->io_req); err = blockif_read(sc->nvstore.ctx, &req->io_req);
break; break;
@ -1359,7 +1354,7 @@ pci_nvme_handle_io_cmd(struct pci_nvme_softc* sc, uint16_t idx)
break; break;
default: default:
WPRINTF(("%s unhandled io command 0x%x\r\n", WPRINTF(("%s unhandled io command 0x%x\r\n",
__func__, NVME_CMD_GET_OPC(cmd->opc_fuse))); __func__, cmd->opc));
err = 1; err = 1;
} }