summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbryanv <bryanv@FreeBSD.org>2013-07-04 17:50:11 +0000
committerbryanv <bryanv@FreeBSD.org>2013-07-04 17:50:11 +0000
commitecdd9ae0054b1b8b776661b78e8a20fb0973775d (patch)
treeadfa592c287e8e552c48a18adac66fc0d37fffd6
parentbe7c32fd304a8aa87a4cd877782d254092d1282f (diff)
downloadFreeBSD-src-ecdd9ae0054b1b8b776661b78e8a20fb0973775d.zip
FreeBSD-src-ecdd9ae0054b1b8b776661b78e8a20fb0973775d.tar.gz
Convert VirtIO to use ithreads instead of taskqueues
Contains projects/virtio commits: r245709: 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. r245710: virtio: Change virtqueue intr handlers to return void r245711: virtio_blk: Remove interrupt taskqueue r245721: vtnet: Remove interrupt taskqueue r245722: virtio_scsi: Remove interrupt taskqueue r245747: vtnet: Remove taskqueue fields missed in r245721 MFC after: 1 month
-rw-r--r--sys/dev/virtio/balloon/virtio_balloon.c6
-rw-r--r--sys/dev/virtio/block/virtio_blk.c47
-rw-r--r--sys/dev/virtio/network/if_vtnet.c104
-rw-r--r--sys/dev/virtio/network/if_vtnetvar.h5
-rw-r--r--sys/dev/virtio/pci/virtio_pci.c88
-rw-r--r--sys/dev/virtio/scsi/virtio_scsi.c105
-rw-r--r--sys/dev/virtio/scsi/virtio_scsivar.h5
-rw-r--r--sys/dev/virtio/virtio_if.m3
-rw-r--r--sys/dev/virtio/virtqueue.c17
-rw-r--r--sys/dev/virtio/virtqueue.h5
10 files changed, 110 insertions, 275 deletions
diff --git a/sys/dev/virtio/balloon/virtio_balloon.c b/sys/dev/virtio/balloon/virtio_balloon.c
index 9b45459..224a651 100644
--- a/sys/dev/virtio/balloon/virtio_balloon.c
+++ b/sys/dev/virtio/balloon/virtio_balloon.c
@@ -90,7 +90,7 @@ static int vtballoon_config_change(device_t);
static void vtballoon_negotiate_features(struct vtballoon_softc *);
static int vtballoon_alloc_virtqueues(struct vtballoon_softc *);
-static int vtballoon_vq_intr(void *);
+static void vtballoon_vq_intr(void *);
static void vtballoon_inflate(struct vtballoon_softc *, int);
static void vtballoon_deflate(struct vtballoon_softc *, int);
@@ -300,7 +300,7 @@ vtballoon_alloc_virtqueues(struct vtballoon_softc *sc)
return (virtio_alloc_virtqueues(dev, 0, nvqs, vq_info));
}
-static int
+static void
vtballoon_vq_intr(void *xsc)
{
struct vtballoon_softc *sc;
@@ -310,8 +310,6 @@ vtballoon_vq_intr(void *xsc)
VTBALLOON_LOCK(sc);
wakeup_one(sc);
VTBALLOON_UNLOCK(sc);
-
- return (1);
}
static void
diff --git a/sys/dev/virtio/block/virtio_blk.c b/sys/dev/virtio/block/virtio_blk.c
index 21d7703..e5f38c41 100644
--- a/sys/dev/virtio/block/virtio_blk.c
+++ b/sys/dev/virtio/block/virtio_blk.c
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/queue.h>
-#include <sys/taskqueue.h>
#include <geom/geom_disk.h>
@@ -85,9 +84,6 @@ struct vtblk_softc {
vtblk_req_ready;
struct vtblk_request *vtblk_req_ordered;
- struct taskqueue *vtblk_tq;
- struct task vtblk_intr_task;
-
int vtblk_max_nsegs;
int vtblk_request_count;
@@ -138,8 +134,7 @@ static struct vtblk_request * vtblk_bio_request(struct vtblk_softc *);
static int vtblk_execute_request(struct vtblk_softc *,
struct vtblk_request *);
-static int vtblk_vq_intr(void *);
-static void vtblk_intr_task(void *, int);
+static void vtblk_vq_intr(void *);
static void vtblk_stop(struct vtblk_softc *);
@@ -333,24 +328,12 @@ vtblk_attach(device_t dev)
vtblk_alloc_disk(sc, &blkcfg);
- TASK_INIT(&sc->vtblk_intr_task, 0, vtblk_intr_task, sc);
- sc->vtblk_tq = taskqueue_create_fast("vtblk_taskq", M_NOWAIT,
- taskqueue_thread_enqueue, &sc->vtblk_tq);
- if (sc->vtblk_tq == NULL) {
- error = ENOMEM;
- device_printf(dev, "cannot allocate taskqueue\n");
- goto fail;
- }
-
error = virtio_setup_intr(dev, INTR_TYPE_BIO | INTR_ENTROPY);
if (error) {
device_printf(dev, "cannot setup virtqueue interrupt\n");
goto fail;
}
- taskqueue_start_threads(&sc->vtblk_tq, 1, PI_DISK, "%s taskq",
- device_get_nameunit(dev));
-
vtblk_create_disk(sc);
virtqueue_enable_intr(sc->vtblk_vq);
@@ -375,12 +358,6 @@ vtblk_detach(device_t dev)
vtblk_stop(sc);
VTBLK_UNLOCK(sc);
- if (sc->vtblk_tq != NULL) {
- taskqueue_drain(sc->vtblk_tq, &sc->vtblk_intr_task);
- taskqueue_free(sc->vtblk_tq);
- sc->vtblk_tq = NULL;
- }
-
vtblk_drain(sc);
if (sc->vtblk_disk != NULL) {
@@ -834,28 +811,16 @@ vtblk_execute_request(struct vtblk_softc *sc, struct vtblk_request *req)
return (error);
}
-static int
-vtblk_vq_intr(void *xsc)
-{
- struct vtblk_softc *sc;
-
- sc = xsc;
-
- virtqueue_disable_intr(sc->vtblk_vq);
- taskqueue_enqueue_fast(sc->vtblk_tq, &sc->vtblk_intr_task);
-
- return (1);
-}
-
static void
-vtblk_intr_task(void *arg, int pending)
+vtblk_vq_intr(void *xsc)
{
struct vtblk_softc *sc;
struct virtqueue *vq;
- sc = arg;
+ sc = xsc;
vq = sc->vtblk_vq;
+again:
VTBLK_LOCK(sc);
if (sc->vtblk_flags & VTBLK_FLAG_DETACH) {
VTBLK_UNLOCK(sc);
@@ -872,9 +837,7 @@ vtblk_intr_task(void *arg, int pending)
if (virtqueue_enable_intr(vq) != 0) {
virtqueue_disable_intr(vq);
VTBLK_UNLOCK(sc);
- taskqueue_enqueue_fast(sc->vtblk_tq,
- &sc->vtblk_intr_task);
- return;
+ goto again;
}
VTBLK_UNLOCK(sc);
diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c
index 8e2de46..29ed747 100644
--- a/sys/dev/virtio/network/if_vtnet.c
+++ b/sys/dev/virtio/network/if_vtnet.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
-#include <sys/taskqueue.h>
#include <sys/random.h>
#include <sys/sglist.h>
#include <sys/lock.h>
@@ -97,7 +96,6 @@ 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);
static int vtnet_change_mtu(struct vtnet_softc *, int);
static int vtnet_ioctl(struct ifnet *, u_long, caddr_t);
@@ -123,8 +121,7 @@ static int vtnet_rx_csum(struct vtnet_softc *, struct mbuf *,
struct virtio_net_hdr *);
static int vtnet_rxeof_merged(struct vtnet_softc *, struct mbuf *, int);
static int vtnet_rxeof(struct vtnet_softc *, int, int *);
-static void vtnet_rx_intr_task(void *, int);
-static int vtnet_rx_vq_intr(void *);
+static void vtnet_rx_vq_intr(void *);
static void vtnet_txeof(struct vtnet_softc *);
static struct mbuf * vtnet_tx_offload(struct vtnet_softc *, struct mbuf *,
@@ -135,8 +132,7 @@ static int vtnet_encap(struct vtnet_softc *, struct mbuf **);
static void vtnet_start_locked(struct ifnet *);
static void vtnet_start(struct ifnet *);
static void vtnet_tick(void *);
-static void vtnet_tx_intr_task(void *, int);
-static int vtnet_tx_vq_intr(void *);
+static void vtnet_tx_vq_intr(void *);
static void vtnet_stop(struct vtnet_softc *);
static int vtnet_reinit(struct vtnet_softc *);
@@ -427,19 +423,6 @@ vtnet_attach(device_t dev)
ifp->if_capabilities |= IFCAP_POLLING;
#endif
- TASK_INIT(&sc->vtnet_rx_intr_task, 0, vtnet_rx_intr_task, sc);
- TASK_INIT(&sc->vtnet_tx_intr_task, 0, vtnet_tx_intr_task, sc);
- TASK_INIT(&sc->vtnet_cfgchg_task, 0, vtnet_config_change_task, sc);
-
- sc->vtnet_tq = taskqueue_create_fast("vtnet_taskq", M_NOWAIT,
- taskqueue_thread_enqueue, &sc->vtnet_tq);
- if (sc->vtnet_tq == NULL) {
- error = ENOMEM;
- device_printf(dev, "cannot allocate taskqueue\n");
- ether_ifdetach(ifp);
- goto fail;
- }
-
error = virtio_setup_intr(dev, INTR_TYPE_NET);
if (error) {
device_printf(dev, "cannot setup virtqueue interrupts\n");
@@ -447,9 +430,6 @@ vtnet_attach(device_t dev)
goto fail;
}
- taskqueue_start_threads(&sc->vtnet_tq, 1, PI_NET, "%s taskq",
- device_get_nameunit(dev));
-
/*
* Device defaults to promiscuous mode for backwards
* compatibility. Turn it off if possible.
@@ -495,18 +475,10 @@ vtnet_detach(device_t dev)
VTNET_UNLOCK(sc);
callout_drain(&sc->vtnet_tick_ch);
- taskqueue_drain(taskqueue_fast, &sc->vtnet_cfgchg_task);
ether_ifdetach(ifp);
}
- if (sc->vtnet_tq != NULL) {
- taskqueue_drain(sc->vtnet_tq, &sc->vtnet_rx_intr_task);
- taskqueue_drain(sc->vtnet_tq, &sc->vtnet_tx_intr_task);
- taskqueue_free(sc->vtnet_tq);
- sc->vtnet_tq = NULL;
- }
-
if (sc->vtnet_vlan_attach != NULL) {
EVENTHANDLER_DEREGISTER(vlan_config, sc->vtnet_vlan_attach);
sc->vtnet_vlan_attach = NULL;
@@ -590,9 +562,11 @@ vtnet_config_change(device_t dev)
sc = device_get_softc(dev);
- taskqueue_enqueue_fast(taskqueue_fast, &sc->vtnet_cfgchg_task);
+ VTNET_LOCK(sc);
+ vtnet_update_link_status(sc);
+ VTNET_UNLOCK(sc);
- return (1);
+ return (0);
}
static void
@@ -788,18 +762,6 @@ vtnet_watchdog(struct vtnet_softc *sc)
vtnet_init_locked(sc);
}
-static void
-vtnet_config_change_task(void *arg, int pending)
-{
- struct vtnet_softc *sc;
-
- sc = arg;
-
- VTNET_LOCK(sc);
- vtnet_update_link_status(sc);
- VTNET_UNLOCK(sc);
-}
-
static int
vtnet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@@ -1705,15 +1667,16 @@ vtnet_rxeof(struct vtnet_softc *sc, int count, int *rx_npktsp)
}
static void
-vtnet_rx_intr_task(void *arg, int pending)
+vtnet_rx_vq_intr(void *xsc)
{
struct vtnet_softc *sc;
struct ifnet *ifp;
int more;
- sc = arg;
+ sc = xsc;
ifp = sc->vtnet_ifp;
+again:
VTNET_LOCK(sc);
#ifdef DEVICE_POLLING
@@ -1730,31 +1693,15 @@ vtnet_rx_intr_task(void *arg, int pending)
}
more = vtnet_rxeof(sc, sc->vtnet_rx_process_limit, NULL);
- if (!more && vtnet_enable_rx_intr(sc) != 0) {
- vtnet_disable_rx_intr(sc);
- more = 1;
- }
-
- VTNET_UNLOCK(sc);
-
- if (more) {
+ if (more || vtnet_enable_rx_intr(sc) != 0) {
+ if (!more)
+ vtnet_disable_rx_intr(sc);
sc->vtnet_stats.rx_task_rescheduled++;
- taskqueue_enqueue_fast(sc->vtnet_tq,
- &sc->vtnet_rx_intr_task);
+ VTNET_UNLOCK(sc);
+ goto again;
}
-}
-
-static int
-vtnet_rx_vq_intr(void *xsc)
-{
- struct vtnet_softc *sc;
- sc = xsc;
-
- vtnet_disable_rx_intr(sc);
- taskqueue_enqueue_fast(sc->vtnet_tq, &sc->vtnet_rx_intr_task);
-
- return (1);
+ VTNET_UNLOCK(sc);
}
static void
@@ -2077,14 +2024,15 @@ vtnet_tick(void *xsc)
}
static void
-vtnet_tx_intr_task(void *arg, int pending)
+vtnet_tx_vq_intr(void *xsc)
{
struct vtnet_softc *sc;
struct ifnet *ifp;
- sc = arg;
+ sc = xsc;
ifp = sc->vtnet_ifp;
+again:
VTNET_LOCK(sc);
#ifdef DEVICE_POLLING
@@ -2109,26 +2057,12 @@ vtnet_tx_intr_task(void *arg, int pending)
vtnet_disable_tx_intr(sc);
sc->vtnet_stats.tx_task_rescheduled++;
VTNET_UNLOCK(sc);
- taskqueue_enqueue_fast(sc->vtnet_tq, &sc->vtnet_tx_intr_task);
- return;
+ goto again;
}
VTNET_UNLOCK(sc);
}
-static int
-vtnet_tx_vq_intr(void *xsc)
-{
- struct vtnet_softc *sc;
-
- sc = xsc;
-
- vtnet_disable_tx_intr(sc);
- taskqueue_enqueue_fast(sc->vtnet_tq, &sc->vtnet_tx_intr_task);
-
- return (1);
-}
-
static void
vtnet_stop(struct vtnet_softc *sc)
{
diff --git a/sys/dev/virtio/network/if_vtnetvar.h b/sys/dev/virtio/network/if_vtnetvar.h
index 184870e..da7e61d 100644
--- a/sys/dev/virtio/network/if_vtnetvar.h
+++ b/sys/dev/virtio/network/if_vtnetvar.h
@@ -79,11 +79,6 @@ struct vtnet_softc {
int vtnet_watchdog_timer;
uint64_t vtnet_features;
- struct taskqueue *vtnet_tq;
- struct task vtnet_rx_intr_task;
- struct task vtnet_tx_intr_task;
- struct task vtnet_cfgchg_task;
-
struct vtnet_statistics vtnet_stats;
struct callout vtnet_tick_ch;
diff --git a/sys/dev/virtio/pci/virtio_pci.c b/sys/dev/virtio/pci/virtio_pci.c
index 917ca84..02a9d23 100644
--- a/sys/dev/virtio/pci/virtio_pci.c
+++ b/sys/dev/virtio/pci/virtio_pci.c
@@ -160,10 +160,12 @@ static void vtpci_reset(struct vtpci_softc *);
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 vtpci_softc *sc, enum intr_type type)
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_softc *sc, enum intr_type type)
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_softc *sc, enum intr_type type)
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_softc *sc, enum intr_type type)
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_softc *sc, int idx)
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);
}
diff --git a/sys/dev/virtio/scsi/virtio_scsi.c b/sys/dev/virtio/scsi/virtio_scsi.c
index 52f1581..d471937 100644
--- a/sys/dev/virtio/scsi/virtio_scsi.c
+++ b/sys/dev/virtio/scsi/virtio_scsi.c
@@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/callout.h>
-#include <sys/taskqueue.h>
#include <sys/queue.h>
#include <sys/sbuf.h>
@@ -172,13 +171,10 @@ static struct vtscsi_request * vtscsi_dequeue_request(struct vtscsi_softc *);
static void vtscsi_complete_request(struct vtscsi_request *);
static void vtscsi_complete_vq(struct vtscsi_softc *, struct virtqueue *);
-static void vtscsi_control_vq_task(void *, int);
-static void vtscsi_event_vq_task(void *, int);
-static void vtscsi_request_vq_task(void *, int);
-static int vtscsi_control_vq_intr(void *);
-static int vtscsi_event_vq_intr(void *);
-static int vtscsi_request_vq_intr(void *);
+static void vtscsi_control_vq_intr(void *);
+static void vtscsi_event_vq_intr(void *);
+static void vtscsi_request_vq_intr(void *);
static void vtscsi_disable_vqs_intr(struct vtscsi_softc *);
static void vtscsi_enable_vqs_intr(struct vtscsi_softc *);
@@ -333,30 +329,12 @@ vtscsi_attach(device_t dev)
goto fail;
}
- TASK_INIT(&sc->vtscsi_control_intr_task, 0,
- vtscsi_control_vq_task, sc);
- TASK_INIT(&sc->vtscsi_event_intr_task, 0,
- vtscsi_event_vq_task, sc);
- TASK_INIT(&sc->vtscsi_request_intr_task, 0,
- vtscsi_request_vq_task, sc);
-
- sc->vtscsi_tq = taskqueue_create_fast("vtscsi_taskq", M_NOWAIT,
- taskqueue_thread_enqueue, &sc->vtscsi_tq);
- if (sc->vtscsi_tq == NULL) {
- error = ENOMEM;
- device_printf(dev, "cannot allocate taskqueue\n");
- goto fail;
- }
-
error = virtio_setup_intr(dev, INTR_TYPE_CAM);
if (error) {
device_printf(dev, "cannot setup virtqueue interrupts\n");
goto fail;
}
- taskqueue_start_threads(&sc->vtscsi_tq, 1, PI_DISK, "%s taskq",
- device_get_nameunit(dev));
-
vtscsi_enable_vqs_intr(sc);
/*
@@ -389,14 +367,6 @@ vtscsi_detach(device_t dev)
vtscsi_stop(sc);
VTSCSI_UNLOCK(sc);
- if (sc->vtscsi_tq != NULL) {
- taskqueue_drain(sc->vtscsi_tq, &sc->vtscsi_control_intr_task);
- taskqueue_drain(sc->vtscsi_tq, &sc->vtscsi_event_intr_task);
- taskqueue_drain(sc->vtscsi_tq, &sc->vtscsi_request_intr_task);
- taskqueue_free(sc->vtscsi_tq);
- sc->vtscsi_tq = NULL;
- }
-
vtscsi_complete_vqs(sc);
vtscsi_drain_vqs(sc);
@@ -2152,14 +2122,15 @@ vtscsi_complete_vq(struct vtscsi_softc *sc, struct virtqueue *vq)
}
static void
-vtscsi_control_vq_task(void *arg, int pending)
+vtscsi_control_vq_intr(void *xsc)
{
struct vtscsi_softc *sc;
struct virtqueue *vq;
- sc = arg;
+ sc = xsc;
vq = sc->vtscsi_control_vq;
+again:
VTSCSI_LOCK(sc);
vtscsi_complete_vq(sc, sc->vtscsi_control_vq);
@@ -2167,24 +2138,23 @@ vtscsi_control_vq_task(void *arg, int pending)
if (virtqueue_enable_intr(vq) != 0) {
virtqueue_disable_intr(vq);
VTSCSI_UNLOCK(sc);
- taskqueue_enqueue_fast(sc->vtscsi_tq,
- &sc->vtscsi_control_intr_task);
- return;
+ goto again;
}
VTSCSI_UNLOCK(sc);
}
static void
-vtscsi_event_vq_task(void *arg, int pending)
+vtscsi_event_vq_intr(void *xsc)
{
struct vtscsi_softc *sc;
struct virtqueue *vq;
struct virtio_scsi_event *event;
- sc = arg;
+ sc = xsc;
vq = sc->vtscsi_event_vq;
+again:
VTSCSI_LOCK(sc);
while ((event = virtqueue_dequeue(vq, NULL)) != NULL)
@@ -2193,23 +2163,22 @@ vtscsi_event_vq_task(void *arg, int pending)
if (virtqueue_enable_intr(vq) != 0) {
virtqueue_disable_intr(vq);
VTSCSI_UNLOCK(sc);
- taskqueue_enqueue_fast(sc->vtscsi_tq,
- &sc->vtscsi_control_intr_task);
- return;
+ goto again;
}
VTSCSI_UNLOCK(sc);
}
static void
-vtscsi_request_vq_task(void *arg, int pending)
+vtscsi_request_vq_intr(void *xsc)
{
struct vtscsi_softc *sc;
struct virtqueue *vq;
- sc = arg;
+ sc = xsc;
vq = sc->vtscsi_request_vq;
+again:
VTSCSI_LOCK(sc);
vtscsi_complete_vq(sc, sc->vtscsi_request_vq);
@@ -2217,56 +2186,12 @@ vtscsi_request_vq_task(void *arg, int pending)
if (virtqueue_enable_intr(vq) != 0) {
virtqueue_disable_intr(vq);
VTSCSI_UNLOCK(sc);
- taskqueue_enqueue_fast(sc->vtscsi_tq,
- &sc->vtscsi_request_intr_task);
- return;
+ goto again;
}
VTSCSI_UNLOCK(sc);
}
-static int
-vtscsi_control_vq_intr(void *xsc)
-{
- struct vtscsi_softc *sc;
-
- sc = xsc;
-
- virtqueue_disable_intr(sc->vtscsi_control_vq);
- taskqueue_enqueue_fast(sc->vtscsi_tq,
- &sc->vtscsi_control_intr_task);
-
- return (1);
-}
-
-static int
-vtscsi_event_vq_intr(void *xsc)
-{
- struct vtscsi_softc *sc;
-
- sc = xsc;
-
- virtqueue_disable_intr(sc->vtscsi_event_vq);
- taskqueue_enqueue_fast(sc->vtscsi_tq,
- &sc->vtscsi_event_intr_task);
-
- return (1);
-}
-
-static int
-vtscsi_request_vq_intr(void *xsc)
-{
- struct vtscsi_softc *sc;
-
- sc = xsc;
-
- virtqueue_disable_intr(sc->vtscsi_request_vq);
- taskqueue_enqueue_fast(sc->vtscsi_tq,
- &sc->vtscsi_request_intr_task);
-
- return (1);
-}
-
static void
vtscsi_disable_vqs_intr(struct vtscsi_softc *sc)
{
diff --git a/sys/dev/virtio/scsi/virtio_scsivar.h b/sys/dev/virtio/scsi/virtio_scsivar.h
index 7afe32f..ca53f21 100644
--- a/sys/dev/virtio/scsi/virtio_scsivar.h
+++ b/sys/dev/virtio/scsi/virtio_scsivar.h
@@ -62,11 +62,6 @@ struct vtscsi_softc {
struct virtqueue *vtscsi_event_vq;
struct virtqueue *vtscsi_request_vq;
- struct taskqueue *vtscsi_tq;
- struct task vtscsi_control_intr_task;
- struct task vtscsi_event_intr_task;
- struct task vtscsi_request_intr_task;
-
struct cam_sim *vtscsi_sim;
struct cam_path *vtscsi_path;
diff --git a/sys/dev/virtio/virtio_if.m b/sys/dev/virtio/virtio_if.m
index 701678c..13b0660 100644
--- a/sys/dev/virtio/virtio_if.m
+++ b/sys/dev/virtio/virtio_if.m
@@ -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);
}
};
diff --git a/sys/dev/virtio/virtqueue.c b/sys/dev/virtio/virtqueue.c
index 1553afa..275a92d 100644
--- a/sys/dev/virtio/virtqueue.c
+++ b/sys/dev/virtio/virtqueue.c
@@ -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)
{
diff --git a/sys/dev/virtio/virtqueue.h b/sys/dev/virtio/virtqueue.h
index 0296b8c..80e52ff 100644
--- a/sys/dev/virtio/virtqueue.h
+++ b/sys/dev/virtio/virtqueue.h
@@ -39,7 +39,7 @@ struct sglist;
#define VIRTIO_RING_F_EVENT_IDX (1 << 29)
/* Device callback for a virtqueue interrupt. */
-typedef int virtqueue_intr_t(void *);
+typedef void virtqueue_intr_t(void *);
#define VIRTQUEUE_MAX_NAME_SZ 32
@@ -70,7 +70,8 @@ void *virtqueue_drain(struct virtqueue *vq, int *last);
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);
OpenPOWER on IntegriCloud