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