aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-05-30 09:05:09 -0400
committerChristoph Hellwig <hch@lst.de>2018-06-01 08:37:35 -0400
commit55fdd6b6134fc91d4722149fa8e4f2df24c428fe (patch)
tree6d091a21477e56ac0ecbaba77212b25ec649493d
parentc86b8f7b4144affc4daa8b4047cd4da936b087ef (diff)
nvmet: mask pending AENs
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>
-rw-r--r--drivers/nvme/target/admin-cmd.c1
-rw-r--r--drivers/nvme/target/core.c9
-rw-r--r--drivers/nvme/target/nvmet.h1
3 files changed, 10 insertions, 1 deletions
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 72ef17616682..ead8fbe6922e 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -144,6 +144,7 @@ static void nvmet_execute_get_log_changed_ns(struct nvmet_req *req)
144 if (!status) 144 if (!status)
145 status = nvmet_zero_sgl(req, len, req->data_len - len); 145 status = nvmet_zero_sgl(req, len, req->data_len - len);
146 ctrl->nr_changed_ns = 0; 146 ctrl->nr_changed_ns = 0;
147 clear_bit(NVME_AEN_CFG_NS_ATTR, &ctrl->aen_masked);
147 mutex_unlock(&ctrl->lock); 148 mutex_unlock(&ctrl->lock);
148out: 149out:
149 nvmet_req_complete(req, status); 150 nvmet_req_complete(req, status);
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 5a086b670f42..a03da764ecae 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -144,6 +144,13 @@ static void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
144 schedule_work(&ctrl->async_event_work); 144 schedule_work(&ctrl->async_event_work);
145} 145}
146 146
147static bool nvmet_aen_disabled(struct nvmet_ctrl *ctrl, u32 aen)
148{
149 if (!(READ_ONCE(ctrl->aen_enabled) & aen))
150 return true;
151 return test_and_set_bit(aen, &ctrl->aen_masked);
152}
153
147static void nvmet_add_to_changed_ns_log(struct nvmet_ctrl *ctrl, __le32 nsid) 154static void nvmet_add_to_changed_ns_log(struct nvmet_ctrl *ctrl, __le32 nsid)
148{ 155{
149 u32 i; 156 u32 i;
@@ -174,7 +181,7 @@ static void nvmet_ns_changed(struct nvmet_subsys *subsys, u32 nsid)
174 181
175 list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) { 182 list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
176 nvmet_add_to_changed_ns_log(ctrl, cpu_to_le32(nsid)); 183 nvmet_add_to_changed_ns_log(ctrl, cpu_to_le32(nsid));
177 if (!(READ_ONCE(ctrl->aen_enabled) & NVME_AEN_CFG_NS_ATTR)) 184 if (nvmet_aen_disabled(ctrl, NVME_AEN_CFG_NS_ATTR))
178 continue; 185 continue;
179 nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, 186 nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE,
180 NVME_AER_NOTICE_NS_CHANGED, 187 NVME_AER_NOTICE_NS_CHANGED,
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index f4d16d9b3582..480dfe10fad9 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -139,6 +139,7 @@ struct nvmet_ctrl {
139 u32 kato; 139 u32 kato;
140 140
141 u32 aen_enabled; 141 u32 aen_enabled;
142 unsigned long aen_masked;
142 struct nvmet_req *async_event_cmds[NVMET_ASYNC_EVENTS]; 143 struct nvmet_req *async_event_cmds[NVMET_ASYNC_EVENTS];
143 unsigned int nr_async_event_cmds; 144 unsigned int nr_async_event_cmds;
144 struct list_head async_events; 145 struct list_head async_events;