Module Name:    src
Committed By:   martin
Date:           Wed Oct  2 18:20:48 UTC 2024

Modified Files:
        src/sys/dev/pci [netbsd-10]: ld_virtio.c vioscsi.c virtio.c
            virtio_pci.c
        src/sys/dev/virtio [netbsd-10]: viocon.c

Log Message:
Pull up following revision(s) (requested by rin in ticket #914):

        sys/dev/pci/virtio_pci.c: revision 1.50
        sys/dev/pci/virtio_pci.c: revision 1.51
        sys/dev/pci/virtio_pci.c: revision 1.52
        sys/dev/pci/virtio_pci.c: revision 1.53
        sys/dev/pci/virtio_pci.c: revision 1.54
        sys/dev/pci/vioscsi.c: revision 1.35
        sys/dev/pci/ld_virtio.c: revision 1.33
        sys/dev/pci/ld_virtio.c: revision 1.34
        sys/dev/virtio/viocon.c: revision 1.9
        sys/dev/pci/ld_virtio.c: revision 1.35
        sys/dev/pci/virtio.c: revision 1.80
        sys/dev/pci/virtio.c: revision 1.81
        sys/dev/pci/virtio.c: revision 1.82
        sys/dev/pci/virtio_pci.c: revision 1.45
        sys/dev/pci/virtio_pci.c: revision 1.46
        sys/dev/pci/virtio_pci.c: revision 1.47
        sys/dev/pci/virtio_pci.c: revision 1.48
        sys/dev/pci/virtio_pci.c: revision 1.49
        sys/dev/pci/virtio.c: revision 1.79

A single SCSI request may require multiple slots in the virtio queue
but the queue isn't sized for the theoretical maximum. So just use
XS_BUSY to pace the scsipi layer.

viocon(4): Show error in assertion failure.

virtio_read_device_config_le_[24]: Fix for {aarch64,arm}eb
Stop byte-swapping for big-endian aarch64 and arm to fix
corrupted read for, e.g., sc_taglen for vio9p(4).

As described as comments in virtio_pci.c, big-endian aarch64 and
armv7 (armeb) are somewhat special. At the moment, all supported
virtual/real machines are configured as little-endian, and only
CPU cores are switched to big-endian mode during early boot stage.

Most peripheral buses for armeb are LSB as a result, and their
default bus_space(9) functions swap byte-order. Therefore, PIOed
data from memory-mapped devices, as well as pci(4) ones, are
actually LSB, but observed as MSB for armeb.

Therefore, we should not swap byte-order further in
virtio_read_device_config_le_[24] on armeb.

See virtio_pci.c and sys/dev/fdt/virtio_mmio_fdt.c also.
fix spelling mistakes, mainly in comments and log messages.

Split KASSERT(A && B) into KASSERT(A); KASSERT(B).

Fix typo in error message.

Modify a confused expression in ld_virtio_attach().

VIRTIO_BLK_MIN_SEGMENTS should be the total number of non-data segments,
so I rename it to VIRTIO_BLK_CTRL_SEGMENTS.
PR kern/57981.

ld@virtio(4): Fix maximum size parameters.
- SEG_MAX is the maximum number of segments.
- SIZE_MAX is the maximum number of bytes in a single segment.
The maximum transfer size is, therefore, SEG_MAX * SIZE_MAX.
=> Don't add two extra segments in the dmamap vr_payload for the
   header and status -- we already have a separate dmamap vr_cmdsts
   for that.
=> Don't recalculate payload dmamap parameters based on division by
   NBPG, just use the ones specified by the host.
=> Allow SIZE_MAX below MAXPHYS as long as SIZE_MAX*SEG_MAX >=
   MAXPHYS.
Even though ldattach clamps ld->sc_maxxfer to MAXPHYS, make sure to
clamp it in ld_virtio_attach before ld_virtio_alloc_reqs since it
determines the dmamap sizes and bounce buffer allocation and there's
no sense in allocating those larger than ld will use anyway.
PR kern/58338

virtio_pci.c: Nix trailing whitespace.

virtio@pci: Unmap the BARs we actually mapped on >=1.0 detach.
PR kern/58335

virtio@pci: Nix useless sc_mapped_iosize.
This appears to have been a mistaken attempt to pass the subregion
length through to bus_space_unmap, which doesn't make any sense --
bus_space_subregion does not allocate anything and the resulting
handle must not be passed to bus_space_unmap.

Once we pass the size that was actually returned by pci_mapreg_map to
bus_space_unmap, which matches the size passed internally by
pci_mapreg_map to bus_space_map, sc_mapped_iosize is no longer used
and can be flushed.
Prompted by PR kern/58335.

virtio@pci: Don't detach on shutdown.
The virtio bus does not keep state in memory that needs to flushed to
persistent storage.  Typically DVF_DETACH_SHUTDOWN is only needed by,
e.g., disk drivers to flush disk caches (although really, vfs sync
should do that anyway, so maybe we should just nix the option
altogether).
Prompted by PR kern/58335.

virtio@pci: Zero sc_bars_iosize[i] on unmap.
No functional change intended, but this makes the code less brittle.
Prompted by PR kern/58335.

virtio_pci.c: Sort includes.
No functional change intended.

virtio_pci.c: Omit needless blank lines and commented code.
No functional change intended.

virtio_pci.c: Sprinkle KNF.
- No parameter names in function prototypes.
- Fix indentation.
- Break overlong lines.
- Blank line between declarations and rest of block.
virtio_pci.c: Sprinkle const.
No functional change intended.

virtio_pci.c: Use container_of, not cast.
virtio(4): Assert child attach finished before we allow queueing.
Should help catch mistakes like:
PR kern/58555: Kernel panic during boot when using viocon with PCIe


To generate a diff of this commit:
cvs rdiff -u -r1.30.4.1 -r1.30.4.2 src/sys/dev/pci/ld_virtio.c
cvs rdiff -u -r1.30.2.1 -r1.30.2.2 src/sys/dev/pci/vioscsi.c
cvs rdiff -u -r1.63.2.5 -r1.63.2.6 src/sys/dev/pci/virtio.c
cvs rdiff -u -r1.38.4.3 -r1.38.4.4 src/sys/dev/pci/virtio_pci.c
cvs rdiff -u -r1.5.4.2 -r1.5.4.3 src/sys/dev/virtio/viocon.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/ld_virtio.c
diff -u src/sys/dev/pci/ld_virtio.c:1.30.4.1 src/sys/dev/pci/ld_virtio.c:1.30.4.2
--- src/sys/dev/pci/ld_virtio.c:1.30.4.1	Sat May 13 10:56:10 2023
+++ src/sys/dev/pci/ld_virtio.c	Wed Oct  2 18:20:48 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: ld_virtio.c,v 1.30.4.1 2023/05/13 10:56:10 martin Exp $	*/
+/*	$NetBSD: ld_virtio.c,v 1.30.4.2 2024/10/02 18:20:48 martin Exp $	*/
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.30.4.1 2023/05/13 10:56:10 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.30.4.2 2024/10/02 18:20:48 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -74,7 +74,7 @@ __KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,
  * Each block request uses at least two segments - one for the header
  * and one for the status.
 */
-#define	VIRTIO_BLK_MIN_SEGMENTS	2
+#define	VIRTIO_BLK_CTRL_SEGMENTS	2
 
 #define VIRTIO_BLK_FLAG_BITS			\
 	VIRTIO_COMMON_FLAG_BITS			\
@@ -128,6 +128,9 @@ struct ld_virtio_softc {
 	struct ld_softc		sc_ld;
 	device_t		sc_dev;
 
+	uint32_t		sc_seg_max; /* max number of segs in xfer */
+	uint32_t		sc_size_max; /* max size of single seg */
+
 	struct virtio_softc	*sc_virtio;
 	struct virtqueue	sc_vq;
 
@@ -220,11 +223,10 @@ ld_virtio_alloc_reqs(struct ld_virtio_so
 			goto err_reqs;
 		}
 		r = bus_dmamap_create(virtio_dmat(sc->sc_virtio),
-				      ld->sc_maxxfer,
-				      (ld->sc_maxxfer / NBPG) +
-				      VIRTIO_BLK_MIN_SEGMENTS,
-				      ld->sc_maxxfer,
-				      0,
+				      /*size*/ld->sc_maxxfer,
+				      /*nseg*/sc->sc_seg_max,
+				      /*maxsegsz*/sc->sc_size_max,
+				      /*boundary*/0,
 				      BUS_DMA_WAITOK|BUS_DMA_ALLOCNOW,
 				      &vr->vr_payload);
 		if (r != 0) {
@@ -264,7 +266,7 @@ ld_virtio_attach(device_t parent, device
 	struct ld_softc *ld = &sc->sc_ld;
 	struct virtio_softc *vsc = device_private(parent);
 	uint64_t features;
-	int qsize, maxxfersize, maxnsegs;
+	int qsize;
 
 	if (virtio_child(vsc) != NULL) {
 		aprint_normal(": child already attached for %s; "
@@ -296,49 +298,53 @@ ld_virtio_attach(device_t parent, device
 	} else
 		ld->sc_secsize = VIRTIO_BLK_BSIZE;
 
-	/* At least genfs_io assumes maxxfer == MAXPHYS. */
-	if (features & VIRTIO_BLK_F_SIZE_MAX) {
-		maxxfersize = virtio_read_device_config_4(vsc,
-		    VIRTIO_BLK_CONFIG_SIZE_MAX);
-		if (maxxfersize < MAXPHYS) {
+	if (features & VIRTIO_BLK_F_SEG_MAX) {
+		sc->sc_seg_max = virtio_read_device_config_4(vsc,
+		    VIRTIO_BLK_CONFIG_SEG_MAX);
+		if (sc->sc_seg_max == 0) {
 			aprint_error_dev(sc->sc_dev,
-			    "Too small SIZE_MAX %dK minimum is %dK\n",
-			    maxxfersize / 1024, MAXPHYS / 1024);
-			// goto err;
-			maxxfersize = MAXPHYS;
-		} else if (maxxfersize > MAXPHYS) {
-			aprint_normal_dev(sc->sc_dev,
-			    "Clip SEG_MAX from %dK to %dK\n",
-			    maxxfersize / 1024,
-			    MAXPHYS / 1024);
-			maxxfersize = MAXPHYS;
+			    "Invalid SEG_MAX %d\n", sc->sc_seg_max);
+			goto err;
 		}
-	} else
-		maxxfersize = MAXPHYS;
+	} else {
+		sc->sc_seg_max = 1;
+		aprint_verbose_dev(sc->sc_dev,
+		    "Unknown SEG_MAX, assuming %"PRIu32"\n", sc->sc_seg_max);
+	}
 
-	if (features & VIRTIO_BLK_F_SEG_MAX) {
-		maxnsegs = virtio_read_device_config_4(vsc,
-		    VIRTIO_BLK_CONFIG_SEG_MAX);
-		if (maxnsegs < VIRTIO_BLK_MIN_SEGMENTS) {
+	/* At least genfs_io assumes size_max*seg_max >= MAXPHYS. */
+	if (features & VIRTIO_BLK_F_SIZE_MAX) {
+		sc->sc_size_max = virtio_read_device_config_4(vsc,
+		    VIRTIO_BLK_CONFIG_SIZE_MAX);
+		if (sc->sc_size_max < MAXPHYS/sc->sc_seg_max) {
 			aprint_error_dev(sc->sc_dev,
-			    "Too small SEG_MAX %d minimum is %d\n",
-			    maxnsegs, VIRTIO_BLK_MIN_SEGMENTS);
-			maxnsegs = maxxfersize / NBPG;
+			    "Too small SIZE_MAX %d minimum is %d\n",
+			    sc->sc_size_max, MAXPHYS/sc->sc_seg_max);
 			// goto err;
+			sc->sc_size_max = MAXPHYS/sc->sc_seg_max;
+		} else if (sc->sc_size_max > MAXPHYS) {
+			aprint_verbose_dev(sc->sc_dev,
+			    "Clip SIZE_MAX from %d to %d\n",
+			    sc->sc_size_max, MAXPHYS);
+			sc->sc_size_max = MAXPHYS;
 		}
-	} else
-		maxnsegs = maxxfersize / NBPG;
+	} else {
+		sc->sc_size_max = MAXPHYS;
+		aprint_verbose_dev(sc->sc_dev,
+		    "Unknown SIZE_MAX, assuming %"PRIu32"\n",
+		    sc->sc_size_max);
+	}
 
-	/* 2 for the minimum size */
-	maxnsegs += VIRTIO_BLK_MIN_SEGMENTS;
+	aprint_normal_dev(sc->sc_dev, "max %"PRIu32" segs"
+	    " of max %"PRIu32" bytes\n",
+	    sc->sc_seg_max, sc->sc_size_max);
 
 	virtio_init_vq_vqdone(vsc, &sc->sc_vq, 0,
 	    ld_virtio_vq_done);
 
-	if (virtio_alloc_vq(vsc, &sc->sc_vq, maxxfersize, maxnsegs,
-	    "I/O request") != 0) {
+	if (virtio_alloc_vq(vsc, &sc->sc_vq, sc->sc_size_max,
+		sc->sc_seg_max + VIRTIO_BLK_CTRL_SEGMENTS, "I/O request") != 0)
 		goto err;
-	}
 	qsize = sc->sc_vq.vq_num;
 
 	if (virtio_child_attach_finish(vsc, &sc->sc_vq, 1,
@@ -348,7 +354,15 @@ ld_virtio_attach(device_t parent, device
 	ld->sc_dv = self;
 	ld->sc_secperunit = virtio_read_device_config_8(vsc,
 	    VIRTIO_BLK_CONFIG_CAPACITY) / (ld->sc_secsize / VIRTIO_BLK_BSIZE);
-	ld->sc_maxxfer = maxxfersize;
+
+	/*
+	 * Clamp ld->sc_maxxfer to MAXPHYS before ld_virtio_alloc_reqs
+	 * allocates DMA maps of at most ld->sc_maxxfer bytes.
+	 * ldattach will also clamp to MAXPHYS, but not until after
+	 * ld_virtio_alloc_reqs is done, so that doesn't help.
+	 */
+	ld->sc_maxxfer = MIN(MAXPHYS, sc->sc_size_max * sc->sc_seg_max);
+
 	if (features & VIRTIO_BLK_F_GEOMETRY) {
 		ld->sc_ncylinders = virtio_read_device_config_2(vsc,
 					VIRTIO_BLK_CONFIG_GEOMETRY_C);
@@ -413,8 +427,9 @@ ld_virtio_start(struct ld_softc *ld, str
 		return r;
 	}
 
+	KASSERT(vr->vr_payload->dm_nsegs <= sc->sc_seg_max);
 	r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs +
-	    VIRTIO_BLK_MIN_SEGMENTS);
+	    VIRTIO_BLK_CTRL_SEGMENTS);
 	if (r != 0) {
 		bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload);
 		return r;
@@ -543,7 +558,7 @@ ld_virtio_dump(struct ld_softc *ld, void
 		return r;
 
 	r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs +
-	    VIRTIO_BLK_MIN_SEGMENTS);
+	    VIRTIO_BLK_CTRL_SEGMENTS);
 	if (r != 0) {
 		bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload);
 		return r;
@@ -679,7 +694,7 @@ ld_virtio_flush(struct ld_softc *ld, boo
 	vr = &sc->sc_reqs[slot];
 	KASSERT(vr->vr_bp == NULL);
 
-	r = virtio_enqueue_reserve(vsc, vq, slot, VIRTIO_BLK_MIN_SEGMENTS);
+	r = virtio_enqueue_reserve(vsc, vq, slot, VIRTIO_BLK_CTRL_SEGMENTS);
 	if (r != 0) {
 		return r;
 	}

Index: src/sys/dev/pci/vioscsi.c
diff -u src/sys/dev/pci/vioscsi.c:1.30.2.1 src/sys/dev/pci/vioscsi.c:1.30.2.2
--- src/sys/dev/pci/vioscsi.c:1.30.2.1	Sat May 13 10:56:10 2023
+++ src/sys/dev/pci/vioscsi.c	Wed Oct  2 18:20:48 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: vioscsi.c,v 1.30.2.1 2023/05/13 10:56:10 martin Exp $	*/
+/*	$NetBSD: vioscsi.c,v 1.30.2.2 2024/10/02 18:20:48 martin 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.30.2.1 2023/05/13 10:56:10 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vioscsi.c,v 1.30.2.2 2024/10/02 18:20:48 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -302,7 +302,7 @@ vioscsi_scsipi_request(struct scsipi_cha
 	 */
 	vr = vioscsi_req_get(sc);
 	if (vr == NULL) {
-		xs->error = XS_RESOURCE_SHORTAGE;
+		xs->error = XS_BUSY;
 		scsipi_done(xs);
 		return;
 	}
@@ -389,11 +389,9 @@ stuffup:
 
 	error = virtio_enqueue_reserve(vsc, vq, slot, nsegs);
 	if (error) {
-		aprint_error_dev(sc->sc_dev, "error reserving %d (nsegs %d)\n",
-		    error, nsegs);
 		bus_dmamap_unload(virtio_dmat(vsc), vr->vr_data);
 		/* slot already freed by virtio_enqueue_reserve() */
-		xs->error = XS_RESOURCE_SHORTAGE;
+		xs->error = XS_BUSY;
 		scsipi_done(xs);
 		return;
 	}

Index: src/sys/dev/pci/virtio.c
diff -u src/sys/dev/pci/virtio.c:1.63.2.5 src/sys/dev/pci/virtio.c:1.63.2.6
--- src/sys/dev/pci/virtio.c:1.63.2.5	Sat Jun  3 14:40:25 2023
+++ src/sys/dev/pci/virtio.c	Wed Oct  2 18:20:48 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: virtio.c,v 1.63.2.5 2023/06/03 14:40:25 martin Exp $	*/
+/*	$NetBSD: virtio.c,v 1.63.2.6 2024/10/02 18:20:48 martin Exp $	*/
 
 /*
  * Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.63.2.5 2023/06/03 14:40:25 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.63.2.6 2024/10/02 18:20:48 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -85,7 +85,7 @@ virtio_set_status(struct virtio_softc *s
  *	virtio_reset(sc);	     // this will stop the device activity
  *	<dequeue finished requests>; // virtio_dequeue() still can be called
  *	<revoke pending requests in the vqs if any>;
- *	virtio_reinit_start(sc);     // dequeue prohibitted
+ *	virtio_reinit_start(sc);     // dequeue prohibited
  *	newfeatures = virtio_negotiate_features(sc, requestedfeatures);
  *	<some other initialization>;
  *	virtio_reinit_end(sc);	     // device activated; enqueue allowed
@@ -276,8 +276,15 @@ virtio_read_device_config_le_2(struct vi
 	uint16_t val;
 
 	val = bus_space_read_2(iot, ioh, index);
+#if !defined(__aarch64__) && !defined(__arm__)
+	/*
+	 * For big-endian aarch64/armv7, bus endian is always LSB, but
+	 * byte-order is automatically swapped by bus_space(9) (see also
+	 * comments in virtio_pci.c). Therefore, no need to swap here.
+	 */
 	if (sc->sc_bus_endian != LITTLE_ENDIAN)
 		val = bswap16(val);
+#endif
 
 	DPRINTFR("read_le_2", "%04x", val, index, 2);
 	DPRINTFR2("read_le_2", "%04x",
@@ -294,8 +301,11 @@ virtio_read_device_config_le_4(struct vi
 	uint32_t val;
 
 	val = bus_space_read_4(iot, ioh, index);
+#if !defined(__aarch64__) && !defined(__arm__)
+	/* See virtio_read_device_config_le_2() above. */
 	if (sc->sc_bus_endian != LITTLE_ENDIAN)
 		val = bswap32(val);
+#endif
 
 	DPRINTFR("read_le_4", "%08x", val, index, 4);
 	DPRINTFR2("read_le_4", "%08x",
@@ -660,7 +670,7 @@ virtio_stop_vq_intr(struct virtio_softc 
 		 * No way to disable the interrupt completely with
 		 * RingEventIdx. Instead advance used_event by half the
 		 * possible value. This won't happen soon and is far enough in
-		 * the past to not trigger a spurios interrupt.
+		 * the past to not trigger a spurious interrupt.
 		 */
 		*vq->vq_used_event = virtio_rw16(sc, vq->vq_used_idx + 0x8000);
 		vq_sync_aring_used(sc, vq, BUS_DMASYNC_PREWRITE);
@@ -1037,6 +1047,7 @@ virtio_enqueue_prep(struct virtio_softc 
 {
 	uint16_t slot;
 
+	KASSERT(sc->sc_child_state == VIRTIO_CHILD_ATTACH_FINISHED);
 	KASSERT(slotp != NULL);
 
 	slot = vq_alloc_slot(sc, vq, 1);
@@ -1059,7 +1070,8 @@ virtio_enqueue_reserve(struct virtio_sof
 	struct vring_desc_extra *vdx;
 	int i;
 
-	KASSERT(1 <= nsegs && nsegs <= vq->vq_num);
+	KASSERT(1 <= nsegs);
+	KASSERT(nsegs <= vq->vq_num);
 
 	vdx = &vq->vq_descx[slot];
 	vd = &vq->vq_desc[slot];

Index: src/sys/dev/pci/virtio_pci.c
diff -u src/sys/dev/pci/virtio_pci.c:1.38.4.3 src/sys/dev/pci/virtio_pci.c:1.38.4.4
--- src/sys/dev/pci/virtio_pci.c:1.38.4.3	Sun Jul  9 13:39:27 2023
+++ src/sys/dev/pci/virtio_pci.c	Wed Oct  2 18:20:48 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: virtio_pci.c,v 1.38.4.3 2023/07/09 13:39:27 martin Exp $ */
+/* $NetBSD: virtio_pci.c,v 1.38.4.4 2024/10/02 18:20:48 martin Exp $ */
 
 /*
  * Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -28,17 +28,18 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: virtio_pci.c,v 1.38.4.3 2023/07/09 13:39:27 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: virtio_pci.c,v 1.38.4.4 2024/10/02 18:20:48 martin Exp $");
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kmem.h>
-#include <sys/module.h>
+#include <sys/types.h>
+
+#include <sys/device.h>
 #include <sys/endian.h>
 #include <sys/interrupt.h>
+#include <sys/kmem.h>
+#include <sys/module.h>
 #include <sys/syslog.h>
-
-#include <sys/device.h>
+#include <sys/systm.h>
 
 #include <dev/pci/pcidevs.h>
 #include <dev/pci/pcireg.h>
@@ -68,7 +69,6 @@ static void	virtio_pci_attach(device_t, 
 static int	virtio_pci_rescan(device_t, const char *, const int *);
 static int	virtio_pci_detach(device_t, int);
 
-
 #define NMAPREG		((PCI_MAPREG_END - PCI_MAPREG_START) / \
 				sizeof(pcireg_t))
 struct virtio_pci_softc {
@@ -79,7 +79,6 @@ struct virtio_pci_softc {
 	bus_space_tag_t		sc_iot;
 	bus_space_handle_t	sc_ioh;
 	bus_size_t		sc_iosize;
-	bus_size_t		sc_mapped_iosize;
 
 	/* BARs */
 	bus_space_tag_t		sc_bars_iot[NMAPREG];
@@ -108,30 +107,35 @@ struct virtio_pci_softc {
 static int	virtio_pci_attach_09(device_t, void *);
 static void	virtio_pci_kick_09(struct virtio_softc *, uint16_t);
 static uint16_t	virtio_pci_read_queue_size_09(struct virtio_softc *, uint16_t);
-static void	virtio_pci_setup_queue_09(struct virtio_softc *, uint16_t, uint64_t);
+static void	virtio_pci_setup_queue_09(struct virtio_softc *, uint16_t,
+		    uint64_t);
 static void	virtio_pci_set_status_09(struct virtio_softc *, int);
-static void	virtio_pci_negotiate_features_09(struct virtio_softc *, uint64_t);
+static void	virtio_pci_negotiate_features_09(struct virtio_softc *,
+		    uint64_t);
 
 static int	virtio_pci_attach_10(device_t, void *);
 static void	virtio_pci_kick_10(struct virtio_softc *, uint16_t);
 static uint16_t	virtio_pci_read_queue_size_10(struct virtio_softc *, uint16_t);
-static void	virtio_pci_setup_queue_10(struct virtio_softc *, uint16_t, uint64_t);
+static void	virtio_pci_setup_queue_10(struct virtio_softc *, uint16_t,
+		    uint64_t);
 static void	virtio_pci_set_status_10(struct virtio_softc *, int);
-static void	virtio_pci_negotiate_features_10(struct virtio_softc *, uint64_t);
-static int	virtio_pci_find_cap(struct virtio_pci_softc *psc, int cfg_type, void *buf, int buflen);
+static void	virtio_pci_negotiate_features_10(struct virtio_softc *,
+		    uint64_t);
+static int	virtio_pci_find_cap(struct virtio_pci_softc *, int, void *,
+		    int);
 
 static int	virtio_pci_alloc_interrupts(struct virtio_softc *);
 static void	virtio_pci_free_interrupts(struct virtio_softc *);
-static int	virtio_pci_adjust_config_region(struct virtio_pci_softc *psc);
-static int	virtio_pci_intr(void *arg);
+static int	virtio_pci_adjust_config_region(struct virtio_pci_softc *);
+static int	virtio_pci_intr(void *);
 static int	virtio_pci_msix_queue_intr(void *);
 static int	virtio_pci_msix_config_intr(void *);
 static int	virtio_pci_setup_interrupts_09(struct virtio_softc *, int);
 static int	virtio_pci_setup_interrupts_10(struct virtio_softc *, int);
 static int	virtio_pci_establish_msix_interrupts(struct virtio_softc *,
-		    struct pci_attach_args *);
+		    const struct pci_attach_args *);
 static int	virtio_pci_establish_intx_interrupt(struct virtio_softc *,
-		    struct pci_attach_args *);
+		    const struct pci_attach_args *);
 static bool	virtio_pci_msix_enabled(struct virtio_pci_softc *);
 
 #define VIRTIO_MSIX_CONFIG_VECTOR_INDEX	0
@@ -163,10 +167,9 @@ static bool	virtio_pci_msix_enabled(stru
 #	define STRUCT_ENDIAN_10	LITTLE_ENDIAN
 #endif
 
-
 CFATTACH_DECL3_NEW(virtio_pci, sizeof(struct virtio_pci_softc),
     virtio_pci_match, virtio_pci_attach, virtio_pci_detach, NULL,
-    virtio_pci_rescan, NULL, DVF_DETACH_SHUTDOWN);
+    virtio_pci_rescan, NULL, 0);
 
 static const struct virtio_ops virtio_pci_ops_09 = {
 	.kick = virtio_pci_kick_09,
@@ -193,17 +196,16 @@ static const struct virtio_ops virtio_pc
 static int
 virtio_pci_match(device_t parent, cfdata_t match, void *aux)
 {
-	struct pci_attach_args *pa;
+	const struct pci_attach_args * const pa = aux;
 
-	pa = (struct pci_attach_args *)aux;
 	switch (PCI_VENDOR(pa->pa_id)) {
 	case PCI_VENDOR_QUMRANET:
 		/* Transitional devices MUST have a PCI Revision ID of 0. */
 		if (((PCI_PRODUCT_QUMRANET_VIRTIO_1000 <=
-		      PCI_PRODUCT(pa->pa_id)) &&
-		     (PCI_PRODUCT(pa->pa_id) <=
-		      PCI_PRODUCT_QUMRANET_VIRTIO_103F)) &&
-	              PCI_REVISION(pa->pa_class) == 0)
+			    PCI_PRODUCT(pa->pa_id)) &&
+			(PCI_PRODUCT(pa->pa_id) <=
+			    PCI_PRODUCT_QUMRANET_VIRTIO_103F)) &&
+		    PCI_REVISION(pa->pa_class) == 0)
 			return 1;
 		/*
 		 * Non-transitional devices SHOULD have a PCI Revision
@@ -211,11 +213,11 @@ virtio_pci_match(device_t parent, cfdata
 		 * Revision ID value.
 		 */
 		if (((PCI_PRODUCT_QUMRANET_VIRTIO_1040 <=
-		      PCI_PRODUCT(pa->pa_id)) &&
-		     (PCI_PRODUCT(pa->pa_id) <=
-		      PCI_PRODUCT_QUMRANET_VIRTIO_107F)) &&
-		      /* XXX: TODO */
-		      PCI_REVISION(pa->pa_class) == 1)
+			    PCI_PRODUCT(pa->pa_id)) &&
+			(PCI_PRODUCT(pa->pa_id) <=
+			    PCI_PRODUCT_QUMRANET_VIRTIO_107F)) &&
+		    /* XXX: TODO */
+		    PCI_REVISION(pa->pa_class) == 1)
 			return 1;
 		break;
 	}
@@ -228,7 +230,7 @@ virtio_pci_attach(device_t parent, devic
 {
 	struct virtio_pci_softc * const psc = device_private(self);
 	struct virtio_softc * const sc = &psc->sc_sc;
-	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
+	const struct pci_attach_args * const pa = aux;
 	pci_chipset_tag_t pc = pa->pa_pc;
 	pcitag_t tag = pa->pa_tag;
 	int revision;
@@ -248,7 +250,7 @@ virtio_pci_attach(device_t parent, devic
 		break;
 	default:
 		aprint_normal(": unknown revision 0x%02x; giving up\n",
-			      revision);
+		    revision);
 		return;
 	}
 
@@ -322,12 +324,12 @@ virtio_pci_rescan(device_t self, const c
 	return 0;
 }
 
-
 static int
 virtio_pci_detach(device_t self, int flags)
 {
 	struct virtio_pci_softc * const psc = device_private(self);
 	struct virtio_softc * const sc = &psc->sc_sc;
+	unsigned i;
 	int r;
 
 	r = config_detach_children(self, flags);
@@ -339,36 +341,42 @@ virtio_pci_detach(device_t self, int fla
 	KASSERT(sc->sc_vqs == NULL);
 	KASSERT(psc->sc_ihs_num == 0);
 
-	if (psc->sc_iosize)
-		bus_space_unmap(psc->sc_iot, psc->sc_ioh,
-			psc->sc_mapped_iosize);
-	psc->sc_iosize = 0;
+	if (sc->sc_version_1) {
+		for (i = 0; i < __arraycount(psc->sc_bars_iot); i++) {
+			if (psc->sc_bars_iosize[i] == 0)
+				continue;
+			bus_space_unmap(psc->sc_bars_iot[i],
+			    psc->sc_bars_ioh[i], psc->sc_bars_iosize[i]);
+			psc->sc_bars_iosize[i] = 0;
+		}
+	} else {
+		if (psc->sc_iosize) {
+			bus_space_unmap(psc->sc_iot, psc->sc_ioh,
+			    psc->sc_iosize);
+			psc->sc_iosize = 0;
+		}
+	}
 
 	return 0;
 }
 
-
 static int
 virtio_pci_attach_09(device_t self, void *aux)
-	//struct virtio_pci_softc *psc, struct pci_attach_args *pa)
 {
 	struct virtio_pci_softc * const psc = device_private(self);
-	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
+	const struct pci_attach_args * const pa = aux;
 	struct virtio_softc * const sc = &psc->sc_sc;
-//	pci_chipset_tag_t pc = pa->pa_pc;
-//	pcitag_t tag = pa->pa_tag;
 
 	/* complete IO region */
 	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0,
-			   &psc->sc_iot, &psc->sc_ioh, NULL, &psc->sc_iosize)) {
+		&psc->sc_iot, &psc->sc_ioh, NULL, &psc->sc_iosize)) {
 		aprint_error_dev(self, "can't map i/o space\n");
 		return EIO;
 	}
-	psc->sc_mapped_iosize = psc->sc_iosize;
 
 	/* queue space */
 	if (bus_space_subregion(psc->sc_iot, psc->sc_ioh,
-			VIRTIO_CONFIG_QUEUE_NOTIFY, 2, &psc->sc_notify_ioh)) {
+		VIRTIO_CONFIG_QUEUE_NOTIFY, 2, &psc->sc_notify_ioh)) {
 		aprint_error_dev(self, "can't map notify i/o space\n");
 		return EIO;
 	}
@@ -377,7 +385,7 @@ virtio_pci_attach_09(device_t self, void
 
 	/* ISR space */
 	if (bus_space_subregion(psc->sc_iot, psc->sc_ioh,
-			VIRTIO_CONFIG_ISR_STATUS, 1, &psc->sc_isr_ioh)) {
+		VIRTIO_CONFIG_ISR_STATUS, 1, &psc->sc_isr_ioh)) {
 		aprint_error_dev(self, "can't map isr i/o space\n");
 		return EIO;
 	}
@@ -386,40 +394,40 @@ virtio_pci_attach_09(device_t self, void
 
 	/* set our version 0.9 ops */
 	sc->sc_ops = &virtio_pci_ops_09;
-	sc->sc_bus_endian    = READ_ENDIAN_09;
+	sc->sc_bus_endian = READ_ENDIAN_09;
 	sc->sc_struct_endian = STRUCT_ENDIAN_09;
 	return 0;
 }
 
-
 static int
 virtio_pci_attach_10(device_t self, void *aux)
 {
 	struct virtio_pci_softc * const psc = device_private(self);
-	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
+	const struct pci_attach_args * const pa = aux;
 	struct virtio_softc * const sc = &psc->sc_sc;
-	pci_chipset_tag_t pc = pa->pa_pc;
-	pcitag_t tag = pa->pa_tag;
+	const pci_chipset_tag_t pc = pa->pa_pc;
+	const pcitag_t tag = pa->pa_tag;
 
 	struct virtio_pci_cap common, isr, device;
 	struct virtio_pci_notify_cap notify;
 	int have_device_cfg = 0;
 	bus_size_t bars[NMAPREG] = { 0 };
 	int bars_idx[NMAPREG] = { 0 };
-	struct virtio_pci_cap *caps[] = { &common, &isr, &device, &notify.cap };
+	struct virtio_pci_cap * const caps[] =
+	    { &common, &isr, &device, &notify.cap };
 	int i, j, ret = 0;
 
 	if (virtio_pci_find_cap(psc, VIRTIO_PCI_CAP_COMMON_CFG,
-			&common, sizeof(common)))
+		&common, sizeof(common)))
 		return ENODEV;
 	if (virtio_pci_find_cap(psc, VIRTIO_PCI_CAP_NOTIFY_CFG,
-			&notify, sizeof(notify)))
+		&notify, sizeof(notify)))
 		return ENODEV;
 	if (virtio_pci_find_cap(psc, VIRTIO_PCI_CAP_ISR_CFG,
-			&isr, sizeof(isr)))
+		&isr, sizeof(isr)))
 		return ENODEV;
 	if (virtio_pci_find_cap(psc, VIRTIO_PCI_CAP_DEVICE_CFG,
-			&device, sizeof(device)))
+		&device, sizeof(device)))
 		memset(&device, 0, sizeof(device));
 	else
 		have_device_cfg = 1;
@@ -428,6 +436,7 @@ virtio_pci_attach_10(device_t self, void
 	for (i = 0; i < __arraycount(caps); i++) {
 		int bar = caps[i]->bar;
 		bus_size_t len = caps[i]->offset + caps[i]->length;
+
 		if (caps[i]->length == 0)
 			continue;
 		if (bars[bar] < len)
@@ -437,13 +446,14 @@ virtio_pci_attach_10(device_t self, void
 	for (i = j = 0; i < __arraycount(bars); i++) {
 		int reg;
 		pcireg_t type;
+
 		if (bars[i] == 0)
 			continue;
 		reg = PCI_BAR(i);
 		type = pci_mapreg_type(pc, tag, reg);
 		if (pci_mapreg_map(pa, reg, type, 0,
-				&psc->sc_bars_iot[j], &psc->sc_bars_ioh[j],
-				NULL, &psc->sc_bars_iosize[j])) {
+			&psc->sc_bars_iot[j], &psc->sc_bars_ioh[j],
+			NULL, &psc->sc_bars_iosize[j])) {
 			aprint_error_dev(self, "can't map bar %u \n", i);
 			ret = EIO;
 			goto err;
@@ -457,8 +467,7 @@ virtio_pci_attach_10(device_t self, void
 
 	i = bars_idx[notify.cap.bar];
 	if (bus_space_subregion(psc->sc_bars_iot[i], psc->sc_bars_ioh[i],
-			notify.cap.offset, notify.cap.length,
-			&psc->sc_notify_ioh)) {
+		notify.cap.offset, notify.cap.length, &psc->sc_notify_ioh)) {
 		aprint_error_dev(self, "can't map notify i/o space\n");
 		ret = EIO;
 		goto err;
@@ -469,23 +478,23 @@ virtio_pci_attach_10(device_t self, void
 
 	if (have_device_cfg) {
 		i = bars_idx[device.bar];
-		if (bus_space_subregion(psc->sc_bars_iot[i], psc->sc_bars_ioh[i],
-				device.offset, device.length,
-				&sc->sc_devcfg_ioh)) {
+		if (bus_space_subregion(psc->sc_bars_iot[i],
+			psc->sc_bars_ioh[i], device.offset, device.length,
+			&sc->sc_devcfg_ioh)) {
 			aprint_error_dev(self, "can't map devcfg i/o space\n");
 			ret = EIO;
 			goto err;
 		}
 		aprint_debug_dev(self,
-			"device.offset = 0x%x, device.length = 0x%x\n",
-			device.offset, device.length);
+		    "device.offset = 0x%x, device.length = 0x%x\n",
+		    device.offset, device.length);
 		sc->sc_devcfg_iosize = device.length;
 		sc->sc_devcfg_iot = psc->sc_bars_iot[i];
 	}
 
 	i = bars_idx[isr.bar];
 	if (bus_space_subregion(psc->sc_bars_iot[i], psc->sc_bars_ioh[i],
-			isr.offset, isr.length, &psc->sc_isr_ioh)) {
+		isr.offset, isr.length, &psc->sc_isr_ioh)) {
 		aprint_error_dev(self, "can't map isr i/o space\n");
 		ret = EIO;
 		goto err;
@@ -495,37 +504,38 @@ virtio_pci_attach_10(device_t self, void
 
 	i = bars_idx[common.bar];
 	if (bus_space_subregion(psc->sc_bars_iot[i], psc->sc_bars_ioh[i],
-			common.offset, common.length, &psc->sc_ioh)) {
+		common.offset, common.length, &psc->sc_ioh)) {
 		aprint_error_dev(self, "can't map common i/o space\n");
 		ret = EIO;
 		goto err;
 	}
 	psc->sc_iosize = common.length;
 	psc->sc_iot = psc->sc_bars_iot[i];
-	psc->sc_mapped_iosize = psc->sc_bars_iosize[i];
 
 	psc->sc_sc.sc_version_1 = 1;
 
 	/* set our version 1.0 ops */
 	sc->sc_ops = &virtio_pci_ops_10;
-	sc->sc_bus_endian    = READ_ENDIAN_10;
+	sc->sc_bus_endian = READ_ENDIAN_10;
 	sc->sc_struct_endian = STRUCT_ENDIAN_10;
 	return 0;
 
 err:
-	/* undo our pci_mapreg_map()s */ 
+	/* undo our pci_mapreg_map()s */
 	for (i = 0; i < __arraycount(bars); i++) {
 		if (psc->sc_bars_iosize[i] == 0)
 			continue;
 		bus_space_unmap(psc->sc_bars_iot[i], psc->sc_bars_ioh[i],
-				psc->sc_bars_iosize[i]);
+		    psc->sc_bars_iosize[i]);
+		psc->sc_bars_iosize[i] = 0;
 	}
 	return ret;
 }
 
 /* v1.0 attach helper */
 static int
-virtio_pci_find_cap(struct virtio_pci_softc *psc, int cfg_type, void *buf, int buflen)
+virtio_pci_find_cap(struct virtio_pci_softc *psc, int cfg_type, void *buf,
+    int buflen)
 {
 	device_t self = psc->sc_sc.sc_dev;
 	pci_chipset_tag_t pc = psc->sc_pa.pa_pc;
@@ -539,13 +549,14 @@ virtio_pci_find_cap(struct virtio_pci_so
 	if (buflen < sizeof(struct virtio_pci_cap))
 		return ERANGE;
 
-	if (!pci_get_capability(pc, tag, PCI_CAP_VENDSPEC, &offset, &v->reg[0]))
+	if (!pci_get_capability(pc, tag, PCI_CAP_VENDSPEC, &offset,
+		&v->reg[0]))
 		return ENOENT;
 
 	do {
 		for (i = 0; i < 4; i++)
 			v->reg[i] =
-				le32toh(pci_conf_read(pc, tag, offset + i * 4));
+			    le32toh(pci_conf_read(pc, tag, offset + i * 4));
 		if (v->vcap.cfg_type == cfg_type)
 			break;
 		offset = v->vcap.cap_next;
@@ -562,7 +573,7 @@ virtio_pci_find_cap(struct virtio_pci_so
 		}
 		for (i = 4; i < len / sizeof(pcireg_t);  i++)
 			v->reg[i] =
-				le32toh(pci_conf_read(pc, tag, offset + i * 4));
+			    le32toh(pci_conf_read(pc, tag, offset + i * 4));
 	}
 
 	/* endian fixup */
@@ -571,7 +582,6 @@ virtio_pci_find_cap(struct virtio_pci_so
 	return 0;
 }
 
-
 /* -------------------------------------
  * Version 0.9 support
  * -------------------------------------*/
@@ -579,7 +589,8 @@ virtio_pci_find_cap(struct virtio_pci_so
 static void
 virtio_pci_kick_09(struct virtio_softc *sc, uint16_t idx)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 
 	bus_space_write_2(psc->sc_notify_iot, psc->sc_notify_ioh, 0, idx);
 }
@@ -597,8 +608,8 @@ virtio_pci_adjust_config_region(struct v
 	sc->sc_devcfg_iosize = psc->sc_iosize - psc->sc_devcfg_offset;
 	sc->sc_devcfg_iot = psc->sc_iot;
 	if (bus_space_subregion(psc->sc_iot, psc->sc_ioh,
-			psc->sc_devcfg_offset, sc->sc_devcfg_iosize,
-			&sc->sc_devcfg_ioh)) {
+		psc->sc_devcfg_offset, sc->sc_devcfg_iosize,
+		&sc->sc_devcfg_ioh)) {
 		aprint_error_dev(self, "can't map config i/o space\n");
 		return EIO;
 	}
@@ -609,7 +620,8 @@ virtio_pci_adjust_config_region(struct v
 static uint16_t
 virtio_pci_read_queue_size_09(struct virtio_softc *sc, uint16_t idx)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 
 	bus_space_write_2(psc->sc_iot, psc->sc_ioh,
 	    VIRTIO_CONFIG_QUEUE_SELECT, idx);
@@ -620,7 +632,8 @@ virtio_pci_read_queue_size_09(struct vir
 static void
 virtio_pci_setup_queue_09(struct virtio_softc *sc, uint16_t idx, uint64_t addr)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 
 	bus_space_write_2(psc->sc_iot, psc->sc_ioh,
 	    VIRTIO_CONFIG_QUEUE_SELECT, idx);
@@ -639,21 +652,24 @@ virtio_pci_setup_queue_09(struct virtio_
 static void
 virtio_pci_set_status_09(struct virtio_softc *sc, int status)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 	int old = 0;
 
 	if (status != 0) {
-	    old = bus_space_read_1(psc->sc_iot, psc->sc_ioh,
-		VIRTIO_CONFIG_DEVICE_STATUS);
+		old = bus_space_read_1(psc->sc_iot, psc->sc_ioh,
+		    VIRTIO_CONFIG_DEVICE_STATUS);
 	}
 	bus_space_write_1(psc->sc_iot, psc->sc_ioh,
 	    VIRTIO_CONFIG_DEVICE_STATUS, status|old);
 }
 
 static void
-virtio_pci_negotiate_features_09(struct virtio_softc *sc, uint64_t guest_features)
+virtio_pci_negotiate_features_09(struct virtio_softc *sc,
+    uint64_t guest_features)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 	uint32_t r;
 
 	r = bus_space_read_4(psc->sc_iot, psc->sc_ioh,
@@ -674,19 +690,20 @@ virtio_pci_negotiate_features_09(struct 
 static void
 virtio_pci_kick_10(struct virtio_softc *sc, uint16_t idx)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 	unsigned offset = sc->sc_vqs[idx].vq_notify_off *
-		psc->sc_notify_off_multiplier;
+	    psc->sc_notify_off_multiplier;
 
 	bus_space_write_2(psc->sc_notify_iot, psc->sc_notify_ioh, offset, idx);
 }
 
-
 static uint16_t
 virtio_pci_read_queue_size_10(struct virtio_softc *sc, uint16_t idx)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
-	bus_space_tag_t	   iot = psc->sc_iot;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
+	bus_space_tag_t iot = psc->sc_iot;
 	bus_space_handle_t ioh = psc->sc_ioh;
 
 	bus_space_write_2(iot, ioh, VIRTIO_CONFIG1_QUEUE_SELECT, idx);
@@ -707,7 +724,7 @@ virtio_pci_read_queue_size_10(struct vir
  */
 static __inline void
 virtio_pci_bus_space_write_8(bus_space_tag_t iot, bus_space_handle_t ioh,
-     bus_size_t offset, uint64_t value)
+    bus_size_t offset, uint64_t value)
 {
 #if _QUAD_HIGHWORD
 	bus_space_write_4(iot, ioh, offset, BUS_ADDR_LO32(value));
@@ -721,9 +738,10 @@ virtio_pci_bus_space_write_8(bus_space_t
 static void
 virtio_pci_setup_queue_10(struct virtio_softc *sc, uint16_t idx, uint64_t addr)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 	struct virtqueue *vq = &sc->sc_vqs[idx];
-	bus_space_tag_t	   iot = psc->sc_iot;
+	bus_space_tag_t iot = psc->sc_iot;
 	bus_space_handle_t ioh = psc->sc_ioh;
 	KASSERT(vq->vq_index == idx);
 
@@ -731,22 +749,22 @@ virtio_pci_setup_queue_10(struct virtio_
 	if (addr == 0) {
 		bus_space_write_2(iot, ioh, VIRTIO_CONFIG1_QUEUE_ENABLE, 0);
 		virtio_pci_bus_space_write_8(iot, ioh,
-		    VIRTIO_CONFIG1_QUEUE_DESC,   0);
+		    VIRTIO_CONFIG1_QUEUE_DESC, 0);
 		virtio_pci_bus_space_write_8(iot, ioh,
-		    VIRTIO_CONFIG1_QUEUE_AVAIL,  0);
+		    VIRTIO_CONFIG1_QUEUE_AVAIL, 0);
 		virtio_pci_bus_space_write_8(iot, ioh,
-		    VIRTIO_CONFIG1_QUEUE_USED,   0);
+		    VIRTIO_CONFIG1_QUEUE_USED, 0);
 	} else {
 		virtio_pci_bus_space_write_8(iot, ioh,
-			VIRTIO_CONFIG1_QUEUE_DESC, addr);
+		    VIRTIO_CONFIG1_QUEUE_DESC, addr);
 		virtio_pci_bus_space_write_8(iot, ioh,
-			VIRTIO_CONFIG1_QUEUE_AVAIL, addr + vq->vq_availoffset);
+		    VIRTIO_CONFIG1_QUEUE_AVAIL, addr + vq->vq_availoffset);
 		virtio_pci_bus_space_write_8(iot, ioh,
-			VIRTIO_CONFIG1_QUEUE_USED, addr + vq->vq_usedoffset);
+		    VIRTIO_CONFIG1_QUEUE_USED, addr + vq->vq_usedoffset);
 		bus_space_write_2(iot, ioh,
-			VIRTIO_CONFIG1_QUEUE_ENABLE, 1);
+		    VIRTIO_CONFIG1_QUEUE_ENABLE, 1);
 		vq->vq_notify_off = bus_space_read_2(iot, ioh,
-			VIRTIO_CONFIG1_QUEUE_NOTIFY_OFF);
+		    VIRTIO_CONFIG1_QUEUE_NOTIFY_OFF);
 	}
 
 	if (psc->sc_ihs_num > 1) {
@@ -754,29 +772,33 @@ virtio_pci_setup_queue_10(struct virtio_
 		if (psc->sc_intr_pervq)
 			vec += idx;
 		bus_space_write_2(iot, ioh,
-			VIRTIO_CONFIG1_QUEUE_MSIX_VECTOR, vec);
+		    VIRTIO_CONFIG1_QUEUE_MSIX_VECTOR, vec);
 	}
 }
 
 static void
 virtio_pci_set_status_10(struct virtio_softc *sc, int status)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
-	bus_space_tag_t	   iot = psc->sc_iot;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
+	bus_space_tag_t iot = psc->sc_iot;
 	bus_space_handle_t ioh = psc->sc_ioh;
 	int old = 0;
 
 	if (status)
 		old = bus_space_read_1(iot, ioh, VIRTIO_CONFIG1_DEVICE_STATUS);
-	bus_space_write_1(iot, ioh, VIRTIO_CONFIG1_DEVICE_STATUS, status | old);
+	bus_space_write_1(iot, ioh, VIRTIO_CONFIG1_DEVICE_STATUS,
+	    status | old);
 }
 
 void
-virtio_pci_negotiate_features_10(struct virtio_softc *sc, uint64_t guest_features)
+virtio_pci_negotiate_features_10(struct virtio_softc *sc,
+    uint64_t guest_features)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
-	device_t self          =  sc->sc_dev;
-	bus_space_tag_t	   iot = psc->sc_iot;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
+	device_t self = sc->sc_dev;
+	bus_space_tag_t iot = psc->sc_iot;
 	bus_space_handle_t ioh = psc->sc_ioh;
 	uint64_t host, negotiated, device_status;
 
@@ -788,31 +810,32 @@ virtio_pci_negotiate_features_10(struct 
 	bus_space_write_4(iot, ioh, VIRTIO_CONFIG1_DEVICE_FEATURE_SELECT, 0);
 	host = bus_space_read_4(iot, ioh, VIRTIO_CONFIG1_DEVICE_FEATURE);
 	bus_space_write_4(iot, ioh, VIRTIO_CONFIG1_DEVICE_FEATURE_SELECT, 1);
-	host |= (uint64_t)
-		bus_space_read_4(iot, ioh, VIRTIO_CONFIG1_DEVICE_FEATURE) << 32;
+	host |= (uint64_t)bus_space_read_4(iot, ioh,
+	    VIRTIO_CONFIG1_DEVICE_FEATURE) << 32;
 
 	negotiated = host & guest_features;
 
 	bus_space_write_4(iot, ioh, VIRTIO_CONFIG1_DRIVER_FEATURE_SELECT, 0);
 	bus_space_write_4(iot, ioh, VIRTIO_CONFIG1_DRIVER_FEATURE,
-			negotiated & 0xffffffff);
+	    negotiated & 0xffffffff);
 	bus_space_write_4(iot, ioh, VIRTIO_CONFIG1_DRIVER_FEATURE_SELECT, 1);
 	bus_space_write_4(iot, ioh, VIRTIO_CONFIG1_DRIVER_FEATURE,
-			negotiated >> 32);
+	    negotiated >> 32);
 	virtio_pci_set_status_10(sc, VIRTIO_CONFIG_DEVICE_STATUS_FEATURES_OK);
 
-	device_status = bus_space_read_1(iot, ioh, VIRTIO_CONFIG1_DEVICE_STATUS);
+	device_status = bus_space_read_1(iot, ioh,
+	    VIRTIO_CONFIG1_DEVICE_STATUS);
 	if ((device_status & VIRTIO_CONFIG_DEVICE_STATUS_FEATURES_OK) == 0) {
 		aprint_error_dev(self, "feature negotiation failed\n");
 		bus_space_write_1(iot, ioh, VIRTIO_CONFIG1_DEVICE_STATUS,
-				VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
+		    VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
 		return;
 	}
 
 	if ((negotiated & VIRTIO_F_VERSION_1) == 0) {
 		aprint_error_dev(self, "host rejected version 1\n");
 		bus_space_write_1(iot, ioh, VIRTIO_CONFIG1_DEVICE_STATUS,
-				VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
+		    VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
 		return;
 	}
 
@@ -820,7 +843,6 @@ virtio_pci_negotiate_features_10(struct 
 	return;
 }
 
-
 /* -------------------------------------
  * Generic PCI interrupt code
  * -------------------------------------*/
@@ -828,8 +850,9 @@ virtio_pci_negotiate_features_10(struct 
 static int
 virtio_pci_setup_interrupts_10(struct virtio_softc *sc, int reinit)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
-	bus_space_tag_t	   iot = psc->sc_iot;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
+	bus_space_tag_t iot = psc->sc_iot;
 	bus_space_handle_t ioh = psc->sc_ioh;
 	int vector, ret, qid;
 
@@ -837,12 +860,10 @@ virtio_pci_setup_interrupts_10(struct vi
 		return 0;
 
 	vector = VIRTIO_MSIX_CONFIG_VECTOR_INDEX;
-	bus_space_write_2(iot, ioh,
-		VIRTIO_CONFIG1_CONFIG_MSIX_VECTOR, vector);
+	bus_space_write_2(iot, ioh, VIRTIO_CONFIG1_CONFIG_MSIX_VECTOR, vector);
 	ret = bus_space_read_2(iot, ioh, VIRTIO_CONFIG1_CONFIG_MSIX_VECTOR);
 	if (ret != vector) {
-		VIRTIO_PCI_LOG(sc, reinit,
-		    "can't set config msix vector\n");
+		VIRTIO_PCI_LOG(sc, reinit, "can't set config msix vector\n");
 		return -1;
 	}
 
@@ -853,9 +874,9 @@ virtio_pci_setup_interrupts_10(struct vi
 			vector += qid;
 		bus_space_write_2(iot, ioh, VIRTIO_CONFIG1_QUEUE_SELECT, qid);
 		bus_space_write_2(iot, ioh, VIRTIO_CONFIG1_QUEUE_MSIX_VECTOR,
-			vector);
+		    vector);
 		ret = bus_space_read_2(iot, ioh,
-			VIRTIO_CONFIG1_QUEUE_MSIX_VECTOR);
+		    VIRTIO_CONFIG1_QUEUE_MSIX_VECTOR);
 		if (ret != vector) {
 			VIRTIO_PCI_LOG(sc, reinit, "can't set queue %d "
 			    "msix vector\n", qid);
@@ -869,7 +890,8 @@ virtio_pci_setup_interrupts_10(struct vi
 static int
 virtio_pci_setup_interrupts_09(struct virtio_softc *sc, int reinit)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 	int offset, vector, ret, qid;
 
 	if (!virtio_pci_msix_enabled(psc))
@@ -915,9 +937,10 @@ virtio_pci_setup_interrupts_09(struct vi
 
 static int
 virtio_pci_establish_msix_interrupts(struct virtio_softc *sc,
-    struct pci_attach_args *pa)
+    const struct pci_attach_args *pa)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 	device_t self = sc->sc_dev;
 	pci_chipset_tag_t pc = pa->pa_pc;
 	struct virtqueue *vq;
@@ -936,7 +959,8 @@ virtio_pci_establish_msix_interrupts(str
 	psc->sc_ihs[idx] = pci_intr_establish_xname(pc, psc->sc_ihp[idx],
 	    sc->sc_ipl, virtio_pci_msix_config_intr, sc, intr_xname);
 	if (psc->sc_ihs[idx] == NULL) {
-		aprint_error_dev(self, "couldn't establish MSI-X for config\n");
+		aprint_error_dev(self,
+		    "couldn't establish MSI-X for config\n");
 		goto error;
 	}
 
@@ -954,29 +978,36 @@ virtio_pci_establish_msix_interrupts(str
 				    PCI_INTR_MPSAFE, true);
 			}
 
-			psc->sc_ihs[n] = pci_intr_establish_xname(pc, psc->sc_ihp[n],
-			    sc->sc_ipl, vq->vq_intrhand, vq->vq_intrhand_arg, intr_xname);
+			psc->sc_ihs[n] = pci_intr_establish_xname(pc,
+			    psc->sc_ihp[n], sc->sc_ipl,
+			    vq->vq_intrhand, vq->vq_intrhand_arg, intr_xname);
 			if (psc->sc_ihs[n] == NULL) {
-				aprint_error_dev(self, "couldn't establish MSI-X for a vq\n");
+				aprint_error_dev(self,
+				    "couldn't establish MSI-X for a vq\n");
 				goto error;
 			}
 		}
 	} else {
-		if (sc->sc_flags & VIRTIO_F_INTR_MPSAFE)
-			pci_intr_setattr(pc, &psc->sc_ihp[idx], PCI_INTR_MPSAFE, true);
+		if (sc->sc_flags & VIRTIO_F_INTR_MPSAFE) {
+			pci_intr_setattr(pc, &psc->sc_ihp[idx],
+			    PCI_INTR_MPSAFE, true);
+		}
 
 		snprintf(intr_xname, sizeof(intr_xname), "%s queues",
 		    device_xname(sc->sc_dev));
-		psc->sc_ihs[idx] = pci_intr_establish_xname(pc, psc->sc_ihp[idx],
-		    sc->sc_ipl, virtio_pci_msix_queue_intr, sc, intr_xname);
+		psc->sc_ihs[idx] = pci_intr_establish_xname(pc,
+		    psc->sc_ihp[idx], sc->sc_ipl,
+		    virtio_pci_msix_queue_intr, sc, intr_xname);
 		if (psc->sc_ihs[idx] == NULL) {
-			aprint_error_dev(self, "couldn't establish MSI-X for queues\n");
+			aprint_error_dev(self,
+			    "couldn't establish MSI-X for queues\n");
 			goto error;
 		}
 	}
 
 	idx = VIRTIO_MSIX_CONFIG_VECTOR_INDEX;
-	intrstr = pci_intr_string(pc, psc->sc_ihp[idx], intrbuf, sizeof(intrbuf));
+	intrstr = pci_intr_string(pc, psc->sc_ihp[idx], intrbuf,
+	    sizeof(intrbuf));
 	aprint_normal_dev(self, "config interrupting at %s\n", intrstr);
 	idx = VIRTIO_MSIX_QUEUE_VECTOR_INDEX;
 	if (psc->sc_intr_pervq) {
@@ -994,10 +1025,12 @@ virtio_pci_establish_msix_interrupts(str
 
 			kcpuset_zero(affinity);
 			kcpuset_set(affinity, affinity_to);
-			r = interrupt_distribute(psc->sc_ihs[n], affinity, NULL);
+			r = interrupt_distribute(psc->sc_ihs[n], affinity,
+			    NULL);
 			if (r == 0) {
 				aprint_normal_dev(self,
-				    "for vq #%d interrupting at %s affinity to %u\n",
+				    "for vq #%d interrupting at %s"
+				    " affinity to %u\n",
 				    qid, intrstr, affinity_to);
 			} else {
 				aprint_normal_dev(self,
@@ -1008,8 +1041,10 @@ virtio_pci_establish_msix_interrupts(str
 
 		kcpuset_destroy(affinity);
 	} else {
-		intrstr = pci_intr_string(pc, psc->sc_ihp[idx], intrbuf, sizeof(intrbuf));
-		aprint_normal_dev(self, "queues interrupting at %s\n", intrstr);
+		intrstr = pci_intr_string(pc, psc->sc_ihp[idx], intrbuf,
+		    sizeof(intrbuf));
+		aprint_normal_dev(self, "queues interrupting at %s\n",
+		    intrstr);
 	}
 
 	return 0;
@@ -1024,12 +1059,15 @@ error:
 			n = idx + qid;
 			if (psc->sc_ihs[n] == NULL)
 				continue;
-			pci_intr_disestablish(psc->sc_pa.pa_pc, psc->sc_ihs[n]);
+			pci_intr_disestablish(psc->sc_pa.pa_pc,
+			    psc->sc_ihs[n]);
 		}
 
 	} else {
-		if (psc->sc_ihs[idx] != NULL)
-			pci_intr_disestablish(psc->sc_pa.pa_pc, psc->sc_ihs[idx]);
+		if (psc->sc_ihs[idx] != NULL) {
+			pci_intr_disestablish(psc->sc_pa.pa_pc,
+			    psc->sc_ihs[idx]);
+		}
 	}
 
 	return -1;
@@ -1037,9 +1075,10 @@ error:
 
 static int
 virtio_pci_establish_intx_interrupt(struct virtio_softc *sc,
-    struct pci_attach_args *pa)
+    const struct pci_attach_args *pa)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 	device_t self = sc->sc_dev;
 	pci_chipset_tag_t pc = pa->pa_pc;
 	char intrbuf[PCI_INTRSTR_LEN];
@@ -1055,7 +1094,8 @@ virtio_pci_establish_intx_interrupt(stru
 		return -1;
 	}
 
-	intrstr = pci_intr_string(pc, psc->sc_ihp[0], intrbuf, sizeof(intrbuf));
+	intrstr = pci_intr_string(pc, psc->sc_ihp[0], intrbuf,
+	    sizeof(intrbuf));
 	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
 
 	return 0;
@@ -1064,7 +1104,8 @@ virtio_pci_establish_intx_interrupt(stru
 static int
 virtio_pci_alloc_interrupts(struct virtio_softc *sc)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 	device_t self = sc->sc_dev;
 	pci_chipset_tag_t pc = psc->sc_pa.pa_pc;
 	pcitag_t tag = psc->sc_pa.pa_tag;
@@ -1156,7 +1197,8 @@ retry:
 static void
 virtio_pci_free_interrupts(struct virtio_softc *sc)
 {
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 
 	for (int i = 0; i < psc->sc_ihs_num; i++) {
 		if (psc->sc_ihs[i] == NULL)
@@ -1165,8 +1207,10 @@ virtio_pci_free_interrupts(struct virtio
 		psc->sc_ihs[i] = NULL;
 	}
 
-	if (psc->sc_ihs_num > 0)
-		pci_intr_release(psc->sc_pa.pa_pc, psc->sc_ihp, psc->sc_ihs_num);
+	if (psc->sc_ihs_num > 0) {
+		pci_intr_release(psc->sc_pa.pa_pc, psc->sc_ihp,
+		    psc->sc_ihs_num);
+	}
 
 	if (psc->sc_ihs != NULL) {
 		kmem_free(psc->sc_ihs, sizeof(*psc->sc_ihs) * psc->sc_ihs_num);
@@ -1193,7 +1237,8 @@ static int
 virtio_pci_intr(void *arg)
 {
 	struct virtio_softc *sc = arg;
-	struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
+	struct virtio_pci_softc * const psc = container_of(sc,
+	    struct virtio_pci_softc, sc_sc);
 	int isr, r = 0;
 
 	/* check and ack the interrupt */

Index: src/sys/dev/virtio/viocon.c
diff -u src/sys/dev/virtio/viocon.c:1.5.4.2 src/sys/dev/virtio/viocon.c:1.5.4.3
--- src/sys/dev/virtio/viocon.c:1.5.4.2	Wed Aug  7 11:05:22 2024
+++ src/sys/dev/virtio/viocon.c	Wed Oct  2 18:20:48 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: viocon.c,v 1.5.4.2 2024/08/07 11:05:22 martin Exp $	*/
+/*	$NetBSD: viocon.c,v 1.5.4.3 2024/10/02 18:20:48 martin Exp $	*/
 /*	$OpenBSD: viocon.c,v 1.8 2021/11/05 11:38:29 mpi Exp $	*/
 
 /*
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.5.4.2 2024/08/07 11:05:22 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.5.4.3 2024/10/02 18:20:48 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -378,7 +378,7 @@ viocon_rx_fill(struct viocon_port *vp)
 		virtio_enqueue_commit(vsc, vq, slot, 0);
 		ndone++;
 	}
-	KASSERT(r == 0 || r == EAGAIN);
+	KASSERTMSG(r == 0 || r == EAGAIN, "r=%d", r);
 	if (ndone > 0)
 		virtio_notify(vsc, vq);
 }
@@ -454,9 +454,9 @@ vioconstart(struct tty *tp)
 			SET(tp->t_state, TS_BUSY);
 			break;
 		}
-		KASSERT(ret == 0);
+		KASSERTMSG(ret == 0, "ret=%d", ret);
 		ret = virtio_enqueue_reserve(vsc, vq, slot, 1);
-		KASSERT(ret == 0);
+		KASSERTMSG(ret == 0, "ret=%d", ret);
 		buf = vp->vp_tx_buf + slot * BUFSIZE;
 		cnt = q_to_b(&tp->t_outq, buf, BUFSIZE);
 		bus_dmamap_sync(virtio_dmat(vsc), vp->vp_dmamap,

Reply via email to