nvmet: add AEN configuration support
authorChristoph Hellwig <hch@lst.de>
Wed, 30 May 2018 13:04:47 +0000 (15:04 +0200)
committerChristoph Hellwig <hch@lst.de>
Fri, 1 Jun 2018 12:37:35 +0000 (14:37 +0200)
AEN configuration via the 'Get Features' and 'Set Features' admin
command is mandatory, so we should be implemeting handling for it.

Signed-off-by: Hannes Reinecke <hare@suse.com>
[hch: use WRITE_ONCE, check for invalid values]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
drivers/nvme/target/admin-cmd.c
drivers/nvme/target/core.c
drivers/nvme/target/nvmet.h

index 52129d13770e1bfe0c6a40f2d8f27731598d7bb5..72ef17616682227ffa185d4b570628823bc4cf67 100644 (file)
@@ -189,7 +189,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
        id->ver = cpu_to_le32(ctrl->subsys->ver);
 
        /* XXX: figure out what to do about RTD3R/RTD3 */
-       id->oaes = cpu_to_le32(1 << 8);
+       id->oaes = cpu_to_le32(NVMET_AEN_CFG_OPTIONAL);
        id->ctratt = cpu_to_le32(1 << 0);
 
        id->oacs = 0;
@@ -435,6 +435,16 @@ static void nvmet_execute_set_features(struct nvmet_req *req)
                req->sq->ctrl->kato = DIV_ROUND_UP(val32, 1000);
                nvmet_set_result(req, req->sq->ctrl->kato);
                break;
+       case NVME_FEAT_ASYNC_EVENT:
+               val32 = le32_to_cpu(req->cmd->common.cdw10[1]);
+               if (val32 & ~NVMET_AEN_CFG_ALL) {
+                       status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+                       break;
+               }
+
+               WRITE_ONCE(req->sq->ctrl->aen_enabled, val32);
+               nvmet_set_result(req, val32);
+               break;
        case NVME_FEAT_HOST_ID:
                status = NVME_SC_CMD_SEQ_ERROR | NVME_SC_DNR;
                break;
@@ -473,9 +483,10 @@ static void nvmet_execute_get_features(struct nvmet_req *req)
                break;
        case NVME_FEAT_WRITE_ATOMIC:
                break;
+#endif
        case NVME_FEAT_ASYNC_EVENT:
+               nvmet_set_result(req, READ_ONCE(req->sq->ctrl->aen_enabled));
                break;
-#endif
        case NVME_FEAT_VOLATILE_WC:
                nvmet_set_result(req, 1);
                break;
index 4fe88e15c64126160d0110818aba9e0e5dd55bfa..5a086b670f4206ccdde91e5979bb2ba707993a3c 100644 (file)
@@ -174,6 +174,8 @@ 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))
+                       continue;
                nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE,
                                NVME_AER_NOTICE_NS_CHANGED,
                                NVME_LOG_CHANGED_NS);
@@ -861,6 +863,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
 
        kref_init(&ctrl->ref);
        ctrl->subsys = subsys;
+       WRITE_ONCE(ctrl->aen_enabled, NVMET_AEN_CFG_OPTIONAL);
 
        ctrl->changed_ns_list = kmalloc_array(NVME_MAX_CHANGED_NAMESPACES,
                        sizeof(__le32), GFP_KERNEL);
index 8cdc1e550396c93b7932fa9a9073fd3c529b4ba5..f4d16d9b3582739481b5fbf086abf584c525c9e2 100644 (file)
 #define NVMET_ASYNC_EVENTS             4
 #define NVMET_ERROR_LOG_SLOTS          128
 
+
+/*
+ * Supported optional AENs:
+ */
+#define NVMET_AEN_CFG_OPTIONAL \
+       NVME_AEN_CFG_NS_ATTR
+
+/*
+ * Plus mandatory SMART AENs (we'll never send them, but allow enabling them):
+ */
+#define NVMET_AEN_CFG_ALL \
+       (NVME_SMART_CRIT_SPARE | NVME_SMART_CRIT_TEMPERATURE | \
+        NVME_SMART_CRIT_RELIABILITY | NVME_SMART_CRIT_MEDIA | \
+        NVME_SMART_CRIT_VOLATILE_MEMORY | NVMET_AEN_CFG_OPTIONAL)
+
 /* Helper Macros when NVMe error is NVME_SC_CONNECT_INVALID_PARAM
  * The 16 bit shift is to set IATTR bit to 1, which means offending
  * offset starts in the data section of connect()
@@ -123,6 +138,7 @@ struct nvmet_ctrl {
        u16                     cntlid;
        u32                     kato;
 
+       u32                     aen_enabled;
        struct nvmet_req        *async_event_cmds[NVMET_ASYNC_EVENTS];
        unsigned int            nr_async_event_cmds;
        struct list_head        async_events;