mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
nvmet: Implement arbitration feature support
NVMe base specification v2.1 mandates support for the arbitration feature (NVME_FEAT_ARBITRATION). Introduce the data structure struct nvmet_feat_arbitration to define the high, medium and low priority weight fields and the arbitration burst field of this feature and implement the functions nvmet_get_feat_arbitration() and nvmet_set_feat_arbitration() functions to get and set these fields. Since there is no generic way to implement support for the arbitration feature, these functions respectively use the controller get_feature() and set_feature() operations to process the feature with the help of the controller driver. If the controller driver does not implement these operations and a get feature command or a set feature command for this feature is received, the command is failed with an invalid field error. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Tested-by: Rick Wertenbroek <rick.wertenbroek@gmail.com> Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Signed-off-by: Keith Busch <kbusch@kernel.org>
This commit is contained in:
committed by
Keith Busch
parent
f1ecd491b6
commit
a0ed77d4c9
@@ -1324,6 +1324,25 @@ static u16 nvmet_set_feat_irq_config(struct nvmet_req *req)
|
||||
return ctrl->ops->set_feature(ctrl, NVME_FEAT_IRQ_CONFIG, &irqcfg);
|
||||
}
|
||||
|
||||
static u16 nvmet_set_feat_arbitration(struct nvmet_req *req)
|
||||
{
|
||||
struct nvmet_ctrl *ctrl = req->sq->ctrl;
|
||||
u32 cdw11 = le32_to_cpu(req->cmd->common.cdw11);
|
||||
struct nvmet_feat_arbitration arb = {
|
||||
.hpw = (cdw11 >> 24) & 0xff,
|
||||
.mpw = (cdw11 >> 16) & 0xff,
|
||||
.lpw = (cdw11 >> 8) & 0xff,
|
||||
.ab = cdw11 & 0x3,
|
||||
};
|
||||
|
||||
if (!ctrl->ops->set_feature) {
|
||||
req->error_loc = offsetof(struct nvme_common_command, cdw10);
|
||||
return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
|
||||
}
|
||||
|
||||
return ctrl->ops->set_feature(ctrl, NVME_FEAT_ARBITRATION, &arb);
|
||||
}
|
||||
|
||||
void nvmet_execute_set_features(struct nvmet_req *req)
|
||||
{
|
||||
struct nvmet_subsys *subsys = nvmet_req_subsys(req);
|
||||
@@ -1337,6 +1356,9 @@ void nvmet_execute_set_features(struct nvmet_req *req)
|
||||
return;
|
||||
|
||||
switch (cdw10 & 0xff) {
|
||||
case NVME_FEAT_ARBITRATION:
|
||||
status = nvmet_set_feat_arbitration(req);
|
||||
break;
|
||||
case NVME_FEAT_NUM_QUEUES:
|
||||
ncqr = (cdw11 >> 16) & 0xffff;
|
||||
nsqr = cdw11 & 0xffff;
|
||||
@@ -1446,6 +1468,30 @@ static u16 nvmet_get_feat_irq_config(struct nvmet_req *req)
|
||||
return NVME_SC_SUCCESS;
|
||||
}
|
||||
|
||||
static u16 nvmet_get_feat_arbitration(struct nvmet_req *req)
|
||||
{
|
||||
struct nvmet_ctrl *ctrl = req->sq->ctrl;
|
||||
struct nvmet_feat_arbitration arb = { };
|
||||
u16 status;
|
||||
|
||||
if (!ctrl->ops->get_feature) {
|
||||
req->error_loc = offsetof(struct nvme_common_command, cdw10);
|
||||
return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
|
||||
}
|
||||
|
||||
status = ctrl->ops->get_feature(ctrl, NVME_FEAT_ARBITRATION, &arb);
|
||||
if (status != NVME_SC_SUCCESS)
|
||||
return status;
|
||||
|
||||
nvmet_set_result(req,
|
||||
((u32)arb.hpw << 24) |
|
||||
((u32)arb.mpw << 16) |
|
||||
((u32)arb.lpw << 8) |
|
||||
(arb.ab & 0x3));
|
||||
|
||||
return NVME_SC_SUCCESS;
|
||||
}
|
||||
|
||||
void nvmet_get_feat_kato(struct nvmet_req *req)
|
||||
{
|
||||
nvmet_set_result(req, req->sq->ctrl->kato * 1000);
|
||||
@@ -1472,8 +1518,6 @@ void nvmet_execute_get_features(struct nvmet_req *req)
|
||||
* need to come up with some fake values for these.
|
||||
*/
|
||||
#if 0
|
||||
case NVME_FEAT_ARBITRATION:
|
||||
break;
|
||||
case NVME_FEAT_POWER_MGMT:
|
||||
break;
|
||||
case NVME_FEAT_TEMP_THRESH:
|
||||
@@ -1483,6 +1527,9 @@ void nvmet_execute_get_features(struct nvmet_req *req)
|
||||
case NVME_FEAT_WRITE_ATOMIC:
|
||||
break;
|
||||
#endif
|
||||
case NVME_FEAT_ARBITRATION:
|
||||
status = nvmet_get_feat_arbitration(req);
|
||||
break;
|
||||
case NVME_FEAT_IRQ_COALESCE:
|
||||
status = nvmet_get_feat_irq_coalesce(req);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user