Source-Changes-HG archive

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

[src/netbsd-8]: src/sys/dev/pci Pull up following revision(s) (requested by j...



details:   https://anonhg.NetBSD.org/src/rev/5b18a8a1118e
branches:  netbsd-8
changeset: 435076:5b18a8a1118e
user:      martin <martin%NetBSD.org@localhost>
date:      Fri Jun 22 10:15:18 2018 +0000

description:
Pull up following revision(s) (requested by jakllsch in ticket #888):

        sys/dev/pci/ld_virtio.c: revision 1.19-1.21,1.23

remove trailing whitespace

add feature/register definitions from virtio-v1.0-cs04

unload payload dma map upon command completion

Make ld_virtio aware of a possible device-side write cache.

The virtio block device capacity config item is expressed always in
request protocol sector units of 512 bytes.

Also, add and use a symbolic constant to refer to request protocol
sector units.

destroy 'sc_sync_wait' condvar and mutex upon detach

diffstat:

 sys/dev/pci/ld_virtio.c |  220 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 202 insertions(+), 18 deletions(-)

diffs (truncated from 394 to 300 lines):

diff -r 30349aaa84d2 -r 5b18a8a1118e sys/dev/pci/ld_virtio.c
--- a/sys/dev/pci/ld_virtio.c   Fri Jun 22 10:08:22 2018 +0000
+++ b/sys/dev/pci/ld_virtio.c   Fri Jun 22 10:15:18 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ld_virtio.c,v 1.15.6.1 2017/09/01 09:59:11 martin Exp $        */
+/*     $NetBSD: ld_virtio.c,v 1.15.6.2 2018/06/22 10:15:18 martin Exp $        */
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.15.6.1 2017/09/01 09:59:11 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.15.6.2 2018/06/22 10:15:18 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -60,6 +60,7 @@
 #define VIRTIO_BLK_CONFIG_GEOMETRY_H   18 /* 8bit */
 #define VIRTIO_BLK_CONFIG_GEOMETRY_S   19 /* 8bit */
 #define VIRTIO_BLK_CONFIG_BLK_SIZE     20 /* 32bit */
+#define VIRTIO_BLK_CONFIG_WRITEBACK    32 /* 8bit */
 
 /* Feature bits */
 #define VIRTIO_BLK_F_BARRIER   (1<<0)
@@ -70,15 +71,19 @@
 #define VIRTIO_BLK_F_BLK_SIZE  (1<<6)
 #define VIRTIO_BLK_F_SCSI      (1<<7)
 #define VIRTIO_BLK_F_FLUSH     (1<<9)
+#define VIRTIO_BLK_F_TOPOLOGY  (1<<10)
+#define VIRTIO_BLK_F_CONFIG_WCE        (1<<11)
 
-/*      
+/*
  * Each block request uses at least two segments - one for the header
  * and one for the status.
-*/     
+*/
 #define        VIRTIO_BLK_MIN_SEGMENTS 2
 
 #define VIRTIO_BLK_FLAG_BITS \
        VIRTIO_COMMON_FLAG_BITS \
+       "\x0c""CONFIG_WCE" \
+       "\x0b""TOPOLOGY" \
        "\x0a""FLUSH" \
        "\x08""SCSI" \
        "\x07""BLK_SIZE" \
@@ -91,11 +96,16 @@
 /* Command */
 #define VIRTIO_BLK_T_IN                0
 #define VIRTIO_BLK_T_OUT       1
+#define VIRTIO_BLK_T_FLUSH     4
 #define VIRTIO_BLK_T_BARRIER   0x80000000
 
+/* Sector */
+#define VIRTIO_BLK_BSIZE       512
+
 /* Status */
 #define VIRTIO_BLK_S_OK                0
 #define VIRTIO_BLK_S_IOERR     1
+#define VIRTIO_BLK_S_UNSUPP    2
 
 /* Request header structure */
 struct virtio_blk_req_hdr {
@@ -103,7 +113,7 @@
        uint32_t        ioprio;
        uint64_t        sector;
 } __packed;
-/* 512*virtio_blk_req_hdr.sector byte payload and 1 byte status follows */
+/* payload and 1 byte status follows */
 
 
 /*
@@ -113,6 +123,7 @@
        struct virtio_blk_req_hdr       vr_hdr;
        uint8_t                         vr_status;
        struct buf                      *vr_bp;
+#define DUMMY_VR_BP                            ((void *)1)
        bus_dmamap_t                    vr_cmdsts;
        bus_dmamap_t                    vr_payload;
 };
@@ -128,6 +139,13 @@
        bus_dma_segment_t       sc_reqs_seg;
 
        int                     sc_readonly;
+
+       enum {
+               SYNC_FREE, SYNC_BUSY, SYNC_DONE
+       }                       sc_sync_use;
+       kcondvar_t              sc_sync_wait;
+       kmutex_t                sc_sync_wait_lock;
+       uint8_t                 sc_sync_status;
 };
 
 static int     ld_virtio_match(device_t, cfdata_t, void *);
@@ -151,6 +169,7 @@
 static int ld_virtio_vq_done(struct virtqueue *);
 static int ld_virtio_dump(struct ld_softc *, void *, int, int);
 static int ld_virtio_start(struct ld_softc *, struct buf *);
+static int ld_virtio_ioctl(struct ld_softc *, u_long, void *, int32_t, bool);
 
 static int
 ld_virtio_alloc_reqs(struct ld_virtio_softc *sc, int qsize)
@@ -263,7 +282,8 @@
        virtio_child_attach_start(vsc, self, IPL_BIO, &sc->sc_vq,
            NULL, virtio_vq_intr, 0,
            (VIRTIO_BLK_F_SIZE_MAX | VIRTIO_BLK_F_SEG_MAX |
-            VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_RO | VIRTIO_BLK_F_BLK_SIZE),
+            VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_RO | VIRTIO_BLK_F_BLK_SIZE |
+            VIRTIO_BLK_F_FLUSH | VIRTIO_BLK_F_CONFIG_WCE),
            VIRTIO_BLK_FLAG_BITS);
 
        features = virtio_features(vsc);
@@ -277,7 +297,7 @@
                ld->sc_secsize = virtio_read_device_config_4(vsc,
                                        VIRTIO_BLK_CONFIG_BLK_SIZE);
        } else
-               ld->sc_secsize = 512;
+               ld->sc_secsize = VIRTIO_BLK_BSIZE;
 
        /* At least genfs_io assumes maxxfer == MAXPHYS. */
        if (features & VIRTIO_BLK_F_SIZE_MAX) {
@@ -327,7 +347,7 @@
 
        ld->sc_dv = self;
        ld->sc_secperunit = virtio_read_device_config_8(vsc,
-                               VIRTIO_BLK_CONFIG_CAPACITY);
+           VIRTIO_BLK_CONFIG_CAPACITY) / (ld->sc_secsize / VIRTIO_BLK_BSIZE);
        ld->sc_maxxfer = maxxfersize;
        if (features & VIRTIO_BLK_F_GEOMETRY) {
                ld->sc_ncylinders = virtio_read_device_config_2(vsc,
@@ -337,13 +357,18 @@
                ld->sc_nsectors   = virtio_read_device_config_1(vsc,
                                        VIRTIO_BLK_CONFIG_GEOMETRY_S);
        }
-       ld->sc_maxqueuecnt = qsize;
+       ld->sc_maxqueuecnt = qsize - 1; /* reserve slot for dumps, flushes */
 
        if (ld_virtio_alloc_reqs(sc, qsize) < 0)
                goto err;
 
+       cv_init(&sc->sc_sync_wait, "vblksync");
+       mutex_init(&sc->sc_sync_wait_lock, MUTEX_DEFAULT, IPL_BIO);
+       sc->sc_sync_use = SYNC_FREE;
+
        ld->sc_dump = ld_virtio_dump;
        ld->sc_start = ld_virtio_start;
+       ld->sc_ioctl = ld_virtio_ioctl;
 
        ld->sc_flags = LDF_ENABLED | LDF_MPSAFE;
        ldattach(ld, BUFQ_DISK_DEFAULT_STRAT);
@@ -398,7 +423,8 @@
        vr->vr_bp = bp;
        vr->vr_hdr.type = isread?VIRTIO_BLK_T_IN:VIRTIO_BLK_T_OUT;
        vr->vr_hdr.ioprio = 0;
-       vr->vr_hdr.sector = bp->b_rawblkno * sc->sc_ld.sc_secsize / 512;
+       vr->vr_hdr.sector = bp->b_rawblkno * sc->sc_ld.sc_secsize /
+           VIRTIO_BLK_BSIZE;
 
        bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
                        0, sizeof(struct virtio_blk_req_hdr),
@@ -436,13 +462,23 @@
        bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
                        0, sizeof(struct virtio_blk_req_hdr),
                        BUS_DMASYNC_POSTWRITE);
+       bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
+                       sizeof(struct virtio_blk_req_hdr), sizeof(uint8_t),
+                       BUS_DMASYNC_POSTREAD);
+       if (bp == DUMMY_VR_BP) {
+               mutex_enter(&sc->sc_sync_wait_lock);
+               sc->sc_sync_status = vr->vr_status;
+               sc->sc_sync_use = SYNC_DONE;
+               cv_signal(&sc->sc_sync_wait);
+               mutex_exit(&sc->sc_sync_wait_lock);
+               virtio_dequeue_commit(vsc, vq, slot);
+               return;
+       }
        bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload,
                        0, bp->b_bcount,
                        (bp->b_flags & B_READ)?BUS_DMASYNC_POSTREAD
                                              :BUS_DMASYNC_POSTWRITE);
