Skip to content

Commit a0ed77d

Browse files
damien-lemoalkeithbusch
authored andcommitted
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 <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Tested-by: Rick Wertenbroek <[email protected]> Tested-by: Manivannan Sadhasivam <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent f1ecd49 commit a0ed77d

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

drivers/nvme/target/admin-cmd.c

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,25 @@ static u16 nvmet_set_feat_irq_config(struct nvmet_req *req)
13241324
return ctrl->ops->set_feature(ctrl, NVME_FEAT_IRQ_CONFIG, &irqcfg);
13251325
}
13261326

1327+
static u16 nvmet_set_feat_arbitration(struct nvmet_req *req)
1328+
{
1329+
struct nvmet_ctrl *ctrl = req->sq->ctrl;
1330+
u32 cdw11 = le32_to_cpu(req->cmd->common.cdw11);
1331+
struct nvmet_feat_arbitration arb = {
1332+
.hpw = (cdw11 >> 24) & 0xff,
1333+
.mpw = (cdw11 >> 16) & 0xff,
1334+
.lpw = (cdw11 >> 8) & 0xff,
1335+
.ab = cdw11 & 0x3,
1336+
};
1337+
1338+
if (!ctrl->ops->set_feature) {
1339+
req->error_loc = offsetof(struct nvme_common_command, cdw10);
1340+
return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
1341+
}
1342+
1343+
return ctrl->ops->set_feature(ctrl, NVME_FEAT_ARBITRATION, &arb);
1344+
}
1345+
13271346
void nvmet_execute_set_features(struct nvmet_req *req)
13281347
{
13291348
struct nvmet_subsys *subsys = nvmet_req_subsys(req);
@@ -1337,6 +1356,9 @@ void nvmet_execute_set_features(struct nvmet_req *req)
13371356
return;
13381357

13391358
switch (cdw10 & 0xff) {
1359+
case NVME_FEAT_ARBITRATION:
1360+
status = nvmet_set_feat_arbitration(req);
1361+
break;
13401362
case NVME_FEAT_NUM_QUEUES:
13411363
ncqr = (cdw11 >> 16) & 0xffff;
13421364
nsqr = cdw11 & 0xffff;
@@ -1446,6 +1468,30 @@ static u16 nvmet_get_feat_irq_config(struct nvmet_req *req)
14461468
return NVME_SC_SUCCESS;
14471469
}
14481470

1471+
static u16 nvmet_get_feat_arbitration(struct nvmet_req *req)
1472+
{
1473+
struct nvmet_ctrl *ctrl = req->sq->ctrl;
1474+
struct nvmet_feat_arbitration arb = { };
1475+
u16 status;
1476+
1477+
if (!ctrl->ops->get_feature) {
1478+
req->error_loc = offsetof(struct nvme_common_command, cdw10);
1479+
return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
1480+
}
1481+
1482+
status = ctrl->ops->get_feature(ctrl, NVME_FEAT_ARBITRATION, &arb);
1483+
if (status != NVME_SC_SUCCESS)
1484+
return status;
1485+
1486+
nvmet_set_result(req,
1487+
((u32)arb.hpw << 24) |
1488+
((u32)arb.mpw << 16) |
1489+
((u32)arb.lpw << 8) |
1490+
(arb.ab & 0x3));
1491+
1492+
return NVME_SC_SUCCESS;
1493+
}
1494+
14491495
void nvmet_get_feat_kato(struct nvmet_req *req)
14501496
{
14511497
nvmet_set_result(req, req->sq->ctrl->kato * 1000);
@@ -1472,8 +1518,6 @@ void nvmet_execute_get_features(struct nvmet_req *req)
14721518
* need to come up with some fake values for these.
14731519
*/
14741520
#if 0
1475-
case NVME_FEAT_ARBITRATION:
1476-
break;
14771521
case NVME_FEAT_POWER_MGMT:
14781522
break;
14791523
case NVME_FEAT_TEMP_THRESH:
@@ -1483,6 +1527,9 @@ void nvmet_execute_get_features(struct nvmet_req *req)
14831527
case NVME_FEAT_WRITE_ATOMIC:
14841528
break;
14851529
#endif
1530+
case NVME_FEAT_ARBITRATION:
1531+
status = nvmet_get_feat_arbitration(req);
1532+
break;
14861533
case NVME_FEAT_IRQ_COALESCE:
14871534
status = nvmet_get_feat_irq_coalesce(req);
14881535
break;

drivers/nvme/target/nvmet.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,4 +921,11 @@ struct nvmet_feat_irq_config {
921921
bool cd;
922922
};
923923

924+
struct nvmet_feat_arbitration {
925+
u8 hpw;
926+
u8 mpw;
927+
u8 lpw;
928+
u8 ab;
929+
};
930+
924931
#endif /* _NVMET_H */

0 commit comments

Comments
 (0)