virtio.c revision 1.42
1/* $NetBSD: virtio.c,v 1.42 2020/09/17 17:09:59 jakllsch Exp $ */ 2 3/* 4 * Copyright (c) 2010 Minoura Makoto. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.42 2020/09/17 17:09:59 jakllsch Exp $"); 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/kernel.h> 34#include <sys/atomic.h> 35#include <sys/bus.h> 36#include <sys/device.h> 37#include <sys/kmem.h> 38#include <sys/module.h> 39 40#define VIRTIO_PRIVATE 41 42#include <dev/pci/virtioreg.h> /* XXX: move to non-pci */ 43#include <dev/pci/virtiovar.h> /* XXX: move to non-pci */ 44 45#define MINSEG_INDIRECT 2 /* use indirect if nsegs >= this value */ 46 47static void virtio_init_vq(struct virtio_softc *, 48 struct virtqueue *, const bool); 49 50void 51virtio_set_status(struct virtio_softc *sc, int status) 52{ 53 sc->sc_ops->set_status(sc, status); 54} 55 56/* 57 * Reset the device. 58 */ 59/* 60 * To reset the device to a known state, do following: 61 * virtio_reset(sc); // this will stop the device activity 62 * <dequeue finished requests>; // virtio_dequeue() still can be called 63 * <revoke pending requests in the vqs if any>; 64 * virtio_reinit_start(sc); // dequeue prohibitted 65 * newfeatures = virtio_negotiate_features(sc, requestedfeatures); 66 * <some other initialization>; 67 * virtio_reinit_end(sc); // device activated; enqueue allowed 68 * Once attached, feature negotiation can only be allowed after virtio_reset. 69 */ 70void 71virtio_reset(struct virtio_softc *sc) 72{ 73 virtio_device_reset(sc); 74} 75 76void 77virtio_reinit_start(struct virtio_softc *sc) 78{ 79 int i; 80 81 virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_ACK); 82 virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER); 83 for (i = 0; i < sc->sc_nvqs; i++) { 84 int n; 85 struct virtqueue *vq = &sc->sc_vqs[i]; 86 n = sc->sc_ops->read_queue_size(sc, vq->vq_index); 87 if (n == 0) /* vq disappeared */ 88 continue; 89 if (n != vq->vq_num) { 90 panic("%s: virtqueue size changed, vq index %d\n", 91 device_xname(sc->sc_dev), 92 vq->vq_index); 93 } 94 virtio_init_vq(sc, vq, true); 95 sc->sc_ops->setup_queue(sc, vq->vq_index, 96 vq->vq_dmamap->dm_segs[0].ds_addr / VIRTIO_PAGE_SIZE); 97 } 98} 99 100void 101virtio_reinit_end(struct virtio_softc *sc) 102{ 103 virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK); 104} 105 106/* 107 * Feature negotiation. 108 */ 109uint32_t 110virtio_negotiate_features(struct virtio_softc *sc, uint32_t guest_features) 111{ 112 uint32_t r; 113 114 if (!(device_cfdata(sc->sc_dev)->cf_flags & 1) && 115 !(device_cfdata(sc->sc_child)->cf_flags & 1)) /* XXX */ 116 guest_features |= VIRTIO_F_RING_INDIRECT_DESC; 117 r = sc->sc_ops->neg_features(sc, guest_features); 118 sc->sc_features = r; 119 if (r & VIRTIO_F_RING_INDIRECT_DESC) 120 sc->sc_indirect = true; 121 else 122 sc->sc_indirect = false; 123 124 return r; 125} 126 127/* 128 * Device configuration registers. 129 */ 130uint8_t 131virtio_read_device_config_1(struct virtio_softc *sc, int index) 132{ 133 return sc->sc_ops->read_dev_cfg_1(sc, index); 134} 135 136uint16_t 137virtio_read_device_config_2(struct virtio_softc *sc, int index) 138{ 139 return sc->sc_ops->read_dev_cfg_2(sc, index); 140} 141 142uint32_t 143virtio_read_device_config_4(struct virtio_softc *sc, int index) 144{ 145 return sc->sc_ops->read_dev_cfg_4(sc, index); 146} 147 148uint64_t 149virtio_read_device_config_8(struct virtio_softc *sc, int index) 150{ 151 return sc->sc_ops->read_dev_cfg_8(sc, index); 152} 153 154void 155virtio_write_device_config_1(struct virtio_softc *sc, 156 int index, uint8_t value) 157{ 158 return sc->sc_ops->write_dev_cfg_1(sc, index, value); 159} 160 161void 162virtio_write_device_config_2(struct virtio_softc *sc, 163 int index, uint16_t value) 164{ 165 return sc->sc_ops->write_dev_cfg_2(sc, index, value); 166} 167 168void 169virtio_write_device_config_4(struct virtio_softc *sc, 170 int index, uint32_t value) 171{ 172 return sc->sc_ops->write_dev_cfg_4(sc, index, value); 173} 174 175void 176virtio_write_device_config_8(struct virtio_softc *sc, 177 int index, uint64_t value) 178{ 179 return sc->sc_ops->write_dev_cfg_8(sc, index, value); 180} 181 182/* 183 * Interrupt handler. 184 */ 185static void 186virtio_soft_intr(void *arg) 187{ 188 struct virtio_softc *sc = arg; 189 190 KASSERT(sc->sc_intrhand != NULL); 191 192 (sc->sc_intrhand)(sc); 193} 194 195/* 196 * dmamap sync operations for a virtqueue. 197 */ 198static inline void 199vq_sync_descs(struct virtio_softc *sc, struct virtqueue *vq, int ops) 200{ 201 /* availoffset == sizeof(vring_desc)*vq_num */ 202 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, 0, vq->vq_availoffset, 203 ops); 204} 205 206static inline void 207vq_sync_aring(struct virtio_softc *sc, struct virtqueue *vq, int ops) 208{ 209 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, 210 vq->vq_availoffset, 211 offsetof(struct vring_avail, ring) 212 + vq->vq_num * sizeof(uint16_t), 213 ops); 214} 215 216static inline void 217vq_sync_uring(struct virtio_softc *sc, struct virtqueue *vq, int ops) 218{ 219 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, 220 vq->vq_usedoffset, 221 offsetof(struct vring_used, ring) 222 + vq->vq_num * sizeof(struct vring_used_elem), 223 ops); 224} 225 226static inline void 227vq_sync_indirect(struct virtio_softc *sc, struct virtqueue *vq, int slot, 228 int ops) 229{ 230 int offset = vq->vq_indirectoffset 231 + sizeof(struct vring_desc) * vq->vq_maxnsegs * slot; 232 233 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, 234 offset, sizeof(struct vring_desc) * vq->vq_maxnsegs, 235 ops); 236} 237 238/* 239 * Can be used as sc_intrhand. 240 */ 241/* 242 * Scan vq, bus_dmamap_sync for the vqs (not for the payload), 243 * and calls (*vq_done)() if some entries are consumed. 244 */ 245bool 246virtio_vq_is_enqueued(struct virtio_softc *sc, struct virtqueue *vq) 247{ 248 249 if (vq->vq_queued) { 250 vq->vq_queued = 0; 251 vq_sync_aring(sc, vq, BUS_DMASYNC_POSTWRITE); 252 } 253 vq_sync_uring(sc, vq, BUS_DMASYNC_POSTREAD); 254 membar_consumer(); 255 256 return (vq->vq_used_idx != vq->vq_used->idx) ? 1 : 0; 257} 258 259int 260virtio_vq_intr(struct virtio_softc *sc) 261{ 262 struct virtqueue *vq; 263 int i, r = 0; 264 265 for (i = 0; i < sc->sc_nvqs; i++) { 266 vq = &sc->sc_vqs[i]; 267 if (virtio_vq_is_enqueued(sc, vq) == 1) { 268 if (vq->vq_done) 269 r |= (vq->vq_done)(vq); 270 } 271 } 272 273 return r; 274} 275 276int 277virtio_vq_intrhand(struct virtio_softc *sc) 278{ 279 struct virtqueue *vq; 280 int i, r = 0; 281 282 for (i = 0; i < sc->sc_nvqs; i++) { 283 vq = &sc->sc_vqs[i]; 284 r |= (vq->vq_intrhand)(vq->vq_intrhand_arg); 285 } 286 287 return r; 288} 289 290/* 291 * Start/stop vq interrupt. No guarantee. 292 */ 293void 294virtio_stop_vq_intr(struct virtio_softc *sc, struct virtqueue *vq) 295{ 296 vq->vq_avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; 297 vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); 298 vq->vq_queued++; 299} 300 301void 302virtio_start_vq_intr(struct virtio_softc *sc, struct virtqueue *vq) 303{ 304 vq->vq_avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; 305 vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); 306 vq->vq_queued++; 307} 308 309/* 310 * Initialize vq structure. 311 */ 312static void 313virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq, 314 const bool reinit) 315{ 316 int i, j; 317 int vq_size = vq->vq_num; 318 319 memset(vq->vq_vaddr, 0, vq->vq_bytesize); 320 321 /* build the indirect descriptor chain */ 322 if (vq->vq_indirect != NULL) { 323 struct vring_desc *vd; 324 325 for (i = 0; i < vq_size; i++) { 326 vd = vq->vq_indirect; 327 vd += vq->vq_maxnsegs * i; 328 for (j = 0; j < vq->vq_maxnsegs-1; j++) { 329 vd[j].next = j + 1; 330 } 331 } 332 } 333 334 /* free slot management */ 335 SIMPLEQ_INIT(&vq->vq_freelist); 336 for (i = 0; i < vq_size; i++) { 337 SIMPLEQ_INSERT_TAIL(&vq->vq_freelist, 338 &vq->vq_entries[i], qe_list); 339 vq->vq_entries[i].qe_index = i; 340 } 341 if (!reinit) 342 mutex_init(&vq->vq_freelist_lock, MUTEX_SPIN, sc->sc_ipl); 343 344 /* enqueue/dequeue status */ 345 vq->vq_avail_idx = 0; 346 vq->vq_used_idx = 0; 347 vq->vq_queued = 0; 348 if (!reinit) { 349 mutex_init(&vq->vq_aring_lock, MUTEX_SPIN, sc->sc_ipl); 350 mutex_init(&vq->vq_uring_lock, MUTEX_SPIN, sc->sc_ipl); 351 } 352 vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); 353 vq_sync_uring(sc, vq, BUS_DMASYNC_PREREAD); 354 vq->vq_queued++; 355} 356 357/* 358 * Allocate/free a vq. 359 */ 360int 361virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int index, 362 int maxsegsize, int maxnsegs, const char *name) 363{ 364 int vq_size, allocsize1, allocsize2, allocsize3, allocsize = 0; 365 int rsegs, r; 366#define VIRTQUEUE_ALIGN(n) (((n)+(VIRTIO_PAGE_SIZE-1))& \ 367 ~(VIRTIO_PAGE_SIZE-1)) 368 369 /* Make sure callers allocate vqs in order */ 370 KASSERT(sc->sc_nvqs == index); 371 372 memset(vq, 0, sizeof(*vq)); 373 374 vq_size = sc->sc_ops->read_queue_size(sc, index); 375 if (vq_size == 0) { 376 aprint_error_dev(sc->sc_dev, 377 "virtqueue not exist, index %d for %s\n", 378 index, name); 379 goto err; 380 } 381 /* allocsize1: descriptor table + avail ring + pad */ 382 allocsize1 = VIRTQUEUE_ALIGN(sizeof(struct vring_desc)*vq_size 383 + sizeof(uint16_t)*(2+vq_size)); 384 /* allocsize2: used ring + pad */ 385 allocsize2 = VIRTQUEUE_ALIGN(sizeof(uint16_t)*2 386 + sizeof(struct vring_used_elem)*vq_size); 387 /* allocsize3: indirect table */ 388 if (sc->sc_indirect && maxnsegs >= MINSEG_INDIRECT) 389 allocsize3 = sizeof(struct vring_desc) * maxnsegs * vq_size; 390 else 391 allocsize3 = 0; 392 allocsize = allocsize1 + allocsize2 + allocsize3; 393 394 /* alloc and map the memory */ 395 r = bus_dmamem_alloc(sc->sc_dmat, allocsize, VIRTIO_PAGE_SIZE, 0, 396 &vq->vq_segs[0], 1, &rsegs, BUS_DMA_NOWAIT); 397 if (r != 0) { 398 aprint_error_dev(sc->sc_dev, 399 "virtqueue %d for %s allocation failed, " 400 "error code %d\n", index, name, r); 401 goto err; 402 } 403 r = bus_dmamem_map(sc->sc_dmat, &vq->vq_segs[0], 1, allocsize, 404 &vq->vq_vaddr, BUS_DMA_NOWAIT); 405 if (r != 0) { 406 aprint_error_dev(sc->sc_dev, 407 "virtqueue %d for %s map failed, " 408 "error code %d\n", index, name, r); 409 goto err; 410 } 411 r = bus_dmamap_create(sc->sc_dmat, allocsize, 1, allocsize, 0, 412 BUS_DMA_NOWAIT, &vq->vq_dmamap); 413 if (r != 0) { 414 aprint_error_dev(sc->sc_dev, 415 "virtqueue %d for %s dmamap creation failed, " 416 "error code %d\n", index, name, r); 417 goto err; 418 } 419 r = bus_dmamap_load(sc->sc_dmat, vq->vq_dmamap, 420 vq->vq_vaddr, allocsize, NULL, BUS_DMA_NOWAIT); 421 if (r != 0) { 422 aprint_error_dev(sc->sc_dev, 423 "virtqueue %d for %s dmamap load failed, " 424 "error code %d\n", index, name, r); 425 goto err; 426 } 427 428 /* set the vq address */ 429 sc->sc_ops->setup_queue(sc, index, 430 vq->vq_dmamap->dm_segs[0].ds_addr / VIRTIO_PAGE_SIZE); 431 432 /* remember addresses and offsets for later use */ 433 vq->vq_owner = sc; 434 vq->vq_num = vq_size; 435 vq->vq_index = index; 436 vq->vq_desc = vq->vq_vaddr; 437 vq->vq_availoffset = sizeof(struct vring_desc)*vq_size; 438 vq->vq_avail = (void*)(((char*)vq->vq_desc) + vq->vq_availoffset); 439 vq->vq_usedoffset = allocsize1; 440 vq->vq_used = (void*)(((char*)vq->vq_desc) + vq->vq_usedoffset); 441 if (allocsize3 > 0) { 442 vq->vq_indirectoffset = allocsize1 + allocsize2; 443 vq->vq_indirect = (void*)(((char*)vq->vq_desc) 444 + vq->vq_indirectoffset); 445 } 446 vq->vq_bytesize = allocsize; 447 vq->vq_maxsegsize = maxsegsize; 448 vq->vq_maxnsegs = maxnsegs; 449 450 /* free slot management */ 451 vq->vq_entries = kmem_zalloc(sizeof(struct vq_entry)*vq_size, 452 KM_SLEEP); 453 virtio_init_vq(sc, vq, false); 454 455 aprint_verbose_dev(sc->sc_dev, 456 "allocated %u byte for virtqueue %d for %s, " 457 "size %d\n", allocsize, index, name, vq_size); 458 if (allocsize3 > 0) 459 aprint_verbose_dev(sc->sc_dev, 460 "using %d byte (%d entries) " 461 "indirect descriptors\n", 462 allocsize3, maxnsegs * vq_size); 463 464 sc->sc_nvqs++; 465 466 return 0; 467 468err: 469 sc->sc_ops->setup_queue(sc, index, 0); 470 if (vq->vq_dmamap) 471 bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap); 472 if (vq->vq_vaddr) 473 bus_dmamem_unmap(sc->sc_dmat, vq->vq_vaddr, allocsize); 474 if (vq->vq_segs[0].ds_addr) 475 bus_dmamem_free(sc->sc_dmat, &vq->vq_segs[0], 1); 476 memset(vq, 0, sizeof(*vq)); 477 478 return -1; 479} 480 481int 482virtio_free_vq(struct virtio_softc *sc, struct virtqueue *vq) 483{ 484 struct vq_entry *qe; 485 int i = 0; 486 487 /* device must be already deactivated */ 488 /* confirm the vq is empty */ 489 SIMPLEQ_FOREACH(qe, &vq->vq_freelist, qe_list) { 490 i++; 491 } 492 if (i != vq->vq_num) { 493 printf("%s: freeing non-empty vq, index %d\n", 494 device_xname(sc->sc_dev), vq->vq_index); 495 return EBUSY; 496 } 497 498 /* tell device that there's no virtqueue any longer */ 499 sc->sc_ops->setup_queue(sc, vq->vq_index, 0); 500 501 kmem_free(vq->vq_entries, sizeof(*vq->vq_entries) * vq->vq_num); 502 bus_dmamap_unload(sc->sc_dmat, vq->vq_dmamap); 503 bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap); 504 bus_dmamem_unmap(sc->sc_dmat, vq->vq_vaddr, vq->vq_bytesize); 505 bus_dmamem_free(sc->sc_dmat, &vq->vq_segs[0], 1); 506 mutex_destroy(&vq->vq_freelist_lock); 507 mutex_destroy(&vq->vq_uring_lock); 508 mutex_destroy(&vq->vq_aring_lock); 509 memset(vq, 0, sizeof(*vq)); 510 511 sc->sc_nvqs--; 512 513 return 0; 514} 515 516/* 517 * Free descriptor management. 518 */ 519static struct vq_entry * 520vq_alloc_entry(struct virtqueue *vq) 521{ 522 struct vq_entry *qe; 523 524 mutex_enter(&vq->vq_freelist_lock); 525 if (SIMPLEQ_EMPTY(&vq->vq_freelist)) { 526 mutex_exit(&vq->vq_freelist_lock); 527 return NULL; 528 } 529 qe = SIMPLEQ_FIRST(&vq->vq_freelist); 530 SIMPLEQ_REMOVE_HEAD(&vq->vq_freelist, qe_list); 531 mutex_exit(&vq->vq_freelist_lock); 532 533 return qe; 534} 535 536static void 537vq_free_entry(struct virtqueue *vq, struct vq_entry *qe) 538{ 539 mutex_enter(&vq->vq_freelist_lock); 540 SIMPLEQ_INSERT_TAIL(&vq->vq_freelist, qe, qe_list); 541 mutex_exit(&vq->vq_freelist_lock); 542 543 return; 544} 545 546/* 547 * Enqueue several dmamaps as a single request. 548 */ 549/* 550 * Typical usage: 551 * <queue size> number of followings are stored in arrays 552 * - command blocks (in dmamem) should be pre-allocated and mapped 553 * - dmamaps for command blocks should be pre-allocated and loaded 554 * - dmamaps for payload should be pre-allocated 555 * r = virtio_enqueue_prep(sc, vq, &slot); // allocate a slot 556 * if (r) // currently 0 or EAGAIN 557 * return r; 558 * r = bus_dmamap_load(dmat, dmamap_payload[slot], data, count, ..); 559 * if (r) { 560 * virtio_enqueue_abort(sc, vq, slot); 561 * return r; 562 * } 563 * r = virtio_enqueue_reserve(sc, vq, slot, 564 * dmamap_payload[slot]->dm_nsegs+1); 565 * // ^ +1 for command 566 * if (r) { // currently 0 or EAGAIN 567 * bus_dmamap_unload(dmat, dmamap_payload[slot]); 568 * return r; // do not call abort() 569 * } 570 * <setup and prepare commands> 571 * bus_dmamap_sync(dmat, dmamap_cmd[slot],... BUS_DMASYNC_PREWRITE); 572 * bus_dmamap_sync(dmat, dmamap_payload[slot],...); 573 * virtio_enqueue(sc, vq, slot, dmamap_cmd[slot], false); 574 * virtio_enqueue(sc, vq, slot, dmamap_payload[slot], iswrite); 575 * virtio_enqueue_commit(sc, vq, slot, true); 576 */ 577 578/* 579 * enqueue_prep: allocate a slot number 580 */ 581int 582virtio_enqueue_prep(struct virtio_softc *sc, struct virtqueue *vq, int *slotp) 583{ 584 struct vq_entry *qe1; 585 586 KASSERT(slotp != NULL); 587 588 qe1 = vq_alloc_entry(vq); 589 if (qe1 == NULL) 590 return EAGAIN; 591 /* next slot is not allocated yet */ 592 qe1->qe_next = -1; 593 *slotp = qe1->qe_index; 594 595 return 0; 596} 597 598/* 599 * enqueue_reserve: allocate remaining slots and build the descriptor chain. 600 */ 601int 602virtio_enqueue_reserve(struct virtio_softc *sc, struct virtqueue *vq, 603 int slot, int nsegs) 604{ 605 int indirect; 606 struct vq_entry *qe1 = &vq->vq_entries[slot]; 607 608 KASSERT(qe1->qe_next == -1); 609 KASSERT(1 <= nsegs && nsegs <= vq->vq_num); 610 611 if ((vq->vq_indirect != NULL) && 612 (nsegs >= MINSEG_INDIRECT) && 613 (nsegs <= vq->vq_maxnsegs)) 614 indirect = 1; 615 else 616 indirect = 0; 617 qe1->qe_indirect = indirect; 618 619 if (indirect) { 620 struct vring_desc *vd; 621 int i; 622 623 vd = &vq->vq_desc[qe1->qe_index]; 624 vd->addr = vq->vq_dmamap->dm_segs[0].ds_addr 625 + vq->vq_indirectoffset; 626 vd->addr += sizeof(struct vring_desc) 627 * vq->vq_maxnsegs * qe1->qe_index; 628 vd->len = sizeof(struct vring_desc) * nsegs; 629 vd->flags = VRING_DESC_F_INDIRECT; 630 631 vd = vq->vq_indirect; 632 vd += vq->vq_maxnsegs * qe1->qe_index; 633 qe1->qe_desc_base = vd; 634 635 for (i = 0; i < nsegs-1; i++) { 636 vd[i].flags = VRING_DESC_F_NEXT; 637 } 638 vd[i].flags = 0; 639 qe1->qe_next = 0; 640 641 return 0; 642 } else { 643 struct vring_desc *vd; 644 struct vq_entry *qe; 645 int i, s; 646 647 vd = &vq->vq_desc[0]; 648 qe1->qe_desc_base = vd; 649 qe1->qe_next = qe1->qe_index; 650 s = slot; 651 for (i = 0; i < nsegs - 1; i++) { 652 qe = vq_alloc_entry(vq); 653 if (qe == NULL) { 654 vd[s].flags = 0; 655 virtio_enqueue_abort(sc, vq, slot); 656 return EAGAIN; 657 } 658 vd[s].flags = VRING_DESC_F_NEXT; 659 vd[s].next = qe->qe_index; 660 s = qe->qe_index; 661 } 662 vd[s].flags = 0; 663 664 return 0; 665 } 666} 667 668/* 669 * enqueue: enqueue a single dmamap. 670 */ 671int 672virtio_enqueue(struct virtio_softc *sc, struct virtqueue *vq, int slot, 673 bus_dmamap_t dmamap, bool write) 674{ 675 struct vq_entry *qe1 = &vq->vq_entries[slot]; 676 struct vring_desc *vd = qe1->qe_desc_base; 677 int i; 678 int s = qe1->qe_next; 679 680 KASSERT(s >= 0); 681 KASSERT(dmamap->dm_nsegs > 0); 682 683 for (i = 0; i < dmamap->dm_nsegs; i++) { 684 vd[s].addr = dmamap->dm_segs[i].ds_addr; 685 vd[s].len = dmamap->dm_segs[i].ds_len; 686 if (!write) 687 vd[s].flags |= VRING_DESC_F_WRITE; 688 s = vd[s].next; 689 } 690 qe1->qe_next = s; 691 692 return 0; 693} 694 695int 696virtio_enqueue_p(struct virtio_softc *sc, struct virtqueue *vq, int slot, 697 bus_dmamap_t dmamap, bus_addr_t start, bus_size_t len, 698 bool write) 699{ 700 struct vq_entry *qe1 = &vq->vq_entries[slot]; 701 struct vring_desc *vd = qe1->qe_desc_base; 702 int s = qe1->qe_next; 703 704 KASSERT(s >= 0); 705 KASSERT(dmamap->dm_nsegs == 1); /* XXX */ 706 KASSERT((dmamap->dm_segs[0].ds_len > start) && 707 (dmamap->dm_segs[0].ds_len >= start + len)); 708 709 vd[s].addr = dmamap->dm_segs[0].ds_addr + start; 710 vd[s].len = len; 711 if (!write) 712 vd[s].flags |= VRING_DESC_F_WRITE; 713 qe1->qe_next = vd[s].next; 714 715 return 0; 716} 717 718/* 719 * enqueue_commit: add it to the aring. 720 */ 721int 722virtio_enqueue_commit(struct virtio_softc *sc, struct virtqueue *vq, int slot, 723 bool notifynow) 724{ 725 struct vq_entry *qe1; 726 727 if (slot < 0) { 728 mutex_enter(&vq->vq_aring_lock); 729 goto notify; 730 } 731 vq_sync_descs(sc, vq, BUS_DMASYNC_PREWRITE); 732 qe1 = &vq->vq_entries[slot]; 733 if (qe1->qe_indirect) 734 vq_sync_indirect(sc, vq, slot, BUS_DMASYNC_PREWRITE); 735 mutex_enter(&vq->vq_aring_lock); 736 vq->vq_avail->ring[(vq->vq_avail_idx++) % vq->vq_num] = slot; 737 738notify: 739 if (notifynow) { 740 vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); 741 vq_sync_uring(sc, vq, BUS_DMASYNC_PREREAD); 742 membar_producer(); 743 vq->vq_avail->idx = vq->vq_avail_idx; 744 vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); 745 membar_producer(); 746 vq->vq_queued++; 747 vq_sync_uring(sc, vq, BUS_DMASYNC_POSTREAD); 748 membar_consumer(); 749 if (!(vq->vq_used->flags & VRING_USED_F_NO_NOTIFY)) 750 sc->sc_ops->kick(sc, vq->vq_index); 751 } 752 mutex_exit(&vq->vq_aring_lock); 753 754 return 0; 755} 756 757/* 758 * enqueue_abort: rollback. 759 */ 760int 761virtio_enqueue_abort(struct virtio_softc *sc, struct virtqueue *vq, int slot) 762{ 763 struct vq_entry *qe = &vq->vq_entries[slot]; 764 struct vring_desc *vd; 765 int s; 766 767 if (qe->qe_next < 0) { 768 vq_free_entry(vq, qe); 769 return 0; 770 } 771 772 s = slot; 773 vd = &vq->vq_desc[0]; 774 while (vd[s].flags & VRING_DESC_F_NEXT) { 775 s = vd[s].next; 776 vq_free_entry(vq, qe); 777 qe = &vq->vq_entries[s]; 778 } 779 vq_free_entry(vq, qe); 780 return 0; 781} 782 783/* 784 * Dequeue a request. 785 */ 786/* 787 * dequeue: dequeue a request from uring; dmamap_sync for uring is 788 * already done in the interrupt handler. 789 */ 790int 791virtio_dequeue(struct virtio_softc *sc, struct virtqueue *vq, 792 int *slotp, int *lenp) 793{ 794 uint16_t slot, usedidx; 795 struct vq_entry *qe; 796 797 if (vq->vq_used_idx == vq->vq_used->idx) 798 return ENOENT; 799 mutex_enter(&vq->vq_uring_lock); 800 usedidx = vq->vq_used_idx++; 801 mutex_exit(&vq->vq_uring_lock); 802 usedidx %= vq->vq_num; 803 slot = vq->vq_used->ring[usedidx].id; 804 qe = &vq->vq_entries[slot]; 805 806 if (qe->qe_indirect) 807 vq_sync_indirect(sc, vq, slot, BUS_DMASYNC_POSTWRITE); 808 809 if (slotp) 810 *slotp = slot; 811 if (lenp) 812 *lenp = vq->vq_used->ring[usedidx].len; 813 814 return 0; 815} 816 817/* 818 * dequeue_commit: complete dequeue; the slot is recycled for future use. 819 * if you forget to call this the slot will be leaked. 820 */ 821int 822virtio_dequeue_commit(struct virtio_softc *sc, struct virtqueue *vq, int slot) 823{ 824 struct vq_entry *qe = &vq->vq_entries[slot]; 825 struct vring_desc *vd = &vq->vq_desc[0]; 826 int s = slot; 827 828 while (vd[s].flags & VRING_DESC_F_NEXT) { 829 s = vd[s].next; 830 vq_free_entry(vq, qe); 831 qe = &vq->vq_entries[s]; 832 } 833 vq_free_entry(vq, qe); 834 835 return 0; 836} 837 838/* 839 * Attach a child, fill all the members. 840 */ 841void 842virtio_child_attach_start(struct virtio_softc *sc, device_t child, int ipl, 843 struct virtqueue *vqs, 844 virtio_callback config_change, 845 virtio_callback intr_hand, 846 int req_flags, int req_features, const char *feat_bits) 847{ 848 char buf[256]; 849 int features; 850 851 sc->sc_child = child; 852 sc->sc_ipl = ipl; 853 sc->sc_vqs = vqs; 854 sc->sc_config_change = config_change; 855 sc->sc_intrhand = intr_hand; 856 sc->sc_flags = req_flags; 857 858 features = virtio_negotiate_features(sc, req_features); 859 snprintb(buf, sizeof(buf), feat_bits, features); 860 aprint_normal(": Features: %s\n", buf); 861 aprint_naive("\n"); 862} 863 864void 865virtio_child_attach_set_vqs(struct virtio_softc *sc, 866 struct virtqueue *vqs, int nvq_pairs) 867{ 868 869 KASSERT(nvq_pairs == 1 || 870 (sc->sc_flags & VIRTIO_F_PCI_INTR_SOFTINT) == 0); 871 if (nvq_pairs > 1) 872 sc->sc_child_mq = true; 873 874 sc->sc_vqs = vqs; 875} 876 877int 878virtio_child_attach_finish(struct virtio_softc *sc) 879{ 880 int r; 881 882 r = sc->sc_ops->setup_interrupts(sc); 883 if (r != 0) { 884 aprint_error_dev(sc->sc_dev, "failed to setup interrupts\n"); 885 goto fail; 886 } 887 888 KASSERT(sc->sc_soft_ih == NULL); 889 if (sc->sc_flags & VIRTIO_F_PCI_INTR_SOFTINT) { 890 u_int flags = SOFTINT_NET; 891 if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE) 892 flags |= SOFTINT_MPSAFE; 893 894 sc->sc_soft_ih = softint_establish(flags, virtio_soft_intr, sc); 895 if (sc->sc_soft_ih == NULL) { 896 sc->sc_ops->free_interrupts(sc); 897 aprint_error_dev(sc->sc_dev, 898 "failed to establish soft interrupt\n"); 899 goto fail; 900 } 901 } 902 903 virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK); 904 return 0; 905 906fail: 907 if (sc->sc_soft_ih) { 908 softint_disestablish(sc->sc_soft_ih); 909 sc->sc_soft_ih = NULL; 910 } 911 912 virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); 913 return 1; 914} 915 916void 917virtio_child_detach(struct virtio_softc *sc) 918{ 919 sc->sc_child = NULL; 920 sc->sc_vqs = NULL; 921 922 virtio_device_reset(sc); 923 924 sc->sc_ops->free_interrupts(sc); 925 926 if (sc->sc_soft_ih) { 927 softint_disestablish(sc->sc_soft_ih); 928 sc->sc_soft_ih = NULL; 929 } 930} 931 932void 933virtio_child_attach_failed(struct virtio_softc *sc) 934{ 935 virtio_child_detach(sc); 936 937 virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); 938 939 sc->sc_child = VIRTIO_CHILD_FAILED; 940} 941 942bus_dma_tag_t 943virtio_dmat(struct virtio_softc *sc) 944{ 945 return sc->sc_dmat; 946} 947 948device_t 949virtio_child(struct virtio_softc *sc) 950{ 951 return sc->sc_child; 952} 953 954int 955virtio_intrhand(struct virtio_softc *sc) 956{ 957 return (sc->sc_intrhand)(sc); 958} 959 960uint32_t 961virtio_features(struct virtio_softc *sc) 962{ 963 return sc->sc_features; 964} 965 966int 967virtiobusprint(void *aux, const char *pnp) 968{ 969 struct virtio_attach_args * const va = aux; 970 971 if (va->sc_childdevid == 0) 972 return QUIET; /* No device present */ 973 974 if (pnp) 975 aprint_normal("Device ID %d at %s", va->sc_childdevid, pnp); 976 977 return UNCONF; 978} 979 980MODULE(MODULE_CLASS_DRIVER, virtio, NULL); 981 982#ifdef _MODULE 983#include "ioconf.c" 984#endif 985 986static int 987virtio_modcmd(modcmd_t cmd, void *opaque) 988{ 989 int error = 0; 990 991#ifdef _MODULE 992 switch (cmd) { 993 case MODULE_CMD_INIT: 994 error = config_init_component(cfdriver_ioconf_virtio, 995 cfattach_ioconf_virtio, cfdata_ioconf_virtio); 996 break; 997 case MODULE_CMD_FINI: 998 error = config_fini_component(cfdriver_ioconf_virtio, 999 cfattach_ioconf_virtio, cfdata_ioconf_virtio); 1000 break; 1001 default: 1002 error = ENOTTY; 1003 break; 1004 } 1005#endif 1006 1007 return error; 1008} 1009