-       bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
-                       sizeof(struct virtio_blk_req_hdr), sizeof(uint8_t),
-                       BUS_DMASYNC_POSTREAD);
+       bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload);
 
        if (vr->vr_status != VIRTIO_BLK_S_OK) {
                bp->b_error = EIO;
@@ -504,7 +540,7 @@
        if (r != 0)
                return r;
 
-       r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 
+       r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs +
            VIRTIO_BLK_MIN_SEGMENTS);
        if (r != 0) {
                bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload);
@@ -514,7 +550,8 @@
        vr->vr_bp = (void*)0xdeadbeef;
        vr->vr_hdr.type = VIRTIO_BLK_T_OUT;
        vr->vr_hdr.ioprio = 0;
-       vr->vr_hdr.sector = (daddr_t) blkno * ld->sc_secsize / 512;
+       vr->vr_hdr.sector = (daddr_t) blkno * ld->sc_secsize /
+           VIRTIO_BLK_BSIZE;
 
        bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
                        0, sizeof(struct virtio_blk_req_hdr),
@@ -549,7 +586,7 @@
                } else
                        break;
        }
-               
+
        bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
                        0, sizeof(struct virtio_blk_req_hdr),
                        BUS_DMASYNC_POSTWRITE);
@@ -596,11 +633,158 @@
 
        ldenddetach(ld);
 
