Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci - Print the negotiated feature bits



details:   https://anonhg.NetBSD.org/src/rev/eff1dbd1abd0
branches:  trunk
changeset: 811382:eff1dbd1abd0
user:      christos <christos%NetBSD.org@localhost>
date:      Tue Oct 27 16:03:04 2015 +0000

description:
- Print the negotiated feature bits
- Define a constant for the minimum number of segments and use that.
- Remove unused sc_lock
- Use single variables instead of arrays of 1 element
- To the transfer size and segment size negotiation more correctly
- Make vr_bp NULL when unused.
- Add missing abort calls

diffstat:

 sys/dev/pci/ld_virtio.c |  131 +++++++++++++++++++++++++++++++++--------------
 1 files changed, 92 insertions(+), 39 deletions(-)

diffs (292 lines):

diff -r 2ef36b2340ca -r eff1dbd1abd0 sys/dev/pci/ld_virtio.c
--- a/sys/dev/pci/ld_virtio.c   Tue Oct 27 15:56:21 2015 +0000
+++ b/sys/dev/pci/ld_virtio.c   Tue Oct 27 16:03:04 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ld_virtio.c,v 1.8 2015/05/05 10:56:13 ozaki-r Exp $    */
+/*     $NetBSD: ld_virtio.c,v 1.9 2015/10/27 16:03:04 christos Exp $   */
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.8 2015/05/05 10:56:13 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.9 2015/10/27 16:03:04 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -67,6 +67,23 @@
 #define VIRTIO_BLK_F_SCSI      (1<<7)
 #define VIRTIO_BLK_F_FLUSH     (1<<9)
 
+/*      
+ * 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 \
+       "\x0a""FLUSH" \
+       "\x08""SCSI" \
+       "\x07""BLK_SIZE" \
+       "\x06""RO" \
+       "\x05""GEOMETRY" \
+       "\x03""SEG_MAX" \
+       "\x02""SIZE_MAX" \
+       "\x01""BARRIER"
+
 /* Command */
 #define VIRTIO_BLK_T_IN                0
 #define VIRTIO_BLK_T_OUT       1
@@ -101,12 +118,10 @@
        device_t                sc_dev;
 
        struct virtio_softc     *sc_virtio;
-       struct virtqueue        sc_vq[1];
+       struct virtqueue        sc_vq;
 
        struct virtio_blk_req   *sc_reqs;
-       bus_dma_segment_t       sc_reqs_segs[1];
-
-       kmutex_t                sc_lock;
+       bus_dma_segment_t       sc_reqs_seg;
 
        int                     sc_readonly;
 };
