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
This commit is contained in:
parent
61762e7dbc
commit
6632efe40d
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
if (more || vtnet_enable_rx_intr(sc) != 0) {
|
||||
if (!more)
|
||||
vtnet_disable_rx_intr(sc);
|
||||
sc->vtnet_stats.rx_task_rescheduled++;
|
||||
VTNET_UNLOCK(sc);
|
||||
goto again;
|
||||
}
|
||||
|
||||
VTNET_UNLOCK(sc);
|
||||
|
||||
if (more) {
|
||||
sc->vtnet_stats.rx_task_rescheduled++;
|
||||
taskqueue_enqueue_fast(sc->vtnet_tq,
|
||||
&sc->vtnet_rx_intr_task);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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_HANDLED : FILTER_STRAY);
|
||||
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];
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -414,16 +414,25 @@ virtqueue_nused(struct virtqueue *vq)
|
||||
}
|
||||
|
||||
int
|
||||
virtqueue_intr_filter(struct virtqueue *vq)
|
||||
{
|
||||
|
||||
if (__predict_false(vq->vq_intrhand == NULL))
|
||||
return (0);
|
||||
if (vq->vq_used_cons_idx == vq->vq_ring.used->idx)
|
||||
return (0);
|
||||
|
||||
virtqueue_disable_intr(vq);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
virtqueue_intr(struct virtqueue *vq)
|
||||
{
|
||||
|
||||
if (vq->vq_intrhand == NULL ||
|
||||
vq->vq_used_cons_idx == vq->vq_ring.used->idx)
|
||||
return (0);
|
||||
|
||||
vq->vq_intrhand(vq->vq_intrhand_arg);
|
||||
|
||||
return (1);
|
||||
if (__predict_true(vq->vq_intrhand != NULL))
|
||||
vq->vq_intrhand(vq->vq_intrhand_arg);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user