qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: <clay.mayers@kioxia.com>
To: <qemu-devel@nongnu.org>
Cc: "Keith Busch" <kbusch@kernel.org>,
	"Klaus Jensen" <its@irrelevant.dk>, "Fam Zheng" <fam@euphon.net>,
	"Phlippe Mathieu-Daudé" <f4bug@amsat.org>
Subject: [PATCH 4/4] hw/block/nvme: add zone descriptor changed AEN
Date: Thu, 20 Oct 2022 17:18:35 -0700	[thread overview]
Message-ID: <20221021001835.942642-5-clay.mayers@kioxia.com> (raw)
In-Reply-To: <20221021001835.942642-1-clay.mayers@kioxia.com>

From: Clay Mayers <clay.mayers@kioxia.com>

If a namespace's param.zoned.finish_time is non-zero,
controllers register with the namespace to be notified
when entries are added to its zone-descriptor-changed
log page.  If the zone-descriptor-changed aen is enabled,
this will cause an AEN to be sent from that controller.

Signed-off-by: Clay Mayers <clay.mayers@kioxia.com>
---
 hw/nvme/ctrl.c       | 62 +++++++++++++++++++++++++++++++++++++++++++-
 hw/nvme/ns.c         |  1 +
 hw/nvme/nvme.h       |  9 +++++++
 include/block/nvme.h |  2 ++
 4 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index c7ee54ef5e..f1cfa272b4 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -1519,6 +1519,52 @@ static void nvme_clear_events(NvmeCtrl *n, uint8_t event_type)
     }
 }
 
+static void nvme_zdc_watch(NvmeCtrl *n, NvmeNamespace *ns, NvmeNotifyFnc fnc)
+{
+    NvmeZdcNotify *watcher = g_malloc0(sizeof(*watcher));
+
+    watcher->n = n;
+    watcher->notify = fnc;
+    QTAILQ_INSERT_TAIL(&ns->zdc_watchers, watcher, entry);
+}
+
+static void nvme_zdc_unwatch(NvmeCtrl *n, NvmeNamespace *ns)
+{
+    NvmeZdcNotify *watcher;
+
+    QTAILQ_FOREACH(watcher, &ns->zdc_watchers, entry) {
+        if (watcher->n == n) {
+            QTAILQ_REMOVE(&ns->zdc_watchers, watcher, entry);
+            break;
+        }
+    }
+}
+
+static void nvme_zdc_notify(NvmeNamespace *ns)
+{
+    NvmeZdcNotify *watcher;
+
+    QTAILQ_FOREACH(watcher, &ns->zdc_watchers, entry) {
+        (*watcher->notify)(watcher->n, ns);
+    }
+}
+
+static void nvme_zdc_aen(NvmeCtrl *n, NvmeNamespace *ns)
+{
+    g_assert(n->id_ctrl.oaes & (1 << 27));
+
+    if (!NVME_AEC_ZONE_CHANGED(n->features.async_config)) {
+        return;
+    }
+
+    if (!n->zdc_event_queued) {
+        n->zdc_event_queued = true;
+        nvme_enqueue_event(n, NVME_AER_TYPE_NOTICE,
+                            NVME_AER_INFO_NOTICE_ZONE_DESC_CHANGED,
+                            NVME_LOG_CHANGED_ZONE, ns->params.nsid);
+    }
+}
+
 static void nvme_zdc_list(NvmeNamespace *ns, NvmeZoneIdList *zlist, bool reset)
 {
     NvmeZdc *zdc;
@@ -1554,6 +1600,7 @@ static void nvme_check_finish(NvmeNamespace *ns, NvmeZoneListHead *list)
                 zdc->zone = zone;
                 zone->zdc_entry = zdc;
                 QTAILQ_INSERT_TAIL(&ns->zdc_list, zdc, entry);
+                nvme_zdc_notify(ns);
             }
         } else if (zone->finish_ms != INT64_MAX) {
             timer_mod_anticipate(ns->active_timer, zone->finish_ms);
@@ -4722,6 +4769,14 @@ static uint16_t nvme_changed_zones(NvmeCtrl *n, uint8_t rae, uint32_t buf_len,
         return NVME_INVALID_NSID | NVME_DNR;
     }
     nvme_zdc_list(ns, &zlist, !rae);
+    if (!rae) {
+        n->zdc_event_queued = false;
+        nvme_clear_events(n, NVME_AER_TYPE_NOTICE);
+        /* send a new aen if there are still zdc entries */
+        if (!QTAILQ_EMPTY(&ns->zdc_list)) {
+            nvme_zdc_notify(ns);
+        }
+    }
 
     return nvme_c2h(n, ((uint8_t *)&zlist) + off, trans_len, req);
 }
@@ -5808,6 +5863,7 @@ static uint16_t nvme_ns_attachment(NvmeCtrl *n, NvmeRequest *req)
                 return NVME_NS_NOT_ATTACHED | NVME_DNR;
             }
 
