svn commit: r254302 - head/sys/dev/nvme

Jim Harris jimharris at FreeBSD.org
Tue Aug 13 21:47:10 UTC 2013


Author: jimharris
Date: Tue Aug 13 21:47:08 2013
New Revision: 254302
URL: http://svnweb.freebsd.org/changeset/base/254302

Log:
  Send a shutdown notification in the driver unload path, to ensure
  notification gets sent in cases where system shuts down with driver
  unloaded.
  
  Sponsored by:	Intel
  Reviewed by:	carl
  MFC after:	3 days

Modified:
  head/sys/dev/nvme/nvme.c
  head/sys/dev/nvme/nvme.h
  head/sys/dev/nvme/nvme_ctrlr.c
  head/sys/dev/nvme/nvme_private.h

Modified: head/sys/dev/nvme/nvme.c
==============================================================================
--- head/sys/dev/nvme/nvme.c	Tue Aug 13 21:45:48 2013	(r254301)
+++ head/sys/dev/nvme/nvme.c	Tue Aug 13 21:47:08 2013	(r254302)
@@ -157,30 +157,14 @@ nvme_shutdown(void)
 {
 	device_t		*devlist;
 	struct nvme_controller	*ctrlr;
-	union cc_register	cc;
-	union csts_register	csts;
 	int			dev, devcount;
 
 	if (devclass_get_devices(nvme_devclass, &devlist, &devcount))
 		return;
 
 	for (dev = 0; dev < devcount; dev++) {
-		/*
-		 * Only notify controller of shutdown when a real shutdown is
-		 *  in process, not when a module unload occurs.  It seems at
-		 *  least some controllers (Chatham at least) don't let you
-		 *  re-enable the controller after shutdown notification has
-		 *  been received.
-		 */
 		ctrlr = DEVICE2SOFTC(devlist[dev]);
-		cc.raw = nvme_mmio_read_4(ctrlr, cc);
-		cc.bits.shn = NVME_SHN_NORMAL;
-		nvme_mmio_write_4(ctrlr, cc, cc.raw);
-		csts.raw = nvme_mmio_read_4(ctrlr, csts);
-		while (csts.bits.shst != NVME_SHST_COMPLETE) {
-			DELAY(5);
-			csts.raw = nvme_mmio_read_4(ctrlr, csts);
-		}
+		nvme_ctrlr_shutdown(ctrlr);
 	}
 
 	free(devlist, M_TEMP);

Modified: head/sys/dev/nvme/nvme.h
==============================================================================
--- head/sys/dev/nvme/nvme.h	Tue Aug 13 21:45:48 2013	(r254301)
+++ head/sys/dev/nvme/nvme.h	Tue Aug 13 21:47:08 2013	(r254302)
@@ -170,27 +170,30 @@ struct nvme_registers
 	union cap_lo_register	cap_lo;
 	union cap_hi_register	cap_hi;
 
-	uint32_t	vs;		/* version */
-	uint32_t	intms;		/* interrupt mask set */
-	uint32_t	intmc;		/* interrupt mask clear */
+	uint32_t		vs;	/* version */
+	uint32_t		intms;	/* interrupt mask set */
+	uint32_t		intmc;	/* interrupt mask clear */
 
 	/** controller configuration */
 	union cc_register	cc;
 
-	uint32_t	reserved1;
-	uint32_t	csts;		/* controller status */
-	uint32_t	reserved2;
+	uint32_t		reserved1;
+
+	/** controller status */
+	union csts_register	csts;
+
+	uint32_t		reserved2;
 
 	/** admin queue attributes */
 	union aqa_register	aqa;
 
-	uint64_t	asq;		/* admin submission queue base addr */
-	uint64_t	acq;		/* admin completion queue base addr */
-	uint32_t	reserved3[0x3f2];
+	uint64_t		asq;	/* admin submission queue base addr */
+	uint64_t		acq;	/* admin completion queue base addr */
+	uint32_t		reserved3[0x3f2];
 
 	struct {
-	    uint32_t	sq_tdbl;	/* submission queue tail doorbell */
-	    uint32_t	cq_hdbl;	/* completion queue head doorbell */
+	    uint32_t		sq_tdbl; /* submission queue tail doorbell */
+	    uint32_t		cq_hdbl; /* completion queue head doorbell */
 	} doorbell[1] __packed;
 } __packed;
 

Modified: head/sys/dev/nvme/nvme_ctrlr.c
==============================================================================
--- head/sys/dev/nvme/nvme_ctrlr.c	Tue Aug 13 21:45:48 2013	(r254301)
+++ head/sys/dev/nvme/nvme_ctrlr.c	Tue Aug 13 21:47:08 2013	(r254302)
@@ -1117,6 +1117,21 @@ nvme_ctrlr_destruct(struct nvme_controll
 {
 	int				i;
 
+	/*
+	 *  Notify the controller of a shutdown, even though this is due to
+	 *   a driver unload, not a system shutdown (this path is not invoked
+	 *   during shutdown).  This ensures the controller receives a
+	 *   shutdown notification in case the system is shutdown before
+	 *   reloading the driver.
+	 *
+	 *  Chatham does not let you re-enable the controller after shutdown
+	 *   notification has been received, so do not send it in this case.
+	 *   This is OK because Chatham does not depend on the shutdown
+	 *   notification anyways.
+	 */
+	if (pci_get_devid(ctrlr->dev) != CHATHAM_PCI_ID)
+		nvme_ctrlr_shutdown(ctrlr);
+
 	nvme_ctrlr_disable(ctrlr);
 	taskqueue_free(ctrlr->taskqueue);
 
@@ -1163,6 +1178,26 @@ nvme_ctrlr_destruct(struct nvme_controll
 }
 
 void
+nvme_ctrlr_shutdown(struct nvme_controller *ctrlr)
+{
+	union cc_register	cc;
+	union csts_register	csts;
+	int			ticks = 0;
+
+	cc.raw = nvme_mmio_read_4(ctrlr, cc);
+	cc.bits.shn = NVME_SHN_NORMAL;
+	nvme_mmio_write_4(ctrlr, cc, cc.raw);
+	csts.raw = nvme_mmio_read_4(ctrlr, csts);
+	while ((csts.bits.shst != NVME_SHST_COMPLETE) && (ticks++ < 5*hz)) {
+		pause("nvme shn", 1);
+		csts.raw = nvme_mmio_read_4(ctrlr, csts);
+	}
+	if (csts.bits.shst != NVME_SHST_COMPLETE)
+		nvme_printf(ctrlr, "did not complete shutdown within 5 seconds "
+		    "of notification\n");
+}
+
+void
 nvme_ctrlr_submit_admin_request(struct nvme_controller *ctrlr,
     struct nvme_request *req)
 {

Modified: head/sys/dev/nvme/nvme_private.h
==============================================================================
--- head/sys/dev/nvme/nvme_private.h	Tue Aug 13 21:45:48 2013	(r254301)
+++ head/sys/dev/nvme/nvme_private.h	Tue Aug 13 21:47:08 2013	(r254302)
@@ -433,6 +433,7 @@ void	nvme_completion_poll_cb(void *arg, 
 
 int	nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev);
 void	nvme_ctrlr_destruct(struct nvme_controller *ctrlr, device_t dev);
+void	nvme_ctrlr_shutdown(struct nvme_controller *ctrlr);
 int	nvme_ctrlr_hw_reset(struct nvme_controller *ctrlr);
 void	nvme_ctrlr_reset(struct nvme_controller *ctrlr);
 /* ctrlr defined as void * to allow use with config_intrhook. */


More information about the svn-src-head mailing list