diff --git a/CHANGELOG.md b/CHANGELOG.md index 3568c4e03..5acfc360c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,9 @@ later again to initialize the controller to the ready state. A controller flag `SPDK_NVME_CTRLR_WRR_SUPPORTED` was added to indicate the controller can support weighted round robin arbitration feature with submission queue. +Added `arbitration_burst` option for arbitration feature, and added three +`low/medium/high_priority_weight` options for weighted round robin arbitration. + ### iSCSI Portals may no longer be associated with a cpumask. The scheduling of diff --git a/include/spdk/nvme.h b/include/spdk/nvme.h index 756433cf8..3179ab2cc 100644 --- a/include/spdk/nvme.h +++ b/include/spdk/nvme.h @@ -81,6 +81,34 @@ struct spdk_nvme_ctrlr_opts { */ enum spdk_nvme_cc_ams arb_mechanism; + /** + * Maximum number of commands that the controller may launch at one time. The + * value is expressed as a power of two, valid values are from 0-7, and 7 means + * unlimited. + */ + uint8_t arbitration_burst; + + /** + * Number of commands that may be executed from the low priority queue in each + * arbitration round. This field is only valid when arb_mechanism is set to + * SPDK_NVME_CC_AMS_WRR (weighted round robin). + */ + uint8_t low_priority_weight; + + /** + * Number of commands that may be executed from the medium priority queue in each + * arbitration round. This field is only valid when arb_mechanism is set to + * SPDK_NVME_CC_AMS_WRR (weighted round robin). + */ + uint8_t medium_priority_weight; + + /** + * Number of commands that may be executed from the high priority queue in each + * arbitration round. This field is only valid when arb_mechanism is set to + * SPDK_NVME_CC_AMS_WRR (weighted round robin). + */ + uint8_t high_priority_weight; + /** * Keep alive timeout in milliseconds (0 = disabled). * diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index 4c8585947..9f659371c 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -515,6 +515,42 @@ nvme_ctrlr_set_intel_supported_features(struct spdk_nvme_ctrlr *ctrlr) ctrlr->feature_supported[SPDK_NVME_INTEL_FEAT_LATENCY_TRACKING] = true; } +static void +nvme_ctrlr_set_arbitration_feature(struct spdk_nvme_ctrlr *ctrlr) +{ + uint32_t cdw11; + struct nvme_completion_poll_status status; + + if (ctrlr->opts.arbitration_burst == 0) { + return; + } + + if (ctrlr->opts.arbitration_burst > 7) { + SPDK_WARNLOG("Valid arbitration burst values is from 0-7\n"); + return; + } + + cdw11 = ctrlr->opts.arbitration_burst; + + if (spdk_nvme_ctrlr_get_flags(ctrlr) & SPDK_NVME_CTRLR_WRR_SUPPORTED) { + cdw11 |= (uint32_t)ctrlr->opts.low_priority_weight << 8; + cdw11 |= (uint32_t)ctrlr->opts.medium_priority_weight << 16; + cdw11 |= (uint32_t)ctrlr->opts.high_priority_weight << 24; + } + + if (spdk_nvme_ctrlr_cmd_set_feature(ctrlr, SPDK_NVME_FEAT_ARBITRATION, + cdw11, 0, NULL, 0, + nvme_completion_poll_cb, &status) < 0) { + SPDK_ERRLOG("Set arbitration feature failed\n"); + return; + } + + if (spdk_nvme_wait_for_completion_timeout(ctrlr->adminq, &status, + ctrlr->opts.admin_timeout_ms / 1000)) { + SPDK_ERRLOG("Timeout to set arbitration feature\n"); + } +} + static void nvme_ctrlr_set_supported_features(struct spdk_nvme_ctrlr *ctrlr) { @@ -542,6 +578,8 @@ nvme_ctrlr_set_supported_features(struct spdk_nvme_ctrlr *ctrlr) if (ctrlr->cdata.vid == SPDK_PCI_VID_INTEL) { nvme_ctrlr_set_intel_supported_features(ctrlr); } + + nvme_ctrlr_set_arbitration_feature(ctrlr); } void