svn commit: r248769 - head/sys/dev/nvme
Jim Harris
jimharris at FreeBSD.org
Tue Mar 26 22:09:52 UTC 2013
Author: jimharris
Date: Tue Mar 26 22:09:51 2013
New Revision: 248769
URL: http://svnweb.freebsd.org/changeset/base/248769
Log:
Replace usages of mtx_pool_find used for admin commands with a polling
mechanism.
Now that all requests are timed, we are guaranteed to get a completion
notification, even if it is an abort status due to a timed out admin
command.
This has the effect of simplifying the controller and namespace setup
code, so that it reads straight through rather than broken up into
a bunch of different callback functions.
Sponsored by: Intel
Reviewed by: carl
Modified:
head/sys/dev/nvme/nvme.c
head/sys/dev/nvme/nvme_ctrlr.c
head/sys/dev/nvme/nvme_ns.c
head/sys/dev/nvme/nvme_private.h
Modified: head/sys/dev/nvme/nvme.c
==============================================================================
--- head/sys/dev/nvme/nvme.c Tue Mar 26 22:06:05 2013 (r248768)
+++ head/sys/dev/nvme/nvme.c Tue Mar 26 22:09:51 2013 (r248769)
@@ -397,3 +397,18 @@ nvme_unregister_consumer(struct nvme_con
consumer->id = INVALID_CONSUMER_ID;
}
+void
+nvme_completion_poll_cb(void *arg, const struct nvme_completion *cpl)
+{
+ struct nvme_completion_poll_status *status = arg;
+
+ /*
+ * Copy status into the argument passed by the caller, so that
+ * the caller can check the status to determine if the
+ * the request passed or failed.
+ */
+ memcpy(&status->cpl, cpl, sizeof(*cpl));
+ wmb();
+ status->done = TRUE;
+}
+
Modified: head/sys/dev/nvme/nvme_ctrlr.c
==============================================================================
--- head/sys/dev/nvme/nvme_ctrlr.c Tue Mar 26 22:06:05 2013 (r248768)
+++ head/sys/dev/nvme/nvme_ctrlr.c Tue Mar 26 22:09:51 2013 (r248769)
@@ -41,24 +41,6 @@ __FBSDID("$FreeBSD$");
static void nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr,
struct nvme_async_event_request *aer);
-static void
-nvme_ctrlr_cb(void *arg, const struct nvme_completion *status)
-{
- struct nvme_completion *cpl = arg;
- struct mtx *mtx;
-
- /*
- * Copy status into the argument passed by the caller, so that
- * the caller can check the status to determine if the
- * the request passed or failed.
- */
- memcpy(cpl, status, sizeof(*cpl));
- mtx = mtx_pool_find(mtxpool_sleep, cpl);
- mtx_lock(mtx);
- wakeup(cpl);
- mtx_unlock(mtx);
-}
-
static int
nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr)
{
@@ -479,18 +461,14 @@ nvme_ctrlr_reset(struct nvme_controller
static int
nvme_ctrlr_identify(struct nvme_controller *ctrlr)
{
- struct mtx *mtx;
- struct nvme_completion cpl;
- int status;
-
- mtx = mtx_pool_find(mtxpool_sleep, &cpl);
+ struct nvme_completion_poll_status status;
- mtx_lock(mtx);
+ status.done = FALSE;
nvme_ctrlr_cmd_identify_controller(ctrlr, &ctrlr->cdata,
- nvme_ctrlr_cb, &cpl);
- status = msleep(&cpl, mtx, PRIBIO, "nvme_start", hz*5);
- mtx_unlock(mtx);
- if ((status != 0) || nvme_completion_is_error(&cpl)) {
+ nvme_completion_poll_cb, &status);
+ while (status.done == FALSE)
+ DELAY(5);
+ if (nvme_completion_is_error(&status.cpl)) {
printf("nvme_identify_controller failed!\n");
return (ENXIO);
}
@@ -514,18 +492,15 @@ nvme_ctrlr_identify(struct nvme_controll
static int
nvme_ctrlr_set_num_qpairs(struct nvme_controller *ctrlr)
{
- struct mtx *mtx;
- struct nvme_completion cpl;
- int cq_allocated, sq_allocated, status;
-
- mtx = mtx_pool_find(mtxpool_sleep, &cpl);
+ struct nvme_completion_poll_status status;
+ int cq_allocated, sq_allocated;
- mtx_lock(mtx);
+ status.done = FALSE;
nvme_ctrlr_cmd_set_num_queues(ctrlr, ctrlr->num_io_queues,
- nvme_ctrlr_cb, &cpl);
- status = msleep(&cpl, mtx, PRIBIO, "nvme_start", hz*5);
- mtx_unlock(mtx);
- if ((status != 0) || nvme_completion_is_error(&cpl)) {
+ nvme_completion_poll_cb, &status);
+ while (status.done == FALSE)
+ DELAY(5);
+ if (nvme_completion_is_error(&status.cpl)) {
printf("nvme_set_num_queues failed!\n");
return (ENXIO);
}
@@ -535,8 +510,8 @@ nvme_ctrlr_set_num_qpairs(struct nvme_co
* Lower 16-bits indicate number of submission queues allocated.
* Upper 16-bits indicate number of completion queues allocated.
*/
- sq_allocated = (cpl.cdw0 & 0xFFFF) + 1;
- cq_allocated = (cpl.cdw0 >> 16) + 1;
+ sq_allocated = (status.cpl.cdw0 & 0xFFFF) + 1;
+ cq_allocated = (status.cpl.cdw0 >> 16) + 1;
/*
* Check that the controller was able to allocate the number of
@@ -558,32 +533,29 @@ nvme_ctrlr_set_num_qpairs(struct nvme_co
static int
nvme_ctrlr_create_qpairs(struct nvme_controller *ctrlr)
{
- struct mtx *mtx;
- struct nvme_qpair *qpair;
- struct nvme_completion cpl;
- int i, status;
-
- mtx = mtx_pool_find(mtxpool_sleep, &cpl);
+ struct nvme_completion_poll_status status;
+ struct nvme_qpair *qpair;
+ int i;
for (i = 0; i < ctrlr->num_io_queues; i++) {
qpair = &ctrlr->ioq[i];
- mtx_lock(mtx);
+ status.done = FALSE;
nvme_ctrlr_cmd_create_io_cq(ctrlr, qpair, qpair->vector,
- nvme_ctrlr_cb, &cpl);
- status = msleep(&cpl, mtx, PRIBIO, "nvme_start", hz*5);
- mtx_unlock(mtx);
- if ((status != 0) || nvme_completion_is_error(&cpl)) {
+ nvme_completion_poll_cb, &status);
+ while (status.done == FALSE)
+ DELAY(5);
+ if (nvme_completion_is_error(&status.cpl)) {
printf("nvme_create_io_cq failed!\n");
return (ENXIO);
}
- mtx_lock(mtx);
+ status.done = FALSE;
nvme_ctrlr_cmd_create_io_sq(qpair->ctrlr, qpair,
- nvme_ctrlr_cb, &cpl);
- status = msleep(&cpl, mtx, PRIBIO, "nvme_start", hz*5);
- mtx_unlock(mtx);
- if ((status != 0) || nvme_completion_is_error(&cpl)) {
+ nvme_completion_poll_cb, &status);
+ while (status.done == FALSE)
+ DELAY(5);
+ if (nvme_completion_is_error(&status.cpl)) {
printf("nvme_create_io_sq failed!\n");
return (ENXIO);
}
@@ -906,9 +878,8 @@ static int
nvme_ctrlr_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
struct thread *td)
{
- struct nvme_controller *ctrlr;
- struct nvme_completion cpl;
- struct mtx *mtx;
+ struct nvme_completion_poll_status status;
+ struct nvme_controller *ctrlr;
ctrlr = cdev->si_drv1;
@@ -925,13 +896,12 @@ nvme_ctrlr_ioctl(struct cdev *cdev, u_lo
}
#endif
/* Refresh data before returning to user. */
- mtx = mtx_pool_find(mtxpool_sleep, &cpl);
- mtx_lock(mtx);
+ status.done = FALSE;
nvme_ctrlr_cmd_identify_controller(ctrlr, &ctrlr->cdata,
- nvme_ctrlr_cb, &cpl);
- msleep(&cpl, mtx, PRIBIO, "nvme_ioctl", 0);
- mtx_unlock(mtx);
- if (nvme_completion_is_error(&cpl))
+ nvme_completion_poll_cb, &status);
+ while (status.done == FALSE)
+ DELAY(5);
+ if (nvme_completion_is_error(&status.cpl))
return (ENXIO);
memcpy(arg, &ctrlr->cdata, sizeof(ctrlr->cdata));
break;
Modified: head/sys/dev/nvme/nvme_ns.c
==============================================================================
--- head/sys/dev/nvme/nvme_ns.c Tue Mar 26 22:06:05 2013 (r248768)
+++ head/sys/dev/nvme/nvme_ns.c Tue Mar 26 22:09:51 2013 (r248769)
@@ -41,32 +41,13 @@ __FBSDID("$FreeBSD$");
#include "nvme_private.h"
-static void
-nvme_ns_cb(void *arg, const struct nvme_completion *status)
-{
- struct nvme_completion *cpl = arg;
- struct mtx *mtx;
-
- /*
- * Copy status into the argument passed by the caller, so that
- * the caller can check the status to determine if the
- * the request passed or failed.
- */
- memcpy(cpl, status, sizeof(*cpl));
- mtx = mtx_pool_find(mtxpool_sleep, cpl);
- mtx_lock(mtx);
- wakeup(cpl);
- mtx_unlock(mtx);
-}
-
static int
nvme_ns_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
struct thread *td)
{
- struct nvme_namespace *ns;
- struct nvme_controller *ctrlr;
- struct nvme_completion cpl;
- struct mtx *mtx;
+ struct nvme_completion_poll_status status;
+ struct nvme_namespace *ns;
+ struct nvme_controller *ctrlr;
ns = cdev->si_drv1;
ctrlr = ns->ctrlr;
@@ -84,13 +65,12 @@ nvme_ns_ioctl(struct cdev *cdev, u_long
}
#endif
/* Refresh data before returning to user. */
- mtx = mtx_pool_find(mtxpool_sleep, &cpl);
- mtx_lock(mtx);
+ status.done = FALSE;
nvme_ctrlr_cmd_identify_namespace(ctrlr, ns->id, &ns->data,
- nvme_ns_cb, &cpl);
- msleep(&cpl, mtx, PRIBIO, "nvme_ioctl", 0);
- mtx_unlock(mtx);
- if (nvme_completion_is_error(&cpl))
+ nvme_completion_poll_cb, &status);
+ while (status.done == FALSE)
+ DELAY(5);
+ if (nvme_completion_is_error(&status.cpl))
return (ENXIO);
memcpy(arg, &ns->data, sizeof(ns->data));
break;
@@ -319,9 +299,7 @@ int
nvme_ns_construct(struct nvme_namespace *ns, uint16_t id,
struct nvme_controller *ctrlr)
{
- struct nvme_completion cpl;
- struct mtx *mtx;
- int status;
+ struct nvme_completion_poll_status status;
ns->ctrlr = ctrlr;
ns->id = id;
@@ -331,14 +309,12 @@ nvme_ns_construct(struct nvme_namespace
nvme_ns_populate_chatham_data(ns);
else {
#endif
- mtx = mtx_pool_find(mtxpool_sleep, &cpl);
-
- mtx_lock(mtx);
+ status.done = FALSE;
nvme_ctrlr_cmd_identify_namespace(ctrlr, id, &ns->data,
- nvme_ns_cb, &cpl);
- status = msleep(&cpl, mtx, PRIBIO, "nvme_start", hz*5);
- mtx_unlock(mtx);
- if ((status != 0) || nvme_completion_is_error(&cpl)) {
+ nvme_completion_poll_cb, &status);
+ while (status.done == FALSE)
+ DELAY(5);
+ if (nvme_completion_is_error(&status.cpl)) {
printf("nvme_identify_namespace failed!\n");
return (ENXIO);
}
Modified: head/sys/dev/nvme/nvme_private.h
==============================================================================
--- head/sys/dev/nvme/nvme_private.h Tue Mar 26 22:06:05 2013 (r248768)
+++ head/sys/dev/nvme/nvme_private.h Tue Mar 26 22:09:51 2013 (r248769)
@@ -116,6 +116,12 @@ MALLOC_DECLARE(M_NVME);
extern uma_zone_t nvme_request_zone;
extern int32_t nvme_retry_count;
+struct nvme_completion_poll_status {
+
+ struct nvme_completion cpl;
+ boolean_t done;
+};
+
struct nvme_request {
struct nvme_command cmd;
@@ -399,6 +405,7 @@ void nvme_payload_map(void *arg, bus_dma
int error);
void nvme_payload_map_uio(void *arg, bus_dma_segment_t *seg, int nseg,
bus_size_t mapsize, int error);
+void nvme_completion_poll_cb(void *arg, const struct nvme_completion *cpl);
int nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev);
void nvme_ctrlr_destruct(struct nvme_controller *ctrlr, device_t dev);
More information about the svn-src-all
mailing list