From owner-svn-src-all@FreeBSD.ORG Tue Aug 21 00:03:04 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E88E4106566C; Tue, 21 Aug 2012 00:03:04 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D026F8FC08; Tue, 21 Aug 2012 00:03:04 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q7L034oZ018610; Tue, 21 Aug 2012 00:03:04 GMT (envelope-from emaste@svn.freebsd.org) Received: (from emaste@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q7L0342r018598; Tue, 21 Aug 2012 00:03:04 GMT (envelope-from emaste@svn.freebsd.org) Message-Id: <201208210003.q7L0342r018598@svn.freebsd.org> From: Ed Maste Date: Tue, 21 Aug 2012 00:03:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r239472 - in stable/9/sys: dev/virtio dev/virtio/balloon dev/virtio/block dev/virtio/network dev/virtio/pci modules modules/virtio X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Aug 2012 00:03:05 -0000 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 ***