Added functions to set interrupt handler and index into virtqueue
This commit is contained in:
parent
702ae62879
commit
3cf221fff2
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_vioif.c,v 1.103 2023/03/23 03:27:48 yamaguchi Exp $ */
|
||||
/* $NetBSD: if_vioif.c,v 1.104 2023/03/23 03:55:11 yamaguchi Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 The NetBSD Foundation, Inc.
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.103 2023/03/23 03:27:48 yamaguchi Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.104 2023/03/23 03:55:11 yamaguchi Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_net_mpsafe.h"
|
||||
|
@ -596,8 +596,10 @@ vioif_attach(device_t parent, device_t self, void *aux)
|
|||
* Allocating a virtqueue for control channel
|
||||
*/
|
||||
sc->sc_ctrlq.ctrlq_vq = &sc->sc_vqs[ctrlq_idx];
|
||||
r = virtio_alloc_vq(vsc, ctrlq->ctrlq_vq, ctrlq_idx,
|
||||
NBPG, 1, "control");
|
||||
virtio_init_vq(vsc, ctrlq->ctrlq_vq, ctrlq_idx,
|
||||
vioif_ctrl_intr, ctrlq);
|
||||
|
||||
r = virtio_alloc_vq(vsc, ctrlq->ctrlq_vq, NBPG, 1, "control");
|
||||
if (r != 0) {
|
||||
aprint_error_dev(self, "failed to allocate "
|
||||
"a virtqueue for control channel, error code %d\n",
|
||||
|
@ -606,9 +608,6 @@ vioif_attach(device_t parent, device_t self, void *aux)
|
|||
sc->sc_has_ctrl = false;
|
||||
cv_destroy(&ctrlq->ctrlq_wait);
|
||||
mutex_destroy(&ctrlq->ctrlq_wait_lock);
|
||||
} else {
|
||||
ctrlq->ctrlq_vq->vq_intrhand = vioif_ctrl_intr;
|
||||
ctrlq->ctrlq_vq->vq_intrhand_arg = (void *) ctrlq;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -623,7 +622,7 @@ vioif_attach(device_t parent, device_t self, void *aux)
|
|||
goto err;
|
||||
|
||||
r = virtio_child_attach_finish(vsc, sc->sc_vqs, nvqs,
|
||||
vioif_config_change, virtio_vq_intrhand, req_flags);
|
||||
vioif_config_change, req_flags);
|
||||
if (r != 0)
|
||||
goto err;
|
||||
|
||||
|
@ -1470,15 +1469,15 @@ vioif_netqueue_init(struct vioif_softc *sc, struct virtio_softc *vsc,
|
|||
"%s-%s", device_xname(sc->sc_dev), qname);
|
||||
|
||||
mutex_init(&netq->netq_lock, MUTEX_DEFAULT, IPL_NET);
|
||||
r = virtio_alloc_vq(vsc, vq, qid,
|
||||
virtio_init_vq(vsc, vq, qid, params[dir].intrhand, netq);
|
||||
|
||||
r = virtio_alloc_vq(vsc, vq,
|
||||
params[dir].segsize + sc->sc_hdr_size,
|
||||
params[dir].nsegs, qname);
|
||||
if (r != 0)
|
||||
goto err;
|
||||
netq->netq_vq = vq;
|
||||
|
||||
netq->netq_vq->vq_intrhand = params[dir].intrhand;
|
||||
netq->netq_vq->vq_intrhand_arg = netq;
|
||||
netq->netq_softint = softint_establish(softint_flags,
|
||||
params[dir].sihand, netq);
|
||||
if (netq->netq_softint == NULL) {
|
||||
|
@ -1534,8 +1533,6 @@ err:
|
|||
softint_disestablish(netq->netq_softint);
|
||||
netq->netq_softint = NULL;
|
||||
}
|
||||
netq->netq_vq->vq_intrhand = NULL;
|
||||
netq->netq_vq->vq_intrhand_arg = NULL;
|
||||
|
||||
virtio_free_vq(vsc, vq);
|
||||
mutex_destroy(&netq->netq_lock);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ld_virtio.c,v 1.31 2023/03/23 03:27:48 yamaguchi Exp $ */
|
||||
/* $NetBSD: ld_virtio.c,v 1.32 2023/03/23 03:55:11 yamaguchi Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Minoura Makoto.
|
||||
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.31 2023/03/23 03:27:48 yamaguchi Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.32 2023/03/23 03:55:11 yamaguchi Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -332,15 +332,17 @@ ld_virtio_attach(device_t parent, device_t self, void *aux)
|
|||
/* 2 for the minimum size */
|
||||
maxnsegs += VIRTIO_BLK_MIN_SEGMENTS;
|
||||
|
||||
if (virtio_alloc_vq(vsc, &sc->sc_vq, 0, maxxfersize, maxnsegs,
|
||||
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) {
|
||||
goto err;
|
||||
}
|
||||
qsize = sc->sc_vq.vq_num;
|
||||
sc->sc_vq.vq_done = ld_virtio_vq_done;
|
||||
|
||||
if (virtio_child_attach_finish(vsc, &sc->sc_vq, 1,
|
||||
NULL, virtio_vq_intr, VIRTIO_F_INTR_MSIX) != 0)
|
||||
NULL, VIRTIO_F_INTR_MSIX) != 0)
|
||||
goto err;
|
||||
|
||||
ld->sc_dv = self;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vio9p.c,v 1.10 2023/03/23 03:27:48 yamaguchi Exp $ */
|
||||
/* $NetBSD: vio9p.c,v 1.11 2023/03/23 03:55:11 yamaguchi Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Internet Initiative Japan, Inc.
|
||||
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vio9p.c,v 1.10 2023/03/23 03:27:48 yamaguchi Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vio9p.c,v 1.11 2023/03/23 03:55:11 yamaguchi Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -507,13 +507,12 @@ vio9p_attach(device_t parent, device_t self, void *aux)
|
|||
if ((features & VIO9P_F_MOUNT_TAG) == 0)
|
||||
goto err_none;
|
||||
|
||||
error = virtio_alloc_vq(vsc, &sc->sc_vq[0], 0, VIO9P_MAX_REQLEN,
|
||||
virtio_init_vq_vqdone(vsc, &sc->sc_vq[0], 0, vio9p_request_done);
|
||||
error = virtio_alloc_vq(vsc, &sc->sc_vq[0], VIO9P_MAX_REQLEN,
|
||||
VIO9P_N_SEGMENTS * 2, "vio9p");
|
||||
if (error != 0)
|
||||
goto err_none;
|
||||
|
||||
sc->sc_vq[0].vq_done = vio9p_request_done;
|
||||
|
||||
sc->sc_buf_tx = kmem_alloc(VIO9P_MAX_REQLEN, KM_SLEEP);
|
||||
sc->sc_buf_rx = kmem_alloc(VIO9P_MAX_REQLEN, KM_SLEEP);
|
||||
|
||||
|
@ -555,7 +554,7 @@ vio9p_attach(device_t parent, device_t self, void *aux)
|
|||
aprint_normal_dev(self, "tagged as %s\n", sc->sc_tag);
|
||||
|
||||
error = virtio_child_attach_finish(vsc, sc->sc_vq,
|
||||
__arraycount(sc->sc_vq), NULL, virtio_vq_intr,
|
||||
__arraycount(sc->sc_vq), NULL,
|
||||
VIRTIO_F_INTR_MPSAFE | VIRTIO_F_INTR_SOFTINT);
|
||||
if (error != 0)
|
||||
goto err_mutex;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: viomb.c,v 1.14 2023/03/23 03:27:48 yamaguchi Exp $ */
|
||||
/* $NetBSD: viomb.c,v 1.15 2023/03/23 03:55:11 yamaguchi Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Minoura Makoto.
|
||||
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: viomb.c,v 1.14 2023/03/23 03:27:48 yamaguchi Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: viomb.c,v 1.15 2023/03/23 03:55:11 yamaguchi Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -163,18 +163,20 @@ viomb_attach(device_t parent, device_t self, void *aux)
|
|||
mutex_init(&sc->sc_waitlock, MUTEX_DEFAULT, IPL_VM); /* spin */
|
||||
cv_init(&sc->sc_wait, "balloon");
|
||||
|
||||
if (virtio_alloc_vq(vsc, &sc->sc_vq[VQ_INFLATE], 0,
|
||||
virtio_init_vq_vqdone(vsc, &sc->sc_vq[VQ_INFLATE], VQ_INFLATE,
|
||||
inflateq_done);
|
||||
virtio_init_vq_vqdone(vsc, &sc->sc_vq[VQ_DEFLATE], VQ_DEFLATE,
|
||||
deflateq_done);
|
||||
|
||||
if (virtio_alloc_vq(vsc, &sc->sc_vq[VQ_INFLATE],
|
||||
sizeof(uint32_t)*PGS_PER_REQ, 1,
|
||||
"inflate") != 0)
|
||||
goto err_mutex;
|
||||
if (virtio_alloc_vq(vsc, &sc->sc_vq[VQ_DEFLATE], 1,
|
||||
if (virtio_alloc_vq(vsc, &sc->sc_vq[VQ_DEFLATE],
|
||||
sizeof(uint32_t)*PGS_PER_REQ, 1,
|
||||
"deflate") != 0)
|
||||
goto err_vq0;
|
||||
|
||||
sc->sc_vq[VQ_INFLATE].vq_done = inflateq_done;
|
||||
sc->sc_vq[VQ_DEFLATE].vq_done = deflateq_done;
|
||||
|
||||
if (bus_dmamap_create(virtio_dmat(vsc), sizeof(uint32_t)*PGS_PER_REQ,
|
||||
1, sizeof(uint32_t)*PGS_PER_REQ, 0,
|
||||
BUS_DMA_NOWAIT, &sc->sc_req.bl_dmamap)) {
|
||||
|
@ -190,7 +192,7 @@ viomb_attach(device_t parent, device_t self, void *aux)
|
|||
}
|
||||
|
||||
if (virtio_child_attach_finish(vsc, sc->sc_vq, __arraycount(sc->sc_vq),
|
||||
viomb_config_change, virtio_vq_intr, 0) != 0)
|
||||
viomb_config_change, 0) != 0)
|
||||
goto err_out;
|
||||
|
||||
if (kthread_create(PRI_IDLE, KTHREAD_MPSAFE, NULL,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: viornd.c,v 1.19 2023/03/23 03:27:48 yamaguchi Exp $ */
|
||||
/* $NetBSD: viornd.c,v 1.20 2023/03/23 03:55:11 yamaguchi Exp $ */
|
||||
/* $OpenBSD: viornd.c,v 1.1 2014/01/21 21:14:58 sf Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -179,7 +179,9 @@ viornd_attach(device_t parent, device_t self, void *aux)
|
|||
virtio_child_attach_start(vsc, self, IPL_NET,
|
||||
0, VIRTIO_COMMON_FLAG_BITS);
|
||||
|
||||
error = virtio_alloc_vq(vsc, &sc->sc_vq, 0, VIORND_BUFSIZE, 1,
|
||||
virtio_init_vq_vqdone(vsc, &sc->sc_vq, 0, viornd_vq_done);
|
||||
|
||||
error = virtio_alloc_vq(vsc, &sc->sc_vq, VIORND_BUFSIZE, 1,
|
||||
"Entropy request");
|
||||
if (error) {
|
||||
aprint_error_dev(sc->sc_dev, "can't alloc virtqueue: %d\n",
|
||||
|
@ -189,7 +191,7 @@ viornd_attach(device_t parent, device_t self, void *aux)
|
|||
sc->sc_vq.vq_done = viornd_vq_done;
|
||||
|
||||
error = virtio_child_attach_finish(vsc, &sc->sc_vq, 1,
|
||||
NULL, virtio_vq_intr, 0);
|
||||
NULL, 0);
|
||||
if (error) {
|
||||
virtio_free_vq(vsc, &sc->sc_vq);
|
||||
goto vio_failed;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vioscsi.c,v 1.31 2023/03/23 03:27:48 yamaguchi Exp $ */
|
||||
/* $NetBSD: vioscsi.c,v 1.32 2023/03/23 03:55:11 yamaguchi 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.31 2023/03/23 03:27:48 yamaguchi Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vioscsi.c,v 1.32 2023/03/23 03:55:11 yamaguchi Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -148,7 +148,9 @@ vioscsi_attach(device_t parent, device_t self, void *aux)
|
|||
sc->sc_seg_max = seg_max;
|
||||
|
||||
for(i=0; i < __arraycount(sc->sc_vqs); i++) {
|
||||
rv = virtio_alloc_vq(vsc, &sc->sc_vqs[i], i, MAXPHYS,
|
||||
virtio_init_vq_vqdone(vsc, &sc->sc_vqs[i], i,
|
||||
vioscsi_vq_done);
|
||||
rv = virtio_alloc_vq(vsc, &sc->sc_vqs[i], MAXPHYS,
|
||||
VIRTIO_SCSI_MIN_SEGMENTS + howmany(MAXPHYS, NBPG),
|
||||
vioscsi_vq_names[i]);
|
||||
if (rv) {
|
||||
|
@ -161,7 +163,6 @@ vioscsi_attach(device_t parent, device_t self, void *aux)
|
|||
sc->sc_vqs[i].vq_done = vioscsi_vq_done;
|
||||
}
|
||||
|
||||
qsize = sc->sc_vqs[VIOSCSI_VQ_REQUEST].vq_num;
|
||||
if (vioscsi_alloc_reqs(sc, vsc, qsize))
|
||||
goto err;
|
||||
|
||||
|
@ -171,8 +172,7 @@ vioscsi_attach(device_t parent, device_t self, void *aux)
|
|||
cmd_per_lun, qsize, seg_max, max_target, max_lun);
|
||||
|
||||
if (virtio_child_attach_finish(vsc, sc->sc_vqs,
|
||||
__arraycount(sc->sc_vqs), NULL, virtio_vq_intr,
|
||||
VIRTIO_F_INTR_MSIX) != 0)
|
||||
__arraycount(sc->sc_vqs), NULL, VIRTIO_F_INTR_MSIX) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: virtio.c,v 1.66 2023/03/23 03:27:48 yamaguchi Exp $ */
|
||||
/* $NetBSD: virtio.c,v 1.67 2023/03/23 03:55:11 yamaguchi Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 The NetBSD Foundation, Inc.
|
||||
|
@ -28,7 +28,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.66 2023/03/23 03:27:48 yamaguchi Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.67 2023/03/23 03:55:11 yamaguchi Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -61,8 +61,8 @@ static const char *virtio_device_name[] = {
|
|||
};
|
||||
#define NDEVNAMES __arraycount(virtio_device_name)
|
||||
|
||||
static void virtio_init_vq(struct virtio_softc *,
|
||||
struct virtqueue *, const bool);
|
||||
static void virtio_reset_vq(struct virtio_softc *,
|
||||
struct virtqueue *);
|
||||
|
||||
void
|
||||
virtio_set_status(struct virtio_softc *sc, int status)
|
||||
|
@ -108,7 +108,7 @@ virtio_reinit_start(struct virtio_softc *sc)
|
|||
device_xname(sc->sc_dev),
|
||||
vq->vq_index);
|
||||
}
|
||||
virtio_init_vq(sc, vq, true);
|
||||
virtio_reset_vq(sc, vq);
|
||||
sc->sc_ops->setup_queue(sc, vq->vq_index,
|
||||
vq->vq_dmamap->dm_segs[0].ds_addr);
|
||||
}
|
||||
|
@ -434,6 +434,31 @@ virtio_soft_intr(void *arg)
|
|||
(*sc->sc_intrhand)(sc);
|
||||
}
|
||||
|
||||
/* set to vq->vq_intrhand in virtio_init_vq_vqdone() */
|
||||
static int
|
||||
virtio_vq_done(void *xvq)
|
||||
{
|
||||
struct virtqueue *vq = xvq;
|
||||
|
||||
return vq->vq_done(vq);
|
||||
}
|
||||
|
||||
static int
|
||||
virtio_vq_intr(struct virtio_softc *sc)
|
||||
{
|
||||
struct virtqueue *vq;
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < sc->sc_nvqs; i++) {
|
||||
vq = &sc->sc_vqs[i];
|
||||
if (virtio_vq_is_enqueued(sc, vq) == 1) {
|
||||
r |= (*vq->vq_intrhand)(vq->vq_intrhand_arg);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* dmamap sync operations for a virtqueue.
|
||||
*/
|
||||
|
@ -563,44 +588,6 @@ virtio_vq_is_enqueued(struct virtio_softc *sc, struct virtqueue *vq)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan vq, bus_dmamap_sync for the vqs (not for the payload),
|
||||
* and calls (*vq_done)() if some entries are consumed.
|
||||
*
|
||||
* Can be used as sc_intrhand.
|
||||
*/
|
||||
int
|
||||
virtio_vq_intr(struct virtio_softc *sc)
|
||||
{
|
||||
struct virtqueue *vq;
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < sc->sc_nvqs; i++) {
|
||||
vq = &sc->sc_vqs[i];
|
||||
if (virtio_vq_is_enqueued(sc, vq) == 1) {
|
||||
if (vq->vq_done)
|
||||
r |= (*vq->vq_done)(vq);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
virtio_vq_intrhand(struct virtio_softc *sc)
|
||||
{
|
||||
struct virtqueue *vq;
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < sc->sc_nvqs; i++) {
|
||||
vq = &sc->sc_vqs[i];
|
||||
r |= (*vq->vq_intrhand)(vq->vq_intrhand_arg);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Increase the event index in order to delay interrupts.
|
||||
*/
|
||||
|
@ -707,9 +694,11 @@ virtio_start_vq_intr(struct virtio_softc *sc, struct virtqueue *vq)
|
|||
/*
|
||||
* Initialize vq structure.
|
||||
*/
|
||||
/*
|
||||
* Reset virtqueue parameters
|
||||
*/
|
||||
static void
|
||||
virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq,
|
||||
const bool reinit)
|
||||
virtio_reset_vq(struct virtio_softc *sc, struct virtqueue *vq)
|
||||
{
|
||||
int i, j;
|
||||
int vq_size = vq->vq_num;
|
||||
|
@ -736,56 +725,75 @@ virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq,
|
|||
qe_list);
|
||||
vq->vq_entries[i].qe_index = i;
|
||||
}
|
||||
if (!reinit)
|
||||
mutex_init(&vq->vq_freelist_lock, MUTEX_SPIN, sc->sc_ipl);
|
||||
|
||||
/* enqueue/dequeue status */
|
||||
vq->vq_avail_idx = 0;
|
||||
vq->vq_used_idx = 0;
|
||||
vq->vq_queued = 0;
|
||||
if (!reinit) {
|
||||
mutex_init(&vq->vq_aring_lock, MUTEX_SPIN, sc->sc_ipl);
|
||||
mutex_init(&vq->vq_uring_lock, MUTEX_SPIN, sc->sc_ipl);
|
||||
}
|
||||
vq_sync_uring_all(sc, vq, BUS_DMASYNC_PREREAD);
|
||||
vq->vq_queued++;
|
||||
}
|
||||
|
||||
/* Initialize vq */
|
||||
void
|
||||
virtio_init_vq_vqdone(struct virtio_softc *sc, struct virtqueue *vq,
|
||||
int index, int (*vq_done)(struct virtqueue *))
|
||||
{
|
||||
|
||||
virtio_init_vq(sc, vq, index, virtio_vq_done, vq);
|
||||
vq->vq_done = vq_done;
|
||||
}
|
||||
|
||||
void
|
||||
virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq, int index,
|
||||
int (*intrhand)(void *), void *arg)
|
||||
{
|
||||
|
||||
memset(vq, 0, sizeof(*vq));
|
||||
|
||||
vq->vq_owner = sc;
|
||||
vq->vq_num = sc->sc_ops->read_queue_size(sc, index);
|
||||
vq->vq_index = index;
|
||||
vq->vq_intrhand = intrhand;
|
||||
vq->vq_intrhand_arg = arg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate/free a vq.
|
||||
*/
|
||||
int
|
||||
virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int index,
|
||||
virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq,
|
||||
int maxsegsize, int maxnsegs, const char *name)
|
||||
{
|
||||
int vq_size, allocsize1, allocsize2, allocsize3, allocsize = 0;
|
||||
bus_size_t size_desc, size_avail, size_used, size_indirect;
|
||||
bus_size_t allocsize = 0, size_desc_avail;
|
||||
int rsegs, r, hdrlen;
|
||||
unsigned int vq_num;
|
||||
#define VIRTQUEUE_ALIGN(n) roundup(n, VIRTIO_PAGE_SIZE)
|
||||
|
||||
memset(vq, 0, sizeof(*vq));
|
||||
vq_num = vq->vq_num;
|
||||
|
||||
vq_size = sc->sc_ops->read_queue_size(sc, index);
|
||||
if (vq_size == 0) {
|
||||
if (vq_num == 0) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"virtqueue not exist, index %d for %s\n",
|
||||
index, name);
|
||||
vq->vq_index, name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
hdrlen = sc->sc_active_features & VIRTIO_F_RING_EVENT_IDX ? 3 : 2;
|
||||
|
||||
/* allocsize1: descriptor table + avail ring + pad */
|
||||
allocsize1 = VIRTQUEUE_ALIGN(sizeof(struct vring_desc) * vq_size
|
||||
+ sizeof(uint16_t) * (hdrlen + vq_size));
|
||||
/* allocsize2: used ring + pad */
|
||||
allocsize2 = VIRTQUEUE_ALIGN(sizeof(uint16_t) * hdrlen
|
||||
+ sizeof(struct vring_used_elem) * vq_size);
|
||||
/* allocsize3: indirect table */
|
||||
if (sc->sc_indirect && maxnsegs >= MINSEG_INDIRECT)
|
||||
allocsize3 = sizeof(struct vring_desc) * maxnsegs * vq_size;
|
||||
else
|
||||
allocsize3 = 0;
|
||||
allocsize = allocsize1 + allocsize2 + allocsize3;
|
||||
size_desc = sizeof(vq->vq_desc[0]) * vq_num;
|
||||
size_avail = sizeof(uint16_t) * hdrlen
|
||||
+ sizeof(vq->vq_avail[0].ring) * vq_num;
|
||||
size_used = sizeof(uint16_t) *hdrlen
|
||||
+ sizeof(vq->vq_used[0].ring) * vq_num;
|
||||
size_indirect = (sc->sc_indirect && maxnsegs >= MINSEG_INDIRECT) ?
|
||||
sizeof(struct vring_desc) * maxnsegs * vq_num : 0;
|
||||
|
||||
size_desc_avail = VIRTQUEUE_ALIGN(size_desc + size_avail);
|
||||
size_used = VIRTQUEUE_ALIGN(size_used);
|
||||
|
||||
allocsize = size_desc_avail + size_used + size_indirect;
|
||||
|
||||
/* alloc and map the memory */
|
||||
r = bus_dmamem_alloc(sc->sc_dmat, allocsize, VIRTIO_PAGE_SIZE, 0,
|
||||
|
@ -793,78 +801,86 @@ virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int index,
|
|||
if (r != 0) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"virtqueue %d for %s allocation failed, "
|
||||
"error code %d\n", index, name, r);
|
||||
"error code %d\n", vq->vq_index, name, r);
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = bus_dmamem_map(sc->sc_dmat, &vq->vq_segs[0], rsegs, allocsize,
|
||||
&vq->vq_vaddr, BUS_DMA_WAITOK);
|
||||
if (r != 0) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"virtqueue %d for %s map failed, "
|
||||
"error code %d\n", index, name, r);
|
||||
"error code %d\n", vq->vq_index, name, r);
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = bus_dmamap_create(sc->sc_dmat, allocsize, 1, allocsize, 0,
|
||||
BUS_DMA_WAITOK, &vq->vq_dmamap);
|
||||
if (r != 0) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"virtqueue %d for %s dmamap creation failed, "
|
||||
"error code %d\n", index, name, r);
|
||||
"error code %d\n", vq->vq_index, name, r);
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = bus_dmamap_load(sc->sc_dmat, vq->vq_dmamap,
|
||||
vq->vq_vaddr, allocsize, NULL, BUS_DMA_WAITOK);
|
||||
if (r != 0) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"virtqueue %d for %s dmamap load failed, "
|
||||
"error code %d\n", index, name, r);
|
||||
"error code %d\n", vq->vq_index, name, r);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* remember addresses and offsets for later use */
|
||||
vq->vq_owner = sc;
|
||||
vq->vq_num = vq_size;
|
||||
vq->vq_index = index;
|
||||
vq->vq_desc = vq->vq_vaddr;
|
||||
vq->vq_availoffset = sizeof(struct vring_desc) * vq_size;
|
||||
vq->vq_avail = (void *)(((char *)vq->vq_desc) + vq->vq_availoffset);
|
||||
vq->vq_used_event = (uint16_t *)((char *)vq->vq_avail +
|
||||
offsetof(struct vring_avail, ring[vq->vq_num]));
|
||||
vq->vq_usedoffset = allocsize1;
|
||||
vq->vq_used = (void *)(((char *)vq->vq_desc) + vq->vq_usedoffset);
|
||||
vq->vq_avail_event = (uint16_t *)((char *)vq->vq_used +
|
||||
offsetof(struct vring_used, ring[vq->vq_num]));
|
||||
|
||||
if (allocsize3 > 0) {
|
||||
vq->vq_indirectoffset = allocsize1 + allocsize2;
|
||||
vq->vq_indirect = (void *)(((char *)vq->vq_desc)
|
||||
+ vq->vq_indirectoffset);
|
||||
}
|
||||
vq->vq_bytesize = allocsize;
|
||||
vq->vq_maxsegsize = maxsegsize;
|
||||
vq->vq_maxnsegs = maxnsegs;
|
||||
|
||||
#define VIRTIO_PTR(base, offset) (void *)((intptr_t)(base) + (offset))
|
||||
/* initialize vring pointers */
|
||||
vq->vq_desc = VIRTIO_PTR(vq->vq_vaddr, 0);
|
||||
vq->vq_availoffset = size_desc;
|
||||
vq->vq_avail = VIRTIO_PTR(vq->vq_vaddr, vq->vq_availoffset);
|
||||
vq->vq_used_event = VIRTIO_PTR(vq->vq_avail,
|
||||
offsetof(struct vring_avail, ring[vq_num]));
|
||||
vq->vq_usedoffset = size_desc_avail;
|
||||
vq->vq_used = VIRTIO_PTR(vq->vq_vaddr, vq->vq_usedoffset);
|
||||
vq->vq_avail_event = VIRTIO_PTR(vq->vq_used,
|
||||
offsetof(struct vring_used, ring[vq_num]));
|
||||
|
||||
if (size_indirect > 0) {
|
||||
vq->vq_indirectoffset = size_desc_avail + size_used;
|
||||
vq->vq_indirect = VIRTIO_PTR(vq->vq_vaddr,
|
||||
vq->vq_indirectoffset);
|
||||
}
|
||||
#undef VIRTIO_PTR
|
||||
|
||||
/* free slot management */
|
||||
vq->vq_entries = kmem_zalloc(sizeof(struct vq_entry) * vq_size,
|
||||
vq->vq_entries = kmem_zalloc(sizeof(struct vq_entry) * vq_num,
|
||||
KM_SLEEP);
|
||||
virtio_init_vq(sc, vq, false);
|
||||
|
||||
mutex_init(&vq->vq_freelist_lock, MUTEX_SPIN, sc->sc_ipl);
|
||||
mutex_init(&vq->vq_aring_lock, MUTEX_SPIN, sc->sc_ipl);
|
||||
mutex_init(&vq->vq_uring_lock, MUTEX_SPIN, sc->sc_ipl);
|
||||
|
||||
virtio_reset_vq(sc, vq);
|
||||
|
||||
/* set the vq address */
|
||||
sc->sc_ops->setup_queue(sc, index,
|
||||
sc->sc_ops->setup_queue(sc, vq->vq_index,
|
||||
vq->vq_dmamap->dm_segs[0].ds_addr);
|
||||
|
||||
aprint_verbose_dev(sc->sc_dev,
|
||||
"allocated %u byte for virtqueue %d for %s, size %d\n",
|
||||
allocsize, index, name, vq_size);
|
||||
if (allocsize3 > 0)
|
||||
"allocated %zu byte for virtqueue %d for %s, size %d\n",
|
||||
allocsize, vq->vq_index, name, vq_num);
|
||||
if (size_indirect > 0)
|
||||
aprint_verbose_dev(sc->sc_dev,
|
||||
"using %d byte (%d entries) indirect descriptors\n",
|
||||
allocsize3, maxnsegs * vq_size);
|
||||
"using %zu byte (%d entries) indirect descriptors\n",
|
||||
size_indirect, maxnsegs * vq_num);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
sc->sc_ops->setup_queue(sc, index, 0);
|
||||
sc->sc_ops->setup_queue(sc, vq->vq_index, 0);
|
||||
if (vq->vq_dmamap)
|
||||
bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap);
|
||||
if (vq->vq_vaddr)
|
||||
|
@ -1279,7 +1295,7 @@ virtio_child_attach_start(struct virtio_softc *sc, device_t child, int ipl,
|
|||
int
|
||||
virtio_child_attach_finish(struct virtio_softc *sc,
|
||||
struct virtqueue *vqs, size_t nvqs,
|
||||
virtio_callback config_change, virtio_callback intr_hand,
|
||||
virtio_callback config_change,
|
||||
int req_flags)
|
||||
{
|
||||
int r;
|
||||
|
@ -1292,8 +1308,9 @@ virtio_child_attach_finish(struct virtio_softc *sc,
|
|||
|
||||
for (size_t _i = 0; _i < nvqs; _i++){
|
||||
KASSERT(vqs[_i].vq_index == _i);
|
||||
KASSERT((req_flags & VIRTIO_F_INTR_PERVQ) == 0 ||
|
||||
vqs[_i].vq_intrhand != NULL);
|
||||
KASSERT(vqs[_i].vq_intrhand != NULL);
|
||||
KASSERT(vqs[_i].vq_done == NULL ||
|
||||
vqs[_i].vq_intrhand == virtio_vq_done);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1302,7 +1319,7 @@ virtio_child_attach_finish(struct virtio_softc *sc,
|
|||
sc->sc_vqs = vqs;
|
||||
sc->sc_nvqs = nvqs;
|
||||
sc->sc_config_change = config_change;
|
||||
sc->sc_intrhand = intr_hand;
|
||||
sc->sc_intrhand = virtio_vq_intr;
|
||||
sc->sc_flags = req_flags;
|
||||
|
||||
r = sc->sc_ops->alloc_interrupts(sc);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: virtiovar.h,v 1.25 2023/03/23 03:27:48 yamaguchi Exp $ */
|
||||
/* $NetBSD: virtiovar.h,v 1.26 2023/03/23 03:55:11 yamaguchi Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Minoura Makoto.
|
||||
|
@ -118,7 +118,7 @@ struct virtqueue {
|
|||
kmutex_t vq_uring_lock;
|
||||
|
||||
/* interrupt handler */
|
||||
int (*vq_done)(struct virtqueue*);
|
||||
int (*vq_done)(struct virtqueue*); /* for compatibility */
|
||||
int (*vq_intrhand)(void *);
|
||||
void *vq_intrhand_arg;
|
||||
|
||||
|
@ -172,7 +172,7 @@ struct virtio_softc {
|
|||
int sc_childdevid;
|
||||
device_t sc_child; /* set by child */
|
||||
virtio_callback sc_config_change; /* set by child */
|
||||
virtio_callback sc_intrhand; /* set by child */
|
||||
virtio_callback sc_intrhand;
|
||||
};
|
||||
#else
|
||||
struct virtio_softc;
|
||||
|
@ -204,7 +204,11 @@ void virtio_write_device_config_8(struct virtio_softc *, int, uint64_t);
|
|||
void virtio_write_device_config_le_2(struct virtio_softc *, int, uint16_t);
|
||||
void virtio_write_device_config_le_4(struct virtio_softc *, int, uint32_t);
|
||||
|
||||
int virtio_alloc_vq(struct virtio_softc*, struct virtqueue*, int, int, int,
|
||||
void virtio_init_vq(struct virtio_softc *, struct virtqueue *, int,
|
||||
int (*)(void *), void *);
|
||||
void virtio_init_vq_vqdone(struct virtio_softc *,struct virtqueue *, int,
|
||||
int (*)(struct virtqueue *));
|
||||
int virtio_alloc_vq(struct virtio_softc*, struct virtqueue*, int, int,
|
||||
const char*);
|
||||
int virtio_free_vq(struct virtio_softc*, struct virtqueue*);
|
||||
void virtio_reset(struct virtio_softc *);
|
||||
|
@ -214,7 +218,7 @@ void virtio_child_attach_start(struct virtio_softc *, device_t, int,
|
|||
uint64_t, const char *);
|
||||
int virtio_child_attach_finish(struct virtio_softc *,
|
||||
struct virtqueue *, size_t,
|
||||
virtio_callback, virtio_callback, int);
|
||||
virtio_callback, int);
|
||||
void virtio_child_attach_failed(struct virtio_softc *);
|
||||
void virtio_child_detach(struct virtio_softc *);
|
||||
|
||||
|
@ -231,8 +235,6 @@ int virtio_dequeue(struct virtio_softc*, struct virtqueue*, int *, int *);
|
|||
int virtio_dequeue_commit(struct virtio_softc*, struct virtqueue*, int);
|
||||
|
||||
bool virtio_vq_is_enqueued(struct virtio_softc *, struct virtqueue *);
|
||||
int virtio_vq_intr(struct virtio_softc *);
|
||||
int virtio_vq_intrhand(struct virtio_softc *);
|
||||
int virtio_postpone_intr(struct virtio_softc *sc, struct virtqueue *vq,
|
||||
uint16_t nslots);
|
||||
int virtio_postpone_intr_smart(struct virtio_softc *sc, struct virtqueue *vq);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: viocon.c,v 1.7 2023/03/23 03:44:28 yamaguchi Exp $ */
|
||||
/* $NetBSD: viocon.c,v 1.8 2023/03/23 03:55:11 yamaguchi 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.7 2023/03/23 03:44:28 yamaguchi Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.8 2023/03/23 03:55:11 yamaguchi Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -225,7 +225,7 @@ viocon_attach(struct device *parent, struct device *self, void *aux)
|
|||
viocon_rx_fill(sc->sc_ports[0]);
|
||||
|
||||
if (virtio_child_attach_finish(vsc, sc->sc_vqs, nvqs,
|
||||
/*config_change*/NULL, virtio_vq_intr, /*req_flags*/0) != 0)
|
||||
/*config_change*/NULL, /*req_flags*/0) != 0)
|
||||
goto err;
|
||||
|
||||
return;
|
||||
|
@ -256,24 +256,26 @@ viocon_port_create(struct viocon_softc *sc, int portidx)
|
|||
txidx = (portidx * VIOCON_PORT_NQS) + VIOCON_PORT_TX;
|
||||
|
||||
snprintf(name, sizeof(name), "p%drx", portidx);
|
||||
if (virtio_alloc_vq(vsc, &sc->sc_vqs[rxidx], rxidx, BUFSIZE, 1,
|
||||
virtio_init_vq_vqdone(vsc, &sc->sc_vqs[rxidx], rxidx,
|
||||
viocon_rx_intr);
|
||||
if (virtio_alloc_vq(vsc, &sc->sc_vqs[rxidx], BUFSIZE, 1,
|
||||
name) != 0) {
|
||||
printf("\nCan't alloc %s virtqueue\n", name);
|
||||
goto err;
|
||||
}
|
||||
vp->vp_rx = &sc->sc_vqs[rxidx];
|
||||
vp->vp_rx->vq_done = viocon_rx_intr;
|
||||
vp->vp_si = softint_establish(SOFTINT_SERIAL, viocon_rx_soft, vp);
|
||||
DPRINTF("%s: rx: %p\n", __func__, vp->vp_rx);
|
||||
|
||||
snprintf(name, sizeof(name), "p%dtx", portidx);
|
||||
if (virtio_alloc_vq(vsc, &sc->sc_vqs[txidx], txidx, BUFSIZE, 1,
|
||||
virtio_init_vq_vqdone(vsc, &sc->sc_vqs[txidx], txidx,
|
||||
viocon_tx_intr);
|
||||
if (virtio_alloc_vq(vsc, &sc->sc_vqs[txidx], BUFSIZE, 1,
|
||||
name) != 0) {
|
||||
printf("\nCan't alloc %s virtqueue\n", name);
|
||||
goto err;
|
||||
}
|
||||
vp->vp_tx = &sc->sc_vqs[txidx];
|
||||
vp->vp_tx->vq_done = viocon_tx_intr;
|
||||
DPRINTF("%s: tx: %p\n", __func__, vp->vp_tx);
|
||||
|
||||
allocsize = (vp->vp_rx->vq_num + vp->vp_tx->vq_num) * BUFSIZE;
|
||||
|
|
Loading…
Reference in New Issue