Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev follow advice of spec and block interrupts via INTMS...



details:   https://anonhg.NetBSD.org/src/rev/b55f63619e94
branches:  trunk
changeset: 348467:b55f63619e94
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Wed Oct 19 19:31:23 2016 +0000

description:
follow advice of spec and block interrupts via INTMS/INTMC for intx handler;
this also makes it possible to offload the actual interrupt processing to softintr
handler, similar as for MSI/MSI-X

diffstat:

 sys/dev/ic/nvme.c      |  40 +++++++++++++++++++++++++-------
 sys/dev/ic/nvmevar.h   |   3 +-
 sys/dev/pci/nvme_pci.c |  62 ++++++++++++++++++++++---------------------------
 3 files changed, 61 insertions(+), 44 deletions(-)

diffs (218 lines):

diff -r cec5092c9e09 -r b55f63619e94 sys/dev/ic/nvme.c
--- a/sys/dev/ic/nvme.c Wed Oct 19 19:10:33 2016 +0000
+++ b/sys/dev/ic/nvme.c Wed Oct 19 19:31:23 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvme.c,v 1.16 2016/10/18 07:48:05 nonaka Exp $ */
+/*     $NetBSD: nvme.c,v 1.17 2016/10/19 19:31:23 jdolecek Exp $       */
 /*     $OpenBSD: nvme.c,v 1.49 2016/04/18 05:59:50 dlg Exp $ */
 
 /*
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.16 2016/10/18 07:48:05 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvme.c,v 1.17 2016/10/19 19:31:23 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1420,19 +1420,38 @@
 nvme_intr(void *xsc)
 {
        struct nvme_softc *sc = xsc;
-       int rv = 0;
 
        /*
         * INTx is level triggered, controller deasserts the interrupt only
         * when we advance command queue head via write to the doorbell.
+        * Tell the controller to block the interrupts while we process
+        * the queue(s).
         */
-       if (nvme_q_complete(sc, sc->sc_admin_q))
-               rv = 1;
+       nvme_write4(sc, NVME_INTMS, 1);
+
+       softint_schedule(sc->sc_softih[0]);
+
+       /* don't know, might not have been for us */
+       return 1;
+}
+
+void
+nvme_softintr_intx(void *xq)
+{
+       struct nvme_queue *q = xq;
+       struct nvme_softc *sc = q->q_sc;
+
+       nvme_q_complete(sc, sc->sc_admin_q);
        if (sc->sc_q != NULL)
-               if (nvme_q_complete(sc, sc->sc_q[0]))
-                       rv = 1;
+               nvme_q_complete(sc, sc->sc_q[0]);
 
-       return rv;
+       /*
+        * Processing done, tell controller to issue interrupts again. There
+        * is no race, as NVMe spec requires the controller to maintain state,
+        * and assert the interrupt whenever there are unacknowledged
+        * completion queue entries.
+        */
+       nvme_write4(sc, NVME_INTMC, 1);
 }
 
 int
@@ -1443,7 +1462,10 @@
        KASSERT(q && q->q_sc && q->q_sc->sc_softih
            && q->q_sc->sc_softih[q->q_id]);
 
-       /* MSI are edge triggered, so can handover processing to softint */
+       /*
+        * MSI/MSI-X are edge triggered, so can handover processing to softint
+        * without masking the interrupt.
+        */
        softint_schedule(q->q_sc->sc_softih[q->q_id]);
 
        return 1;
