summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2018-01-03 21:11:35 +0000
committerPatrick Mooney <pmooney@pfmooney.com>2018-02-28 18:42:18 +0000
commit887132348b2882cd572106fe2dede45955e3a623 (patch)
treea49b5f4ba88d51aa9ae2cddc7d3646e3303fa2eb /usr/src/cmd
parent9c1f0b4865ff20abeb270b5e73b7372aa4f49fea (diff)
downloadillumos-joyent-887132348b2882cd572106fe2dede45955e3a623.tar.gz
OS-6681 modernize viona driver
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com> Reviewed by: Mike Gerdts <mike.gerdts@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/bhyve/Makefile.com1
-rw-r--r--usr/src/cmd/bhyve/pci_emul.c5
-rw-r--r--usr/src/cmd/bhyve/pci_emul.h7
-rw-r--r--usr/src/cmd/bhyve/pci_virtio_viona.c472
-rw-r--r--usr/src/cmd/devfsadm/i386/misc_link_i386.c6
5 files changed, 312 insertions, 179 deletions
diff --git a/usr/src/cmd/bhyve/Makefile.com b/usr/src/cmd/bhyve/Makefile.com
index b80bf910de..b9ad3fde70 100644
--- a/usr/src/cmd/bhyve/Makefile.com
+++ b/usr/src/cmd/bhyve/Makefile.com
@@ -42,6 +42,7 @@ SRCS = acpi.c \
pci_virtio_block.c \
pci_virtio_net.c \
pci_virtio_rnd.c \
+ pci_virtio_viona.c \
pci_xhci.c \
pm.c \
post.c \
diff --git a/usr/src/cmd/bhyve/pci_emul.c b/usr/src/cmd/bhyve/pci_emul.c
index 101773b4e5..d48af9521b 100644
--- a/usr/src/cmd/bhyve/pci_emul.c
+++ b/usr/src/cmd/bhyve/pci_emul.c
@@ -1580,6 +1580,11 @@ pci_lintr_update(struct pci_devinst *pi)
pci_irq_assert(pi);
}
pthread_mutex_unlock(&pi->pi_lintr.lock);
+#ifndef __FreeBSD__
+ if (pi->pi_d->pe_lintrupdate != NULL) {
+ pi->pi_d->pe_lintrupdate(pi);
+ }
+#endif /* __FreeBSD__ */
}
int
diff --git a/usr/src/cmd/bhyve/pci_emul.h b/usr/src/cmd/bhyve/pci_emul.h
index 0fffb19dee..a0aaa425be 100644
--- a/usr/src/cmd/bhyve/pci_emul.h
+++ b/usr/src/cmd/bhyve/pci_emul.h
@@ -25,6 +25,9 @@
*
* $FreeBSD$
*/
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
#ifndef _PCI_EMUL_H_
#define _PCI_EMUL_H_
@@ -69,6 +72,10 @@ struct pci_devemu {
uint64_t (*pe_barread)(struct vmctx *ctx, int vcpu,
struct pci_devinst *pi, int baridx,
uint64_t offset, int size);
+
+#ifndef __FreeBSD__
+ void (*pe_lintrupdate)(struct pci_devinst *pi);
+#endif /* __FreeBSD__ */
};
#define PCI_EMUL_SET(x) DATA_SET(pci_devemu_set, x);
diff --git a/usr/src/cmd/bhyve/pci_virtio_viona.c b/usr/src/cmd/bhyve/pci_virtio_viona.c
index e5a5cb584f..1c4b739711 100644
--- a/usr/src/cmd/bhyve/pci_virtio_viona.c
+++ b/usr/src/cmd/bhyve/pci_virtio_viona.c
@@ -34,7 +34,7 @@
* http://www.illumos.org/license/CDDL.
*
* Copyright 2015 Pluribus Networks Inc.
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#include <sys/cdefs.h>
@@ -85,18 +85,6 @@
#define VIONA_REGSZ VIONA_R_MAX+1
/*
- * Host capabilities
- */
-#define VIRTIO_NET_F_MAC (1 << 5) /* host supplies MAC */
-#define VIRTIO_NET_F_MRG_RXBUF (1 << 15) /* host can merge RX buffers */
-#define VIRTIO_NET_F_STATUS (1 << 16) /* config status field available */
-
-#define VIONA_S_HOSTCAPS \
- (VIRTIO_NET_F_MAC | \
- VIRTIO_NET_F_MRG_RXBUF | \
- VIRTIO_NET_F_STATUS)
-
-/*
* Queue definitions.
*/
#define VIONA_RXQ 0
@@ -108,7 +96,7 @@
/*
* Debug printf
*/
-static int pci_viona_debug;
+static volatile int pci_viona_debug;
#define DPRINTF(params) if (pci_viona_debug) printf params
#define WPRINTF(params) printf params
@@ -124,26 +112,20 @@ struct pci_viona_softc {
int vsc_isr;
datalink_id_t vsc_linkid;
- char vsc_linkname[MAXLINKNAMELEN];
int vsc_vnafd;
+ /* Configurable parameters */
+ char vsc_linkname[MAXLINKNAMELEN];
+ uint32_t vsc_feature_mask;
+ uint16_t vsc_vq_size;
+
uint32_t vsc_features;
uint8_t vsc_macaddr[6];
uint64_t vsc_pfn[VIONA_MAXQ];
uint16_t vsc_msix_table_idx[VIONA_MAXQ];
- /*
- * Flag to see if host is already sending data out.
- * If it is, no need to wait for lock and send interrupt to host
- * for new data.
- */
- boolean_t vsc_tx_kick_lock_held;
-
- pthread_t tx_tid;
- pthread_mutex_t tx_mtx;
- pthread_cond_t tx_cond;
+ boolean_t vsc_msix_active;
};
-#define viona_ctx(sc) ((sc)->vsc_pi->pi_vmctx)
/*
* Return the size of IO BAR that maps virtio header and device specific
@@ -160,15 +142,14 @@ pci_viona_iosize(struct pci_devinst *pi)
}
static uint16_t
-pci_viona_qsize(int qnum)
+pci_viona_qsize(struct pci_viona_softc *sc, int qnum)
{
/* XXX no ctl queue currently */
if (qnum == VIONA_CTLQ) {
return (0);
}
- /* XXX fixed currently. Maybe different for tx/rx/ctl */
- return (VIONA_RINGSZ);
+ return (sc->vsc_vq_size);
}
static void
@@ -180,21 +161,13 @@ pci_viona_ring_reset(struct pci_viona_softc *sc, int ring)
switch (ring) {
case VIONA_RXQ:
- error = ioctl(sc->vsc_vnafd, VNA_IOC_RX_RING_RESET);
- if (error != 0) {
- WPRINTF(("ioctl viona rx ring reset failed %d\n",
- error));
- } else {
- sc->vsc_pfn[VIONA_RXQ] = 0;
- }
- break;
case VIONA_TXQ:
- error = ioctl(sc->vsc_vnafd, VNA_IOC_TX_RING_RESET);
+ error = ioctl(sc->vsc_vnafd, VNA_IOC_RING_RESET, ring);
if (error != 0) {
- WPRINTF(("ioctl viona tx ring reset failed %d\n",
- error));
+ WPRINTF(("ioctl viona ring %u reset failed %d\n",
+ ring, errno));
} else {
- sc->vsc_pfn[VIONA_TXQ] = 0;
+ sc->vsc_pfn[ring] = 0;
}
break;
case VIONA_CTLQ:
@@ -220,11 +193,11 @@ static void *
pci_viona_poll_thread(void *param)
{
struct pci_viona_softc *sc = param;
- pollfd_t pollset;
- int error;
+ pollfd_t pollset;
+ const int fd = sc->vsc_vnafd;
- pollset.fd = sc->vsc_vnafd;
- pollset.events = POLLIN | POLLOUT;
+ pollset.fd = fd;
+ pollset.events = POLLRDBAND;
for (;;) {
if (poll(&pollset, 1, -1) < 0) {
@@ -236,23 +209,35 @@ pci_viona_poll_thread(void *param)
break;
}
}
- if (pollset.revents & POLLIN) {
- pci_generate_msix(sc->vsc_pi,
- sc->vsc_msix_table_idx[VIONA_RXQ]);
- error = ioctl(sc->vsc_vnafd, VNA_IOC_RX_INTR_CLR);
- if (error != 0) {
- WPRINTF(("ioctl viona rx intr clear failed"
- " %d\n", error));
+ if (pollset.revents & POLLRDBAND) {
+ vioc_intr_poll_t vip;
+ uint_t i;
+ int res;
+ boolean_t assert_lintr = B_FALSE;
+ const boolean_t do_msix = pci_msix_enabled(sc->vsc_pi);
+
+ res = ioctl(fd, VNA_IOC_INTR_POLL, &vip);
+ for (i = 0; res > 0 && i < VIONA_VQ_MAX; i++) {
+ if (vip.vip_status[i] == 0) {
+ continue;
+ }
+ if (do_msix) {
+ pci_generate_msix(sc->vsc_pi,
+ sc->vsc_msix_table_idx[i]);
+ } else {
+ assert_lintr = B_TRUE;
+ }
+ res = ioctl(fd, VNA_IOC_RING_INTR_CLR, i);
+ if (res != 0) {
+ WPRINTF(("ioctl viona vq %d intr "
+ "clear failed %d\n", i, errno));
+ }
}
- }
-
- if (pollset.revents & POLLOUT) {
- pci_generate_msix(sc->vsc_pi,
- sc->vsc_msix_table_idx[VIONA_TXQ]);
- error = ioctl(sc->vsc_vnafd, VNA_IOC_TX_INTR_CLR);
- if (error != 0) {
- WPRINTF(("ioctl viona tx intr clear failed"
- " %d\n", error));
+ if (assert_lintr) {
+ pthread_mutex_lock(&sc->vsc_mtx);
+ sc->vsc_isr |= VTCFG_ISR_QUEUES;
+ pci_lintr_assert(sc->vsc_pi);
+ pthread_mutex_unlock(&sc->vsc_mtx);
}
}
}
@@ -261,57 +246,6 @@ pci_viona_poll_thread(void *param)
}
static void
-pci_viona_ping_rxq(struct pci_viona_softc *sc)
-{
- int error;
-
- error = ioctl(sc->vsc_vnafd, VNA_IOC_RX_RING_KICK);
- if (error != 0) {
- WPRINTF(("ioctl viona rx ring kick failed %d\n", error));
- }
-}
-
-static void *
-pci_viona_tx_thread(void *param)
-{
- struct pci_viona_softc *sc = (struct pci_viona_softc *)param;
- int error;
-
- pthread_mutex_lock(&sc->tx_mtx);
- for (;;) {
- error = pthread_cond_wait(&sc->tx_cond, &sc->tx_mtx);
- assert(error == 0);
- sc->vsc_tx_kick_lock_held = B_TRUE;
- error = ioctl(sc->vsc_vnafd, VNA_IOC_TX_RING_KICK);
- if (error != 0) {
- WPRINTF(("ioctl viona tx ring kick failed %d\n",
- error));
- }
- sc->vsc_tx_kick_lock_held = B_FALSE;
- }
- pthread_mutex_unlock(&sc->tx_mtx);
-
- return (NULL);
-}
-
-static void
-pci_viona_ping_txq(struct pci_viona_softc *sc)
-{
- /* Signal the tx thread for processing */
- if (sc->vsc_tx_kick_lock_held)
- return;
- pthread_mutex_lock(&sc->tx_mtx);
- pthread_cond_signal(&sc->tx_cond);
- pthread_mutex_unlock(&sc->tx_mtx);
-}
-
-static void
-pci_viona_ping_ctlq(struct pci_viona_softc *sc)
-{
- DPRINTF(("viona: control qnotify!\n\r"));
-}
-
-static void
pci_viona_ring_init(struct pci_viona_softc *sc, uint64_t pfn)
{
int qnum = sc->vsc_curq;
@@ -320,29 +254,19 @@ pci_viona_ring_init(struct pci_viona_softc *sc, uint64_t pfn)
assert(qnum < VIONA_MAXQ);
+ if (qnum == VIONA_CTLQ) {
+ return;
+ }
+
sc->vsc_pfn[qnum] = (pfn << VRING_PFN);
- vna_ri.ri_qsize = pci_viona_qsize(qnum);
+ vna_ri.ri_index = qnum;
+ vna_ri.ri_qsize = pci_viona_qsize(sc, qnum);
vna_ri.ri_qaddr = (pfn << VRING_PFN);
+ error = ioctl(sc->vsc_vnafd, VNA_IOC_RING_INIT, &vna_ri);
- switch (qnum) {
- case VIONA_RXQ:
- error = ioctl(sc->vsc_vnafd, VNA_IOC_RX_RING_INIT, &vna_ri);
- if (error != 0) {
- WPRINTF(("ioctl viona rx ring init failed %d\n",
- error));
- }
- break;
- case VIONA_TXQ:
- error = ioctl(sc->vsc_vnafd, VNA_IOC_TX_RING_INIT, &vna_ri);
- if (error != 0) {
- WPRINTF(("ioctl viona tx ring init failed %d\n",
- error));
- }
- break;
- case VIONA_CTLQ:
- default:
- break;
+ if (error != 0) {
+ WPRINTF(("ioctl viona ring %u init failed %d\n", qnum, errno));
}
}
@@ -350,30 +274,20 @@ static int
pci_viona_viona_init(struct vmctx *ctx, struct pci_viona_softc *sc)
{
vioc_create_t vna_create;
-#if notyet
- char devname[MAXNAMELEN];
- int ctlfd;
-#endif
int error;
- sc->vsc_vnafd = open("/devices/pseudo/viona@0:ctl", O_RDWR | O_EXCL);
+ sc->vsc_vnafd = open("/dev/viona", O_RDWR | O_EXCL);
if (sc->vsc_vnafd == -1) {
- WPRINTF(("open viona ctl failed\n"));
+ WPRINTF(("open viona ctl failed: %d\n", errno));
return (-1);
}
vna_create.c_linkid = sc->vsc_linkid;
- strlcpy(vna_create.c_vmname, vmname,
- sizeof (vna_create.c_vmname));
-#if notyet
- vm_get_memory_seg(ctx, 1 * (1024 * 1024UL), &vna_create.c_lomem_size,
- NULL);
- vm_get_memory_seg(ctx, 4 * (1024 * 1024 * 1024UL),
- &vna_create.c_himem_size, NULL);
-#endif
+ vna_create.c_vmfd = vm_get_device_fd(ctx);
error = ioctl(sc->vsc_vnafd, VNA_IOC_CREATE, &vna_create);
if (error != 0) {
- WPRINTF(("ioctl viona create failed %d\n", error));
+ (void) close(sc->vsc_vnafd);
+ WPRINTF(("ioctl viona create failed %d\n", errno));
return (-1);
}
@@ -381,15 +295,99 @@ pci_viona_viona_init(struct vmctx *ctx, struct pci_viona_softc *sc)
}
static int
+pci_viona_parse_opts(struct pci_viona_softc *sc, char *opts)
+{
+ char *next, *cp, *vnic = NULL;
+ int err = 0;
+
+ sc->vsc_vq_size = VIONA_RINGSZ;
+ sc->vsc_feature_mask = 0;
+
+ for (; opts != NULL && *opts != '\0'; opts = next) {
+ char *val;
+
+ if ((cp = strchr(opts, ',')) != NULL) {
+ *cp = '\0';
+ next = cp + 1;
+ } else {
+ next = NULL;
+ }
+
+ if ((cp = strchr(opts, '=')) == NULL) {
+ /* vnic chosen with bare name */
+ if (vnic != NULL) {
+ fprintf(stderr,
+ "viona: unexpected vnic name '%s'", opts);
+ err = -1;
+ } else {
+ vnic = opts;
+ }
+ continue;
+ }
+
+ /* <param>=<value> handling */
+ val = cp + 1;
+ *cp = '\0';
+ if (strcmp(opts, "feature_mask") == 0) {
+ long num;
+
+ errno = 0;
+ num = strtol(val, NULL, 0);
+ if (errno != 0 || num < 0) {
+ fprintf(stderr,
+ "viona: invalid mask '%s'", val);
+ } else {
+ sc->vsc_feature_mask = num;
+ }
+ } else if (strcmp(opts, "vqsize") == 0) {
+ long num;
+
+ errno = 0;
+ num = strtol(val, NULL, 0);
+ if (errno != 0) {
+ fprintf(stderr,
+ "viona: invalid vsqize '%s'", val);
+ err = -1;
+ } else if (num <= 2 || num > 32768) {
+ fprintf(stderr,
+ "viona: vqsize out of range", num);
+ err = -1;
+ } else if ((1 << (ffs(num) - 1)) != num) {
+ fprintf(stderr,
+ "viona: vqsize must be power of 2", num);
+ err = -1;
+ } else {
+ sc->vsc_vq_size = num;
+ }
+ } else {
+ fprintf(stderr,
+ "viona: unrecognized option '%s'", opts);
+ err = -1;
+ }
+ }
+ if (vnic == NULL) {
+ fprintf(stderr, "viona: vnic name required");
+ sc->vsc_linkname[0] = '\0';
+ err = -1;
+ } else {
+ (void) strlcpy(sc->vsc_linkname, vnic, MAXLINKNAMELEN);
+ }
+
+ DPRINTF(("viona=%p dev=%s vqsize=%x feature_mask=%x\n", sc,
+ sc->vsc_linkname, sc->vsc_vq_size, sc->vsc_feature_mask));
+ return (err);
+}
+
+static int
pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
{
dladm_handle_t handle;
dladm_status_t status;
dladm_vnic_attr_t attr;
char errmsg[DLADM_STRSIZE];
- int error;
+ int error, i;
struct pci_viona_softc *sc;
- int i;
+ uint64_t ioport;
if (opts == NULL) {
printf("virtio-viona: vnic required\n");
@@ -404,7 +402,10 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
pthread_mutex_init(&sc->vsc_mtx, NULL);
- strlcpy(sc->vsc_linkname, opts, MAXLINKNAMELEN);
+ if (pci_viona_parse_opts(sc, opts) != 0) {
+ free(sc);
+ return (1);
+ }
if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) {
WPRINTF(("could not open /dev/dld"));
@@ -430,7 +431,6 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
return (1);
}
- sc->vsc_tx_kick_lock_held = B_FALSE;
memcpy(sc->vsc_macaddr, attr.va_mac_addr, ETHERADDRL);
dladm_close(handle);
@@ -449,42 +449,44 @@ pci_viona_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK);
pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_NET);
+ pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_VENDOR);
/* MSI-X support */
for (i = 0; i < VIONA_MAXQ; i++)
sc->vsc_msix_table_idx[i] = VIRTIO_MSI_NO_VECTOR;
- /*
- * BAR 1 used to map MSI-X table and PBA
- */
+ /* BAR 1 used to map MSI-X table and PBA */
if (pci_emul_add_msixcap(pi, VIONA_MAXQ, 1)) {
free(sc);
return (1);
}
- pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VIONA_REGSZ);
+ /* BAR 0 for legacy-style virtio register access. */
+ error = pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VIONA_REGSZ);
+ if (error != NULL) {
+ WPRINTF(("could not allocate virtio BAR\n"));
+ free(sc);
+ return (1);
+ }
+
+ /* Install ioport hook for virtqueue notification */
+ ioport = pi->pi_bar[0].addr + VTCFG_R_QNOTIFY;
+ error = ioctl(sc->vsc_vnafd, VNA_IOC_SET_NOTIFY_IOP, ioport);
+ if (error != 0) {
+ WPRINTF(("could not install ioport hook at %x\n", ioport));
+ free(sc);
+ return (1);
+ }
/*
- * Initialize tx semaphore & spawn TX processing thread
- * As of now, only one thread for TX desc processing is
- * spawned.
+ * Need a legacy interrupt for virtio compliance, even though MSI-X
+ * operation is _strongly_ suggested for adequate performance.
*/
- pthread_mutex_init(&sc->tx_mtx, NULL);
- pthread_cond_init(&sc->tx_cond, NULL);
- pthread_create(&sc->tx_tid, NULL, pci_viona_tx_thread, (void *)sc);
+ pci_lintr_request(pi);
return (0);
}
-/*
- * Function pointer array to handle queue notifications
- */
-static void (*pci_viona_qnotify[VIONA_MAXQ])(struct pci_viona_softc *) = {
- pci_viona_ping_rxq,
- pci_viona_ping_txq,
- pci_viona_ping_ctlq
-};
-
static uint64_t
viona_adjust_offset(struct pci_devinst *pi, uint64_t offset)
{
@@ -501,6 +503,109 @@ viona_adjust_offset(struct pci_devinst *pi, uint64_t offset)
}
static void
+pci_viona_ring_set_msix(struct pci_devinst *pi, uint_t ring)
+{
+ struct pci_viona_softc *sc = pi->pi_arg;
+ struct msix_table_entry mte;
+ uint16_t tab_index;
+ vioc_ring_msi_t vrm;
+ int res;
+
+ assert(ring <= VIONA_VQ_TX);
+
+ vrm.rm_index = ring;
+ vrm.rm_addr = 0;
+ vrm.rm_msg = 0;
+ tab_index = sc->vsc_msix_table_idx[ring];
+
+ if (tab_index != VIRTIO_MSI_NO_VECTOR && sc->vsc_msix_active) {
+ mte = pi->pi_msix.table[tab_index];
+ if ((mte.vector_control & PCIM_MSIX_VCTRL_MASK) == 0) {
+ vrm.rm_addr = mte.addr;
+ vrm.rm_msg = mte.msg_data;
+ }
+ }
+
+ res = ioctl(sc->vsc_vnafd, VNA_IOC_RING_SET_MSI, &vrm);
+ if (res != 0) {
+ WPRINTF(("ioctl viona set_msi %d failed %d\n", ring, errno));
+ }
+}
+
+static void
+pci_viona_lintrupdate(struct pci_devinst *pi)
+{
+ struct pci_viona_softc *sc = pi->pi_arg;
+ boolean_t msix_on = B_FALSE;
+
+ pthread_mutex_lock(&sc->vsc_mtx);
+ msix_on = pci_msix_enabled(pi) && (pi->pi_msix.function_mask == 0);
+ if ((sc->vsc_msix_active && !msix_on) ||
+ (msix_on && !sc->vsc_msix_active)) {
+ uint_t i;
+
+ sc->vsc_msix_active = msix_on;
+ /* Update in-kernel ring configs */
+ for (i = 0; i <= VIONA_VQ_TX; i++) {
+ pci_viona_ring_set_msix(pi, i);
+ }
+ }
+ pthread_mutex_unlock(&sc->vsc_mtx);
+}
+
+static void
+pci_viona_msix_update(struct pci_devinst *pi, uint64_t offset)
+{
+ struct pci_viona_softc *sc = pi->pi_arg;
+ uint_t tab_index, i;
+
+ pthread_mutex_lock(&sc->vsc_mtx);
+ if (!sc->vsc_msix_active) {
+ pthread_mutex_unlock(&sc->vsc_mtx);
+ return;
+ }
+
+ /*
+ * Rather than update every possible MSI-X vector, cheat and use the
+ * offset to calculate the entry within the table. Since this should
+ * only be called when a write to the table succeeds, the index should
+ * be valid.
+ */
+ tab_index = offset / MSIX_TABLE_ENTRY_SIZE;
+
+ for (i = 0; i <= VIONA_VQ_TX; i++) {
+ if (sc->vsc_msix_table_idx[i] != tab_index) {
+ continue;
+ }
+ pci_viona_ring_set_msix(pi, i);
+ }
+
+ pthread_mutex_unlock(&sc->vsc_mtx);
+}
+
+static void
+pci_viona_qnotify(struct pci_viona_softc *sc, int ring)
+{
+ int error;
+
+ switch (ring) {
+ case VIONA_TXQ:
+ case VIONA_RXQ:
+ error = ioctl(sc->vsc_vnafd, VNA_IOC_RING_KICK, ring);
+ if (error != 0) {
+ WPRINTF(("ioctl viona ring %d kick failed %d\n",
+ ring, errno));
+ }
+ break;
+ case VIONA_CTLQ:
+ DPRINTF(("viona: control qnotify!\n"));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
int baridx, uint64_t offset, int size, uint64_t value)
{
@@ -510,7 +615,9 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
if (baridx == pci_msix_table_bar(pi) ||
baridx == pci_msix_pba_bar(pi)) {
- pci_emul_msix_twrite(pi, offset, size, value);
+ if (pci_emul_msix_twrite(pi, offset, size, value) == 0) {
+ pci_viona_msix_update(pi, offset);
+ }
return;
}
@@ -529,10 +636,14 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
switch (offset) {
case VTCFG_R_GUESTCAP:
assert(size == 4);
+ value &= ~(sc->vsc_feature_mask);
err = ioctl(sc->vsc_vnafd, VNA_IOC_SET_FEATURES, &value);
- if (err != 0)
+ if (err != 0) {
WPRINTF(("ioctl feature negotiation returned"
- " err = %d\n", err));
+ " err = %d\n", errno));
+ } else {
+ sc->vsc_features = value;
+ }
break;
case VTCFG_R_PFN:
assert(size == 4);
@@ -546,7 +657,7 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
case VTCFG_R_QNOTIFY:
assert(size == 2);
assert(value < VIONA_MAXQ);
- (*pci_viona_qnotify[value])(sc);
+ pci_viona_qnotify(sc, value);
break;
case VTCFG_R_STATUS:
assert(size == 1);
@@ -597,7 +708,7 @@ pci_viona_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
pthread_mutex_unlock(&sc->vsc_mtx);
}
-uint64_t
+static uint64_t
pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
int baridx, uint64_t offset, int size)
{
@@ -627,9 +738,11 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
case VTCFG_R_HOSTCAP:
assert(size == 4);
err = ioctl(sc->vsc_vnafd, VNA_IOC_GET_FEATURES, &value);
- if (err != 0)
+ if (err != 0) {
WPRINTF(("ioctl get host features returned"
- " err = %d\n", err));
+ " err = %d\n", errno));
+ }
+ value &= ~sc->vsc_feature_mask;
break;
case VTCFG_R_GUESTCAP:
assert(size == 4);
@@ -641,7 +754,7 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
break;
case VTCFG_R_QNUM:
assert(size == 2);
- value = pci_viona_qsize(sc->vsc_curq);
+ value = pci_viona_qsize(sc, sc->vsc_curq);
break;
case VTCFG_R_QSEL:
assert(size == 2);
@@ -705,9 +818,10 @@ pci_viona_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
}
struct pci_devemu pci_de_viona = {
- .pe_emu = "virtio-net-viona",
+ .pe_emu = "virtio-net-viona",
.pe_init = pci_viona_init,
.pe_barwrite = pci_viona_write,
- .pe_barread = pci_viona_read
+ .pe_barread = pci_viona_read,
+ .pe_lintrupdate = pci_viona_lintrupdate
};
PCI_EMUL_SET(pci_de_viona);
diff --git a/usr/src/cmd/devfsadm/i386/misc_link_i386.c b/usr/src/cmd/devfsadm/i386/misc_link_i386.c
index f1a6ef1172..99085a3d4f 100644
--- a/usr/src/cmd/devfsadm/i386/misc_link_i386.c
+++ b/usr/src/cmd/devfsadm/i386/misc_link_i386.c
@@ -84,6 +84,9 @@ static devfsadm_create_t misc_cbt[] = {
{ "pseudo", "ddi_pseudo", "ucode",
TYPE_EXACT | DRV_EXACT, ILEVEL_0, ln_minor_name,
},
+ { "pseudo", "ddi_pseudo", "viona",
+ TYPE_EXACT | DRV_EXACT, ILEVEL_0, ln_minor_name,
+ }
};
DEVFSADM_CREATE_INIT_V0(misc_cbt);
@@ -109,6 +112,9 @@ static devfsadm_remove_t misc_remove_cbt[] = {
},
{ "serial", "^tty[a-z]$", RM_ALWAYS | RM_PRE,
ILEVEL_1, devfsadm_rm_all
+ },
+ { "pseudo", "^viona$", RM_ALWAYS | RM_PRE | RM_HOT,
+ ILEVEL_0, devfsadm_rm_all
}
};