@@ -142,7 +157,7 @@
 
        allocsize = sizeof(struct virtio_blk_req) * qsize;
        r = bus_dmamem_alloc(sc->sc_virtio->sc_dmat, allocsize, 0, 0,
-                            &sc->sc_reqs_segs[0], 1, &rsegs, BUS_DMA_NOWAIT);
+                            &sc->sc_reqs_seg, 1, &rsegs, BUS_DMA_NOWAIT);
        if (r != 0) {
                aprint_error_dev(sc->sc_dev,
                                 "DMA memory allocation failed, size %d, "
@@ -150,7 +165,7 @@
                goto err_none;
        }
        r = bus_dmamem_map(sc->sc_virtio->sc_dmat,
-                          &sc->sc_reqs_segs[0], 1, allocsize,
+                          &sc->sc_reqs_seg, 1, allocsize,
                           &vaddr, BUS_DMA_NOWAIT);
        if (r != 0) {
                aprint_error_dev(sc->sc_dev,
@@ -187,7 +202,8 @@
                }
                r = bus_dmamap_create(sc->sc_virtio->sc_dmat,
                                      ld->sc_maxxfer,
-                                     (ld->sc_maxxfer / NBPG) + 2,
+                                     (ld->sc_maxxfer / NBPG) +
+                                     VIRTIO_BLK_MIN_SEGMENTS,
                                      ld->sc_maxxfer,
                                      0,
                                      BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
@@ -217,7 +233,7 @@
        }
        bus_dmamem_unmap(sc->sc_virtio->sc_dmat, sc->sc_reqs, allocsize);
 err_dmamem_alloc:
-       bus_dmamem_free(sc->sc_virtio->sc_dmat, &sc->sc_reqs_segs[0], 1);
+       bus_dmamem_free(sc->sc_virtio->sc_dmat, &sc->sc_reqs_seg, 1);
 err_none:
        return -1;
 }
@@ -229,7 +245,8 @@
        struct ld_softc *ld = &sc->sc_ld;
        struct virtio_softc *vsc = device_private(parent);
        uint32_t features;
-       int qsize, maxxfersize;
+       char buf[256];
+       int qsize, maxxfersize, maxnsegs;
 
        if (vsc->sc_child != NULL) {
                aprint_normal(": child already attached for %s; "
@@ -237,15 +254,13 @@
                              device_xname(parent));
                return;
        }
-       aprint_normal("\n");
-       aprint_naive("\n");
 
        sc->sc_dev = self;
        sc->sc_virtio = vsc;
 
        vsc->sc_child = self;
        vsc->sc_ipl = IPL_BIO;
-       vsc->sc_vqs = &sc->sc_vq[0];
+       vsc->sc_vqs = &sc->sc_vq;
        vsc->sc_nvqs = 1;
        vsc->sc_config_change = NULL;
        vsc->sc_intrhand = virtio_vq_intr;
@@ -262,29 +277,57 @@
        else
                sc->sc_readonly = 0;
 
-       ld->sc_secsize = 512;
+       snprintb(buf, sizeof(buf), VIRTIO_BLK_FLAG_BITS, features);
+       aprint_normal(": Features: %s\n", buf);
+       aprint_naive("\n");
        if (features & VIRTIO_BLK_F_BLK_SIZE) {
                ld->sc_secsize = virtio_read_device_config_4(vsc,
                                        VIRTIO_BLK_CONFIG_BLK_SIZE);
-       }
-       maxxfersize = MAXPHYS;
-#if 0  /* At least genfs_io assumes maxxfer == MAXPHYS. */
-       if (features & VIRTIO_BLK_F_SEG_MAX) {
+       } else
+               ld->sc_secsize = 512;
+
+       /* At least genfs_io assumes maxxfer == MAXPHYS. */
+       if (features & VIRTIO_BLK_F_SIZE_MAX) {
                maxxfersize = virtio_read_device_config_4(vsc,
-                                       VIRTIO_BLK_CONFIG_SEG_MAX)
-                               * ld->sc_secsize;
-               if (maxxfersize > MAXPHYS)
+                   VIRTIO_BLK_CONFIG_SIZE_MAX);
+               if (maxxfersize < MAXPHYS) {
+                       aprint_error_dev(sc->sc_dev,
+                           "Too small SIZE_MAX %dK minimum is %dK\n",
+                           maxxfersize / 1024, MAXPHYS / 1024);
+                       // goto err;
+                       maxxfersize = MAXPHYS;
+               } else if (maxxfersize > MAXPHYS) {
+                       aprint_normal_dev(sc->sc_dev,
+                           "Clip SEG_MAX from %dK to %dK\n",
+                           maxxfersize / 1024,
+                           MAXPHYS / 1024);
                        maxxfersize = MAXPHYS;
-       }
-#endif
+               }
+       } else
+               maxxfersize = MAXPHYS;
 
