summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2021-08-31 04:21:05 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2021-08-31 04:21:05 +0000
commite55fd2619aaba6001aa4e0a47efe9839eccb9b41 (patch)
tree390b9b7c49e3f4f32cff2d0274f9b51514b1a536 /sys/dev
parentae6ab869fb0996ddda5362912882260544733cbb (diff)
sprinkle barriers and dmamem_syncs around the hibernate io path.
at the very least it stops the compiler omgoptimising away important code. tested by and ok deraadt@ jmatthew@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/nvme.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/sys/dev/ic/nvme.c b/sys/dev/ic/nvme.c
index 68318ba1364..4240971f8e0 100644
--- a/sys/dev/ic/nvme.c
+++ b/sys/dev/ic/nvme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nvme.c,v 1.102 2021/08/29 11:23:29 kettenis Exp $ */
+/* $OpenBSD: nvme.c,v 1.103 2021/08/31 04:21:04 dlg Exp $ */
/*
* Copyright (c) 2014 David Gwynne <dlg@openbsd.org>
@@ -1551,6 +1551,7 @@ nvme_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size,
u_int64_t data_bus_phys, page_bus_phys;
u_int16_t flags;
int i;
+ int error;
if (op == HIB_INIT) {
struct device *disk;
@@ -1652,28 +1653,44 @@ nvme_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size,
nvme_write4(my->sc, NVME_SQTDBL(NVME_HIB_Q, my->sc->sc_dstrd),
my->sq_tail);
+ nvme_barrier(my->sc, NVME_SQTDBL(NVME_HIB_Q, my->sc->sc_dstrd), 4,
+ BUS_SPACE_BARRIER_WRITE);
+
+ error = 0;
icqe = NVME_DMA_KVA(my->sc->sc_hib_q->q_cq_dmamem);
icqe += my->cq_head;
+
+ nvme_dmamem_sync(my->sc, my->sc->sc_hib_q->q_cq_dmamem,
+ BUS_DMASYNC_POSTREAD);
for (;;) {
flags = lemtoh16(&icqe->flags);
- if ((flags & NVME_CQE_PHASE) == my->cqe_phase)
+ if ((flags & NVME_CQE_PHASE) == my->cqe_phase) {
+ if ((NVME_CQE_SC(flags) != NVME_CQE_SC_SUCCESS) ||
+ (icqe->cid != blkno % 0xffff))
+ error = EIO;
+
break;
+ }
- delay(10);
+ delay(1);
+ nvme_dmamem_sync(my->sc, my->sc->sc_hib_q->q_cq_dmamem,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_POSTREAD);
}
+ nvme_dmamem_sync(my->sc, my->sc->sc_hib_q->q_cq_dmamem,
+ BUS_DMASYNC_PREREAD);
if (++my->cq_head == my->sc->sc_hib_q->q_entries) {
my->cq_head = 0;
my->cqe_phase ^= NVME_CQE_PHASE;
}
+
nvme_write4(my->sc, NVME_CQHDBL(NVME_HIB_Q, my->sc->sc_dstrd),
my->cq_head);
- if ((NVME_CQE_SC(flags) != NVME_CQE_SC_SUCCESS) ||
- (icqe->cid != blkno % 0xffff))
- return (EIO);
+ nvme_barrier(my->sc, NVME_CQHDBL(NVME_HIB_Q, my->sc->sc_dstrd), 4,
+ BUS_SPACE_BARRIER_WRITE);
- return (0);
+ return (error);
}
#endif