Index: sys/dev/nvme/nvme_private.h =================================================================== --- sys/dev/nvme/nvme_private.h +++ sys/dev/nvme/nvme_private.h @@ -215,6 +215,7 @@ boolean_t is_enabled; struct mtx lock __aligned(CACHE_LINE_SIZE); + struct mtx complete_lock __aligned(CACHE_LINE_SIZE); } __aligned(CACHE_LINE_SIZE); Index: sys/dev/nvme/nvme_qpair.c =================================================================== --- sys/dev/nvme/nvme_qpair.c +++ sys/dev/nvme/nvme_qpair.c @@ -541,6 +541,8 @@ if (!qpair->is_enabled) return (false); + mtx_lock(&qpair->complete_lock); + /* * A panic can stop the CPU this routine is running on at any point. If * we're called during a panic, complete the sq_head wrap protocol for @@ -625,6 +627,7 @@ nvme_mmio_write_4(qpair->ctrlr, doorbell[qpair->id].cq_hdbl, qpair->cq_head); } + mtx_unlock(&qpair->complete_lock); return (done != 0); } @@ -676,6 +679,7 @@ } mtx_init(&qpair->lock, "nvme qpair lock", NULL, MTX_DEF); + mtx_init(&qpair->complete_lock, "nvme qpair process completions lock", NULL, MTX_DEF); /* Note: NVMe PRP format is restricted to 4-byte alignment. */ err = bus_dma_tag_create(bus_get_dma_tag(ctrlr->dev), @@ -796,6 +800,9 @@ if (mtx_initialized(&qpair->lock)) mtx_destroy(&qpair->lock); + if (mtx_initialized(&qpair->complete_lock)) + mtx_destroy(&qpair->complete_lock); + if (qpair->res) bus_release_resource(qpair->ctrlr->dev, SYS_RES_IRQ, rman_get_rid(qpair->res), qpair->res); @@ -890,6 +897,9 @@ uint32_t csts; uint8_t cfs; + /* XXX debugging XXX */ + nvme_printf(ctrlr, "nvme_timeout\n"); + /* * Read csts to get value of cfs - controller fatal status. * If no fatal status, try to call the completion routine, and