svn commit: r226826 - in projects/virtio/sys/dev/virtio: block network pci

Peter Grehan grehan at FreeBSD.org
Thu Oct 27 05:48:21 UTC 2011


Author: grehan
Date: Thu Oct 27 05:48:21 2011
New Revision: 226826
URL: http://svn.freebsd.org/changeset/base/226826

Log:
  Sync to change #162500 in Bryan Venteicher's hg repo

Modified:
  projects/virtio/sys/dev/virtio/block/virtio_blk.c
  projects/virtio/sys/dev/virtio/network/if_vtnet.c
  projects/virtio/sys/dev/virtio/pci/virtio_pci.c

Modified: projects/virtio/sys/dev/virtio/block/virtio_blk.c
==============================================================================
--- projects/virtio/sys/dev/virtio/block/virtio_blk.c	Thu Oct 27 04:56:53 2011	(r226825)
+++ projects/virtio/sys/dev/virtio/block/virtio_blk.c	Thu Oct 27 05:48:21 2011	(r226826)
@@ -124,6 +124,7 @@ static int	vtblk_maximum_segments(struct
 static int	vtblk_alloc_virtqueue(struct vtblk_softc *);
 static void	vtblk_alloc_disk(struct vtblk_softc *,
 		    struct virtio_blk_config *);
+static void	vtblk_create_disk(struct vtblk_softc *);
 
 static int	vtblk_open(struct disk *);
 static int	vtblk_close(struct disk *);
@@ -365,8 +366,7 @@ vtblk_attach(device_t dev)
 		goto fail;
 	}
 
-	if (vtblk_no_ident == 0)
-		vtblk_get_ident(sc);
+	vtblk_create_disk(sc);
 
 	virtqueue_enable_intr(sc->vtblk_vq);
 
@@ -541,7 +541,8 @@ vtblk_strategy(struct bio *bp)
 
 	/*
 	 * Prevent read/write buffers spanning too many segments from
-	 * getting into the queue.
+	 * 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 -
@@ -642,7 +643,7 @@ vtblk_alloc_disk(struct vtblk_softc *sc,
 	 * by physically contiguous pages. Therefore, we have to assume
 	 * no pages are contiguous. This may impose an artificially low
 	 * maximum I/O size. But in practice, since QEMU advertises 128
-	 * segments, this gives us a maxinum IO size of 125 * PAGE_SIZE,
+	 * segments, this gives us a maximum IO size of 125 * PAGE_SIZE,
 	 * which is typically greater than MAXPHYS. Eventually we should
 	 * just advertise MAXPHYS and split buffers that are too big.
 	 *
@@ -661,6 +662,25 @@ vtblk_alloc_disk(struct vtblk_softc *sc,
 
 	if (virtio_with_feature(dev, VIRTIO_BLK_F_FLUSH))
 		dp->d_flags |= DISKFLAG_CANFLUSHCACHE;
+}
+
+static void
+vtblk_create_disk(struct vtblk_softc *sc)
+{
+	struct disk *dp;
+
+	dp = sc->vtblk_disk;
+
+	/*
+	 * Retrieving the identification string must be done after
+	 * the virtqueue interrupt is setup otherwise it will hang.
+	 */
+	vtblk_get_ident(sc);
+
+	device_printf(sc->vtblk_dev, "%juMB (%ju %u byte sectors)\n",
+	    (uintmax_t) dp->d_mediasize >> 20,
+	    (uintmax_t) dp->d_mediasize / dp->d_sectorsize,
+	    dp->d_sectorsize);
 
 	disk_create(dp, DISK_VERSION);
 }
@@ -864,6 +884,9 @@ vtblk_get_ident(struct vtblk_softc *sc)
 	dp = sc->vtblk_disk;
 	len = MIN(VIRTIO_BLK_ID_BYTES, DISK_IDENT_SIZE);
 
+	if (vtblk_no_ident != 0)
+		return;
+
 	req = vtblk_dequeue_request(sc);
 	if (req == NULL)
 		return;