+       cv_destroy(&sc->sc_sync_wait);
+       mutex_destroy(&sc->sc_sync_wait_lock);
+
        virtio_child_detach(sc->sc_virtio);
 
        return 0;
 }
 
+static int
+ld_virtio_flush(struct ld_softc *ld, bool poll)
+{
+       struct ld_virtio_softc * const sc = device_private(ld->sc_dv);
+       struct virtio_softc * const vsc = sc->sc_virtio;
+       const uint32_t features = virtio_features(vsc);
+       struct virtqueue *vq = &sc->sc_vq;
+       struct virtio_blk_req *vr;
+       int slot;
+       int r;
+
+       if ((features & VIRTIO_BLK_F_FLUSH) == 0)
+               return 0;
+
+       mutex_enter(&sc->sc_sync_wait_lock);
+       while (sc->sc_sync_use != SYNC_FREE) {
+               if (poll) {
+                       mutex_exit(&sc->sc_sync_wait_lock);
+                       ld_virtio_vq_done(vq);
+                       mutex_enter(&sc->sc_sync_wait_lock);
+                       continue;
+               }
+               cv_wait(&sc->sc_sync_wait, &sc->sc_sync_wait_lock);
+       }
+       sc->sc_sync_use = SYNC_BUSY;
+       mutex_exit(&sc->sc_sync_wait_lock);
+
+       r = virtio_enqueue_prep(vsc, vq, &slot);
+       if (r != 0) {
+               return r;
+       }
+
+       vr = &sc->sc_reqs[slot];
+       KASSERT(vr->vr_bp == NULL);
+
+       r = virtio_enqueue_reserve(vsc, vq, slot, VIRTIO_BLK_MIN_SEGMENTS);
+       if (r != 0) {
+               return r;
+       }
+
+       vr->vr_bp = DUMMY_VR_BP;
+       vr->vr_hdr.type = VIRTIO_BLK_T_FLUSH;
+       vr->vr_hdr.ioprio = 0;
+       vr->vr_hdr.sector = 0;
+
+       bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
+                       0, sizeof(struct virtio_blk_req_hdr),
+                       BUS_DMASYNC_PREWRITE);
+       bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
+                       offsetof(struct virtio_blk_req, vr_status),
+                       sizeof(uint8_t),
+                       BUS_DMASYNC_PREREAD);
+
+       virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts,
+                        0, sizeof(struct virtio_blk_req_hdr),
+                        true);
+       virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts,
+                        offsetof(struct virtio_blk_req, vr_status),
+                        sizeof(uint8_t),
+                        false);
+       virtio_enqueue_commit(vsc, vq, slot, true);
+
+       mutex_enter(&sc->sc_sync_wait_lock);
+       while (sc->sc_sync_use != SYNC_DONE) {
+               if (poll) {
+                       mutex_exit(&sc->sc_sync_wait_lock);
+                       ld_virtio_vq_done(vq);
+                       mutex_enter(&sc->sc_sync_wait_lock);
+                       continue;
+               }
+               cv_wait(&sc->sc_sync_wait, &sc->sc_sync_wait_lock);



Home | Main Index | Thread Index | Old Index