Port-RISCV archive

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

Re: VisionFive 2 hangs at boot with NVMe



Hi folks,

diff -u a/sys/dev/ic/nvme.c b/sys/dev/ic/nvme.c
--- a/sys/dev/ic/nvme.c
+++ b/sys/dev/ic/nvme.c
@@ -2025,6 +2025,29 @@
 	kmem_free(q, sizeof(*q));
 }
 
+static bool
+nvme_q_pending(struct nvme_softc *sc, struct nvme_queue *q)
+{
+	struct nvme_cqe *ring = NVME_DMA_KVA(q->q_cq_dmamem);
+	uint16_t flags;
+
+	mutex_enter(&q->q_cq_mtx);
+	nvme_dmamem_sync(sc, q->q_cq_dmamem, BUS_DMASYNC_POSTREAD);
+	flags = lemtoh16(&ring[q->q_cq_head].flags);
+	nvme_dmamem_sync(sc, q->q_cq_dmamem, BUS_DMASYNC_PREREAD);
+	mutex_exit(&q->q_cq_mtx);
+
+	return (flags & NVME_CQE_PHASE) == q->q_cq_phase;
+}
+
+bool
+nvme_intx_pending(struct nvme_softc *sc)
+{
+
+	return nvme_q_pending(sc, sc->sc_admin_q) ||
+	    (sc->sc_q != NULL && nvme_q_pending(sc, sc->sc_q[0]));
+}
+
 int
 nvme_intr(void *xsc)
 {
@@ -2058,13 +2081,12 @@
 	if (sc->sc_q != NULL)
 	        nvme_q_complete(sc, sc->sc_q[0]);
 
-	/*
-	 * 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.
-	 */
+	/* Processing done, tell controller to issue interrupts again. */
 	nvme_write4(sc, NVME_INTMC, 1);
+
+	/* Some controllers do not reassert for entries posted while masked. */
+	if (nvme_intx_pending(sc))
+		softint_schedule(sc->sc_softih[0]);
 }
 
 int
diff -u a/sys/dev/ic/nvmevar.h b/sys/dev/ic/nvmevar.h
--- a/sys/dev/ic/nvmevar.h
+++ b/sys/dev/ic/nvmevar.h
@@ -193,6 +193,7 @@
 int	nvme_resume(struct nvme_softc *);
 int	nvme_intr(void *);
 void	nvme_softintr_intx(void *);
+bool	nvme_intx_pending(struct nvme_softc *);
 int	nvme_intr_msi(void *);
 void	nvme_softintr_msi(void *);
 
diff -u a/sys/dev/pci/nvme_pci.c b/sys/dev/pci/nvme_pci.c
--- a/sys/dev/pci/nvme_pci.c
+++ b/sys/dev/pci/nvme_pci.c
@@ -74,6 +74,7 @@
 	struct nvme_softc	psc_nvme;
 
 	pci_chipset_tag_t	psc_pc;
+	pcitag_t		psc_tag;
 	pci_intr_handle_t	*psc_intrs;
 	int			psc_nintrs;
 };
@@ -157,6 +158,7 @@
 
 	sc->sc_dev = self;
 	psc->psc_pc = pa->pa_pc;
+	psc->psc_tag = pa->pa_tag;
 	if (pci_dma64_available(pa))
 		sc->sc_dmat = pa->pa_dmat64;
 	else
@@ -309,6 +311,46 @@
 	return 0;
 }
 
+static void
+nvme_pci_intx_disable(struct nvme_pci_softc *psc, bool disable)
+{
+	pcireg_t command;
+
+	/* Write only the Command half to keep W1C Status bits intact. */
+	command = pci_conf_read(psc->psc_pc, psc->psc_tag,
+	    PCI_COMMAND_STATUS_REG) & PCI_COMMAND_MASK;
+	if (disable)
+		command |= PCI_COMMAND_INTERRUPT_DISABLE;
+	else
+		command &= ~PCI_COMMAND_INTERRUPT_DISABLE;
+	pci_conf_write(psc->psc_pc, psc->psc_tag, PCI_COMMAND_STATUS_REG,
+	    command);
+	(void)pci_conf_read(psc->psc_pc, psc->psc_tag, PCI_COMMAND_STATUS_REG);
+}
+
+static int
+nvme_pci_intr_intx(void *arg)
+{
+	struct nvme_softc *sc = arg;
+
+	/* Some controllers keep INTx asserted after INTMS is set. */
+	nvme_pci_intx_disable((struct nvme_pci_softc *)sc, true);
+	return nvme_intr(sc);
+}
+
+static void
+nvme_pci_softintr_intx(void *arg)
+{
+	struct nvme_queue *q = arg;
+	struct nvme_softc *sc = q->q_sc;
+
+	nvme_softintr_intx(q);
+	nvme_pci_intx_disable((struct nvme_pci_softc *)sc, false);
+
+	if (nvme_intx_pending(sc))
+		softint_schedule(sc->sc_softih[0]);
+}
+
 static int
 nvme_pci_intr_establish(struct nvme_softc *sc, uint16_t qid,
     struct nvme_queue *q)
@@ -336,6 +378,11 @@
 		ih_arg = sc;
 		ih_func = nvme_intr;
 		ih_func_soft = nvme_softintr_intx;
+		if (pci_intr_type(psc->psc_pc, psc->psc_intrs[0]) ==
+		    PCI_INTR_TYPE_INTX) {
+			ih_func = nvme_pci_intr_intx;
+			ih_func_soft = nvme_pci_softintr_intx;
+		}
 	} else {
 		if (qid == NVME_ADMIN_Q) {
 			snprintf(intr_xname, sizeof(intr_xname), "%s adminq",


Could you please try this and ping me back ?

Cheers/Esenlikler,
berte
>En Taro Adun<

On Saturday, October 17th, 2026 at 9:32 PM, Robert Swindells <rjs%fdy2.co.uk@localhost> wrote:

> 
> Benny Siegert <bsiegert%netbsd.org@localhost> wrote:
> > On Sat, 17 Oct 2026, Martin Husemann wrote:
> >
> >> On Sat, Oct 17, 2026 at 04:53:38PM +0000, Benny Siegert wrote:
> >>> The one that does not work is an NVMe 1.4.
> >>
> >> Same here, I tried two different ones but both are 1.4.
> >
> > Oddly enough, it looks like it's not specific to RISC-V!
> 
> Have you tried the 1.4 one with x86_64.
> 
> > When I put the NVMe 1.4 SSD into an Orange Pi 5 (so aarch64), I can also
> > reproduce the crash -- when initializing the SSD, nothing happens for 16
> > seconds, then a heartbeat panic. Unfortunately, the keyboard does not work
> > in ddb.
> >
> > This same machine is otherwise running in production with the NVMe 1.1
> > SSD.
> 
> The RK3588 has a fairly complicated setup process to use MSI interrupts,
> you need to go back to set some device registers after you know which
> interrupt number has been chosen.
> 
> Someone could check what UEFI is doing on an RK3588 but it is a
> different software stack below NetBSD to that on the VisionFive 2.
> 
> I am running my native RK3588 pcie driver with MSI&MSI-X disabled for
> now, it does work with a 1.4 ssd though.
>


Home | Main Index | Thread Index | Old Index