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