svn commit: r275640 - head/sys/dev/virtio/mmio
Andrew Turner
andrew at FreeBSD.org
Tue Dec 9 10:31:36 UTC 2014
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 at 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);
+ }
+ }
+ }
}
More information about the svn-src-head
mailing list