| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: virtio.c,v 1.47 2021/02/05 20:45:38 reinoud Exp $ */ | | 1 | /* $NetBSD: virtio.c,v 1.48 2021/02/07 09:26:17 skrll Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2020 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2020 The NetBSD Foundation, Inc. |
5 | * Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg. | | 5 | * Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg. |
6 | * Copyright (c) 2010 Minoura Makoto. | | 6 | * Copyright (c) 2010 Minoura Makoto. |
7 | * All rights reserved. | | 7 | * All rights reserved. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -18,27 +18,27 @@ | | | @@ -18,27 +18,27 @@ |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | */ | | 28 | */ |
29 | | | 29 | |
30 | #include <sys/cdefs.h> | | 30 | #include <sys/cdefs.h> |
31 | __KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.47 2021/02/05 20:45:38 reinoud Exp $"); | | 31 | __KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.48 2021/02/07 09:26:17 skrll Exp $"); |
32 | | | 32 | |
33 | #include <sys/param.h> | | 33 | #include <sys/param.h> |
34 | #include <sys/systm.h> | | 34 | #include <sys/systm.h> |
35 | #include <sys/kernel.h> | | 35 | #include <sys/kernel.h> |
36 | #include <sys/atomic.h> | | 36 | #include <sys/atomic.h> |
37 | #include <sys/bus.h> | | 37 | #include <sys/bus.h> |
38 | #include <sys/device.h> | | 38 | #include <sys/device.h> |
39 | #include <sys/kmem.h> | | 39 | #include <sys/kmem.h> |
40 | #include <sys/module.h> | | 40 | #include <sys/module.h> |
41 | | | 41 | |
42 | #define VIRTIO_PRIVATE | | 42 | #define VIRTIO_PRIVATE |
43 | | | 43 | |
44 | #include <dev/pci/virtioreg.h> /* XXX: move to non-pci */ | | 44 | #include <dev/pci/virtioreg.h> /* XXX: move to non-pci */ |
| @@ -639,27 +639,27 @@ virtio_init_vq(struct virtio_softc *sc, | | | @@ -639,27 +639,27 @@ virtio_init_vq(struct virtio_softc *sc, |
639 | | | 639 | |
640 | /* enqueue/dequeue status */ | | 640 | /* enqueue/dequeue status */ |
641 | vq->vq_avail_idx = 0; | | 641 | vq->vq_avail_idx = 0; |
642 | vq->vq_used_idx = 0; | | 642 | vq->vq_used_idx = 0; |
643 | vq->vq_queued = 0; | | 643 | vq->vq_queued = 0; |
644 | if (!reinit) { | | 644 | if (!reinit) { |
645 | mutex_init(&vq->vq_aring_lock, MUTEX_SPIN, sc->sc_ipl); | | 645 | mutex_init(&vq->vq_aring_lock, MUTEX_SPIN, sc->sc_ipl); |
646 | mutex_init(&vq->vq_uring_lock, MUTEX_SPIN, sc->sc_ipl); | | 646 | mutex_init(&vq->vq_uring_lock, MUTEX_SPIN, sc->sc_ipl); |
647 | } | | 647 | } |
648 | vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); | | 648 | vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); |
649 | vq_sync_uring(sc, vq, BUS_DMASYNC_PREREAD); | | 649 | vq_sync_uring(sc, vq, BUS_DMASYNC_PREREAD); |
650 | vq->vq_queued++; | | 650 | vq->vq_queued++; |
651 | } | | 651 | } |
652 | | | 652 | |
653 | /* | | 653 | /* |
654 | * Allocate/free a vq. | | 654 | * Allocate/free a vq. |
655 | */ | | 655 | */ |
656 | int | | 656 | int |
657 | virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int index, | | 657 | virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int index, |
658 | int maxsegsize, int maxnsegs, const char *name) | | 658 | int maxsegsize, int maxnsegs, const char *name) |
659 | { | | 659 | { |
660 | int vq_size, allocsize1, allocsize2, allocsize3, allocsize = 0; | | 660 | int vq_size, allocsize1, allocsize2, allocsize3, allocsize = 0; |
661 | int rsegs, r, hdrlen; | | 661 | int rsegs, r, hdrlen; |
662 | #define VIRTQUEUE_ALIGN(n) (((n)+(VIRTIO_PAGE_SIZE-1))& \ | | 662 | #define VIRTQUEUE_ALIGN(n) (((n)+(VIRTIO_PAGE_SIZE-1))& \ |
663 | ~(VIRTIO_PAGE_SIZE-1)) | | 663 | ~(VIRTIO_PAGE_SIZE-1)) |
664 | | | 664 | |
665 | /* Make sure callers allocate vqs in order */ | | 665 | /* Make sure callers allocate vqs in order */ |
| @@ -854,27 +854,27 @@ vq_free_entry(struct virtqueue *vq, stru | | | @@ -854,27 +854,27 @@ vq_free_entry(struct virtqueue *vq, stru |
854 | * Typical usage: | | 854 | * Typical usage: |
855 | * <queue size> number of followings are stored in arrays | | 855 | * <queue size> number of followings are stored in arrays |
856 | * - command blocks (in dmamem) should be pre-allocated and mapped | | 856 | * - command blocks (in dmamem) should be pre-allocated and mapped |
857 | * - dmamaps for command blocks should be pre-allocated and loaded | | 857 | * - dmamaps for command blocks should be pre-allocated and loaded |
858 | * - dmamaps for payload should be pre-allocated | | 858 | * - dmamaps for payload should be pre-allocated |
859 | * r = virtio_enqueue_prep(sc, vq, &slot); // allocate a slot | | 859 | * r = virtio_enqueue_prep(sc, vq, &slot); // allocate a slot |
860 | * if (r) // currently 0 or EAGAIN | | 860 | * if (r) // currently 0 or EAGAIN |
861 | * return r; | | 861 | * return r; |
862 | * r = bus_dmamap_load(dmat, dmamap_payload[slot], data, count, ..); | | 862 | * r = bus_dmamap_load(dmat, dmamap_payload[slot], data, count, ..); |
863 | * if (r) { | | 863 | * if (r) { |
864 | * virtio_enqueue_abort(sc, vq, slot); | | 864 | * virtio_enqueue_abort(sc, vq, slot); |
865 | * return r; | | 865 | * return r; |
866 | * } | | 866 | * } |
867 | * r = virtio_enqueue_reserve(sc, vq, slot, | | 867 | * r = virtio_enqueue_reserve(sc, vq, slot, |
868 | * dmamap_payload[slot]->dm_nsegs+1); | | 868 | * dmamap_payload[slot]->dm_nsegs+1); |
869 | * // ^ +1 for command | | 869 | * // ^ +1 for command |
870 | * if (r) { // currently 0 or EAGAIN | | 870 | * if (r) { // currently 0 or EAGAIN |
871 | * bus_dmamap_unload(dmat, dmamap_payload[slot]); | | 871 | * bus_dmamap_unload(dmat, dmamap_payload[slot]); |
872 | * return r; // do not call abort() | | 872 | * return r; // do not call abort() |
873 | * } | | 873 | * } |
874 | * <setup and prepare commands> | | 874 | * <setup and prepare commands> |
875 | * bus_dmamap_sync(dmat, dmamap_cmd[slot],... BUS_DMASYNC_PREWRITE); | | 875 | * bus_dmamap_sync(dmat, dmamap_cmd[slot],... BUS_DMASYNC_PREWRITE); |
876 | * bus_dmamap_sync(dmat, dmamap_payload[slot],...); | | 876 | * bus_dmamap_sync(dmat, dmamap_payload[slot],...); |
877 | * virtio_enqueue(sc, vq, slot, dmamap_cmd[slot], false); | | 877 | * virtio_enqueue(sc, vq, slot, dmamap_cmd[slot], false); |
878 | * virtio_enqueue(sc, vq, slot, dmamap_payload[slot], iswrite); | | 878 | * virtio_enqueue(sc, vq, slot, dmamap_payload[slot], iswrite); |
879 | * virtio_enqueue_commit(sc, vq, slot, true); | | 879 | * virtio_enqueue_commit(sc, vq, slot, true); |
880 | */ | | 880 | */ |
| @@ -1149,27 +1149,27 @@ virtio_dequeue_commit(struct virtio_soft | | | @@ -1149,27 +1149,27 @@ virtio_dequeue_commit(struct virtio_soft |
1149 | s = virtio_rw16(sc, vd[s].next); | | 1149 | s = virtio_rw16(sc, vd[s].next); |
1150 | vq_free_entry(vq, qe); | | 1150 | vq_free_entry(vq, qe); |
1151 | qe = &vq->vq_entries[s]; | | 1151 | qe = &vq->vq_entries[s]; |
1152 | } | | 1152 | } |
1153 | vq_free_entry(vq, qe); | | 1153 | vq_free_entry(vq, qe); |
1154 | | | 1154 | |
1155 | return 0; | | 1155 | return 0; |
1156 | } | | 1156 | } |
1157 | | | 1157 | |
1158 | /* | | 1158 | /* |
1159 | * Attach a child, fill all the members. | | 1159 | * Attach a child, fill all the members. |
1160 | */ | | 1160 | */ |
1161 | void | | 1161 | void |
1162 | virtio_child_attach_start(struct virtio_softc *sc, device_t child, int ipl, | | 1162 | virtio_child_attach_start(struct virtio_softc *sc, device_t child, int ipl, |
1163 | struct virtqueue *vqs, | | 1163 | struct virtqueue *vqs, |
1164 | virtio_callback config_change, | | 1164 | virtio_callback config_change, |
1165 | virtio_callback intr_hand, | | 1165 | virtio_callback intr_hand, |
1166 | int req_flags, int req_features, const char *feat_bits) | | 1166 | int req_flags, int req_features, const char *feat_bits) |
1167 | { | | 1167 | { |
1168 | char buf[1024]; | | 1168 | char buf[1024]; |
1169 | | | 1169 | |
1170 | sc->sc_child = child; | | 1170 | sc->sc_child = child; |
1171 | sc->sc_ipl = ipl; | | 1171 | sc->sc_ipl = ipl; |
1172 | sc->sc_vqs = vqs; | | 1172 | sc->sc_vqs = vqs; |
1173 | sc->sc_config_change = config_change; | | 1173 | sc->sc_config_change = config_change; |
1174 | sc->sc_intrhand = intr_hand; | | 1174 | sc->sc_intrhand = intr_hand; |
1175 | sc->sc_flags = req_flags; | | 1175 | sc->sc_flags = req_flags; |
| @@ -1197,27 +1197,27 @@ int | | | @@ -1197,27 +1197,27 @@ int |
1197 | virtio_child_attach_finish(struct virtio_softc *sc) | | 1197 | virtio_child_attach_finish(struct virtio_softc *sc) |
1198 | { | | 1198 | { |
1199 | int r; | | 1199 | int r; |
1200 | | | 1200 | |
1201 | sc->sc_finished_called = true; | | 1201 | sc->sc_finished_called = true; |
1202 | r = sc->sc_ops->setup_interrupts(sc); | | 1202 | r = sc->sc_ops->setup_interrupts(sc); |
1203 | if (r != 0) { | | 1203 | if (r != 0) { |
1204 | aprint_error_dev(sc->sc_dev, "failed to setup interrupts\n"); | | 1204 | aprint_error_dev(sc->sc_dev, "failed to setup interrupts\n"); |
1205 | goto fail; | | 1205 | goto fail; |
1206 | } | | 1206 | } |
1207 | | | 1207 | |
1208 | KASSERT(sc->sc_soft_ih == NULL); | | 1208 | KASSERT(sc->sc_soft_ih == NULL); |
1209 | if (sc->sc_flags & VIRTIO_F_INTR_SOFTINT) { | | 1209 | if (sc->sc_flags & VIRTIO_F_INTR_SOFTINT) { |
1210 | u_int flags = SOFTINT_NET; | | 1210 | u_int flags = SOFTINT_NET; |
1211 | if (sc->sc_flags & VIRTIO_F_INTR_MPSAFE) | | 1211 | if (sc->sc_flags & VIRTIO_F_INTR_MPSAFE) |
1212 | flags |= SOFTINT_MPSAFE; | | 1212 | flags |= SOFTINT_MPSAFE; |
1213 | | | 1213 | |
1214 | sc->sc_soft_ih = softint_establish(flags, virtio_soft_intr, sc); | | 1214 | sc->sc_soft_ih = softint_establish(flags, virtio_soft_intr, sc); |
1215 | if (sc->sc_soft_ih == NULL) { | | 1215 | if (sc->sc_soft_ih == NULL) { |
1216 | sc->sc_ops->free_interrupts(sc); | | 1216 | sc->sc_ops->free_interrupts(sc); |
1217 | aprint_error_dev(sc->sc_dev, | | 1217 | aprint_error_dev(sc->sc_dev, |
1218 | "failed to establish soft interrupt\n"); | | 1218 | "failed to establish soft interrupt\n"); |
1219 | goto fail; | | 1219 | goto fail; |
1220 | } | | 1220 | } |
1221 | } | | 1221 | } |
1222 | | | 1222 | |
1223 | virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK); | | 1223 | virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK); |
| @@ -1313,41 +1313,41 @@ virtio_attach_failed(struct virtio_softc | | | @@ -1313,41 +1313,41 @@ virtio_attach_failed(struct virtio_softc |
1313 | return 0; | | 1313 | return 0; |
1314 | } | | 1314 | } |
1315 | | | 1315 | |
1316 | void | | 1316 | void |
1317 | virtio_print_device_type(device_t self, int id, int revision) | | 1317 | virtio_print_device_type(device_t self, int id, int revision) |
1318 | { | | 1318 | { |
1319 | aprint_normal_dev(self, "%s device (rev. 0x%02x)\n", | | 1319 | aprint_normal_dev(self, "%s device (rev. 0x%02x)\n", |
1320 | (id < NDEVNAMES ? virtio_device_name[id] : "Unknown"), | | 1320 | (id < NDEVNAMES ? virtio_device_name[id] : "Unknown"), |
1321 | revision); | | 1321 | revision); |
1322 | } | | 1322 | } |
1323 | | | 1323 | |
1324 | | | 1324 | |
1325 | MODULE(MODULE_CLASS_DRIVER, virtio, NULL); | | 1325 | MODULE(MODULE_CLASS_DRIVER, virtio, NULL); |
1326 | | | 1326 | |
1327 | #ifdef _MODULE | | 1327 | #ifdef _MODULE |
1328 | #include "ioconf.c" | | 1328 | #include "ioconf.c" |
1329 | #endif | | 1329 | #endif |
1330 | | | 1330 | |
1331 | static int | | 1331 | static int |
1332 | virtio_modcmd(modcmd_t cmd, void *opaque) | | 1332 | virtio_modcmd(modcmd_t cmd, void *opaque) |
1333 | { | | 1333 | { |
1334 | int error = 0; | | 1334 | int error = 0; |
1335 | | | 1335 | |
1336 | #ifdef _MODULE | | 1336 | #ifdef _MODULE |
1337 | switch (cmd) { | | 1337 | switch (cmd) { |
1338 | case MODULE_CMD_INIT: | | 1338 | case MODULE_CMD_INIT: |
1339 | error = config_init_component(cfdriver_ioconf_virtio, | | 1339 | error = config_init_component(cfdriver_ioconf_virtio, |
1340 | cfattach_ioconf_virtio, cfdata_ioconf_virtio); | | 1340 | cfattach_ioconf_virtio, cfdata_ioconf_virtio); |
1341 | break; | | 1341 | break; |
1342 | case MODULE_CMD_FINI: | | 1342 | case MODULE_CMD_FINI: |
1343 | error = config_fini_component(cfdriver_ioconf_virtio, | | 1343 | error = config_fini_component(cfdriver_ioconf_virtio, |
1344 | cfattach_ioconf_virtio, cfdata_ioconf_virtio); | | 1344 | cfattach_ioconf_virtio, cfdata_ioconf_virtio); |
1345 | break; | | 1345 | break; |
1346 | default: | | 1346 | default: |
1347 | error = ENOTTY; | | 1347 | error = ENOTTY; |
1348 | break; | | 1348 | break; |
1349 | } | | 1349 | } |
1350 | #endif | | 1350 | #endif |
1351 | | | 1351 | |
1352 | return error; | | 1352 | return error; |
1353 | } | | 1353 | } |