svn commit: r239472 - in stable/9/sys: dev/virtio
dev/virtio/balloon dev/virtio/block dev/virtio/network
dev/virtio/pci modules modules/virtio
Ed Maste
emaste at FreeBSD.org
Tue Aug 21 00:03:05 UTC 2012
Author: emaste
Date: Tue Aug 21 00:03:04 2012
New Revision: 239472
URL: http://svn.freebsd.org/changeset/base/239472
Log:
MFC r227652, r228301, r234270, r234349
Sync Bryan Venteicher's virtio base, PCI front-end, and net/block/balloon
drivers from HEAD.
Added:
stable/9/sys/dev/virtio/
- copied from r227652, head/sys/dev/virtio/
stable/9/sys/modules/virtio/
- copied from r227652, head/sys/modules/virtio/
Modified:
stable/9/sys/dev/virtio/balloon/virtio_balloon.c
stable/9/sys/dev/virtio/balloon/virtio_balloon.h
stable/9/sys/dev/virtio/block/virtio_blk.c
stable/9/sys/dev/virtio/block/virtio_blk.h
stable/9/sys/dev/virtio/network/if_vtnet.c
stable/9/sys/dev/virtio/network/if_vtnetvar.h
stable/9/sys/dev/virtio/network/virtio_net.h
stable/9/sys/dev/virtio/pci/virtio_pci.c
stable/9/sys/dev/virtio/pci/virtio_pci.h
stable/9/sys/dev/virtio/virtio.h
stable/9/sys/dev/virtio/virtio_ring.h
stable/9/sys/dev/virtio/virtqueue.c
stable/9/sys/dev/virtio/virtqueue.h
stable/9/sys/modules/Makefile
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/dev/ (props changed)
stable/9/sys/modules/ (props changed)
Modified: stable/9/sys/dev/virtio/balloon/virtio_balloon.c
==============================================================================
--- head/sys/dev/virtio/balloon/virtio_balloon.c Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/balloon/virtio_balloon.c Tue Aug 21 00:03:04 2012 (r239472)
@@ -122,6 +122,9 @@ static void vtballoon_add_sysctl(struct
*/
#define VTBALLOON_PAGES_PER_REQUEST 256
+/* Must be able to fix all pages frames in one page (segment). */
+CTASSERT(VTBALLOON_PAGES_PER_REQUEST * sizeof(uint32_t) <= PAGE_SIZE);
+
#define VTBALLOON_MTX(_sc) &(_sc)->vtballoon_mtx
#define VTBALLOON_LOCK_INIT(_sc, _name) mtx_init(VTBALLOON_MTX((_sc)), _name, \
"VirtIO Balloon Lock", MTX_SPIN)
@@ -138,7 +141,7 @@ static device_method_t vtballoon_methods
/* VirtIO methods. */
DEVMETHOD(virtio_config_change, vtballoon_config_change),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t vtballoon_driver = {
@@ -402,13 +405,13 @@ vtballoon_send_page_frames(struct vtball
error = virtqueue_enqueue(vq, vq, &sg, 1, 0);
KASSERT(error == 0, ("error enqueuing page frames to virtqueue"));
+ virtqueue_notify(vq);
/*
* Inflate and deflate operations are done synchronously. The
* interrupt handler will wake us up.
*/
VTBALLOON_LOCK(sc);
- virtqueue_notify(vq);
while ((c = virtqueue_dequeue(vq, NULL)) == NULL)
msleep_spin(sc, VTBALLOON_MTX(sc), "vtbspf", 0);
@@ -475,7 +478,6 @@ vtballoon_update_size(struct vtballoon_s
virtio_write_dev_config_4(sc->vtballoon_dev,
offsetof(struct virtio_balloon_config, actual),
htole32(sc->vtballoon_current_npages));
-
}
static int
Modified: stable/9/sys/dev/virtio/balloon/virtio_balloon.h
==============================================================================
--- head/sys/dev/virtio/balloon/virtio_balloon.h Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/balloon/virtio_balloon.h Tue Aug 21 00:03:04 2012 (r239472)
@@ -1,7 +1,30 @@
-/*
+/*-
* This header is BSD licensed so anyone can use the definitions to implement
* compatible drivers/servers.
*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
* $FreeBSD$
*/
Modified: stable/9/sys/dev/virtio/block/virtio_blk.c
==============================================================================
--- head/sys/dev/virtio/block/virtio_blk.c Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/block/virtio_blk.c Tue Aug 21 00:03:04 2012 (r239472)
@@ -70,8 +70,8 @@ struct vtblk_softc {
uint32_t vtblk_flags;
#define VTBLK_FLAG_INDIRECT 0x0001
#define VTBLK_FLAG_READONLY 0x0002
-#define VTBLK_FLAG_DETACHING 0x0004
-#define VTBLK_FLAG_SUSPENDED 0x0008
+#define VTBLK_FLAG_DETACH 0x0004
+#define VTBLK_FLAG_SUSPEND 0x0008
#define VTBLK_FLAG_DUMPING 0x0010
struct virtqueue *vtblk_vq;
@@ -82,14 +82,12 @@ struct vtblk_softc {
TAILQ_HEAD(, vtblk_request)
vtblk_req_free;
TAILQ_HEAD(, vtblk_request)
- vtblk_req_ready;
+ vtblk_req_ready;
struct taskqueue *vtblk_tq;
struct task vtblk_intr_task;
- int vtblk_sector_size;
int vtblk_max_nsegs;
- int vtblk_unit;
int vtblk_request_count;
struct vtblk_request vtblk_dump_request;
@@ -118,6 +116,13 @@ static int vtblk_suspend(device_t);
static int vtblk_resume(device_t);
static int vtblk_shutdown(device_t);
+static int vtblk_open(struct disk *);
+static int vtblk_close(struct disk *);
+static int vtblk_ioctl(struct disk *, u_long, void *, int,
+ struct thread *);
+static int vtblk_dump(void *, void *, vm_offset_t, off_t, size_t);
+static void vtblk_strategy(struct bio *);
+
static void vtblk_negotiate_features(struct vtblk_softc *);
static int vtblk_maximum_segments(struct vtblk_softc *,
struct virtio_blk_config *);
@@ -126,13 +131,7 @@ static void vtblk_alloc_disk(struct vtbl
struct virtio_blk_config *);
static void vtblk_create_disk(struct vtblk_softc *);
-static int vtblk_open(struct disk *);
-static int vtblk_close(struct disk *);
-static int vtblk_ioctl(struct disk *, u_long, void *, int,
- struct thread *);
-static int vtblk_dump(void *, void *, vm_offset_t, off_t, size_t);
-static void vtblk_strategy(struct bio *);
-
+static int vtblk_quiesce(struct vtblk_softc *);
static void vtblk_startio(struct vtblk_softc *);
static struct vtblk_request * vtblk_bio_request(struct vtblk_softc *);
static int vtblk_execute_request(struct vtblk_softc *,
@@ -150,6 +149,7 @@ static int vtblk_flush_dump(struct vtblk
static int vtblk_poll_request(struct vtblk_softc *,
struct vtblk_request *);
+static void vtblk_finish_completed(struct vtblk_softc *);
static void vtblk_drain_vq(struct vtblk_softc *, int);
static void vtblk_drain(struct vtblk_softc *);
@@ -163,7 +163,8 @@ static struct vtblk_request * vtblk_dequ
static void vtblk_enqueue_ready(struct vtblk_softc *,
struct vtblk_request *);
-static void vtblk_bio_error(struct bio *, int);
+static int vtblk_request_error(struct vtblk_request *);
+static void vtblk_finish_bio(struct bio *, int);
/* Tunables. */
static int vtblk_no_ident = 0;
@@ -185,16 +186,14 @@ TUNABLE_INT("hw.vtblk.no_ident", &vtblk_
mtx_init(VTBLK_MTX((_sc)), (_name), \
"VTBLK Lock", MTX_DEF)
#define VTBLK_LOCK(_sc) mtx_lock(VTBLK_MTX((_sc)))
-#define VTBLK_TRYLOCK(_sc) mtx_trylock(VTBLK_MTX((_sc)))
#define VTBLK_UNLOCK(_sc) mtx_unlock(VTBLK_MTX((_sc)))
#define VTBLK_LOCK_DESTROY(_sc) mtx_destroy(VTBLK_MTX((_sc)))
#define VTBLK_LOCK_ASSERT(_sc) mtx_assert(VTBLK_MTX((_sc)), MA_OWNED)
#define VTBLK_LOCK_ASSERT_NOTOWNED(_sc) \
mtx_assert(VTBLK_MTX((_sc)), MA_NOTOWNED)
-#define VTBLK_BIO_SEGMENTS(_bp) sglist_count((_bp)->bio_data, (_bp)->bio_bcount)
-
#define VTBLK_DISK_NAME "vtbd"
+#define VTBLK_QUIESCE_TIMEOUT (30 * hz)
/*
* Each block request uses at least two segments - one for the header
@@ -213,7 +212,7 @@ static device_method_t vtblk_methods[] =
DEVMETHOD(device_resume, vtblk_resume),
DEVMETHOD(device_shutdown, vtblk_shutdown),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t vtblk_driver = {
@@ -281,7 +280,6 @@ vtblk_attach(device_t dev)
sc = device_get_softc(dev);
sc->vtblk_dev = dev;
- sc->vtblk_unit = device_get_unit(dev);
VTBLK_LOCK_INIT(sc, device_get_nameunit(dev));
@@ -299,13 +297,8 @@ vtblk_attach(device_t dev)
sc->vtblk_flags |= VTBLK_FLAG_READONLY;
/* Get local copy of config. */
- if (virtio_with_feature(dev, VIRTIO_BLK_F_TOPOLOGY) == 0) {
- bzero(&blkcfg, sizeof(struct virtio_blk_config));
- virtio_read_device_config(dev, 0, &blkcfg,
- offsetof(struct virtio_blk_config, physical_block_exp));
- } else
- virtio_read_device_config(dev, 0, &blkcfg,
- sizeof(struct virtio_blk_config));
+ virtio_read_device_config(dev, 0, &blkcfg,
+ sizeof(struct virtio_blk_config));
/*
* With the current sglist(9) implementation, it is not easy
@@ -323,11 +316,13 @@ vtblk_attach(device_t dev)
}
sc->vtblk_max_nsegs = vtblk_maximum_segments(sc, &blkcfg);
+ if (sc->vtblk_max_nsegs <= VTBLK_MIN_SEGMENTS) {
+ error = EINVAL;
+ device_printf(dev, "fewer than minimum number of segments "
+ "allowed: %d\n", sc->vtblk_max_nsegs);
+ goto fail;
+ }
- /*
- * Allocate working sglist. The number of segments may be too
- * large to safely store on the stack.
- */
sc->vtblk_sglist = sglist_alloc(sc->vtblk_max_nsegs, M_NOWAIT);
if (sc->vtblk_sglist == NULL) {
error = ENOMEM;
@@ -385,7 +380,7 @@ vtblk_detach(device_t dev)
sc = device_get_softc(dev);
VTBLK_LOCK(sc);
- sc->vtblk_flags |= VTBLK_FLAG_DETACHING;
+ sc->vtblk_flags |= VTBLK_FLAG_DETACH;
if (device_is_attached(dev))
vtblk_stop(sc);
VTBLK_UNLOCK(sc);
@@ -417,15 +412,19 @@ static int
vtblk_suspend(device_t dev)
{
struct vtblk_softc *sc;
+ int error;
sc = device_get_softc(dev);
VTBLK_LOCK(sc);
- sc->vtblk_flags |= VTBLK_FLAG_SUSPENDED;
- /* TODO Wait for any inflight IO to complete? */
+ sc->vtblk_flags |= VTBLK_FLAG_SUSPEND;
+ /* XXX BMV: virtio_stop(), etc needed here? */
+ error = vtblk_quiesce(sc);
+ if (error)
+ sc->vtblk_flags &= ~VTBLK_FLAG_SUSPEND;
VTBLK_UNLOCK(sc);
- return (0);
+ return (error);
}
static int
@@ -436,8 +435,9 @@ vtblk_resume(device_t dev)
sc = device_get_softc(dev);
VTBLK_LOCK(sc);
- sc->vtblk_flags &= ~VTBLK_FLAG_SUSPENDED;
- /* TODO Resume IO? */
+ /* XXX BMV: virtio_reinit(), etc needed here? */
+ sc->vtblk_flags &= ~VTBLK_FLAG_SUSPEND;
+ vtblk_startio(sc);
VTBLK_UNLOCK(sc);
return (0);
@@ -458,7 +458,7 @@ vtblk_open(struct disk *dp)
if ((sc = dp->d_drv1) == NULL)
return (ENXIO);
- return (sc->vtblk_flags & VTBLK_FLAG_DETACHING ? ENXIO : 0);
+ return (sc->vtblk_flags & VTBLK_FLAG_DETACH ? ENXIO : 0);
}
static int
@@ -498,11 +498,7 @@ vtblk_dump(void *arg, void *virtual, vm_
if ((sc = dp->d_drv1) == NULL)
return (ENXIO);
- if (VTBLK_TRYLOCK(sc) == 0) {
- device_printf(sc->vtblk_dev,
- "softc already locked, cannot dump...\n");
- return (EBUSY);
- }
+ VTBLK_LOCK(sc);
if ((sc->vtblk_flags & VTBLK_FLAG_DUMPING) == 0) {
vtblk_prepare_dump(sc);
@@ -513,6 +509,10 @@ vtblk_dump(void *arg, void *virtual, vm_
error = vtblk_write_dump(sc, virtual, offset, length);
else if (virtual == NULL && offset == 0)
error = vtblk_flush_dump(sc);
+ else {
+ error = EINVAL;
+ sc->vtblk_flags &= ~VTBLK_FLAG_DUMPING;
+ }
VTBLK_UNLOCK(sc);
@@ -525,7 +525,7 @@ vtblk_strategy(struct bio *bp)
struct vtblk_softc *sc;
if ((sc = bp->bio_disk->d_drv1) == NULL) {
- vtblk_bio_error(bp, EINVAL);
+ vtblk_finish_bio(bp, EINVAL);
return;
}
@@ -535,29 +535,37 @@ vtblk_strategy(struct bio *bp)
*/
if (sc->vtblk_flags & VTBLK_FLAG_READONLY &&
(bp->bio_cmd == BIO_WRITE || bp->bio_cmd == BIO_FLUSH)) {
- vtblk_bio_error(bp, EROFS);
+ vtblk_finish_bio(bp, EROFS);
return;
}
+#ifdef INVARIANTS
/*
* Prevent read/write buffers spanning too many segments from
* getting into the queue. This should only trip if d_maxsize
* was incorrectly set.
*/
if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
- KASSERT(VTBLK_BIO_SEGMENTS(bp) <= sc->vtblk_max_nsegs -
- VTBLK_MIN_SEGMENTS,
+ int nsegs, max_nsegs;
+
+ nsegs = sglist_count(bp->bio_data, bp->bio_bcount);
+ max_nsegs = sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS;
+
+ KASSERT(nsegs <= max_nsegs,
("bio spanned too many segments: %d, max: %d",
- VTBLK_BIO_SEGMENTS(bp),
- sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS));
+ nsegs, max_nsegs));
}
+#endif
VTBLK_LOCK(sc);
- if ((sc->vtblk_flags & VTBLK_FLAG_DETACHING) == 0) {
+ if (sc->vtblk_flags & VTBLK_FLAG_DETACH)
+ vtblk_finish_bio(bp, ENXIO);
+ else {
bioq_disksort(&sc->vtblk_bioq, bp);
- vtblk_startio(sc);
- } else
- vtblk_bio_error(bp, ENXIO);
+
+ if ((sc->vtblk_flags & VTBLK_FLAG_SUSPEND) == 0)
+ vtblk_startio(sc);
+ }
VTBLK_UNLOCK(sc);
}
@@ -622,7 +630,7 @@ vtblk_alloc_disk(struct vtblk_softc *sc,
dp->d_ioctl = vtblk_ioctl;
dp->d_strategy = vtblk_strategy;
dp->d_name = VTBLK_DISK_NAME;
- dp->d_unit = sc->vtblk_unit;
+ dp->d_unit = device_get_unit(dev);
dp->d_drv1 = sc;
if ((sc->vtblk_flags & VTBLK_FLAG_READONLY) == 0)
@@ -632,10 +640,9 @@ vtblk_alloc_disk(struct vtblk_softc *sc,
dp->d_mediasize = blkcfg->capacity * 512;
if (virtio_with_feature(dev, VIRTIO_BLK_F_BLK_SIZE))
- sc->vtblk_sector_size = blkcfg->blk_size;
+ dp->d_sectorsize = blkcfg->blk_size;
else
- sc->vtblk_sector_size = 512;
- dp->d_sectorsize = sc->vtblk_sector_size;
+ dp->d_sectorsize = 512;
/*
* The VirtIO maximum I/O size is given in terms of segments.
@@ -685,6 +692,26 @@ vtblk_create_disk(struct vtblk_softc *sc
disk_create(dp, DISK_VERSION);
}
+static int
+vtblk_quiesce(struct vtblk_softc *sc)
+{
+ int error;
+
+ error = 0;
+
+ VTBLK_LOCK_ASSERT(sc);
+
+ while (!virtqueue_empty(sc->vtblk_vq)) {
+ if (mtx_sleep(&sc->vtblk_vq, VTBLK_MTX(sc), PRIBIO, "vtblkq",
+ VTBLK_QUIESCE_TIMEOUT) == EWOULDBLOCK) {
+ error = EBUSY;
+ break;
+ }
+ }
+
+ return (error);
+}
+
static void
vtblk_startio(struct vtblk_softc *sc)
{
@@ -697,9 +724,6 @@ vtblk_startio(struct vtblk_softc *sc)
VTBLK_LOCK_ASSERT(sc);
- if (sc->vtblk_flags & VTBLK_FLAG_SUSPENDED)
- return;
-
while (!virtqueue_full(vq)) {
if ((req = vtblk_dequeue_ready(sc)) == NULL)
req = vtblk_bio_request(sc);
@@ -752,9 +776,8 @@ vtblk_bio_request(struct vtblk_softc *sc
req->vbr_hdr.sector = bp->bio_offset / 512;
break;
default:
- KASSERT(0, ("bio with unhandled cmd: %d", bp->bio_cmd));
- req->vbr_hdr.type = -1;
- break;
+ panic("%s: bio with unhandled cmd: %d", __FUNCTION__,
+ bp->bio_cmd);
}
if (bp->bio_flags & BIO_ORDERED)
@@ -768,7 +791,7 @@ vtblk_execute_request(struct vtblk_softc
{
struct sglist *sg;
struct bio *bp;
- int writable, error;
+ int readable, writable, error;
sg = sc->vtblk_sglist;
bp = req->vbr_bp;
@@ -799,10 +822,9 @@ vtblk_execute_request(struct vtblk_softc
KASSERT(sg->sg_nseg >= VTBLK_MIN_SEGMENTS,
("fewer than min segments: %d", sg->sg_nseg));
- error = virtqueue_enqueue(sc->vtblk_vq, req, sg,
- sg->sg_nseg - writable, writable);
+ readable = sg->sg_nseg - writable;
- return (error);
+ return (virtqueue_enqueue(sc->vtblk_vq, req, sg, readable, writable));
}
static int
@@ -822,37 +844,23 @@ static void
vtblk_intr_task(void *arg, int pending)
{
struct vtblk_softc *sc;
- struct vtblk_request *req;
struct virtqueue *vq;
- struct bio *bp;
sc = arg;
vq = sc->vtblk_vq;
VTBLK_LOCK(sc);
- if (sc->vtblk_flags & VTBLK_FLAG_DETACHING) {
+ if (sc->vtblk_flags & VTBLK_FLAG_DETACH) {
VTBLK_UNLOCK(sc);
return;
}
- while ((req = virtqueue_dequeue(vq, NULL)) != NULL) {
- bp = req->vbr_bp;
+ vtblk_finish_completed(sc);
- if (req->vbr_ack == VIRTIO_BLK_S_OK)
- bp->bio_resid = 0;
- else {
- bp->bio_flags |= BIO_ERROR;
- if (req->vbr_ack == VIRTIO_BLK_S_UNSUPP)
- bp->bio_error = ENOTSUP;
- else
- bp->bio_error = EIO;
- }
-
- biodone(bp);
- vtblk_enqueue_request(sc, req);
- }
-
- vtblk_startio(sc);
+ if ((sc->vtblk_flags & VTBLK_FLAG_SUSPEND) == 0)
+ vtblk_startio(sc);
+ else
+ wakeup(&sc->vtblk_vq);
if (virtqueue_enable_intr(vq) != 0) {
virtqueue_disable_intr(vq);
@@ -905,9 +913,10 @@ vtblk_get_ident(struct vtblk_softc *sc)
VTBLK_LOCK(sc);
error = vtblk_poll_request(sc, req);
- vtblk_enqueue_request(sc, req);
VTBLK_UNLOCK(sc);
+ vtblk_enqueue_request(sc, req);
+
if (error) {
device_printf(sc->vtblk_dev,
"error getting device identifier: %d\n", error);
@@ -1006,17 +1015,35 @@ vtblk_poll_request(struct vtblk_softc *s
r = virtqueue_poll(vq, NULL);
KASSERT(r == req, ("unexpected request response"));
- if (req->vbr_ack != VIRTIO_BLK_S_OK) {
- error = req->vbr_ack == VIRTIO_BLK_S_UNSUPP ? ENOTSUP : EIO;
- if (bootverbose)
- device_printf(dev,
- "vtblk_poll_request: IO error: %d\n", error);
+ error = vtblk_request_error(req);
+ if (error && bootverbose) {
+ device_printf(dev, "vtblk_poll_request: IO error: %d\n",
+ error);
}
return (error);
}
static void
+vtblk_finish_completed(struct vtblk_softc *sc)
+{
+ struct vtblk_request *req;
+ struct bio *bp;
+ int error;
+
+ while ((req = virtqueue_dequeue(sc->vtblk_vq, NULL)) != NULL) {
+ bp = req->vbr_bp;
+
+ error = vtblk_request_error(req);
+ if (error)
+ disk_err(bp, "hard error", -1, 1);
+
+ vtblk_finish_bio(bp, error);
+ vtblk_enqueue_request(sc, req);
+ }
+}
+
+static void
vtblk_drain_vq(struct vtblk_softc *sc, int skip_done)
{
struct virtqueue *vq;
@@ -1028,7 +1055,7 @@ vtblk_drain_vq(struct vtblk_softc *sc, i
while ((req = virtqueue_drain(vq, &last)) != NULL) {
if (!skip_done)
- vtblk_bio_error(req->vbr_bp, ENXIO);
+ vtblk_finish_bio(req->vbr_bp, ENXIO);
vtblk_enqueue_request(sc, req);
}
@@ -1045,17 +1072,19 @@ vtblk_drain(struct vtblk_softc *sc)
bioq = &sc->vtblk_bioq;
- if (sc->vtblk_vq != NULL)
+ if (sc->vtblk_vq != NULL) {
+ vtblk_finish_completed(sc);
vtblk_drain_vq(sc, 0);
+ }
while ((req = vtblk_dequeue_ready(sc)) != NULL) {
- vtblk_bio_error(req->vbr_bp, ENXIO);
+ vtblk_finish_bio(req->vbr_bp, ENXIO);
vtblk_enqueue_request(sc, req);
}
while (bioq_first(bioq) != NULL) {
bp = bioq_takefirst(bioq);
- vtblk_bio_error(bp, ENXIO);
+ vtblk_finish_bio(bp, ENXIO);
}
vtblk_free_requests(sc);
@@ -1065,9 +1094,9 @@ static int
vtblk_alloc_requests(struct vtblk_softc *sc)
{
struct vtblk_request *req;
- int i, size;
+ int i, nreqs;
- size = virtqueue_size(sc->vtblk_vq);
+ nreqs = virtqueue_size(sc->vtblk_vq);
/*
* Preallocate sufficient requests to keep the virtqueue full. Each
@@ -1075,9 +1104,9 @@ vtblk_alloc_requests(struct vtblk_softc
* the number allocated when indirect descriptors are not available.
*/
if ((sc->vtblk_flags & VTBLK_FLAG_INDIRECT) == 0)
- size /= VTBLK_MIN_SEGMENTS;
+ nreqs /= VTBLK_MIN_SEGMENTS;
- for (i = 0; i < size; i++) {
+ for (i = 0; i < nreqs; i++) {
req = uma_zalloc(vtblk_req_zone, M_NOWAIT);
if (req == NULL)
return (ENOMEM);
@@ -1094,6 +1123,9 @@ vtblk_free_requests(struct vtblk_softc *
{
struct vtblk_request *req;
+ KASSERT(TAILQ_EMPTY(&sc->vtblk_req_ready),
+ ("ready requests left on queue"));
+
while ((req = vtblk_dequeue_request(sc)) != NULL) {
sc->vtblk_request_count--;
uma_zfree(vtblk_req_zone, req);
@@ -1141,9 +1173,35 @@ vtblk_enqueue_ready(struct vtblk_softc *
TAILQ_INSERT_HEAD(&sc->vtblk_req_ready, req, vbr_link);
}
+static int
+vtblk_request_error(struct vtblk_request *req)
+{
+ int error;
+
+ switch (req->vbr_ack) {
+ case VIRTIO_BLK_S_OK:
+ error = 0;
+ break;
+ case VIRTIO_BLK_S_UNSUPP:
+ error = ENOTSUP;
+ break;
+ default:
+ error = EIO;
+ break;
+ }
+
+ return (error);
+}
+
static void
-vtblk_bio_error(struct bio *bp, int error)
+vtblk_finish_bio(struct bio *bp, int error)
{
- biofinish(bp, NULL, error);
+ if (error) {
+ bp->bio_resid = bp->bio_bcount;
+ bp->bio_error = error;
+ bp->bio_flags |= BIO_ERROR;
+ }
+
+ biodone(bp);
}
Modified: stable/9/sys/dev/virtio/block/virtio_blk.h
==============================================================================
--- head/sys/dev/virtio/block/virtio_blk.h Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/block/virtio_blk.h Tue Aug 21 00:03:04 2012 (r239472)
@@ -1,7 +1,30 @@
-/*
+/*-
* This header is BSD licensed so anyone can use the definitions to implement
* compatible drivers/servers.
*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
* $FreeBSD$
*/
@@ -39,16 +62,6 @@ struct virtio_blk_config {
/* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
uint32_t blk_size;
-
- /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */
- /* exponent for physical block per logical block. */
- uint8_t physical_block_exp;
- /* alignment offset in logical blocks. */
- uint8_t alignment_offset;
- /* minimum I/O size without performance penalty in logical blocks. */
- uint16_t min_io_size;
- /* optimal sustained I/O size in logical blocks. */
- uint32_t opt_io_size;
} __packed;
/*
Modified: stable/9/sys/dev/virtio/network/if_vtnet.c
==============================================================================
--- head/sys/dev/virtio/network/if_vtnet.c Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/network/if_vtnet.c Tue Aug 21 00:03:04 2012 (r239472)
@@ -223,7 +223,7 @@ static device_method_t vtnet_methods[] =
/* VirtIO methods. */
DEVMETHOD(virtio_config_change, vtnet_config_change),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t vtnet_driver = {
@@ -317,8 +317,20 @@ vtnet_attach(device_t dev)
if (virtio_with_feature(dev, VIRTIO_NET_F_CTRL_VQ)) {
sc->vtnet_flags |= VTNET_FLAG_CTRL_VQ;
- if (virtio_with_feature(dev, VIRTIO_NET_F_CTRL_RX))
+ if (virtio_with_feature(dev, VIRTIO_NET_F_CTRL_RX)) {
+ sc->vtnet_mac_filter = malloc(
+ sizeof(struct vtnet_mac_filter), M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+ if (sc->vtnet_mac_filter == NULL) {
+ device_printf(dev,
+ "cannot allocate mac filter table\n");
+ error = ENOMEM;
+ goto fail;
+ }
+
sc->vtnet_flags |= VTNET_FLAG_CTRL_RX;
+ }
+
if (virtio_with_feature(dev, VIRTIO_NET_F_CTRL_VLAN))
sc->vtnet_flags |= VTNET_FLAG_VLAN_FILTER;
}
@@ -505,7 +517,12 @@ vtnet_detach(device_t dev)
sc->vtnet_vlan_detach = NULL;
}
- if (ifp) {
+ if (sc->vtnet_mac_filter != NULL) {
+ free(sc->vtnet_mac_filter, M_DEVBUF);
+ sc->vtnet_mac_filter = NULL;
+ }
+
+ if (ifp != NULL) {
if_free(ifp);
sc->vtnet_ifp = NULL;
}
@@ -742,17 +759,11 @@ vtnet_update_link_status(struct vtnet_so
if (link && ((sc->vtnet_flags & VTNET_FLAG_LINK) == 0)) {
sc->vtnet_flags |= VTNET_FLAG_LINK;
- if (bootverbose)
- device_printf(dev, "Link is up\n");
-
if_link_state_change(ifp, LINK_STATE_UP);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
vtnet_start_locked(ifp);
} else if (!link && (sc->vtnet_flags & VTNET_FLAG_LINK)) {
sc->vtnet_flags &= ~VTNET_FLAG_LINK;
- if (bootverbose)
- device_printf(dev, "Link is down\n");
-
if_link_state_change(ifp, LINK_STATE_DOWN);
}
}
@@ -1105,7 +1116,7 @@ vtnet_alloc_rxbuf(struct vtnet_softc *sc
KASSERT(sc->vtnet_flags & VTNET_FLAG_LRO_NOMRG,
("chained Rx mbuf requested without LRO_NOMRG"));
- for (i = 0; i < nbufs - 1; i++) {
+ for (i = 1; i < nbufs; i++) {
m = m_getjcl(M_DONTWAIT, MT_DATA, 0, clsize);
if (m == NULL)
goto fail;
@@ -1143,9 +1154,8 @@ vtnet_replace_rxbuf(struct vtnet_softc *
clsize = sc->vtnet_rx_mbuf_size;
nreplace = 0;
- if (m->m_next != NULL)
- KASSERT(sc->vtnet_flags & VTNET_FLAG_LRO_NOMRG,
- ("chained Rx mbuf without LRO_NOMRG"));
+ KASSERT(sc->vtnet_flags & VTNET_FLAG_LRO_NOMRG ||
+ m->m_next == NULL, ("chained Rx mbuf without LRO_NOMRG"));
/*
* Since LRO_NOMRG mbuf chains are so large, we want to avoid
@@ -1275,8 +1285,8 @@ vtnet_enqueue_rxbuf(struct vtnet_softc *
int offset, error;
VTNET_LOCK_ASSERT(sc);
- if ((sc->vtnet_flags & VTNET_FLAG_LRO_NOMRG) == 0)
- KASSERT(m->m_next == NULL, ("chained Rx mbuf"));
+ KASSERT(sc->vtnet_flags & VTNET_FLAG_LRO_NOMRG ||
+ m->m_next == NULL, ("chained Rx mbuf without LRO_NOMRG"));
sglist_init(&sg, VTNET_MAX_RX_SEGS, segs);
@@ -1688,7 +1698,8 @@ vtnet_rxeof(struct vtnet_softc *sc, int
break;
}
- virtqueue_notify(vq);
+ if (deq > 0)
+ virtqueue_notify(vq);
if (rx_npktsp != NULL)
*rx_npktsp = rx_npkts;
@@ -1946,9 +1957,14 @@ vtnet_encap(struct vtnet_softc *sc, stru
struct mbuf *m;
int error;
+ m = *m_head;
+
txhdr = uma_zalloc(vtnet_tx_header_zone, M_NOWAIT | M_ZERO);
- if (txhdr == NULL)
+ if (txhdr == NULL) {
+ *m_head = NULL;
+ m_freem(m);
return (ENOMEM);
+ }
/*
* Always use the non-mergeable header to simplify things. When
@@ -1957,21 +1973,22 @@ vtnet_encap(struct vtnet_softc *sc, stru
* the correct header size to the host.
*/
hdr = &txhdr->vth_uhdr.hdr;
- m = *m_head;
-
- error = ENOBUFS;
if (m->m_flags & M_VLANTAG) {
m = ether_vlanencap(m, m->m_pkthdr.ether_vtag);
- if ((*m_head = m) == NULL)
+ if ((*m_head = m) == NULL) {
+ error = ENOBUFS;
goto fail;
+ }
m->m_flags &= ~M_VLANTAG;
}
if (m->m_pkthdr.csum_flags != 0) {
m = vtnet_tx_offload(sc, m, hdr);
- if ((*m_head = m) == NULL)
+ if ((*m_head = m) == NULL) {
+ error = ENOBUFS;
goto fail;
+ }
}
error = vtnet_enqueue_txbuf(sc, m_head, txhdr);
@@ -2387,6 +2404,7 @@ vtnet_rx_filter_mac(struct vtnet_softc *
uint8_t ack;
ifp = sc->vtnet_ifp;
+ filter = sc->vtnet_mac_filter;
ucnt = 0;
mcnt = 0;
promisc = 0;
@@ -2397,19 +2415,6 @@ vtnet_rx_filter_mac(struct vtnet_softc *
KASSERT(sc->vtnet_flags & VTNET_FLAG_CTRL_RX,
("CTRL_RX feature not negotiated"));
- /*
- * Allocate the MAC filtering table. Note we could do this
- * at attach time, but it is probably not worth keeping it
- * around for an infrequent occurrence.
- */
- filter = malloc(sizeof(struct vtnet_mac_filter), M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (filter == NULL) {
- device_printf(sc->vtnet_dev,
- "cannot allocate MAC address filtering table\n");
- return;
- }
-
/* Unicast MAC addresses: */
if_addr_rlock(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
@@ -2481,8 +2486,6 @@ vtnet_rx_filter_mac(struct vtnet_softc *
if_printf(ifp, "error setting host MAC filter table\n");
out:
- free(filter, M_DEVBUF);
-
if (promisc)
if (vtnet_set_promisc(sc, 1) != 0)
if_printf(ifp, "cannot enable promiscuous mode\n");
Modified: stable/9/sys/dev/virtio/network/if_vtnetvar.h
==============================================================================
--- head/sys/dev/virtio/network/if_vtnetvar.h Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/network/if_vtnetvar.h Tue Aug 21 00:03:04 2012 (r239472)
@@ -99,6 +99,7 @@ struct vtnet_softc {
#define VTNET_MEDIATYPE (IFM_ETHER | IFM_1000_T | IFM_FDX)
char vtnet_hwaddr[ETHER_ADDR_LEN];
+ struct vtnet_mac_filter *vtnet_mac_filter;
/*
* During reset, the host's VLAN filtering table is lost. The
* array below is used to restore all the VLANs configured on
Modified: stable/9/sys/dev/virtio/network/virtio_net.h
==============================================================================
--- head/sys/dev/virtio/network/virtio_net.h Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/network/virtio_net.h Tue Aug 21 00:03:04 2012 (r239472)
@@ -1,7 +1,30 @@
-/*
+/*-
* This header is BSD licensed so anyone can use the definitions to implement
* compatible drivers/servers.
*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
* $FreeBSD$
*/
Modified: stable/9/sys/dev/virtio/pci/virtio_pci.c
==============================================================================
--- head/sys/dev/virtio/pci/virtio_pci.c Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/pci/virtio_pci.c Tue Aug 21 00:03:04 2012 (r239472)
@@ -189,7 +189,7 @@ static device_method_t vtpci_methods[] =
DEVMETHOD(virtio_bus_read_device_config, vtpci_read_dev_config),
DEVMETHOD(virtio_bus_write_device_config, vtpci_write_dev_config),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t vtpci_driver = {
Modified: stable/9/sys/dev/virtio/pci/virtio_pci.h
==============================================================================
--- head/sys/dev/virtio/pci/virtio_pci.h Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/pci/virtio_pci.h Tue Aug 21 00:03:04 2012 (r239472)
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright IBM Corp. 2007
*
* Authors:
@@ -7,6 +7,29 @@
* This header is BSD licensed so anyone can use the definitions to implement
* compatible drivers/servers.
*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
* $FreeBSD$
*/
Modified: stable/9/sys/dev/virtio/virtio.h
==============================================================================
--- head/sys/dev/virtio/virtio.h Fri Nov 18 05:43:43 2011 (r227652)
+++ stable/9/sys/dev/virtio/virtio.h Tue Aug 21 00:03:04 2012 (r239472)
@@ -1,7 +1,30 @@
-/*
+/*-
* This header is BSD licensed so anyone can use the definitions to implement
* compatible drivers/servers.
*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable
mailing list