+            nvme_zdc_unwatch(n, ns);
             ctrl->namespaces[nsid] = NULL;
             ns->attached--;
 
@@ -7535,7 +7591,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
 
     id->cntlid = cpu_to_le16(n->cntlid);
 
-    id->oaes = cpu_to_le32(NVME_OAES_NS_ATTR);
+    id->oaes = cpu_to_le32(NVME_OAES_NS_ATTR | NVME_OAES_ZDC);
     id->ctratt |= cpu_to_le32(NVME_CTRATT_ELBAS);
 
     id->rab = 6;
@@ -7652,6 +7708,10 @@ void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns)
 
     n->dmrsl = MIN_NON_ZERO(n->dmrsl,
                             BDRV_REQUEST_MAX_BYTES / nvme_l2b(ns, 1));
+
+    if (ns->params.fto) {
+        nvme_zdc_watch(n, ns, nvme_zdc_aen);
+    }
 }
 
 static void nvme_realize(PCIDevice *pci_dev, Error **errp)
diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
index 25cd490c99..5629b61302 100644
--- a/hw/nvme/ns.c
+++ b/hw/nvme/ns.c
@@ -241,6 +241,7 @@ static void nvme_ns_zoned_init_state(NvmeNamespace *ns)
     QTAILQ_INIT(&ns->closed_zones);
     QTAILQ_INIT(&ns->full_zones);
     QTAILQ_INIT(&ns->zdc_list);
+    QTAILQ_INIT(&ns->zdc_watchers);
 
     zone = ns->zone_array;
     for (i = 0; i < ns->num_zones; i++, zone++) {
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index 2b7997e4a7..5499105e7b 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -91,6 +91,14 @@ static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys,
 #define NVME_NS(obj) \
     OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS)
 
+typedef void (*NvmeNotifyFnc)(NvmeCtrl *n, NvmeNamespace *ns);
+
+typedef struct NvmeZdcNotify {
+    QTAILQ_ENTRY(NvmeZdcNotify) entry;
+    NvmeNotifyFnc notify;
+    NvmeCtrl *n;
+} NvmeZdcNotify;
+
 typedef struct NvmeZdc {
     QTAILQ_ENTRY(NvmeZdc) entry;
     NvmeZone *zone;
@@ -179,6 +187,7 @@ typedef struct NvmeNamespace {
 
     int64_t         fto_ms;
     QEMUTimer       *active_timer;
+    QTAILQ_HEAD(, NvmeZdcNotify) zdc_watchers;
     QTAILQ_HEAD(, NvmeZdc) zdc_list;
 
     NvmeNamespaceParams params;
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 9467d4b939..1662046c0d 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -830,6 +830,7 @@ enum NvmeAsyncEventRequest {
     NVME_AER_INFO_SMART_TEMP_THRESH         = 1,
     NVME_AER_INFO_SMART_SPARE_THRESH        = 2,
     NVME_AER_INFO_NOTICE_NS_ATTR_CHANGED    = 0,
+    NVME_AER_INFO_NOTICE_ZONE_DESC_CHANGED  = 0xef,
 };
 
 typedef struct QEMU_PACKED NvmeAerResult {
@@ -1133,6 +1134,7 @@ typedef struct NvmeIdCtrlNvm {
 
 enum NvmeIdCtrlOaes {
     NVME_OAES_NS_ATTR   = 1 << 8,
+    NVME_OAES_ZDC       = 1 << 27,
 };
 
 enum NvmeIdCtrlCtratt {
-- 
2.27.0



  parent reply	other threads:[~2022-10-21  0:38 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-21  0:18 [PATCH 0/4] hw/block/nvme: Implement ZNS finish-zone ZDC AEN clay.mayers
2022-10-21  0:18 ` [PATCH 1/4] hw/block/nvme: add ZONE_FINISH_RECOMMENDED functionality clay.mayers
2022-10-21  6:36   ` Klaus Jensen
2022-10-21  0:18 ` [PATCH 2/4] hw/block/nvme: add zone descriptor changed log page clay.mayers
2022-10-21  6:26   ` Klaus Jensen
2022-10-21 15:24     ` Clay Mayers
2022-10-21  0:18 ` [PATCH 3/4] hw/block/nvme: supply dw1 for aen result clay.mayers
2022-10-21  5:59   ` Klaus Jensen
2022-10-21 15:25     ` Clay Mayers
2022-10-21  0:18 ` clay.mayers [this message]
2022-10-21  6:41   ` [PATCH 4/4] hw/block/nvme: add zone descriptor changed AEN Klaus Jensen
2022-10-21 16:39     ` Clay Mayers
2022-10-21  5:57 ` [PATCH 0/4] hw/block/nvme: Implement ZNS finish-zone ZDC AEN Klaus Jensen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221021001835.942642-5-clay.mayers@kioxia.com \
    --to=clay.mayers@kioxia.com \
    --cc=f4bug@amsat.org \
    --cc=fam@euphon.net \
    --cc=its@irrelevant.dk \
    --cc=kbusch@kernel.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).