Modified: projects/virtio/sys/dev/virtio/network/if_vtnet.c
==============================================================================
--- projects/virtio/sys/dev/virtio/network/if_vtnet.c	Thu Oct 27 04:56:53 2011	(r226825)
+++ projects/virtio/sys/dev/virtio/network/if_vtnet.c	Thu Oct 27 05:48:21 2011	(r226826)
@@ -94,6 +94,7 @@ static void	vtnet_negotiate_features(str
 static int	vtnet_alloc_virtqueues(struct vtnet_softc *);
 static void	vtnet_get_hwaddr(struct vtnet_softc *);
 static void	vtnet_set_hwaddr(struct vtnet_softc *);
+static int	vtnet_is_link_up(struct vtnet_softc *);
 static void	vtnet_update_link_status(struct vtnet_softc *);
 static void	vtnet_watchdog(struct vtnet_softc *);
 static void	vtnet_config_change_task(void *, int);
@@ -611,29 +612,24 @@ vtnet_negotiate_features(struct vtnet_so
 	if (virtio_with_feature(dev, VIRTIO_NET_F_MRG_RXBUF) == 0 &&
 	    virtio_with_feature(dev, VTNET_LRO_FEATURES)) {
 		/*
-		 * LRO without mergeable buffers requires special handling.
-		 * Unfortunately, this configuration is less than ideal since
-		 * each receive buffer must be large enough to maximum TCP
-		 * packet along with the Ethernet header and vtnet_rx_header.
-		 * This requires 34 descriptors when using MCLBYTES clusters.
-		 *
-		 * The QEMU and vhost receive virtqueue are 256 descriptors
-		 * big. This means that unless indirect descriptors are
-		 * negotiated, the receive queue can only hold seven buffers.
-		 * Therefore LRO is disabled unless indirect descriptors are
-		 * available.
+		 * LRO without mergeable buffers requires special care. This
+		 * is not ideal because every receive buffer must be large
+		 * enough to hold the maximum TCP packet, the Ethernet header,
+		 * and the vtnet_rx_header. This requires up to 34 descriptors
+		 * when using MCLBYTES clusters. If we do not have indirect
+		 * descriptors, LRO is disabled since the virtqueue will not
+		 * be able to contain very many receive buffers.
 		 */
+		if (virtio_with_feature(dev,
+		    VIRTIO_RING_F_INDIRECT_DESC) == 0) {
+			device_printf(dev,
+			    "LRO disabled due to lack of both mergeable "
+			    "buffers and indirect descriptors\n");
 
-		if (virtio_with_feature(dev, VIRTIO_RING_F_INDIRECT_DESC))
-			sc->vtnet_flags |= VTNET_FLAG_LRO_NOMRG;
-		else {
 			sc->vtnet_features = virtio_negotiate_features(dev,
 			    features & ~VTNET_LRO_FEATURES);
-
-			device_printf(dev, "LRO disbled because mergeable "
-			    "buffers and indirect descriptors were not "
-			    "negotiated\n");
-		}
+		} else
+			sc->vtnet_flags |= VTNET_FLAG_LRO_NOMRG;
 	}
 }
 
@@ -711,12 +707,11 @@ vtnet_set_hwaddr(struct vtnet_softc *sc)
 	    sc->vtnet_hwaddr, ETHER_ADDR_LEN);
 }
 
