Date: Tue, 9 Dec 2014 10:31:35 +0000 (UTC) From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r275640 - head/sys/dev/virtio/mmio Message-ID: <201412091031.sB9AVZ2Y072700@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: andrew Date: Tue Dec 9 10:31:35 2014 New Revision: 275640 URL: https://svnweb.freebsd.org/changeset/base/275640 Log: Update the virtio driver to work on the ARM AArch64 Foundation Model. There are two main parts to get it to work, 1) most of the register accesses need to be word sized, other than the config register which needs to be byte aligned, and 2) we don't need the platform driver for this to work on the Foundation Model, allow it to be NULL. Differential Revision: https://reviews.freebsd.org/D1240 Reviewed by: bryanv Sponsored by: The FreeBSD Foundation Modified: head/sys/dev/virtio/mmio/virtio_mmio.c Modified: head/sys/dev/virtio/mmio/virtio_mmio.c ============================================================================== --- head/sys/dev/virtio/mmio/virtio_mmio.c Tue Dec 9 10:21:31 2014 (r275639) +++ head/sys/dev/virtio/mmio/virtio_mmio.c Tue Dec 9 10:31:35 2014 (r275640) @@ -1,11 +1,15 @@ /*- * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> + * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * + * Portions of this software were developed by Andrew Turner + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -131,15 +135,24 @@ static void vtmmio_vq_intr(void *); /* * I/O port read/write wrappers. */ -#define vtmmio_write_config_1(sc, o, v) \ - bus_write_1((sc)->res[0], (o), (v)); \ - VIRTIO_MMIO_NOTE(sc->platform, (o)) -#define vtmmio_write_config_2(sc, o, v) \ - bus_write_2((sc)->res[0], (o), (v)); \ - VIRTIO_MMIO_NOTE(sc->platform, (o)) -#define vtmmio_write_config_4(sc, o, v) \ - bus_write_4((sc)->res[0], (o), (v)); \ - VIRTIO_MMIO_NOTE(sc->platform, (o)) +#define vtmmio_write_config_1(sc, o, v) \ +do { \ + bus_write_1((sc)->res[0], (o), (v)); \ + if (sc->platform != NULL) \ + VIRTIO_MMIO_NOTE(sc->platform, (o)); \ +} while (0) +#define vtmmio_write_config_2(sc, o, v) \ +do { \ + bus_write_2((sc)->res[0], (o), (v)); \ + if (sc->platform != NULL) \ + VIRTIO_MMIO_NOTE(sc->platform, (o)); \ +} while (0) +#define vtmmio_write_config_4(sc, o, v) \ +do { \ + bus_write_4((sc)->res[0], (o), (v)); \ + if (sc->platform != NULL) \ + VIRTIO_MMIO_NOTE(sc->platform, (o)); \ +} while (0) #define vtmmio_read_config_1(sc, o) \ bus_read_1((sc)->res[0], (o)) @@ -200,11 +213,13 @@ vtmmio_setup_intr(device_t dev, enum int sc = device_get_softc(dev); - err = VIRTIO_MMIO_SETUP_INTR(sc->platform, sc->dev, - vtmmio_vq_intr, sc); - if (err == 0) { - /* Okay we have backend-specific interrupts */ - return (0); + if (sc->platform != NULL) { + err = VIRTIO_MMIO_SETUP_INTR(sc->platform, sc->dev, + vtmmio_vq_intr, sc); + if (err == 0) { + /* Okay we have backend-specific interrupts */ + return (0); + } } rid = 0; @@ -473,8 +488,8 @@ vtmmio_alloc_virtqueues(device_t dev, in struct vq_alloc_info *info; struct vtmmio_softc *sc; struct virtqueue *vq; + uint32_t size; int idx, error; - uint16_t size; sc = device_get_softc(dev); @@ -492,8 +507,10 @@ vtmmio_alloc_virtqueues(device_t dev, in vqx = &sc->vtmmio_vqs[idx]; info = &vq_info[idx]; + vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx); + vtmmio_select_virtqueue(sc, idx); - size = vtmmio_read_config_2(sc, VIRTIO_MMIO_QUEUE_NUM); + size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX); error = virtqueue_alloc(dev, idx, size, VIRTIO_MMIO_VRING_ALIGN, 0xFFFFFFFFUL, info, &vq); @@ -503,6 +520,10 @@ vtmmio_alloc_virtqueues(device_t dev, in idx, error); break; } + + vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NUM, size); + vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_ALIGN, + VIRTIO_MMIO_VRING_ALIGN); #if 0 device_printf(dev, "virtqueue paddr 0x%08lx\n", (uint64_t)virtqueue_paddr(vq)); @@ -572,7 +593,7 @@ vtmmio_notify_virtqueue(device_t dev, ui sc = device_get_softc(dev); - vtmmio_write_config_2(sc, VIRTIO_MMIO_QUEUE_NOTIFY, queue); + vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NOTIFY, queue); } static uint8_t @@ -582,7 +603,7 @@ vtmmio_get_status(device_t dev) sc = device_get_softc(dev); - return (vtmmio_read_config_1(sc, VIRTIO_MMIO_STATUS)); + return (vtmmio_read_config_4(sc, VIRTIO_MMIO_STATUS)); } static void @@ -595,7 +616,7 @@ vtmmio_set_status(device_t dev, uint8_t if (status != VIRTIO_CONFIG_STATUS_RESET) status |= vtmmio_get_status(dev); - vtmmio_write_config_1(sc, VIRTIO_MMIO_STATUS, status); + vtmmio_write_config_4(sc, VIRTIO_MMIO_STATUS, status); } static void @@ -611,13 +632,16 @@ vtmmio_read_dev_config(device_t dev, bus off = VIRTIO_MMIO_CONFIG + offset; for (d = dst; length > 0; d += size, off += size, length -= size) { +#ifdef ALLOW_WORD_ALIGNED_ACCESS if (length >= 4) { size = 4; *(uint32_t *)d = vtmmio_read_config_4(sc, off); } else if (length >= 2) { size = 2; *(uint16_t *)d = vtmmio_read_config_2(sc, off); - } else { + } else +#endif + { size = 1; *d = vtmmio_read_config_1(sc, off); } @@ -637,13 +661,16 @@ vtmmio_write_dev_config(device_t dev, bu off = VIRTIO_MMIO_CONFIG + offset; for (s = src; length > 0; s += size, off += size, length -= size) { +#ifdef ALLOW_WORD_ALIGNED_ACCESS if (length >= 4) { size = 4; vtmmio_write_config_4(sc, off, *(uint32_t *)s); } else if (length >= 2) { size = 2; vtmmio_write_config_2(sc, off, *(uint16_t *)s); - } else { + } else +#endif + { size = 1; vtmmio_write_config_1(sc, off, *s); } @@ -711,7 +738,7 @@ vtmmio_reinit_virtqueue(struct vtmmio_so KASSERT(vq != NULL, ("%s: vq %d not allocated", __func__, idx)); vtmmio_select_virtqueue(sc, idx); - size = vtmmio_read_config_2(sc, VIRTIO_MMIO_QUEUE_NUM); + size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX); error = virtqueue_reinit(vq, size); if (error) @@ -778,7 +805,7 @@ static void vtmmio_select_virtqueue(struct vtmmio_softc *sc, int idx) { - vtmmio_write_config_2(sc, VIRTIO_MMIO_QUEUE_SEL, idx); + vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx); } static void @@ -787,14 +814,27 @@ vtmmio_vq_intr(void *arg) struct vtmmio_virtqueue *vqx; struct vtmmio_softc *sc; struct virtqueue *vq; + uint32_t status; int idx; sc = arg; + status = vtmmio_read_config_4(sc, VIRTIO_MMIO_INTERRUPT_STATUS); + vtmmio_write_config_4(sc, VIRTIO_MMIO_INTERRUPT_ACK, status); + + /* The config changed */ + if (status & VIRTIO_MMIO_INT_CONFIG) + if (sc->vtmmio_child_dev != NULL) + VIRTIO_CONFIG_CHANGE(sc->vtmmio_child_dev); + /* Notify all virtqueues. */ - for (idx = 0; idx < sc->vtmmio_nvqs; idx++) { - vqx = &sc->vtmmio_vqs[idx]; - vq = vqx->vtv_vq; - virtqueue_intr(vq); - }; + if (status & VIRTIO_MMIO_INT_VRING) { + for (idx = 0; idx < sc->vtmmio_nvqs; idx++) { + vqx = &sc->vtmmio_vqs[idx]; + if (vqx->vtv_no_intr == 0) { + vq = vqx->vtv_vq; + virtqueue_intr(vq); + } + } + } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412091031.sB9AVZ2Y072700>