From: wyung@micron.com (Winson Yung (wyung))
Subject: [PATCH] NVMe: Add support to receive NVMe asynchronous events
Date: Mon, 26 May 2014 13:04:55 -0700 [thread overview]
Message-ID: <53839E67.1010006@micron.com> (raw)
As a NVMe mandatory admin command, this driver should be setup so
that it can receive drive critical asynchronous notification for
issue such as device reliability, temperature above threshold, or
available spare space fallen below threshould. This patch enables
very basic mechanism to log the asynchronous events in kernel log.
Signed-off-by: Winson Yung <wyung at micron.com>
---
drivers/block/nvme-core.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index cd8a8bc7..4cd9f8e 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -198,6 +198,7 @@ static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx,
#define CMD_CTX_COMPLETED (0x310 + CMD_CTX_BASE)
#define CMD_CTX_INVALID (0x314 + CMD_CTX_BASE)
#define CMD_CTX_ABORT (0x318 + CMD_CTX_BASE)
+#define CMD_CTX_ASYNC_EVENT (0x319 + CMD_CTX_BASE)
static void special_completion(struct nvme_queue *nvmeq, void *ctx,
struct nvme_completion *cqe)
@@ -227,7 +228,27 @@ static void special_completion(struct nvme_queue *nvmeq, void *ctx,
static void async_completion(struct nvme_queue *nvmeq, void *ctx,
struct nvme_completion *cqe)
{
+ int cmdid;
+ struct nvme_queue *adminq;
+ struct nvme_dev *dev = nvmeq->dev;
struct async_cmd_info *cmdinfo = ctx;
+
+ if (ctx == CMD_CTX_ASYNC_EVENT) {
+ dev_warn(nvmeq->q_dmadev, "An async event is detected (DW0:%X)\n",
+ cqe->result);
+
+ adminq = rcu_dereference(dev->queues[0]);
+
+ /* Allocate a cmdid entry for next async event */
+ cmdid = alloc_cmdid(adminq, CMD_CTX_ASYNC_EVENT,
+ async_completion, 0);
+ if (cmdid < 0)
+ dev_warn(nvmeq->q_dmadev,
+ "Failure creating new entry for next async event\n");
+
+ return; /* Report asynchronous critical event, and exit */
+ }
+
cmdinfo->result = le32_to_cpup(&cqe->result);
cmdinfo->status = le16_to_cpup(&cqe->status) >> 1;
queue_kthread_work(cmdinfo->worker, &cmdinfo->work);
@@ -2381,6 +2402,37 @@ static int nvme_delete_cq(struct nvme_queue *nvmeq)
nvme_del_cq_work_handler);
}
+static int nvme_enable_async_events(struct nvme_dev *dev)
+{
+ int status, cmdid;
+ u32 result, async_events;
+ struct nvme_queue *adminq;
+
+ async_events = NVME_SMART_CRIT_SPARE |
+ NVME_SMART_CRIT_TEMPERATURE |
+ NVME_SMART_CRIT_RELIABILITY |
+ NVME_SMART_CRIT_MEDIA |
+ NVME_SMART_CRIT_VOLATILE_MEMORY;
+
+ status = nvme_set_features(dev, NVME_FEAT_ASYNC_EVENT,
+ async_events, 0, &result);
+
+ if (status < 0)
+ return status;
+
+ if (status > 0) {
+ dev_err(&dev->pci_dev->dev, "Could not enable async event (%d)\n",
+ status);
+ return -EBUSY;
+ }
+
+ adminq = rcu_dereference(dev->queues[0]);
+
+ /* Allocate a cmdid entry in preparation of next incoming async event */
+ cmdid = alloc_cmdid(adminq, CMD_CTX_ASYNC_EVENT, async_completion, 0);
+ return cmdid;
+}
+
static void nvme_del_sq_work_handler(struct kthread_work *work)
{
struct nvme_queue *nvmeq = container_of(work, struct nvme_queue,
@@ -2638,6 +2690,11 @@ static int nvme_dev_start(struct nvme_dev *dev)
goto disable;
}
+ /* Enable receive asynchronous event */
+ result = nvme_enable_async_events(dev);
+ if (result < 0 && result != -EBUSY)
+ goto disable;
+
result = nvme_setup_io_queues(dev);
if (result && result != -EBUSY)
goto disable;
--
1.7.9.5
next reply other threads:[~2014-05-26 20:04 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-26 20:04 Winson Yung (wyung) [this message]
2014-05-26 21:42 ` [PATCH] NVMe: Add support to receive NVMe asynchronous events Keith Busch
2014-05-27 5:02 ` Winson Yung (wyung)
2014-05-26 23:51 ` Matthew Wilcox
2014-05-27 0:56 ` Keith Busch
2014-05-27 5:35 ` Winson Yung (wyung)
2014-05-27 5:50 ` Keith Busch
2014-05-27 6:56 ` Robles, Raymond C
2014-05-28 20:35 ` Winson Yung (wyung)
2014-05-29 6:40 ` Keith Busch
2014-05-27 5:15 ` Winson Yung (wyung)
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=53839E67.1010006@micron.com \
--to=wyung@micron.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.