nvmet: mask pending AENs
authorChristoph Hellwig <hch@lst.de>
Wed, 30 May 2018 13:05:09 +0000 (15:05 +0200)
committerChristoph Hellwig <hch@lst.de>
Fri, 1 Jun 2018 12:37:35 +0000 (14:37 +0200)
Per section 5.2 of the NVMe 1.3 spec:

  "When the controller posts a completion queue entry for an outstanding
  Asynchronous Event Request command and thus reports an asynchronous
  event, subsequent events of that event type are automatically masked by
  the controller until the host clears that event. An event is cleared by
  reading the log page associated with that event using the Get Log Page
  command (see section 5.14)."

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
drivers/nvme/target/admin-cmd.c
drivers/nvme/target/core.c
drivers/nvme/target/nvmet.h

index 72ef17616682227ffa185d4b570628823bc4cf67..ead8fbe6922e5caacbd230edc7079fc9189e8cd1 100644 (file)
@@ -144,6 +144,7 @@ static void nvmet_execute_get_log_changed_ns(struct nvmet_req *req)
        if (!status)
                status = nvmet_zero_sgl(req, len, req->data_len - len);
        ctrl->nr_changed_ns = 0;
+       clear_bit(NVME_AEN_CFG_NS_ATTR, &ctrl->aen_masked);
        mutex_unlock(&ctrl->lock);
 out:
        nvmet_req_complete(req, status);
index 5a086b670f4206ccdde91e5979bb2ba707993a3c..a03da764ecae8cb3ec9bf0bb9c68971669b895fc 100644 (file)
@@ -144,6 +144,13 @@ static void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
        schedule_work(&ctrl->async_event_work);
 }
 
+static bool nvmet_aen_disabled(struct nvmet_ctrl *ctrl, u32 aen)
+{
+       if (!(READ_ONCE(ctrl->aen_enabled) & aen))
+               return true;
+       return test_and_set_bit(aen, &ctrl->aen_masked);
+}
+
 static void nvmet_add_to_changed_ns_log(struct nvmet_ctrl *ctrl, __le32 nsid)
 {
        u32 i;
@@ -174,7 +181,7 @@ static void nvmet_ns_changed(struct nvmet_subsys *subsys, u32 nsid)
 
        list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
                nvmet_add_to_changed_ns_log(ctrl, cpu_to_le32(nsid));
-               if (!(READ_ONCE(ctrl->aen_enabled) & NVME_AEN_CFG_NS_ATTR))
+               if (nvmet_aen_disabled(ctrl, NVME_AEN_CFG_NS_ATTR))
                        continue;
                nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE,
                                NVME_AER_NOTICE_NS_CHANGED,
index f4d16d9b3582739481b5fbf086abf584c525c9e2..480dfe10fad943e269449111f2372e8a876a0f95 100644 (file)
@@ -139,6 +139,7 @@ struct nvmet_ctrl {
        u32                     kato;
 
        u32                     aen_enabled;
+       unsigned long           aen_masked;
        struct nvmet_req        *async_event_cmds[NVMET_ASYNC_EVENTS];
        unsigned int            nr_async_event_cmds;
        struct list_head        async_events;