diff -r cec5092c9e09 -r b55f63619e94 sys/dev/ic/nvmevar.h
--- a/sys/dev/ic/nvmevar.h      Wed Oct 19 19:10:33 2016 +0000
+++ b/sys/dev/ic/nvmevar.h      Wed Oct 19 19:31:23 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmevar.h,v 1.6 2016/09/27 03:33:32 pgoyette Exp $     */
+/*     $NetBSD: nvmevar.h,v 1.7 2016/10/19 19:31:23 jdolecek Exp $     */
 /*     $OpenBSD: nvmevar.h,v 1.8 2016/04/14 11:18:32 dlg Exp $ */
 
 /*
@@ -151,6 +151,7 @@
 int    nvme_rescan(device_t, const char *, const int *);
 void   nvme_childdet(device_t, device_t);
 int    nvme_intr(void *);
+void   nvme_softintr_intx(void *);
 int    nvme_intr_msi(void *);
 void   nvme_softintr_msi(void *);
 
diff -r cec5092c9e09 -r b55f63619e94 sys/dev/pci/nvme_pci.c
--- a/sys/dev/pci/nvme_pci.c    Wed Oct 19 19:10:33 2016 +0000
+++ b/sys/dev/pci/nvme_pci.c    Wed Oct 19 19:31:23 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvme_pci.c,v 1.15 2016/09/27 03:33:32 pgoyette Exp $   */
+/*     $NetBSD: nvme_pci.c,v 1.16 2016/10/19 19:31:23 jdolecek Exp $   */
 /*     $OpenBSD: nvme_pci.c,v 1.3 2016/04/14 11:18:32 dlg Exp $ */
 
 /*
@@ -43,7 +43,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvme_pci.c,v 1.15 2016/09/27 03:33:32 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvme_pci.c,v 1.16 2016/10/19 19:31:23 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -193,14 +193,12 @@
                goto intr_release;
        }
 
-       if (sc->sc_use_mq) {
-               sc->sc_softih = kmem_zalloc(
-                   sizeof(*sc->sc_softih) * psc->psc_nintrs, KM_SLEEP);
-               if (sc->sc_softih == NULL) {
-                       aprint_error_dev(self,
-                           "unable to allocate softih memory\n");
-                       goto intr_free;
-               }
+       sc->sc_softih = kmem_zalloc(
+           sizeof(*sc->sc_softih) * psc->psc_nintrs, KM_SLEEP);
+       if (sc->sc_softih == NULL) {
+               aprint_error_dev(self,
+                   "unable to allocate softih memory\n");
+               goto intr_free;
        }
 
        if (nvme_attach(sc) != 0) {
@@ -215,10 +213,7 @@
        return;
 
 softintr_free:
-       if (sc->sc_softih) {
-               kmem_free(sc->sc_softih,
-                   sizeof(*sc->sc_softih) * psc->psc_nintrs);
-       }
+       kmem_free(sc->sc_softih, sizeof(*sc->sc_softih) * psc->psc_nintrs);
 intr_free:
        kmem_free(sc->sc_ih, sizeof(*sc->sc_ih) * psc->psc_nintrs);
        sc->sc_nq = 0;
@@ -251,11 +246,9 @@
        if (error)
                return error;
 
-       if (sc->sc_softih) {
-               kmem_free(sc->sc_softih,
-                   sizeof(*sc->sc_softih) * psc->psc_nintrs);
-               sc->sc_softih = NULL;
-       }
+       kmem_free(sc->sc_softih, sizeof(*sc->sc_softih) * psc->psc_nintrs);
+       sc->sc_softih = NULL;
+
        kmem_free(sc->sc_ih, sizeof(*sc->sc_ih) * psc->psc_nintrs);
        pci_intr_release(psc->psc_pc, psc->psc_intrs, psc->psc_nintrs);
        bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
@@ -271,6 +264,7 @@
        char intrbuf[PCI_INTRSTR_LEN];
        const char *intrstr = NULL;
        int (*ih_func)(void *);
+       void (*ih_func_soft)(void *);
        void *ih_arg;
 #ifdef __HAVE_PCI_MSI_MSIX
        int error;
@@ -291,6 +285,7 @@
                    device_xname(sc->sc_dev));
                ih_arg = sc;
                ih_func = nvme_intr;
+               ih_func_soft = nvme_softintr_intx;
 #ifdef __HAVE_PCI_MSI_MSIX
        }
        else {
@@ -303,6 +298,7 @@
                }
                ih_arg = q;
                ih_func = nvme_intr_msi;
+               ih_func_soft = nvme_softintr_msi;
        }
 #endif /* __HAVE_PCI_MSI_MSIX */
 
@@ -315,22 +311,20 @@
                return 1;
        }
 
-       /* if MSI, establish also the software interrupt */
-       if (sc->sc_softih) {
-               sc->sc_softih[qid] = softint_establish(
-                   SOFTINT_BIO|(nvme_pci_mpsafe ? SOFTINT_MPSAFE : 0),
-                   nvme_softintr_msi, q);
-               if (sc->sc_softih[qid] == NULL) {
-                       pci_intr_disestablish(psc->psc_pc, sc->sc_ih[qid]);
-                       sc->sc_ih[qid] = NULL;
-       
-                       aprint_error_dev(sc->sc_dev,
-                           "unable to establish %s soft interrupt\n",
-                           intr_xname);
-                       return 1;
-               }
+       /* establish also the software interrupt */
+       sc->sc_softih[qid] = softint_establish(
+           SOFTINT_BIO|(nvme_pci_mpsafe ? SOFTINT_MPSAFE : 0),
+           ih_func_soft, q);
+       if (sc->sc_softih[qid] == NULL) {
+               pci_intr_disestablish(psc->psc_pc, sc->sc_ih[qid]);
+               sc->sc_ih[qid] = NULL;
+
+               aprint_error_dev(sc->sc_dev,
+                   "unable to establish %s soft interrupt\n",
+                   intr_xname);
+               return 1;
        }
-       
+
        intrstr = pci_intr_string(psc->psc_pc, psc->psc_intrs[qid], intrbuf,
            sizeof(intrbuf));
        if (!sc->sc_use_mq) {



Home | Main Index | Thread Index | Old Index