-static void
-vtnet_update_link_status(struct vtnet_softc *sc)
+static int
+vtnet_is_link_up(struct vtnet_softc *sc)
 {
 	device_t dev;
 	struct ifnet *ifp;
-	int link;
 	uint16_t status;
 
 	dev = sc->vtnet_dev;
@@ -724,15 +719,26 @@ vtnet_update_link_status(struct vtnet_so
 
 	VTNET_LOCK_ASSERT(sc);
 
-	if (ifp->if_capenable & IFCAP_LINKSTATE) {
-		status = virtio_read_dev_config_2(dev,
-		    offsetof(struct virtio_net_config, status));
-		if (status & VIRTIO_NET_S_LINK_UP)
-			link = 1;
-		else
-			link = 0;
-	} else
-		link = 1;
+	if ((ifp->if_capenable & IFCAP_LINKSTATE) == 0)
+		return (1);
+
+	status = virtio_read_dev_config_2(dev,
+	    offsetof(struct virtio_net_config, status));
+
+	return ((status & VIRTIO_NET_S_LINK_UP) != 0);
+}
+
+static void
+vtnet_update_link_status(struct vtnet_softc *sc)
+{
+	device_t dev;
+	struct ifnet *ifp;
+	int link;
+
+	dev = sc->vtnet_dev;
+	ifp = sc->vtnet_ifp;
+
+	link = vtnet_is_link_up(sc);
 
 	if (link && ((sc->vtnet_flags & VTNET_FLAG_LINK) == 0)) {
 		sc->vtnet_flags |= VTNET_FLAG_LINK;
@@ -2630,7 +2636,7 @@ vtnet_ifmedia_sts(struct ifnet *ifp, str
 	ifmr->ifm_active = IFM_ETHER;
 
 	VTNET_LOCK(sc);
-	if (sc->vtnet_flags & VTNET_FLAG_LINK) {
+	if (vtnet_is_link_up(sc) != 0) {
 		ifmr->ifm_status |= IFM_ACTIVE;
 		ifmr->ifm_active |= VTNET_MEDIATYPE;
 	} else
@@ -2692,6 +2698,9 @@ vtnet_add_statistics(struct vtnet_softc 
 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_csum_offloaded",
 	    CTLFLAG_RD, &stats->tx_csum_offloaded,
 	    "Offloaded checksum of transmitted buffer");
+	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_tso_offloaded",
+	    CTLFLAG_RD, &stats->tx_tso_offloaded,
+	    "Segmentation offload of transmitted buffer");
 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_csum_bad_ethtype",
 	    CTLFLAG_RD, &stats->tx_csum_bad_ethtype,
 	    "Aborted transmit of checksum offloaded buffer with unknown "

Modified: projects/virtio/sys/dev/virtio/pci/virtio_pci.c
==============================================================================
--- projects/virtio/sys/dev/virtio/pci/virtio_pci.c	Thu Oct 27 04:56:53 2011	(r226825)
+++ projects/virtio/sys/dev/virtio/pci/virtio_pci.c	Thu Oct 27 05:48:21 2011	(r226826)
@@ -126,6 +126,8 @@ static void	vtpci_set_status(device_t, u
 static void	vtpci_read_dev_config(device_t, bus_size_t, void *, int);
 static void	vtpci_write_dev_config(device_t, bus_size_t, void *, int);
 
+static void	vtpci_describe_features(struct vtpci_softc *, const char *,
+		    uint64_t);
 static void	vtpci_probe_and_attach_child(struct vtpci_softc *);
 
 static int	vtpci_alloc_interrupts(struct vtpci_softc *, int, int,
@@ -409,22 +411,18 @@ vtpci_negotiate_features(device_t dev, u
 	sc = device_get_softc(dev);
 
 	host_features = vtpci_read_config_4(sc, VIRTIO_PCI_HOST_FEATURES);
-	if (bootverbose)
-		virtio_describe(dev, "available", host_features,
-		    sc->vtpci_child_feat_desc);
+	vtpci_describe_features(sc, "host", host_features);
 
 	/*
-	 * Limit negotiated features to what the host, guest, and
-	 * virtqueue all support.
+	 * Limit negotiated features to what the driver, virtqueue, and
+	 * host all support.
 	 */
 	features = host_features & child_features;
 	features = virtqueue_filter_features(features);
 	sc->vtpci_features = features;
-	vtpci_write_config_4(sc, VIRTIO_PCI_GUEST_FEATURES, features);
 
-	if (bootverbose)
-		virtio_describe(dev, "negotiated", features,
-		    sc->vtpci_child_feat_desc);
+	vtpci_describe_features(sc, "negotiated", features);
+	vtpci_write_config_4(sc, VIRTIO_PCI_GUEST_FEATURES, features);
 
 	return (features);
 }
@@ -710,6 +708,21 @@ vtpci_write_dev_config(device_t dev, bus
 }
 
 static void
+vtpci_describe_features(struct vtpci_softc *sc, const char *msg,
+    uint64_t features)
+{
+	device_t dev, child;
+
+	dev = sc->vtpci_dev;
+	child = sc->vtpci_child_dev;
+
+	if (device_is_attached(child) && bootverbose == 0)
+		return;
+
+	virtio_describe(dev, msg, features, sc->vtpci_child_feat_desc);
+}
+
+static void
 vtpci_probe_and_attach_child(struct vtpci_softc *sc)
 {
 	device_t dev, child;


More information about the svn-src-projects mailing list