From acb9849c05c90b7d666f277af5e676121876b718 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Thu, 29 Aug 2019 04:11:20 -0400 Subject: [PATCH] nvme: add arbitration configuration options to NVMe driver Weighted Round Robin can be enabled for users, and users can allocate different priority IO queues for different purpose. For now we will enable this feature in the NVMe driver first, following patches will enable this feature in bdev layer. Change-Id: I0f799236ca04eb85ef3c9f972ed63ff2718563ba Signed-off-by: Changpeng Liu Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/466852 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto --- CHANGELOG.md | 3 +++ include/spdk/nvme.h | 28 ++++++++++++++++++++++++++++ lib/nvme/nvme_ctrlr.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) 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