Date: Tue, 13 Aug 2013 21:47:08 +0000 (UTC) From: Jim Harris <jimharris@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r254302 - head/sys/dev/nvme Message-ID: <201308132147.r7DLl8E3008759@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308132147.r7DLl8E3008759>