nvmf: Allow 4 byte property operations on 8 byte properties

The first 4 or last 4 bytes of an 8 byte property can now
be written independently.

Change-Id: I894f8349be836511c18c380262eae46951060766
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/421
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Ben Walker 2020-02-03 15:00:35 -07:00 committed by Tomasz Zawadzki
parent 8175aa1fea
commit e8c195b3eb

View File

@ -663,11 +663,11 @@ nvmf_prop_get_cc(struct spdk_nvmf_ctrlr *ctrlr)
} }
static bool static bool
nvmf_prop_set_cc(struct spdk_nvmf_ctrlr *ctrlr, uint64_t value) nvmf_prop_set_cc(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value)
{ {
union spdk_nvme_cc_register cc, diff; union spdk_nvme_cc_register cc, diff;
cc.raw = (uint32_t)value; cc.raw = value;
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "cur CC: 0x%08x\n", ctrlr->vcprop.cc.raw); SPDK_DEBUGLOG(SPDK_LOG_NVMF, "cur CC: 0x%08x\n", ctrlr->vcprop.cc.raw);
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "new CC: 0x%08x\n", cc.raw); SPDK_DEBUGLOG(SPDK_LOG_NVMF, "new CC: 0x%08x\n", cc.raw);
@ -759,9 +759,18 @@ nvmf_prop_get_aqa(struct spdk_nvmf_ctrlr *ctrlr)
} }
static bool static bool
nvmf_prop_set_aqa(struct spdk_nvmf_ctrlr *ctrlr, uint64_t value) nvmf_prop_set_aqa(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value)
{ {
ctrlr->vcprop.aqa.raw = (uint32_t)value; union spdk_nvme_aqa_register aqa;
aqa.raw = value;
if (aqa.bits.asqs > ctrlr->vcprop.cap.bits.mqes ||
aqa.bits.acqs > ctrlr->vcprop.cap.bits.mqes) {
return false;
}
ctrlr->vcprop.aqa.raw = value;
return true; return true;
} }
@ -773,9 +782,17 @@ nvmf_prop_get_asq(struct spdk_nvmf_ctrlr *ctrlr)
} }
static bool static bool
nvmf_prop_set_asq(struct spdk_nvmf_ctrlr *ctrlr, uint64_t value) nvmf_prop_set_asq_lower(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value)
{ {
ctrlr->vcprop.asq = value; ctrlr->vcprop.asq = (ctrlr->vcprop.asq & (0xFFFFFFFFULL << 32ULL)) | value;
return true;
}
static bool
nvmf_prop_set_asq_upper(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value)
{
ctrlr->vcprop.asq = (ctrlr->vcprop.asq & 0xFFFFFFFFULL) | ((uint64_t)value << 32ULL);
return true; return true;
} }
@ -787,9 +804,17 @@ nvmf_prop_get_acq(struct spdk_nvmf_ctrlr *ctrlr)
} }
static bool static bool
nvmf_prop_set_acq(struct spdk_nvmf_ctrlr *ctrlr, uint64_t value) nvmf_prop_set_acq_lower(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value)
{ {
ctrlr->vcprop.acq = value; ctrlr->vcprop.acq = (ctrlr->vcprop.acq & (0xFFFFFFFFULL << 32ULL)) | value;
return true;
}
static bool
nvmf_prop_set_acq_upper(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value)
{
ctrlr->vcprop.acq = (ctrlr->vcprop.acq & 0xFFFFFFFFULL) | ((uint64_t)value << 32ULL);
return true; return true;
} }
@ -799,36 +824,37 @@ struct nvmf_prop {
uint8_t size; uint8_t size;
char name[11]; char name[11];
uint64_t (*get_cb)(struct spdk_nvmf_ctrlr *ctrlr); uint64_t (*get_cb)(struct spdk_nvmf_ctrlr *ctrlr);
bool (*set_cb)(struct spdk_nvmf_ctrlr *ctrlr, uint64_t value); bool (*set_cb)(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value);
bool (*set_upper_cb)(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value);
}; };
#define PROP(field, size, get_cb, set_cb) \ #define PROP(field, size, get_cb, set_cb, set_upper_cb) \
{ \ { \
offsetof(struct spdk_nvme_registers, field), \ offsetof(struct spdk_nvme_registers, field), \
SPDK_NVMF_PROP_SIZE_##size, \ size, \
#field, \ #field, \
get_cb, set_cb \ get_cb, set_cb, set_upper_cb \
} }
static const struct nvmf_prop nvmf_props[] = { static const struct nvmf_prop nvmf_props[] = {
PROP(cap, 8, nvmf_prop_get_cap, NULL), PROP(cap, 8, nvmf_prop_get_cap, NULL, NULL),
PROP(vs, 4, nvmf_prop_get_vs, NULL), PROP(vs, 4, nvmf_prop_get_vs, NULL, NULL),
PROP(cc, 4, nvmf_prop_get_cc, nvmf_prop_set_cc), PROP(cc, 4, nvmf_prop_get_cc, nvmf_prop_set_cc, NULL),
PROP(csts, 4, nvmf_prop_get_csts, NULL), PROP(csts, 4, nvmf_prop_get_csts, NULL, NULL),
PROP(aqa, 4, nvmf_prop_get_aqa, nvmf_prop_set_aqa), PROP(aqa, 4, nvmf_prop_get_aqa, nvmf_prop_set_aqa, NULL),
PROP(asq, 8, nvmf_prop_get_asq, nvmf_prop_set_asq), PROP(asq, 8, nvmf_prop_get_asq, nvmf_prop_set_asq_lower, nvmf_prop_set_asq_upper),
PROP(acq, 8, nvmf_prop_get_acq, nvmf_prop_set_acq), PROP(acq, 8, nvmf_prop_get_acq, nvmf_prop_set_acq_lower, nvmf_prop_set_acq_upper),
}; };
static const struct nvmf_prop * static const struct nvmf_prop *
find_prop(uint32_t ofst) find_prop(uint32_t ofst, uint8_t size)
{ {
size_t i; size_t i;
for (i = 0; i < SPDK_COUNTOF(nvmf_props); i++) { for (i = 0; i < SPDK_COUNTOF(nvmf_props); i++) {
const struct nvmf_prop *prop = &nvmf_props[i]; const struct nvmf_prop *prop = &nvmf_props[i];
if (prop->ofst == ofst) { if ((ofst >= prop->ofst) && (ofst + size <= prop->ofst + prop->size)) {
return prop; return prop;
} }
} }
@ -843,6 +869,7 @@ spdk_nvmf_property_get(struct spdk_nvmf_request *req)
struct spdk_nvmf_fabric_prop_get_cmd *cmd = &req->cmd->prop_get_cmd; struct spdk_nvmf_fabric_prop_get_cmd *cmd = &req->cmd->prop_get_cmd;
struct spdk_nvmf_fabric_prop_get_rsp *response = &req->rsp->prop_get_rsp; struct spdk_nvmf_fabric_prop_get_rsp *response = &req->rsp->prop_get_rsp;
const struct nvmf_prop *prop; const struct nvmf_prop *prop;
uint8_t size;
response->status.sc = 0; response->status.sc = 0;
response->value.u64 = 0; response->value.u64 = 0;
@ -850,32 +877,47 @@ spdk_nvmf_property_get(struct spdk_nvmf_request *req)
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "size %d, offset 0x%x\n", SPDK_DEBUGLOG(SPDK_LOG_NVMF, "size %d, offset 0x%x\n",
cmd->attrib.size, cmd->ofst); cmd->attrib.size, cmd->ofst);
if (cmd->attrib.size != SPDK_NVMF_PROP_SIZE_4 && switch (cmd->attrib.size) {
cmd->attrib.size != SPDK_NVMF_PROP_SIZE_8) { case SPDK_NVMF_PROP_SIZE_4:
size = 4;
break;
case SPDK_NVMF_PROP_SIZE_8:
size = 8;
break;
default:
SPDK_ERRLOG("Invalid size value %d\n", cmd->attrib.size); SPDK_ERRLOG("Invalid size value %d\n", cmd->attrib.size);
response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC; response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM; response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
prop = find_prop(cmd->ofst); prop = find_prop(cmd->ofst, size);
if (prop == NULL || prop->get_cb == NULL) { if (prop == NULL || prop->get_cb == NULL) {
/* Reserved properties return 0 when read */
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "name: %s\n", prop->name);
if (cmd->attrib.size != prop->size) {
SPDK_ERRLOG("offset 0x%x size mismatch: cmd %u, prop %u\n",
cmd->ofst, cmd->attrib.size, prop->size);
response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC; response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM; response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "name: %s\n", prop->name);
response->value.u64 = prop->get_cb(ctrlr); response->value.u64 = prop->get_cb(ctrlr);
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "response value: 0x%" PRIx64 "\n", response->value.u64); SPDK_DEBUGLOG(SPDK_LOG_NVMF, "response value: 0x%" PRIx64 "\n", response->value.u64);
if (size != prop->size) {
/* The size must be 4 and the prop->size is 8. Figure out which part of the property to read. */
assert(size == 4);
assert(prop->size == 8);
if (cmd->ofst == prop->ofst) {
/* Keep bottom 4 bytes only */
response->value.u64 &= 0xFFFFFFFF;
} else {
/* Keep top 4 bytes only */
response->value.u64 >>= 32;
}
}
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
@ -887,11 +929,27 @@ spdk_nvmf_property_set(struct spdk_nvmf_request *req)
struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
const struct nvmf_prop *prop; const struct nvmf_prop *prop;
uint64_t value; uint64_t value;
uint8_t size;
bool ret;
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "size %d, offset 0x%x, value 0x%" PRIx64 "\n", SPDK_DEBUGLOG(SPDK_LOG_NVMF, "size %d, offset 0x%x, value 0x%" PRIx64 "\n",
cmd->attrib.size, cmd->ofst, cmd->value.u64); cmd->attrib.size, cmd->ofst, cmd->value.u64);
prop = find_prop(cmd->ofst); switch (cmd->attrib.size) {
case SPDK_NVMF_PROP_SIZE_4:
size = 4;
break;
case SPDK_NVMF_PROP_SIZE_8:
size = 8;
break;
default:
SPDK_ERRLOG("Invalid size value %d\n", cmd->attrib.size);
response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
prop = find_prop(cmd->ofst, size);
if (prop == NULL || prop->set_cb == NULL) { if (prop == NULL || prop->set_cb == NULL) {
SPDK_ERRLOG("Invalid offset 0x%x\n", cmd->ofst); SPDK_ERRLOG("Invalid offset 0x%x\n", cmd->ofst);
response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC; response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
@ -900,20 +958,29 @@ spdk_nvmf_property_set(struct spdk_nvmf_request *req)
} }
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "name: %s\n", prop->name); SPDK_DEBUGLOG(SPDK_LOG_NVMF, "name: %s\n", prop->name);
if (cmd->attrib.size != prop->size) {
SPDK_ERRLOG("offset 0x%x size mismatch: cmd %u, prop %u\n",
cmd->ofst, cmd->attrib.size, prop->size);
response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
value = cmd->value.u64; value = cmd->value.u64;
if (prop->size == SPDK_NVMF_PROP_SIZE_4) {
value = (uint32_t)value; if (prop->size == 4) {
ret = prop->set_cb(ctrlr, (uint32_t)value);
} else if (size != prop->size) {
/* The size must be 4 and the prop->size is 8. Figure out which part of the property to write. */
assert(size == 4);
assert(prop->size == 8);
if (cmd->ofst == prop->ofst) {
ret = prop->set_cb(ctrlr, (uint32_t)value);
} else {
ret = prop->set_upper_cb(ctrlr, (uint32_t)value);
}
} else {
ret = prop->set_cb(ctrlr, (uint32_t)value);
if (ret) {
ret = prop->set_upper_cb(ctrlr, (uint32_t)(value >> 32));
}
} }
if (!prop->set_cb(ctrlr, value)) { if (!ret) {
SPDK_ERRLOG("prop set_cb failed\n"); SPDK_ERRLOG("prop set_cb failed\n");
response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC; response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM; response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;