Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci allocate bus dma maps during attachment, rather ...



details:   https://anonhg.NetBSD.org/src/rev/d02197f8abdb
branches:  trunk
changeset: 351962:d02197f8abdb
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Tue Mar 07 22:03:04 2017 +0000

description:
allocate bus dma maps during attachment, rather than creating and destroying
them for each request; besides being faster, bus_dmamap_destroy() is not
safe to be called from interrupt context

adresses PR kern/52034 by Benny Siegert

diffstat:

 sys/dev/pci/vioscsi.c |  110 +++++++++++++++++++++++++++++++------------------
 1 files changed, 70 insertions(+), 40 deletions(-)

diffs (177 lines):

diff -r e9da3d13403d -r d02197f8abdb sys/dev/pci/vioscsi.c
--- a/sys/dev/pci/vioscsi.c     Tue Mar 07 19:10:07 2017 +0000
+++ b/sys/dev/pci/vioscsi.c     Tue Mar 07 22:03:04 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vioscsi.c,v 1.8 2016/10/04 18:23:24 jdolecek Exp $     */
+/*     $NetBSD: vioscsi.c,v 1.9 2017/03/07 22:03:04 jdolecek Exp $     */
 /*     $OpenBSD: vioscsi.c,v 1.3 2015/03/14 03:38:49 jsg Exp $ */
 
 /*
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vioscsi.c,v 1.8 2016/10/04 18:23:24 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vioscsi.c,v 1.9 2017/03/07 22:03:04 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -58,6 +58,7 @@
 
        struct virtqueue         sc_vqs[3];
        struct vioscsi_req      *sc_reqs;
+       int                      sc_nreqs;
        bus_dma_segment_t        sc_reqs_segs[1];
 
        u_int32_t                sc_seg_max;
@@ -470,47 +471,17 @@
 
        if ((r = virtio_enqueue_prep(vsc, vq, &slot)) != 0) {
                DPRINTF(("%s: virtio_enqueue_get error %d\n", __func__, r));
-               goto err1;
+               return NULL;
        }
+       KASSERT(slot < sc->sc_nreqs);
        vr = &sc->sc_reqs[slot];
 
        vr->vr_req.id = slot;
        vr->vr_req.task_attr = VIRTIO_SCSI_S_SIMPLE;
 
-       r = bus_dmamap_create(vsc->sc_dmat,
-           offsetof(struct vioscsi_req, vr_xs), 1,
-           offsetof(struct vioscsi_req, vr_xs), 0,
-           BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_control);
-       if (r != 0) {
-               DPRINTF(("%s: bus_dmamap_create xs error %d\n", __func__, r));
-               goto err2;
-       }
-       r = bus_dmamap_create(vsc->sc_dmat, MAXPHYS, sc->sc_seg_max,
-           MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_data);
-       if (r != 0) {
-               DPRINTF(("%s: bus_dmamap_create data error %d\n", __func__, r));
-               goto err3;
-       }
-       r = bus_dmamap_load(vsc->sc_dmat, vr->vr_control,
-           vr, offsetof(struct vioscsi_req, vr_xs), NULL,
-           BUS_DMA_NOWAIT);
-       if (r != 0) {
-               DPRINTF(("%s: bus_dmamap_create ctrl error %d\n", __func__, r));
-               goto err4;
-       }
-
        DPRINTF(("%s: %p, %d\n", __func__, vr, slot));
 
        return vr;
-
-err4:
-       bus_dmamap_destroy(vsc->sc_dmat, vr->vr_data);
-err3:
-       bus_dmamap_destroy(vsc->sc_dmat, vr->vr_control);
-err2:
-       virtio_enqueue_abort(vsc, vq, slot);
-err1:
-       return NULL;
 }
 
 static void
@@ -522,8 +493,7 @@
 
        DPRINTF(("%s: %p, %d\n", __func__, vr, slot));
 
-       bus_dmamap_destroy(vsc->sc_dmat, vr->vr_control);
-       bus_dmamap_destroy(vsc->sc_dmat, vr->vr_data);
+       bus_dmamap_unload(vsc->sc_dmat, vr->vr_data);
 
        virtio_dequeue_commit(vsc, vq, slot);
 }
@@ -533,8 +503,9 @@
     int qsize, uint32_t seg_max)
 {
        size_t allocsize;
-       int r, rsegs;
+       int r, rsegs, slot;
        void *vaddr;
+       struct vioscsi_req *vr;
 
        allocsize = qsize * sizeof(struct vioscsi_req);
        r = bus_dmamem_alloc(vsc->sc_dmat, allocsize, 0, 0,
@@ -543,7 +514,7 @@
                aprint_error_dev(sc->sc_dev,
                    "%s: bus_dmamem_alloc, size %zu, error %d\n", __func__,
                    allocsize, r);
-               return 1;
+               return r;
        }
        r = bus_dmamem_map(vsc->sc_dmat, &sc->sc_reqs_segs[0], 1,
            allocsize, &vaddr, BUS_DMA_NOWAIT);
@@ -551,9 +522,68 @@
                aprint_error_dev(sc->sc_dev,
                    "%s: bus_dmamem_map failed, error %d\n", __func__, r);
                bus_dmamem_free(vsc->sc_dmat, &sc->sc_reqs_segs[0], 1);
-               return 1;
+               return r;
        }
+       memset(vaddr, 0, allocsize);
+
        sc->sc_reqs = vaddr;
-       memset(vaddr, 0, allocsize);
+       sc->sc_nreqs = qsize;
+
+       /* Prepare maps for the requests */ 
+       for (slot=0; slot < qsize; slot++) {
+               vr = &sc->sc_reqs[slot];
+
+               r = bus_dmamap_create(vsc->sc_dmat,
+                   offsetof(struct vioscsi_req, vr_xs), 1,
+                   offsetof(struct vioscsi_req, vr_xs), 0,
+                   BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_control);
+               if (r != 0) {
+                       aprint_error_dev(sc->sc_dev,
+                           "%s: bus_dmamem_create failed, error %d\n",
+                           __func__, r);
+                       goto cleanup;
+               }
+
+               r = bus_dmamap_create(vsc->sc_dmat, MAXPHYS, sc->sc_seg_max,
+                   MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_data);
+               if (r != 0) {
+                       aprint_error_dev(sc->sc_dev,
+                           "%s: bus_dmamem_map failed, error %d\n",
+                           __func__, r);
+                       goto cleanup;
+               }
+
+               r = bus_dmamap_load(vsc->sc_dmat, vr->vr_control,
+                   vr, offsetof(struct vioscsi_req, vr_xs), NULL,
+                   BUS_DMA_NOWAIT);
+               if (r != 0) {
+                       aprint_error_dev(sc->sc_dev,
+                           "%s: bus_dmamap_create ctrl error %d\n",
+                           __func__, r);
+                       goto cleanup;
+               }
+       }
+
        return 0;
+
+cleanup:
+       for (; slot > 0; slot--) {
+               vr = &sc->sc_reqs[slot];
+
+               if (vr->vr_control) {
+                       /* this will also unload the mapping if loaded */
+                       bus_dmamap_destroy(vsc->sc_dmat, vr->vr_control);
+                       vr->vr_control = NULL;
+               }
+
+               if (vr->vr_data) {
+                       bus_dmamap_destroy(vsc->sc_dmat, vr->vr_data);
+                       vr->vr_data = NULL;
+               }
+       }
+
+       bus_dmamem_unmap(vsc->sc_dmat, vaddr, allocsize);
+       bus_dmamem_free(vsc->sc_dmat, &sc->sc_reqs_segs[0], 1);
+
+       return r;
 }



Home | Main Index | Thread Index | Old Index