svn commit: r245709 - in projects/virtio/sys/dev/virtio: . pci

Bryan Venteicher bryanv at FreeBSD.org
Mon Jan 21 06:42:58 UTC 2013


Author: bryanv
Date: Mon Jan 21 06:42:56 2013
New Revision: 245709
URL: http://svnweb.freebsd.org/changeset/base/245709

Log:
  virtio: Add support for ithread(9)
  
  Each VirtIO device was scheduling its own taskqueue(9) to do the
  off-level interrupt handling. ithreads(9) is the more nature way
  to do this. The primary motivation for this work to better support
  network multiqueue.
  
  Currently, the ithreads are just scheduling the device's taskqueue
  as before. The taskqueues in each driver will be removed in
  subsequent commits.
  
  Approved by:	grehan (implicit)

Modified:
  projects/virtio/sys/dev/virtio/pci/virtio_pci.c
  projects/virtio/sys/dev/virtio/virtio_if.m
  projects/virtio/sys/dev/virtio/virtqueue.c
  projects/virtio/sys/dev/virtio/virtqueue.h

Modified: projects/virtio/sys/dev/virtio/pci/virtio_pci.c
==============================================================================
--- projects/virtio/sys/dev/virtio/pci/virtio_pci.c	Mon Jan 21 04:06:04 2013	(r245708)
+++ projects/virtio/sys/dev/virtio/pci/virtio_pci.c	Mon Jan 21 06:42:56 2013	(r245709)
@@ -160,10 +160,12 @@ static void	vtpci_reset(struct vtpci_sof
 
 static void	vtpci_select_virtqueue(struct vtpci_softc *, int);
 
-static int	vtpci_legacy_intr(void *);
-static int	vtpci_vq_shared_intr(void *);
-static int	vtpci_vq_intr(void *);
-static int	vtpci_config_intr(void *);
+static void	vtpci_legacy_intr(void *);
+static int	vtpci_vq_shared_intr_filter(void *);
+static void	vtpci_vq_shared_intr(void *);
+static int	vtpci_vq_intr_filter(void *);
+static void	vtpci_vq_intr(void *);
+static void	vtpci_config_intr(void *);
 
 #define vtpci_setup_msi_interrupt vtpci_setup_legacy_interrupt
 
@@ -932,7 +934,7 @@ vtpci_setup_legacy_interrupt(struct vtpc
 	dev = sc->vtpci_dev;
 
 	ires = &sc->vtpci_intr_res[0];
-	error = bus_setup_intr(dev, ires->irq, type, vtpci_legacy_intr, NULL,
+	error = bus_setup_intr(dev, ires->irq, type, NULL, vtpci_legacy_intr,
 	    sc, &ires->intrhand);
 
 	return (error);
@@ -949,11 +951,11 @@ vtpci_setup_msix_interrupts(struct vtpci
 	dev = sc->vtpci_dev;
 
 	/*
-	 * The first resource is used for configuration changed interrupts.
+	 * The first MSIX vector is used for configuration changed interrupts.
 	 */
 	ires = &sc->vtpci_intr_res[0];
-	error = bus_setup_intr(dev, ires->irq, type, vtpci_config_intr,
-	    NULL, sc, &ires->intrhand);
+	error = bus_setup_intr(dev, ires->irq, type, NULL, vtpci_config_intr,
+	    sc, &ires->intrhand);
 	if (error)
 		return (error);
 
@@ -961,13 +963,9 @@ vtpci_setup_msix_interrupts(struct vtpci
 		ires = &sc->vtpci_intr_res[1];
 
 		error = bus_setup_intr(dev, ires->irq, type,
-		    vtpci_vq_shared_intr, NULL, sc, &ires->intrhand);
-		if (error)
-			return (error);
+		    vtpci_vq_shared_intr_filter, vtpci_vq_shared_intr, sc,
+		    &ires->intrhand);
 	} else {
-		/*
-		 * Each remaining resource is assigned to a specific virtqueue.
-		 */
 		for (i = 0; i < sc->vtpci_nvqs; i++) {
 			vqx = &sc->vtpci_vqx[i];
 			if (vqx->ires_idx < 1)
@@ -975,17 +973,17 @@ vtpci_setup_msix_interrupts(struct vtpci
 
 			ires = &sc->vtpci_intr_res[vqx->ires_idx];
 			error = bus_setup_intr(dev, ires->irq, type,
-			    vtpci_vq_intr, NULL, vqx->vq, &ires->intrhand);
+			    vtpci_vq_intr_filter, vtpci_vq_intr, vqx->vq,
+			    &ires->intrhand);
 			if (error)
-				return (error);
+				break;
 		}
 	}
 
-	error = vtpci_set_host_msix_vectors(sc);
-	if (error)
-		return (error);
+	if (error == 0)
+		error = vtpci_set_host_msix_vectors(sc);
 
-	return (0);
+	return (error);
 }
 
 static int
@@ -1191,7 +1189,7 @@ vtpci_select_virtqueue(struct vtpci_soft
 	vtpci_write_config_2(sc, VIRTIO_PCI_QUEUE_SEL, idx);
 }
 
-static int
+static void
 vtpci_legacy_intr(void *xsc)
 {
 	struct vtpci_softc *sc;
@@ -1208,15 +1206,14 @@ vtpci_legacy_intr(void *xsc)
 	if (isr & VIRTIO_PCI_ISR_CONFIG)
 		vtpci_config_intr(sc);
 
-	if (isr & VIRTIO_PCI_ISR_INTR)
+	if (isr & VIRTIO_PCI_ISR_INTR) {
 		for (i = 0; i < sc->vtpci_nvqs; i++, vqx++)
 			virtqueue_intr(vqx->vq);
-
-	return (isr ? FILTER_HANDLED : FILTER_STRAY);
+	}
 }
 
 static int
-vtpci_vq_shared_intr(void *xsc)
+vtpci_vq_shared_intr_filter(void *xsc)
 {
 	struct vtpci_softc *sc;
 	struct vtpci_virtqueue *vqx;
@@ -1227,36 +1224,55 @@ vtpci_vq_shared_intr(void *xsc)
 	vqx = &sc->vtpci_vqx[0];
 
 	for (i = 0; i < sc->vtpci_nvqs; i++, vqx++)
-		rc |= virtqueue_intr(vqx->vq);
+		rc |= virtqueue_intr_filter(vqx->vq);
+
+	return (rc ? FILTER_SCHEDULE_THREAD : FILTER_STRAY);
+}
+
+static void
+vtpci_vq_shared_intr(void *xsc)
+{
+	struct vtpci_softc *sc;
+	struct vtpci_virtqueue *vqx;
+	int i;
+
+	sc = xsc;
+	vqx = &sc->vtpci_vqx[0];
 
-	return (rc ? FILTER_HANDLED : FILTER_STRAY);
+	for (i = 0; i < sc->vtpci_nvqs; i++, vqx++)
+		virtqueue_intr(vqx->vq);
 }
 
 static int
-vtpci_vq_intr(void *xvq)
+vtpci_vq_intr_filter(void *xvq)
 {
 	struct virtqueue *vq;
 	int rc;
 
 	vq = xvq;
-	rc = virtqueue_intr(vq);
+	rc = virtqueue_intr_filter(vq);
 
-	return (rc ? FILTER_HANDLED : FILTER_STRAY);
+	return (rc ? FILTER_SCHEDULE_THREAD : FILTER_STRAY);
 }
 
-static int
+static void
+vtpci_vq_intr(void *xvq)
+{
+	struct virtqueue *vq;
+
+	vq = xvq;
+	virtqueue_intr(vq);
+}
+
+static void
 vtpci_config_intr(void *xsc)
 {
 	struct vtpci_softc *sc;
 	device_t child;
-	int rc;
 
-	rc = 0;
 	sc = xsc;
 	child = sc->vtpci_child_dev;
 
 	if (child != NULL)
-		rc = VIRTIO_CONFIG_CHANGE(child);
-
-	return (rc ? FILTER_HANDLED : FILTER_STRAY);
+		VIRTIO_CONFIG_CHANGE(child);
 }

Modified: projects/virtio/sys/dev/virtio/virtio_if.m
==============================================================================
--- projects/virtio/sys/dev/virtio/virtio_if.m	Mon Jan 21 04:06:04 2013	(r245708)
+++ projects/virtio/sys/dev/virtio/virtio_if.m	Mon Jan 21 06:42:56 2013	(r245709)
@@ -33,8 +33,7 @@ CODE {
 	static int
 	virtio_default_config_change(device_t dev)
 	{
-		/* Return that we've handled the change. */
-		return (1);
+		return (0);
 	}
 };
 

Modified: projects/virtio/sys/dev/virtio/virtqueue.c
==============================================================================
--- projects/virtio/sys/dev/virtio/virtqueue.c	Mon Jan 21 04:06:04 2013	(r245708)
+++ projects/virtio/sys/dev/virtio/virtqueue.c	Mon Jan 21 06:42:56 2013	(r245709)
@@ -414,18 +414,27 @@ virtqueue_nused(struct virtqueue *vq)
 }
 
 int
-virtqueue_intr(struct virtqueue *vq)
+virtqueue_intr_filter(struct virtqueue *vq)
 {
 
-	if (vq->vq_intrhand == NULL ||
-	    vq->vq_used_cons_idx == vq->vq_ring.used->idx)
+	if (__predict_false(vq->vq_intrhand == NULL))
+		return (0);
+	if (vq->vq_used_cons_idx == vq->vq_ring.used->idx)
 		return (0);
 
-	vq->vq_intrhand(vq->vq_intrhand_arg);
+	virtqueue_disable_intr(vq);
 
 	return (1);
 }
 
+void
+virtqueue_intr(struct virtqueue *vq)
+{
+
+	if (__predict_true(vq->vq_intrhand != NULL))
+		vq->vq_intrhand(vq->vq_intrhand_arg);
+}
+
 int
 virtqueue_enable_intr(struct virtqueue *vq)
 {

Modified: projects/virtio/sys/dev/virtio/virtqueue.h
==============================================================================
--- projects/virtio/sys/dev/virtio/virtqueue.h	Mon Jan 21 04:06:04 2013	(r245708)
+++ projects/virtio/sys/dev/virtio/virtqueue.h	Mon Jan 21 06:42:56 2013	(r245709)
@@ -70,7 +70,8 @@ void	*virtqueue_drain(struct virtqueue *
 void	 virtqueue_free(struct virtqueue *vq);
 int	 virtqueue_reinit(struct virtqueue *vq, uint16_t size);
 
-int	 virtqueue_intr(struct virtqueue *vq);
+int	 virtqueue_intr_filter(struct virtqueue *vq);
+void	 virtqueue_intr(struct virtqueue *vq);
 int	 virtqueue_enable_intr(struct virtqueue *vq);
 int	 virtqueue_postpone_intr(struct virtqueue *vq);
 void	 virtqueue_disable_intr(struct virtqueue *vq);


More information about the svn-src-projects mailing list