From nobody Mon Feb 9 16:18:50 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1600982974; cv=none; d=zohomail.com; s=zohoarc; b=W0hMuUNkeuPuT9G3Q+IpYLuAl6CmZ/ypRv+Upj1w4+6tyCpw9LZOQ/QipFBN/QbjnVwyOY5b1kMca3pYJEGMqnwYYTOS+iVbZ9nGuhcHTX2W5+DAK+TJO+iN3Gw1ES8usthLmi2mhxxyevC5R/05xAAzs+Ag6gHO78oz7Zn9ll8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1600982974; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=YPMTy5VauD8fw3RCtj4eD6/YQHE7icVqOIkeeHteLak=; b=k9oxhRAqX34PUHhxNNpvn7qQVAcfPJB+5DMtDpQOngtE52lnAgkVafD9cH4WagofiS53Lo4g7Deb0Zbrn1289vjEAgJrQM2xKR2E64vQ/xuK82d2FpJlCHBJsChN24Z20kOz1gs7sXODkT8cpGvzPOHowki/v4m32SBJc42+5jI= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1600982973999619.0043022947764; Thu, 24 Sep 2020 14:29:33 -0700 (PDT) Received: from localhost ([::1]:42552 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kLYo0-0004Wn-3A for importer@patchew.org; Thu, 24 Sep 2020 17:29:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38850) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kLY8A-0004rE-HX; Thu, 24 Sep 2020 16:46:20 -0400 Received: from new2-smtp.messagingengine.com ([66.111.4.224]:49809) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kLY7s-0007nz-W5; Thu, 24 Sep 2020 16:46:12 -0400 Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailnew.nyi.internal (Postfix) with ESMTP id E613B580100; Thu, 24 Sep 2020 16:45:39 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute7.internal (MEProxy); Thu, 24 Sep 2020 16:45:39 -0400 Received: from apples.local (80-167-98-190-cable.dk.customer.tdc.net [80.167.98.190]) by mail.messagingengine.com (Postfix) with ESMTPA id B64FE3064680; Thu, 24 Sep 2020 16:45:37 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=YPMTy5VauD8fw 3RCtj4eD6/YQHE7icVqOIkeeHteLak=; b=onpnjY6BpC76U77nbqkLp9J+PvaAD GBGv8LB421q4LHzu2lxWthW3GuOpaIQfffcMfpk+nnlq4YYvaPcy/EQ+ycA9sYOJ eBiGiYFlaqsmCYEnOVhbhy/9HDU6t7OU/nKg1YunIhFieWjWFJFHo482Q9XaC4hg lGXRh4cI+bsTMn8/5IN9tcDHdMEOia8+KBKDhBK5qw6EXhnHlzCktp2gotiSx4x2 e+pDfAtWefdSBPuvuvCMcJcwT9mFUzBPS+YyYcp4+N54RK1Lt4fcTQM1rYL2qR+M Br6I59Oe6f6I4PYirCDogncst4asB9KzkBXCBLShRBUe7MO3kq4vCEQUA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=YPMTy5VauD8fw3RCtj4eD6/YQHE7icVqOIkeeHteLak=; b=HxpxVMZm h0WWe130N9fcAf82A1jgsGm9rTBwIz/y4BY6eyQOTSIrZpbRGDEj5qSbNAcK+Mk3 5FE3L09X8xuV6bAoKJD4WIxVeJ9TWECW6RcXRhj95Rt8AFDefjjNK/1tPWn8KoG8 jHvBjcKND5KfySSC3qCmYH8W1AH4HGo17Q63BtSVTIV+0jNJtOUUesQfDfRQ0M9k NxbCOr/YiMJylorHMbxv5IilHFb0PruEGlSop9NCP+ryM2xyipOuM/9L4TUhmcyE gT0VfxsYUBTePYhpSs3+Ss8MQiYCiKrcSSc7yzridHT8+pK9zOGm605/R/eM2HpW 467u68t6jxZnLw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrudekgdduheduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeejfeejjeejffelfeeuhffftddvgfegudejvddvffdtvdfhgeejkeehuefhjeej ueenucffohhmrghinheprhgvshhouhhrtggvshdrrggtthhivhgvpdhrvghsohhurhgtvg hsrdhophgvnhenucfkphepkedtrdduieejrdelkedrudeltdenucevlhhushhtvghrufhi iigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehithhssehirhhrvghlvghvrghnth drughk X-ME-Proxy: From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH 15/16] hw/block/nvme: support zone active excursions Date: Thu, 24 Sep 2020 22:45:15 +0200 Message-Id: <20200924204516.1881843-16-its@irrelevant.dk> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200924204516.1881843-1-its@irrelevant.dk> References: <20200924204516.1881843-1-its@irrelevant.dk> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=66.111.4.224; envelope-from=its@irrelevant.dk; helo=new2-smtp.messagingengine.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/24 14:55:29 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Klaus Jensen , Max Reitz , Keith Busch , Klaus Jensen Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" From: Klaus Jensen Allow the controller to release active resources by transitioning zones to the full state if enabled. Signed-off-by: Klaus Jensen --- docs/specs/nvme.txt | 5 ++ hw/block/nvme-ns.h | 3 + include/block/nvme.h | 30 ++++++-- hw/block/nvme-ns.c | 3 + hw/block/nvme.c | 170 ++++++++++++++++++++++++++++++++++++++---- hw/block/trace-events | 5 +- 6 files changed, 197 insertions(+), 19 deletions(-) diff --git a/docs/specs/nvme.txt b/docs/specs/nvme.txt index 921dbce2dc01..a286d9c07025 100644 --- a/docs/specs/nvme.txt +++ b/docs/specs/nvme.txt @@ -36,6 +36,11 @@ nvme-ns Options `zns.mor`; Specifies the number of open resources available. This is a 0s based value. =20 + `zns.zoc`; Specifies Zone Operation Characteristics (ZOC). Only 0x2 is + supported, which allows Zone Active Excursions. If enabled, the contr= oller + will release active resources when needed by transitioning zones to t= he + Full state. + =20 Reference Specifications ------------------------ diff --git a/hw/block/nvme-ns.h b/hw/block/nvme-ns.h index 1fdcdf706ff6..d9093fdad984 100644 --- a/hw/block/nvme-ns.h +++ b/hw/block/nvme-ns.h @@ -30,6 +30,7 @@ typedef struct NvmeNamespaceParams { uint8_t zdes; uint32_t mar; uint32_t mor; + uint16_t zoc; } zns; } NvmeNamespaceParams; =20 @@ -83,6 +84,8 @@ typedef struct NvmeNamespace { QTAILQ_HEAD(, NvmeZone) lru_open; QTAILQ_HEAD(, NvmeZone) lru_active; } resources; + + NvmeChangedZoneList changed_list; } zns; } NvmeNamespace; =20 diff --git a/include/block/nvme.h b/include/block/nvme.h index d51f397e7ff1..0948a262b2df 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -687,6 +687,7 @@ typedef struct QEMU_PACKED NvmeDsmRange { enum NvmeAsyncEventRequest { NVME_AER_TYPE_ERROR =3D 0, NVME_AER_TYPE_SMART =3D 1, + NVME_AER_TYPE_NOTICE =3D 2, NVME_AER_TYPE_IO_SPECIFIC =3D 6, NVME_AER_TYPE_VENDOR_SPECIFIC =3D 7, NVME_AER_INFO_ERR_INVALID_DB_REGISTER =3D 0, @@ -698,13 +699,15 @@ enum NvmeAsyncEventRequest { NVME_AER_INFO_SMART_RELIABILITY =3D 0, NVME_AER_INFO_SMART_TEMP_THRESH =3D 1, NVME_AER_INFO_SMART_SPARE_THRESH =3D 2, + NVME_AER_INFO_NOTICE_ZONE_DESCR_CHANGED =3D 0xef, }; =20 typedef struct QEMU_PACKED NvmeAerResult { - uint8_t event_type; - uint8_t event_info; - uint8_t log_page; - uint8_t resv; + uint8_t event_type; + uint8_t event_info; + uint8_t log_page; + uint8_t resv; + uint32_t nsid; } NvmeAerResult; =20 typedef struct QEMU_PACKED NvmeCqe { @@ -882,6 +885,15 @@ typedef struct QEMU_PACKED NvmeZoneDescriptor { uint8_t rsvd32[32]; } NvmeZoneDescriptor; =20 +#define NVME_CHANGED_ZONE_LIST_MAX_IDS 511 + +typedef struct QEMU_PACKED NvmeChangedZoneList { + uint16_t num_ids; + uint8_t rsvd2[6]; + uint64_t ids[NVME_CHANGED_ZONE_LIST_MAX_IDS]; +} NvmeChangedZoneList; + +#define NVME_ZA_ZFC (1 << 0) #define NVME_ZA_ZDEV (1 << 7) =20 #define NVME_ZA_SET(za, attrs) ((za) |=3D (attrs)) @@ -996,6 +1008,10 @@ typedef struct QEMU_PACKED NvmeIdCtrl { uint8_t vs[1024]; } NvmeIdCtrl; =20 +enum NvmeIdCtrlOaes { + NVME_OAES_ZDCN =3D 1 << 27, +}; + enum NvmeIdCtrlOacs { NVME_OACS_SECURITY =3D 1 << 0, NVME_OACS_FORMAT =3D 1 << 1, @@ -1064,6 +1080,7 @@ typedef struct QEMU_PACKED NvmeIdCtrlZns { #define NVME_AEC_SMART(aec) (aec & 0xff) #define NVME_AEC_NS_ATTR(aec) ((aec >> 8) & 0x1) #define NVME_AEC_FW_ACTIVATION(aec) ((aec >> 9) & 0x1) +#define NVME_AEC_ZDCN(aec) ((aec >> 27) & 0x1) =20 #define NVME_ERR_REC_TLER(err_rec) (err_rec & 0xffff) #define NVME_ERR_REC_DULBE(err_rec) (err_rec & 0x10000) @@ -1231,9 +1248,11 @@ typedef struct QEMU_PACKED NvmeIdNsZns { uint8_t vs[256]; } NvmeIdNsZns; =20 +#define NVME_ID_NS_ZNS_ZOC_ZAE (1 << 1) + static inline void _nvme_check_size(void) { - QEMU_BUILD_BUG_ON(sizeof(NvmeAerResult) !=3D 4); + QEMU_BUILD_BUG_ON(sizeof(NvmeAerResult) !=3D 8); QEMU_BUILD_BUG_ON(sizeof(NvmeCqe) !=3D 16); QEMU_BUILD_BUG_ON(sizeof(NvmeDsmRange) !=3D 16); QEMU_BUILD_BUG_ON(sizeof(NvmeCmd) !=3D 64); @@ -1258,5 +1277,6 @@ static inline void _nvme_check_size(void) QEMU_BUILD_BUG_ON(sizeof(NvmeEffectsLog) !=3D 4096); QEMU_BUILD_BUG_ON(sizeof(NvmeZoneDescriptor) !=3D 64); QEMU_BUILD_BUG_ON(sizeof(NvmeLBAFE) !=3D 16); + QEMU_BUILD_BUG_ON(sizeof(NvmeChangedZoneList) !=3D 4096); } #endif diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c index 547090282660..9a9f728d791f 100644 --- a/hw/block/nvme-ns.c +++ b/hw/block/nvme-ns.c @@ -104,6 +104,8 @@ static void nvme_ns_init_zoned(NvmeNamespace *ns) NvmeIdNsNvm *id_ns =3D nvme_ns_id_nvm(ns); NvmeIdNsZns *id_ns_zns =3D nvme_ns_id_zoned(ns); =20 + id_ns_zns->zoc =3D cpu_to_le16(ns->params.zns.zoc); + for (int i =3D 0; i <=3D id_ns->nlbaf; i++) { id_ns_zns->lbafe[i].zsze =3D ns->params.zns.zsze ? ns->params.zns.zsze : cpu_to_le64(pow2ceil(ns->params.zns.zcap= )); @@ -442,6 +444,7 @@ static Property nvme_ns_props[] =3D { DEFINE_PROP_UINT8("zns.zdes", NvmeNamespace, params.zns.zdes, 0), DEFINE_PROP_UINT32("zns.mar", NvmeNamespace, params.zns.mar, 0xfffffff= f), DEFINE_PROP_UINT32("zns.mor", NvmeNamespace, params.zns.mor, 0xfffffff= f), + DEFINE_PROP_UINT16("zns.zoc", NvmeNamespace, params.zns.zoc, 0), DEFINE_PROP_END_OF_LIST(), }; =20 diff --git a/hw/block/nvme.c b/hw/block/nvme.c index a43a593ab89e..ecc88e858eee 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -880,10 +880,11 @@ static void nvme_process_aers(void *opaque) =20 req =3D n->aer_reqs[n->outstanding_aers]; =20 - result =3D (NvmeAerResult *) &req->cqe.dw0; + result =3D (NvmeAerResult *) &req->cqe.qw0; result->event_type =3D event->result.event_type; result->event_info =3D event->result.event_info; result->log_page =3D event->result.log_page; + result->nsid =3D event->result.nsid; g_free(event); =20 trace_pci_nvme_aer_post_cqe(result->event_type, result->event_info, @@ -893,12 +894,14 @@ static void nvme_process_aers(void *opaque) } } =20 -static void nvme_enqueue_event(NvmeCtrl *n, uint8_t event_type, - uint8_t event_info, uint8_t log_page) +static void nvme_enqueue_event(NvmeCtrl *n, NvmeNamespace *ns, + uint8_t event_type, uint8_t event_info, + uint8_t log_page) { NvmeAsyncEvent *event; =20 - trace_pci_nvme_enqueue_event(event_type, event_info, log_page); + trace_pci_nvme_enqueue_event(ns ? ns->params.nsid : -1, event_type, + event_info, log_page); =20 if (n->aer_queued =3D=3D n->params.aer_max_queued) { trace_pci_nvme_enqueue_event_noqueue(n->aer_queued); @@ -912,6 +915,11 @@ static void nvme_enqueue_event(NvmeCtrl *n, uint8_t ev= ent_type, .log_page =3D log_page, }; =20 + if (event_info =3D=3D NVME_AER_INFO_NOTICE_ZONE_DESCR_CHANGED) { + assert(ns); + event->result.nsid =3D ns->params.nsid; + } + QTAILQ_INSERT_TAIL(&n->aer_queue, event, entry); n->aer_queued++; =20 @@ -1192,10 +1200,54 @@ static inline void nvme_zone_reset_wp(NvmeZone *zon= e) zone->wp_staging =3D nvme_zslba(zone); } =20 +static void nvme_zone_changed(NvmeCtrl *n, NvmeNamespace *ns, NvmeZone *zo= ne, + NvmeRequest *req) +{ + uint16_t num_ids =3D le16_to_cpu(ns->zns.changed_list.num_ids); + + trace_pci_nvme_zone_changed(nvme_cid(req), ns->params.nsid, + nvme_zslba(zone)); + + if (num_ids < NVME_CHANGED_ZONE_LIST_MAX_IDS) { + for (int i =3D 0; i < num_ids; i++) { + if (ns->zns.changed_list.ids[i] =3D=3D zone->zd->zslba) { + goto out; + } + } + + ns->zns.changed_list.ids[num_ids] =3D zone->zd->zslba; + ns->zns.changed_list.num_ids =3D cpu_to_le16(num_ids + 1); + } else { + memset(&ns->zns.changed_list, 0x0, sizeof(NvmeChangedZoneList)); + ns->zns.changed_list.num_ids =3D cpu_to_le16(0xffff); + } + +out: + nvme_zns_commit_zone(ns, zone); + + if (NVME_AEC_ZDCN(n->features.async_config)) { + nvme_enqueue_event(n, ns, NVME_AER_TYPE_NOTICE, + NVME_AER_INFO_NOTICE_ZONE_DESCR_CHANGED, + NVME_LOG_CHANGED_ZONE_LIST); + } +} + static uint16_t nvme_zrm_transition(NvmeCtrl *n, NvmeNamespace *ns, NvmeZone *zone, NvmeZoneState to, NvmeRequest *req); =20 +static void nvme_zone_active_excursion(NvmeCtrl *n, NvmeNamespace *ns, + NvmeZone *zone, NvmeRequest *req) +{ + trace_pci_nvme_zone_active_excursion(ns->params.nsid, nvme_zslba(zone), + nvme_zs_str(zone)); + + nvme_zrm_transition(n, ns, zone, NVME_ZS_ZSF, req); + NVME_ZA_SET(zone->zd->za, NVME_ZA_ZFC); + + nvme_zone_changed(n, ns, zone, req); +} + static uint16_t nvme_zrm_release_open(NvmeCtrl *n, NvmeNamespace *ns, NvmeRequest *req) { @@ -1237,6 +1289,57 @@ static uint16_t nvme_zrm_release_open(NvmeCtrl *n, N= vmeNamespace *ns, return NVME_TOO_MANY_OPEN_ZONES; } =20 +static uint16_t nvme_zrm_release_active(NvmeCtrl *n, NvmeNamespace *ns, + NvmeRequest *req) +{ + NvmeZone *candidate =3D NULL; + NvmeZoneDescriptor *zd; + NvmeZoneState zs; + + trace_pci_nvme_zone_zrm_release_active(nvme_cid(req), ns->params.nsid); + + if (ns->params.zns.zoc & NVME_ID_NS_ZNS_ZOC_ZAE) { + return NVME_TOO_MANY_ACTIVE_ZONES; + } + + QTAILQ_FOREACH(candidate, &ns->zns.resources.lru_active, lru_entry) { + zd =3D candidate->zd; + zs =3D nvme_zs(candidate); + + trace_pci_nvme_zone_zrm_candidate(nvme_cid(req), ns->params.nsid, + nvme_zslba(candidate), + nvme_wp(candidate), zs); + + goto out; + } + + /* + * If all zone resources are tied up on open zones we have to transiti= on + * one of those to full. + */ + QTAILQ_FOREACH(candidate, &ns->zns.resources.lru_open, lru_entry) { + zd =3D candidate->zd; + zs =3D nvme_zs(candidate); + + trace_pci_nvme_zone_zrm_candidate(nvme_cid(req), ns->params.nsid, + nvme_zslba(candidate), + nvme_wp(candidate), zs); + + /* the zone cannot be finished if it is currently writing */ + if (candidate->wp_staging !=3D le64_to_cpu(zd->wp)) { + continue; + } + + break; + } + + assert(candidate); + +out: + nvme_zone_active_excursion(n, ns, candidate, req); + return NVME_SUCCESS; +} + static uint16_t nvme_zrm_transition(NvmeCtrl *n, NvmeNamespace *ns, NvmeZone *zone, NvmeZoneState to, NvmeRequest *req) @@ -1261,8 +1364,10 @@ static uint16_t nvme_zrm_transition(NvmeCtrl *n, Nvm= eNamespace *ns, =20 case NVME_ZS_ZSC: if (!ns->zns.resources.active) { - trace_pci_nvme_err_too_many_active_zones(nvme_cid(req)); - return NVME_TOO_MANY_ACTIVE_ZONES; + status =3D nvme_zrm_release_active(n, ns, req); + if (status) { + return status; + } } =20 ns->zns.resources.active--; @@ -1273,8 +1378,10 @@ static uint16_t nvme_zrm_transition(NvmeCtrl *n, Nvm= eNamespace *ns, case NVME_ZS_ZSIO: case NVME_ZS_ZSEO: if (!ns->zns.resources.active) { - trace_pci_nvme_err_too_many_active_zones(nvme_cid(req)); - return NVME_TOO_MANY_ACTIVE_ZONES; + status =3D nvme_zrm_release_active(n, ns, req); + if (status) { + return status; + } } =20 if (!ns->zns.resources.open) { @@ -2498,6 +2605,40 @@ static uint16_t nvme_effects_log(NvmeCtrl *n, uint32= _t buf_len, uint64_t off, DMA_DIRECTION_FROM_DEVICE, req); } =20 +static uint16_t nvme_changed_zone_info(NvmeCtrl *n, uint32_t buf_len, + uint64_t off, NvmeRequest *req) +{ + uint32_t nsid =3D le32_to_cpu(req->cmd.nsid); + NvmeNamespace *ns =3D nvme_ns(n, nsid); + uint32_t trans_len; + uint16_t status; + + if (unlikely(!ns)) { + return NVME_INVALID_NSID | NVME_DNR; + } + + if (!nvme_ns_zoned(ns)) { + return NVME_INVALID_LOG_ID | NVME_DNR; + } + + if (off > sizeof(NvmeChangedZoneList)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + trans_len =3D MIN(sizeof(NvmeChangedZoneList) - off, buf_len); + + status =3D nvme_dma(n, (uint8_t *)&ns->zns.changed_list + off, trans_l= en, + DMA_DIRECTION_FROM_DEVICE, req); + if (status) { + return status; + } + + memset(&ns->zns.changed_list, 0x0, sizeof(NvmeChangedZoneList)); + nvme_clear_events(n, NVME_AER_TYPE_NOTICE); + + return NVME_SUCCESS; +} + static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req) { NvmeCmd *cmd =3D &req->cmd; @@ -2543,6 +2684,8 @@ static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest= *req) return nvme_fw_log_info(n, len, off, req); case NVME_LOG_EFFECTS: return nvme_effects_log(n, len, off, req); + case NVME_LOG_CHANGED_ZONE_LIST: + return nvme_changed_zone_info(n, len, off, req); default: trace_pci_nvme_err_invalid_log_page(nvme_cid(req), lid); return NVME_INVALID_FIELD | NVME_DNR; @@ -3161,7 +3304,7 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeReq= uest *req) if (((n->temperature >=3D n->features.temp_thresh_hi) || (n->temperature <=3D n->features.temp_thresh_low)) && NVME_AEC_SMART(n->features.async_config) & NVME_SMART_TEMPERAT= URE) { - nvme_enqueue_event(n, NVME_AER_TYPE_SMART, + nvme_enqueue_event(n, NULL, NVME_AER_TYPE_SMART, NVME_AER_INFO_SMART_TEMP_THRESH, NVME_LOG_SMART_INFO); } @@ -3725,7 +3868,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr,= int val) * fashion. */ if (n->outstanding_aers) { - nvme_enqueue_event(n, NVME_AER_TYPE_ERROR, + nvme_enqueue_event(n, NULL, NVME_AER_TYPE_ERROR, NVME_AER_INFO_ERR_INVALID_DB_REGISTER, NVME_LOG_ERROR_INFO); } @@ -3742,7 +3885,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr,= int val) qid, new_head); =20 if (n->outstanding_aers) { - nvme_enqueue_event(n, NVME_AER_TYPE_ERROR, + nvme_enqueue_event(n, NULL, NVME_AER_TYPE_ERROR, NVME_AER_INFO_ERR_INVALID_DB_VALUE, NVME_LOG_ERROR_INFO); } @@ -3779,7 +3922,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr,= int val) " sqid=3D%"PRIu32", ignoring", qid); =20 if (n->outstanding_aers) { - nvme_enqueue_event(n, NVME_AER_TYPE_ERROR, + nvme_enqueue_event(n, NULL, NVME_AER_TYPE_ERROR, NVME_AER_INFO_ERR_INVALID_DB_REGISTER, NVME_LOG_ERROR_INFO); } @@ -3796,7 +3939,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr,= int val) qid, new_tail); =20 if (n->outstanding_aers) { - nvme_enqueue_event(n, NVME_AER_TYPE_ERROR, + nvme_enqueue_event(n, NULL, NVME_AER_TYPE_ERROR, NVME_AER_INFO_ERR_INVALID_DB_VALUE, NVME_LOG_ERROR_INFO); } @@ -4095,6 +4238,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pc= i_dev) id->ieee[2] =3D 0xb3; id->mdts =3D n->params.mdts; id->ver =3D cpu_to_le32(NVME_SPEC_VER); + id->oaes =3D cpu_to_le32(NVME_OAES_ZDCN); id->oacs =3D cpu_to_le16(0); =20 /* diff --git a/hw/block/trace-events b/hw/block/trace-events index 18f7b24ef5e9..ebd786b77868 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -78,7 +78,7 @@ pci_nvme_aer(uint16_t cid) "cid %"PRIu16"" pci_nvme_aer_aerl_exceeded(void) "aerl exceeded" pci_nvme_aer_masked(uint8_t type, uint8_t mask) "type 0x%"PRIx8" mask 0x%"= PRIx8"" pci_nvme_aer_post_cqe(uint8_t typ, uint8_t info, uint8_t log_page) "type 0= x%"PRIx8" info 0x%"PRIx8" lid 0x%"PRIx8"" -pci_nvme_enqueue_event(uint8_t typ, uint8_t info, uint8_t log_page) "type = 0x%"PRIx8" info 0x%"PRIx8" lid 0x%"PRIx8"" +pci_nvme_enqueue_event(uint32_t nsid, uint8_t typ, uint8_t info, uint8_t l= og_page) "nsid 0x%"PRIx32" type 0x%"PRIx8" info 0x%"PRIx8" lid 0x%"PRIx8"" pci_nvme_enqueue_event_noqueue(int queued) "queued %d" pci_nvme_enqueue_event_masked(uint8_t typ) "type 0x%"PRIx8"" pci_nvme_no_outstanding_aers(void) "ignoring event; no outstanding AERs" @@ -91,6 +91,9 @@ pci_nvme_mmio_doorbell_sq(uint16_t sqid, uint16_t new_tai= l) "sqid %"PRIu16" new_ pci_nvme_zone_zrm_transition(uint16_t cid, uint32_t nsid, uint64_t zslba, = uint8_t from, uint8_t to) "cid %"PRIu16" nsid %"PRIu32" zslba 0x%"PRIx64" f= rom 0x%"PRIx8" to 0x%"PRIx8"" pci_nvme_zone_zrm_candidate(uint16_t cid, uint32_t nsid, uint64_t zslba, u= int64_t wp, uint8_t zc) "cid %"PRIu16" nsid %"PRIu32" zslba 0x%"PRIx64" wp = 0x%"PRIx64" zc 0x%"PRIx8"" pci_nvme_zone_zrm_release_open(uint16_t cid, uint32_t nsid) "cid %"PRIu16"= nsid %"PRIu32"" +pci_nvme_zone_zrm_release_active(uint16_t cid, uint32_t nsid) "cid %"PRIu1= 6" nsid %"PRIu32"" +pci_nvme_zone_changed(uint16_t cid, uint32_t nsid, uint64_t zslba) "cid %"= PRIu16" nsid %"PRIu32" zslba 0x%"PRIx64"" +pci_nvme_zone_active_excursion(uint32_t nsid, uint64_t zslba, const char *= zc) "nsid %"PRIu32" zslba 0x%"PRIx64" zc \"%s\"" pci_nvme_mmio_intm_set(uint64_t data, uint64_t new_mask) "wrote MMIO, inte= rrupt mask set, data=3D0x%"PRIx64", new_mask=3D0x%"PRIx64"" pci_nvme_mmio_intm_clr(uint64_t data, uint64_t new_mask) "wrote MMIO, inte= rrupt mask clr, data=3D0x%"PRIx64", new_mask=3D0x%"PRIx64"" pci_nvme_mmio_cfg(uint64_t data) "wrote MMIO, config controller config=3D0= x%"PRIx64"" --=20 2.28.0