Page MenuHomeFreeBSD

D54960.diff
No OneTemporary

D54960.diff

diff --git a/sys/dev/virtio/block/virtio_blk.c b/sys/dev/virtio/block/virtio_blk.c
--- a/sys/dev/virtio/block/virtio_blk.c
+++ b/sys/dev/virtio/block/virtio_blk.c
@@ -59,10 +59,15 @@
struct vtblk_softc *vbr_sc;
bus_dmamap_t vbr_mapp;
+ struct virtio_blk_outhdr *vbr_hdr;
+ vm_paddr_t vbr_hdr_paddr;
+ bus_dmamap_t vbr_hdr_mapp;
+ uint8_t *vbr_ack;
+ vm_paddr_t vbr_ack_paddr;
+ bus_dmamap_t vbr_ack_mapp;
+
/* Fields after this point are zeroed for each request. */
- struct virtio_blk_outhdr vbr_hdr;
struct bio *vbr_bp;
- uint8_t vbr_ack;
uint8_t vbr_requeue_on_error;
uint8_t vbr_busdma_wait;
int vbr_error;
@@ -78,6 +83,8 @@
struct vtblk_softc {
device_t vtblk_dev;
struct mtx vtblk_mtx;
+ struct mtx vtblk_hdr_mtx;
+ struct mtx vtblk_ack_mtx;
uint64_t vtblk_features;
uint32_t vtblk_flags;
#define VTBLK_FLAG_INDIRECT 0x0001
@@ -91,6 +98,8 @@
struct virtqueue *vtblk_vq;
struct sglist *vtblk_sglist;
bus_dma_tag_t vtblk_dmat;
+ bus_dma_tag_t vtblk_hdr_dmat;
+ bus_dma_tag_t vtblk_ack_dmat;
struct disk *vtblk_disk;
struct bio_queue_head vtblk_bioq;
@@ -385,7 +394,7 @@
maxphys, /* max request size */
sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS, /* max # segments */
maxphys, /* maxsegsize */
- 0, /* flags */
+ BUS_DMA_COHERENT, /* flags */
busdma_lock_mutex, /* lockfunc */
&sc->vtblk_mtx, /* lockarg */
&sc->vtblk_dmat);
@@ -394,6 +403,46 @@
goto fail;
}
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(dev), /* parent */
+ (sc->vtblk_flags & VTBLK_FLAG_BUSDMA_ALIGN) ? PAGE_SIZE :
+ sizeof(struct virtio_blk_outhdr), /* alignment */
+ 0, /* boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ sizeof(struct virtio_blk_outhdr), /* max request size */
+ 1, /* max # segments */
+ sizeof(struct virtio_blk_outhdr), /* maxsegsize */
+ BUS_DMA_COHERENT, /* flags */
+ busdma_lock_mutex, /* lockfunc */
+ &sc->vtblk_hdr_mtx, /* lockarg */
+ &sc->vtblk_hdr_dmat);
+ if (error) {
+ device_printf(dev, "cannot create hdr bus dma tag\n");
+ goto fail;
+ }
+
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(dev), /* parent */
+ (sc->vtblk_flags & VTBLK_FLAG_BUSDMA_ALIGN) ? PAGE_SIZE :
+ sizeof(uint8_t), /* alignment */
+ 0, /* boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ sizeof(uint8_t), /* max request size */
+ 1, /* max # segments */
+ sizeof(uint8_t), /* maxsegsize */
+ BUS_DMA_COHERENT, /* flags */
+ busdma_lock_mutex, /* lockfunc */
+ &sc->vtblk_ack_mtx, /* lockarg */
+ &sc->vtblk_ack_dmat);
+ if (error) {
+ device_printf(dev, "cannot create ack bus dma tag\n");
+ goto fail;
+ }
+
#ifdef __powerpc__
/*
* Virtio uses physical addresses rather than bus addresses, so we
@@ -452,6 +501,16 @@
sc->vtblk_disk = NULL;
}
+ if (sc->vtblk_ack_dmat != NULL) {
+ bus_dma_tag_destroy(sc->vtblk_ack_dmat);
+ sc->vtblk_ack_dmat = NULL;
+ }
+
+ if (sc->vtblk_hdr_dmat != NULL) {
+ bus_dma_tag_destroy(sc->vtblk_hdr_dmat);
+ sc->vtblk_hdr_dmat = NULL;
+ }
+
if (sc->vtblk_dmat != NULL) {
bus_dma_tag_destroy(sc->vtblk_dmat);
sc->vtblk_dmat = NULL;
@@ -839,6 +898,36 @@
disk_create(dp, DISK_VERSION);
}
+static void
+vtblk_ack_load_callback(void *arg, bus_dma_segment_t *segs, int nsegs,
+ int error)
+{
+ struct vtblk_request *req;
+
+ if (error != 0)
+ return;
+
+ KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
+
+ req = (struct vtblk_request *)arg;
+ req->vbr_ack_paddr = segs[0].ds_addr;
+}
+
+static void
+vtblk_hdr_load_callback(void *arg, bus_dma_segment_t *segs, int nsegs,
+ int error)
+{
+ struct vtblk_request *req;
+
+ if (error != 0)
+ return;
+
+ KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
+
+ req = (struct vtblk_request *)arg;
+ req->vbr_hdr_paddr = segs[0].ds_addr;
+}
+
static int
vtblk_request_prealloc(struct vtblk_softc *sc)
{
@@ -861,13 +950,42 @@
return (ENOMEM);
req->vbr_sc = sc;
+
if (bus_dmamap_create(sc->vtblk_dmat, 0, &req->vbr_mapp)) {
free(req, M_DEVBUF);
return (ENOMEM);
}
- MPASS(sglist_count(&req->vbr_hdr, sizeof(req->vbr_hdr)) == 1);
- MPASS(sglist_count(&req->vbr_ack, sizeof(req->vbr_ack)) == 1);
+ if (bus_dmamem_alloc(sc->vtblk_hdr_dmat, (void **)&req->vbr_hdr,
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
+ &req->vbr_hdr_mapp)) {
+ panic("bus_dma_alloc vbr_hdr, fail\n");
+ return (ENOMEM);
+ }
+
+ if (bus_dmamem_alloc(sc->vtblk_ack_dmat, (void **)&req->vbr_ack,
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
+ &req->vbr_ack_mapp)) {
+ panic("bus_dma_alloc vbr_ack, fail\n");
+ return (ENOMEM);
+ }
+
+ MPASS(sglist_count(req->vbr_hdr, sizeof(*req->vbr_hdr)) == 1);
+ MPASS(sglist_count(req->vbr_ack, sizeof(*req->vbr_ack)) == 1);
+
+ if (bus_dmamap_load(sc->vtblk_hdr_dmat, req->vbr_hdr_mapp,
+ req->vbr_hdr, sizeof(struct virtio_blk_outhdr),
+ vtblk_hdr_load_callback, req, BUS_DMA_NOWAIT)) {
+ panic("vbr_req_mapp hdr load failed\n");
+ return (ENOMEM);
+ }
+
+ if (bus_dmamap_load(sc->vtblk_ack_dmat, req->vbr_ack_mapp,
+ req->vbr_ack, sizeof(uint8_t), vtblk_ack_load_callback,
+ req, BUS_DMA_NOWAIT)) {
+ panic("vbr_req_mapp ack load failed\n");
+ return (ENOMEM);
+ }
sc->vtblk_request_count++;
vtblk_request_enqueue(sc, req);
@@ -885,8 +1003,13 @@
while ((req = vtblk_request_dequeue(sc)) != NULL) {
sc->vtblk_request_count--;
+ bus_dmamap_unload(sc->vtblk_dmat, req->vbr_ack_mapp);
+ bus_dmamem_free(sc->vtblk_dmat, req->vbr_ack,
+ req->vbr_ack_mapp);
+ bus_dmamap_unload(sc->vtblk_dmat, req->vbr_hdr_mapp);
+ bus_dmamem_free(sc->vtblk_dmat, req->vbr_hdr,
+ req->vbr_hdr_mapp);
bus_dmamap_destroy(sc->vtblk_dmat, req->vbr_mapp);
- free(req, M_DEVBUF);
}
KASSERT(sc->vtblk_request_count == 0,
@@ -901,8 +1024,10 @@
req = TAILQ_FIRST(&sc->vtblk_req_free);
if (req != NULL) {
TAILQ_REMOVE(&sc->vtblk_req_free, req, vbr_link);
- bzero(&req->vbr_hdr, sizeof(struct vtblk_request) -
- offsetof(struct vtblk_request, vbr_hdr));
+ bzero(req->vbr_hdr, sizeof(struct virtio_blk_outhdr));
+ *req->vbr_ack = 0;
+ bzero(&req->vbr_bp, sizeof(struct vtblk_request) -
+ offsetof(struct vtblk_request, vbr_bp));
}
return (req);
@@ -965,32 +1090,35 @@
bp = bioq_takefirst(bioq);
req->vbr_bp = bp;
- req->vbr_ack = -1;
- req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1);
+ *req->vbr_ack = -1;
+ req->vbr_hdr->ioprio = vtblk_gtoh32(sc, 1);
switch (bp->bio_cmd) {
case BIO_FLUSH:
- req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_FLUSH);
- req->vbr_hdr.sector = 0;
+ req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_FLUSH);
+ req->vbr_hdr->sector = 0;
break;
case BIO_READ:
- req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_IN);
- req->vbr_hdr.sector = vtblk_gtoh64(sc, bp->bio_offset / VTBLK_BSIZE);
+ req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_IN);
+ req->vbr_hdr->sector = vtblk_gtoh64(sc, bp->bio_offset /
+ VTBLK_BSIZE);
break;
case BIO_WRITE:
- req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_OUT);
- req->vbr_hdr.sector = vtblk_gtoh64(sc, bp->bio_offset / VTBLK_BSIZE);
+ req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_OUT);
+ req->vbr_hdr->sector = vtblk_gtoh64(sc, bp->bio_offset /
+ VTBLK_BSIZE);
break;
case BIO_DELETE:
- req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_DISCARD);
- req->vbr_hdr.sector = vtblk_gtoh64(sc, bp->bio_offset / VTBLK_BSIZE);
+ req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_DISCARD);
+ req->vbr_hdr->sector = vtblk_gtoh64(sc, bp->bio_offset /
+ VTBLK_BSIZE);
break;
default:
panic("%s: bio with unhandled cmd: %d", __func__, bp->bio_cmd);
}
if (bp->bio_flags & BIO_ORDERED)
- req->vbr_hdr.type |= vtblk_gtoh32(sc, VIRTIO_BLK_T_BARRIER);
+ req->vbr_hdr->type |= vtblk_gtoh32(sc, VIRTIO_BLK_T_BARRIER);
return (req);
}
@@ -1072,13 +1200,17 @@
goto out;
}
ordered = 1;
- req->vbr_hdr.type &= vtblk_gtoh32(sc,
+ req->vbr_hdr->type &= vtblk_gtoh32(sc,
~VIRTIO_BLK_T_BARRIER);
}
}
+ bus_dmamap_sync(sc->vtblk_dmat, req->vbr_hdr_mapp,
+ BUS_DMASYNC_PREWRITE);
+
sglist_reset(sg);
- sglist_append(sg, &req->vbr_hdr, sizeof(struct virtio_blk_outhdr));
+ sglist_append_phys(sg, req->vbr_hdr_paddr,
+ sizeof(struct virtio_blk_outhdr));
if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
/*
@@ -1125,8 +1257,10 @@
}
}
+ bus_dmamap_sync(sc->vtblk_dmat, req->vbr_ack_mapp, BUS_DMASYNC_PREREAD);
+
writable++;
- sglist_append(sg, &req->vbr_ack, sizeof(uint8_t));
+ sglist_append_phys(sg, req->vbr_ack_paddr, sizeof(uint8_t));
readable = sg->sg_nseg - writable;
if (req->vbr_mapp != NULL) {
@@ -1168,7 +1302,10 @@
{
int error;
- switch (req->vbr_ack) {
+ bus_dmamap_sync(req->vbr_sc->vtblk_dmat, req->vbr_ack_mapp,
+ BUS_DMASYNC_POSTREAD);
+
+ switch (*req->vbr_ack) {
case VIRTIO_BLK_S_OK:
error = 0;
break;
@@ -1409,10 +1546,10 @@
if (req == NULL)
return;
- req->vbr_ack = -1;
- req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_GET_ID);
- req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1);
- req->vbr_hdr.sector = 0;
+ *req->vbr_ack = -1;
+ req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_GET_ID);
+ req->vbr_hdr->ioprio = vtblk_gtoh32(sc, 1);
+ req->vbr_hdr->sector = 0;
req->vbr_bp = &buf;
g_reset_bio(&buf);
@@ -1547,10 +1684,10 @@
req = &sc->vtblk_dump_request;
req->vbr_sc = sc;
- req->vbr_ack = -1;
- req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_OUT);
- req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1);
- req->vbr_hdr.sector = vtblk_gtoh64(sc, offset / VTBLK_BSIZE);
+ *req->vbr_ack = -1;
+ req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_OUT);
+ req->vbr_hdr->ioprio = vtblk_gtoh32(sc, 1);
+ req->vbr_hdr->sector = vtblk_gtoh64(sc, offset / VTBLK_BSIZE);
req->vbr_bp = &buf;
g_reset_bio(&buf);
@@ -1570,10 +1707,10 @@
req = &sc->vtblk_dump_request;
req->vbr_sc = sc;
- req->vbr_ack = -1;
- req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_FLUSH);
- req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1);
- req->vbr_hdr.sector = 0;
+ *req->vbr_ack = -1;
+ req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_FLUSH);
+ req->vbr_hdr->ioprio = vtblk_gtoh32(sc, 1);
+ req->vbr_hdr->sector = 0;
req->vbr_bp = &buf;
g_reset_bio(&buf);

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 16, 3:52 AM (19 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28114292
Default Alt Text
D54960.diff (10 KB)

Event Timeline