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