diff options
-rw-r--r-- | sys/dev/pv/vioscsi.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/sys/dev/pv/vioscsi.c b/sys/dev/pv/vioscsi.c index cb41a862413..1b8daab6502 100644 --- a/sys/dev/pv/vioscsi.c +++ b/sys/dev/pv/vioscsi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vioscsi.c,v 1.6 2017/05/14 12:17:47 krw Exp $ */ +/* $OpenBSD: vioscsi.c,v 1.7 2017/05/15 19:02:16 sf Exp $ */ /* * Copyright (c) 2013 Google Inc. * @@ -40,6 +40,12 @@ enum { vioscsi_debug = 0 }; } while (0) +#define MAX_XFER MAX(MAXPHYS,MAXBSIZE) +/* Number of DMA segments for buffers that the device must support */ +#define SEG_MAX (MAX_XFER/PAGE_SIZE + 1) +/* In the virtqueue, we need space for header and footer, too */ +#define ALLOC_SEGS (SEG_MAX + 2) + enum vioscsi_req_state { FREE, ALLOC, INQUEUE, DONE }; struct vioscsi_req { @@ -60,8 +66,6 @@ struct vioscsi_softc { struct virtqueue sc_vqs[3]; struct vioscsi_req *sc_reqs; bus_dma_segment_t sc_reqs_segs[1]; - - u_int32_t sc_seg_max; }; int vioscsi_match(struct device *, void *, void *); @@ -137,11 +141,14 @@ vioscsi_attach(struct device *parent, struct device *self, void *aux) uint16_t max_target = virtio_read_device_config_2(vsc, VIRTIO_SCSI_CONFIG_MAX_TARGET); - sc->sc_seg_max = seg_max; + if (seg_max < SEG_MAX) { + printf("\nMax number of segments %d too small\n", seg_max); + goto err; + } for (i = 0; i < nitems(sc->sc_vqs); i++) { - rv = virtio_alloc_vq(vsc, &sc->sc_vqs[i], i, MAXPHYS, - 1 + howmany(MAXPHYS, NBPG), vioscsi_vq_names[i]); + rv = virtio_alloc_vq(vsc, &sc->sc_vqs[i], i, MAX_XFER, + ALLOC_SEGS, vioscsi_vq_names[i]); if (rv) { printf(": failed to allocate virtqueue %d\n", i); return; @@ -167,6 +174,11 @@ vioscsi_attach(struct device *parent, struct device *self, void *aux) saa.saa_sc_link = &sc->sc_link; sc->sc_scsibus = (struct scsibus *)config_found(self, &saa, scsiprint); + return; + +err: + vsc->sc_child = VIRTIO_CHILD_ERROR; + return; } void @@ -442,8 +454,8 @@ vioscsi_alloc_reqs(struct vioscsi_softc *sc, struct virtio_softc *vsc, printf("bus_dmamap_create vr_control failed, error %d\n", r); return 1; } - r = bus_dmamap_create(vsc->sc_dmat, MAXPHYS, sc->sc_seg_max, - MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_data); + r = bus_dmamap_create(vsc->sc_dmat, MAX_XFER, SEG_MAX, + MAX_XFER, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_data); if (r != 0) { printf("bus_dmamap_create vr_data failed, error %d\n", r ); return 1; |