-       if (virtio_alloc_vq(vsc, &sc->sc_vq[0], 0,
-                           maxxfersize, maxxfersize / NBPG + 2,
-                           "I/O request") != 0) {
+       if (features & VIRTIO_BLK_F_SEG_MAX) {
+               maxnsegs = virtio_read_device_config_4(vsc,
+                   VIRTIO_BLK_CONFIG_SEG_MAX);
+               if (maxnsegs < VIRTIO_BLK_MIN_SEGMENTS) {
+                       aprint_error_dev(sc->sc_dev,
+                           "Too small SEG_MAX %d minimum is %d\n",
+                           maxnsegs, VIRTIO_BLK_MIN_SEGMENTS);
+                       maxnsegs = maxxfersize / NBPG;
+                       // goto err;
+               }
+       } else
+               maxnsegs = maxxfersize / NBPG;
+
+       /* 2 for the minimum size */
+       maxnsegs += VIRTIO_BLK_MIN_SEGMENTS;
+
+       if (virtio_alloc_vq(vsc, &sc->sc_vq, 0, maxxfersize, maxnsegs,
+           "I/O request") != 0) {
                goto err;
        }
-       qsize = sc->sc_vq[0].vq_num;
-       sc->sc_vq[0].vq_done = ld_virtio_vq_done;
+       qsize = sc->sc_vq.vq_num;
+       sc->sc_vq.vq_done = ld_virtio_vq_done;
 
        ld->sc_dv = self;
        ld->sc_secperunit = virtio_read_device_config_8(vsc,
@@ -303,8 +346,6 @@
        if (ld_virtio_alloc_reqs(sc, qsize) < 0)
                goto err;
 
-       mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
-
        ld->sc_dump = ld_virtio_dump;
        ld->sc_flush = NULL;
        ld->sc_start = ld_virtio_start;
@@ -325,7 +366,7 @@
        /* splbio */
        struct ld_virtio_softc *sc = device_private(ld->sc_dv);
        struct virtio_softc *vsc = sc->sc_virtio;
-       struct virtqueue *vq = &sc->sc_vq[0];
+       struct virtqueue *vq = &sc->sc_vq;
        struct virtio_blk_req *vr;
        int r;
        int isread = (bp->b_flags & B_READ);
@@ -337,16 +378,25 @@
        r = virtio_enqueue_prep(vsc, vq, &slot);
        if (r != 0)
                return r;
+
        vr = &sc->sc_reqs[slot];
+       KASSERT(vr->vr_bp == NULL);
+
        r = bus_dmamap_load(vsc->sc_dmat, vr->vr_payload,
                            bp->b_data, bp->b_bcount, NULL,
                            ((isread?BUS_DMA_READ:BUS_DMA_WRITE)
                             |BUS_DMA_NOWAIT));
-       if (r != 0)
+       if (r != 0) {
+               aprint_error_dev(sc->sc_dev,
+                   "payload dmamap failed, error code %d\n", r);
+               virtio_enqueue_abort(vsc, vq, slot);
                return r;
+       }
 
-       r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 2);
+       r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs +
+           VIRTIO_BLK_MIN_SEGMENTS);
        if (r != 0) {
+               virtio_enqueue_abort(vsc, vq, slot);
                bus_dmamap_unload(vsc->sc_dmat, vr->vr_payload);
                return r;
        }
@@ -387,6 +437,8 @@
        struct virtio_blk_req *vr = &sc->sc_reqs[slot];
        struct buf *bp = vr->vr_bp;
 
+       vr->vr_bp = NULL;
+
        bus_dmamap_sync(vsc->sc_dmat, vr->vr_cmdsts,
                        0, sizeof(struct virtio_blk_req_hdr),
                        BUS_DMASYNC_POSTWRITE);
@@ -433,7 +485,7 @@
 {
        struct ld_virtio_softc *sc = device_private(ld->sc_dv);
        struct virtio_softc *vsc = sc->sc_virtio;
-       struct virtqueue *vq = &sc->sc_vq[0];
+       struct virtqueue *vq = &sc->sc_vq;
        struct virtio_blk_req *vr;
        int slot, r;
 
@@ -458,7 +510,8 @@
        if (r != 0)
                return r;
 
-       r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 2);
+       r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 
+           VIRTIO_BLK_MIN_SEGMENTS);
        if (r != 0) {
                bus_dmamap_unload(vsc->sc_dmat, vr->vr_payload);
                return r;
@@ -530,12 +583,12 @@
        bus_dma_tag_t dmat = sc->sc_virtio->sc_dmat;
        int r, i, qsize;
 
-       qsize = sc->sc_vq[0].vq_num;
+       qsize = sc->sc_vq.vq_num;
        r = ldbegindetach(ld, flags);
        if (r != 0)
                return r;
        virtio_reset(sc->sc_virtio);
-       virtio_free_vq(sc->sc_virtio, &sc->sc_vq[0]);
+       virtio_free_vq(sc->sc_virtio, &sc->sc_vq);
 
        for (i = 0; i < qsize; i++) {
                bus_dmamap_destroy(dmat,
@@ -545,7 +598,7 @@
        }
        bus_dmamem_unmap(dmat, sc->sc_reqs,
                         sizeof(struct virtio_blk_req) * qsize);
-       bus_dmamem_free(dmat, &sc->sc_reqs_segs[0], 1);
+       bus_dmamem_free(dmat, &sc->sc_reqs_seg, 1);
 
        ldenddetach(ld);
 



Home | Main Index | Thread Index | Old Index