Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Begin to detangle virtio from its PCI attachment
details: https://anonhg.NetBSD.org/src/rev/4e771d30ebaf
branches: trunk
changeset: 319547:4e771d30ebaf
user: jakllsch <jakllsch%NetBSD.org@localhost>
date: Sat Jun 02 22:43:15 2018 +0000
description:
Begin to detangle virtio from its PCI attachment
diffstat:
sys/dev/pci/virtio.c | 459 +++---------------------------------
sys/dev/pci/virtio_pci.c | 583 ++++++++++++++++++++++++++++++++++++++++++++--
sys/dev/pci/virtiovar.h | 32 +-
3 files changed, 621 insertions(+), 453 deletions(-)
diffs (truncated from 1358 to 300 lines):
diff -r 8975792b6e17 -r 4e771d30ebaf sys/dev/pci/virtio.c
--- a/sys/dev/pci/virtio.c Sat Jun 02 22:30:19 2018 +0000
+++ b/sys/dev/pci/virtio.c Sat Jun 02 22:43:15 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: virtio.c,v 1.30 2018/02/14 14:04:48 uwe Exp $ */
+/* $NetBSD: virtio.c,v 1.31 2018/06/02 22:43:15 jakllsch Exp $ */
/*
* Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.30 2018/02/14 14:04:48 uwe Exp $");
+__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.31 2018/06/02 22:43:15 jakllsch Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -48,300 +48,15 @@
#define MINSEG_INDIRECT 2 /* use indirect if nsegs >= this value */
-static int virtio_intr(void *arg);
-static int virtio_msix_queue_intr(void *);
-static int virtio_msix_config_intr(void *);
-static int virtio_setup_msix_vectors(struct virtio_softc *);
-static int virtio_setup_msix_interrupts(struct virtio_softc *,
- struct pci_attach_args *);
-static int virtio_setup_intx_interrupt(struct virtio_softc *,
- struct pci_attach_args *);
-static int virtio_setup_interrupts(struct virtio_softc *);
-static void virtio_free_interrupts(struct virtio_softc *);
-static void virtio_soft_intr(void *arg);
static void virtio_init_vq(struct virtio_softc *,
struct virtqueue *, const bool);
-
-/* we use the legacy virtio spec, so the pci registers are host native
- * byte order, not pci (i.e. LE) byte order */
-static inline uint16_t
-nbo_bus_space_read_2(bus_space_tag_t space, bus_space_handle_t handle,
- bus_size_t offset)
-{
- return le16toh(bus_space_read_2(space, handle, offset));
-}
-
-static inline uint32_t
-nbo_bus_space_read_4(bus_space_tag_t space, bus_space_handle_t handle,
- bus_size_t offset)
-{
- return le32toh(bus_space_read_4(space, handle, offset));
-}
-
-static void
-nbo_bus_space_write_2(bus_space_tag_t space, bus_space_handle_t handle,
- bus_size_t offset, uint16_t value)
-{
- bus_space_write_2(space, handle, offset, htole16(value));
-}
-
-static void
-nbo_bus_space_write_4(bus_space_tag_t space, bus_space_handle_t handle,
- bus_size_t offset, uint32_t value)
-{
- bus_space_write_4(space, handle, offset, htole32(value));
-}
-
-/* some functions access registers at 4 byte offset for little/high halves */
-#if BYTE_ORDER == BIG_ENDIAN
-#define REG_HI_OFF 0
-#define REG_LO_OFF 4
-#else
-#define REG_HI_OFF 4
-#define REG_LO_OFF 0
-#endif
-
void
virtio_set_status(struct virtio_softc *sc, int status)
{
- int old = 0;
-
- if (status != 0)
- old = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
- VIRTIO_CONFIG_DEVICE_STATUS);
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_STATUS,
- status|old);
-}
-
-#define VIRTIO_MSIX_CONFIG_VECTOR_INDEX 0
-#define VIRTIO_MSIX_QUEUE_VECTOR_INDEX 1
-
-static int
-virtio_setup_msix_vectors(struct virtio_softc *sc)
-{
- int offset, vector, ret, qid;
-
- offset = VIRTIO_CONFIG_MSI_CONFIG_VECTOR;
- vector = VIRTIO_MSIX_CONFIG_VECTOR_INDEX;
-
- nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, vector);
- ret = nbo_bus_space_read_2(sc->sc_iot, sc->sc_ioh, offset);
- aprint_debug_dev(sc->sc_dev, "expected=%d, actual=%d\n",
- vector, ret);
- if (ret != vector)
- return -1;
-
- for (qid = 0; qid < sc->sc_nvqs; qid++) {
- offset = VIRTIO_CONFIG_QUEUE_SELECT;
- nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, qid);
-
- offset = VIRTIO_CONFIG_MSI_QUEUE_VECTOR;
- vector = VIRTIO_MSIX_QUEUE_VECTOR_INDEX;
-
- nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, vector);
- ret = nbo_bus_space_read_2(sc->sc_iot, sc->sc_ioh, offset);
- aprint_debug_dev(sc->sc_dev, "expected=%d, actual=%d\n",
- vector, ret);
- if (ret != vector)
- return -1;
- }
-
- return 0;
-}
-
-static int
-virtio_setup_msix_interrupts(struct virtio_softc *sc,
- struct pci_attach_args *pa)
-{
- device_t self = sc->sc_dev;
- pci_chipset_tag_t pc = pa->pa_pc;
- char intrbuf[PCI_INTRSTR_LEN];
- char const *intrstr;
- int idx;
-
- idx = VIRTIO_MSIX_CONFIG_VECTOR_INDEX;
- if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE)
- pci_intr_setattr(pc, &sc->sc_ihp[idx], PCI_INTR_MPSAFE, true);
-
- sc->sc_ihs[idx] = pci_intr_establish_xname(pc, sc->sc_ihp[idx],
- sc->sc_ipl, virtio_msix_config_intr, sc, device_xname(sc->sc_dev));
- if (sc->sc_ihs[idx] == NULL) {
- aprint_error_dev(self, "couldn't establish MSI-X for config\n");
- goto error;
- }
-
- idx = VIRTIO_MSIX_QUEUE_VECTOR_INDEX;
- if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE)
- pci_intr_setattr(pc, &sc->sc_ihp[idx], PCI_INTR_MPSAFE, true);
-
- sc->sc_ihs[idx] = pci_intr_establish_xname(pc, sc->sc_ihp[idx],
- sc->sc_ipl, virtio_msix_queue_intr, sc, device_xname(sc->sc_dev));
- if (sc->sc_ihs[idx] == NULL) {
- aprint_error_dev(self, "couldn't establish MSI-X for queues\n");
- goto error;
- }
-
- if (virtio_setup_msix_vectors(sc) != 0) {
- aprint_error_dev(self, "couldn't setup MSI-X vectors\n");
- goto error;
- }
-
- idx = VIRTIO_MSIX_CONFIG_VECTOR_INDEX;
- intrstr = pci_intr_string(pc, sc->sc_ihp[idx], intrbuf, sizeof(intrbuf));
- aprint_normal_dev(self, "config interrupting at %s\n", intrstr);
- idx = VIRTIO_MSIX_QUEUE_VECTOR_INDEX;
- intrstr = pci_intr_string(pc, sc->sc_ihp[idx], intrbuf, sizeof(intrbuf));
- aprint_normal_dev(self, "queues interrupting at %s\n", intrstr);
-
- return 0;
-
-error:
- idx = VIRTIO_MSIX_CONFIG_VECTOR_INDEX;
- if (sc->sc_ihs[idx] != NULL)
- pci_intr_disestablish(sc->sc_pc, sc->sc_ihs[idx]);
- idx = VIRTIO_MSIX_QUEUE_VECTOR_INDEX;
- if (sc->sc_ihs[idx] != NULL)
- pci_intr_disestablish(sc->sc_pc, sc->sc_ihs[idx]);
-
- return -1;
+ sc->sc_ops->set_status(sc, status);
}
-static int
-virtio_setup_intx_interrupt(struct virtio_softc *sc,
- struct pci_attach_args *pa)
-{
- device_t self = sc->sc_dev;
- pci_chipset_tag_t pc = pa->pa_pc;
- char intrbuf[PCI_INTRSTR_LEN];
- char const *intrstr;
-
- if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE)
- pci_intr_setattr(pc, &sc->sc_ihp[0], PCI_INTR_MPSAFE, true);
-
- sc->sc_ihs[0] = pci_intr_establish_xname(pc, sc->sc_ihp[0],
- sc->sc_ipl, virtio_intr, sc, device_xname(sc->sc_dev));
- if (sc->sc_ihs[0] == NULL) {
- aprint_error_dev(self, "couldn't establish INTx\n");
- return -1;
- }
-
- intrstr = pci_intr_string(pc, sc->sc_ihp[0], intrbuf, sizeof(intrbuf));
- aprint_normal_dev(self, "interrupting at %s\n", intrstr);
-
- return 0;
-}
-
-static int
-virtio_setup_interrupts(struct virtio_softc *sc)
-{
- device_t self = sc->sc_dev;
- pci_chipset_tag_t pc = sc->sc_pa.pa_pc;
- int error;
- int nmsix;
- int counts[PCI_INTR_TYPE_SIZE];
- pci_intr_type_t max_type;
-
- nmsix = pci_msix_count(sc->sc_pa.pa_pc, sc->sc_pa.pa_tag);
- aprint_debug_dev(self, "pci_msix_count=%d\n", nmsix);
-
- /* We need at least two: one for config and the other for queues */
- if ((sc->sc_flags & VIRTIO_F_PCI_INTR_MSIX) == 0 || nmsix < 2) {
- /* Try INTx only */
- max_type = PCI_INTR_TYPE_INTX;
- counts[PCI_INTR_TYPE_INTX] = 1;
- } else {
- /* Try MSI-X first and INTx second */
- max_type = PCI_INTR_TYPE_MSIX;
- counts[PCI_INTR_TYPE_MSIX] = 2;
- counts[PCI_INTR_TYPE_MSI] = 0;
- counts[PCI_INTR_TYPE_INTX] = 1;
- }
-
- retry:
- error = pci_intr_alloc(&sc->sc_pa, &sc->sc_ihp, counts, max_type);
- if (error != 0) {
- aprint_error_dev(self, "couldn't map interrupt\n");
- return -1;
- }
-
- if (pci_intr_type(pc, sc->sc_ihp[0]) == PCI_INTR_TYPE_MSIX) {
- sc->sc_ihs = kmem_alloc(sizeof(*sc->sc_ihs) * 2,
- KM_SLEEP);
-
- error = virtio_setup_msix_interrupts(sc, &sc->sc_pa);
- if (error != 0) {
- kmem_free(sc->sc_ihs, sizeof(*sc->sc_ihs) * 2);
- pci_intr_release(pc, sc->sc_ihp, 2);
-
- /* Retry INTx */
- max_type = PCI_INTR_TYPE_INTX;
- counts[PCI_INTR_TYPE_INTX] = 1;
- goto retry;
- }
-
- sc->sc_ihs_num = 2;
- sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_MSI;
- } else if (pci_intr_type(pc, sc->sc_ihp[0]) == PCI_INTR_TYPE_INTX) {
- sc->sc_ihs = kmem_alloc(sizeof(*sc->sc_ihs) * 1,
- KM_SLEEP);
-
- error = virtio_setup_intx_interrupt(sc, &sc->sc_pa);
- if (error != 0) {
- kmem_free(sc->sc_ihs, sizeof(*sc->sc_ihs) * 1);
- pci_intr_release(pc, sc->sc_ihp, 1);
- return -1;
- }
-
- sc->sc_ihs_num = 1;
- sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI;
- }
-
- KASSERT(sc->sc_soft_ih == NULL);
- if (sc->sc_flags & VIRTIO_F_PCI_INTR_SOFTINT) {
- u_int flags = SOFTINT_NET;
- if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE)
- flags |= SOFTINT_MPSAFE;
-
- sc->sc_soft_ih = softint_establish(flags, virtio_soft_intr, sc);
- if (sc->sc_soft_ih == NULL) {
- virtio_free_interrupts(sc);
- aprint_error_dev(sc->sc_dev,
- "failed to establish soft interrupt\n");
- return -1;
- }
- }
-
- return 0;
-}
-
-static void
-virtio_free_interrupts(struct virtio_softc *sc)
-{
- for (int i = 0; i < sc->sc_ihs_num; i++) {
- if (sc->sc_ihs[i] == NULL)
- continue;
- pci_intr_disestablish(sc->sc_pc, sc->sc_ihs[i]);
- sc->sc_ihs[i] = NULL;
- }
-
Home |
Main Index |
Thread Index |
Old Index