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