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:
parent
8175aa1fea
commit
e8c195b3eb
153
lib/nvmf/ctrlr.c
153
lib/nvmf/ctrlr.c
@ -663,11 +663,11 @@ nvmf_prop_get_cc(struct spdk_nvmf_ctrlr *ctrlr)
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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, "new CC: 0x%08x\n", cc.raw);
|
||||
@ -759,9 +759,18 @@ nvmf_prop_get_aqa(struct spdk_nvmf_ctrlr *ctrlr)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -773,9 +782,17 @@ nvmf_prop_get_asq(struct spdk_nvmf_ctrlr *ctrlr)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -787,9 +804,17 @@ nvmf_prop_get_acq(struct spdk_nvmf_ctrlr *ctrlr)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -799,36 +824,37 @@ struct nvmf_prop {
|
||||
uint8_t size;
|
||||
char name[11];
|
||||
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), \
|
||||
SPDK_NVMF_PROP_SIZE_##size, \
|
||||
size, \
|
||||
#field, \
|
||||
get_cb, set_cb \
|
||||
get_cb, set_cb, set_upper_cb \
|
||||
}
|
||||
|
||||
static const struct nvmf_prop nvmf_props[] = {
|
||||
PROP(cap, 8, nvmf_prop_get_cap, NULL),
|
||||
PROP(vs, 4, nvmf_prop_get_vs, NULL),
|
||||
PROP(cc, 4, nvmf_prop_get_cc, nvmf_prop_set_cc),
|
||||
PROP(csts, 4, nvmf_prop_get_csts, NULL),
|
||||
PROP(aqa, 4, nvmf_prop_get_aqa, nvmf_prop_set_aqa),
|
||||
PROP(asq, 8, nvmf_prop_get_asq, nvmf_prop_set_asq),
|
||||
PROP(acq, 8, nvmf_prop_get_acq, nvmf_prop_set_acq),
|
||||
PROP(cap, 8, nvmf_prop_get_cap, NULL, NULL),
|
||||
PROP(vs, 4, nvmf_prop_get_vs, NULL, NULL),
|
||||
PROP(cc, 4, nvmf_prop_get_cc, nvmf_prop_set_cc, NULL),
|
||||
PROP(csts, 4, nvmf_prop_get_csts, NULL, NULL),
|
||||
PROP(aqa, 4, nvmf_prop_get_aqa, nvmf_prop_set_aqa, NULL),
|
||||
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_lower, nvmf_prop_set_acq_upper),
|
||||
};
|
||||
|
||||
static const struct nvmf_prop *
|
||||
find_prop(uint32_t ofst)
|
||||
find_prop(uint32_t ofst, uint8_t size)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < SPDK_COUNTOF(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;
|
||||
}
|
||||
}
|
||||
@ -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_rsp *response = &req->rsp->prop_get_rsp;
|
||||
const struct nvmf_prop *prop;
|
||||
uint8_t size;
|
||||
|
||||
response->status.sc = 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",
|
||||
cmd->attrib.size, cmd->ofst);
|
||||
|
||||
if (cmd->attrib.size != SPDK_NVMF_PROP_SIZE_4 &&
|
||||
cmd->attrib.size != SPDK_NVMF_PROP_SIZE_8) {
|
||||
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);
|
||||
prop = find_prop(cmd->ofst, size);
|
||||
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.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
|
||||
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
|
||||
}
|
||||
|
||||
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "name: %s\n", prop->name);
|
||||
|
||||
response->value.u64 = prop->get_cb(ctrlr);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -887,11 +929,27 @@ spdk_nvmf_property_set(struct spdk_nvmf_request *req)
|
||||
struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
|
||||
const struct nvmf_prop *prop;
|
||||
uint64_t value;
|
||||
uint8_t size;
|
||||
bool ret;
|
||||
|
||||
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "size %d, offset 0x%x, value 0x%" PRIx64 "\n",
|
||||
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) {
|
||||
SPDK_ERRLOG("Invalid offset 0x%x\n", cmd->ofst);
|
||||
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);
|
||||
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;
|
||||
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");
|
||||
response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
|
||||
response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
|
||||
|
Loading…
Reference in New Issue
Block a user