1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2013 Nexenta Inc. All rights reserved. 14 */ 15 16 /* Based on the NetBSD virtio driver by Minoura Makoto. */ 17 /* 18 * Copyright (c) 2010 Minoura Makoto. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms, with or without 22 * modification, are permitted provided that the following conditions 23 * are met: 24 * 1. Redistributions of source code must retain the above copyright 25 * notice, this list of conditions and the following disclaimer. 26 * 2. Redistributions in binary form must reproduce the above copyright 27 * notice, this list of conditions and the following disclaimer in the 28 * documentation and/or other materials provided with the distribution. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 39 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 */ 41 42 #include <sys/types.h> 43 #include <sys/errno.h> 44 #include <sys/param.h> 45 #include <sys/stropts.h> 46 #include <sys/stream.h> 47 #include <sys/strsubr.h> 48 #include <sys/kmem.h> 49 #include <sys/conf.h> 50 #include <sys/devops.h> 51 #include <sys/ksynch.h> 52 #include <sys/stat.h> 53 #include <sys/modctl.h> 54 #include <sys/debug.h> 55 #include <sys/pci.h> 56 #include <sys/ethernet.h> 57 58 #define VLAN_TAGSZ 4 59 60 #include <sys/dlpi.h> 61 #include <sys/taskq.h> 62 #include <sys/cyclic.h> 63 64 #include <sys/pattr.h> 65 #include <sys/strsun.h> 66 67 #include <sys/random.h> 68 #include <sys/sysmacros.h> 69 #include <sys/stream.h> 70 71 #include <sys/mac.h> 72 #include <sys/mac_provider.h> 73 #include <sys/mac_ether.h> 74 75 #include "virtiovar.h" 76 #include "virtioreg.h" 77 78 #if !defined(__packed) 79 #define __packed __attribute__((packed)) 80 #endif /* __packed */ 81 82 /* Configuration registers */ 83 #define VIRTIO_NET_CONFIG_MAC 0 /* 8bit x 6byte */ 84 #define VIRTIO_NET_CONFIG_STATUS 6 /* 16bit */ 85 86 /* Feature bits */ 87 #define VIRTIO_NET_F_CSUM (1 << 0) /* Host handles pkts w/ partial csum */ 88 #define VIRTIO_NET_F_GUEST_CSUM (1 << 1) /* Guest handles pkts w/ part csum */ 89 #define VIRTIO_NET_F_MAC (1 << 5) /* Host has given MAC address. */ 90 #define VIRTIO_NET_F_GSO (1 << 6) /* Host handles pkts w/ any GSO type */ 91 #define VIRTIO_NET_F_GUEST_TSO4 (1 << 7) /* Guest can handle TSOv4 in. */ 92 #define VIRTIO_NET_F_GUEST_TSO6 (1 << 8) /* Guest can handle TSOv6 in. */ 93 #define VIRTIO_NET_F_GUEST_ECN (1 << 9) /* Guest can handle TSO[6] w/ ECN in */ 94 #define VIRTIO_NET_F_GUEST_UFO (1 << 10) /* Guest can handle UFO in. */ 95 #define VIRTIO_NET_F_HOST_TSO4 (1 << 11) /* Host can handle TSOv4 in. */ 96 #define VIRTIO_NET_F_HOST_TSO6 (1 << 12) /* Host can handle TSOv6 in. */ 97 #define VIRTIO_NET_F_HOST_ECN (1 << 13) /* Host can handle TSO[6] w/ ECN in */ 98 #define VIRTIO_NET_F_HOST_UFO (1 << 14) /* Host can handle UFO in. */ 99 #define VIRTIO_NET_F_MRG_RXBUF (1 << 15) /* Host can merge receive buffers. */ 100 #define VIRTIO_NET_F_STATUS (1 << 16) /* Config.status available */ 101 #define VIRTIO_NET_F_CTRL_VQ (1 << 17) /* Control channel available */ 102 #define VIRTIO_NET_F_CTRL_RX (1 << 18) /* Control channel RX mode support */ 103 #define VIRTIO_NET_F_CTRL_VLAN (1 << 19) /* Control channel VLAN filtering */ 104 #define VIRTIO_NET_F_CTRL_RX_EXTRA (1 << 20) /* Extra RX mode control support */ 105 106 /* Status */ 107 #define VIRTIO_NET_S_LINK_UP 1 108 109 /* Packet header structure */ 110 struct virtio_net_hdr { 111 uint8_t flags; 112 uint8_t gso_type; 113 uint16_t hdr_len; 114 uint16_t gso_size; 115 uint16_t csum_start; 116 uint16_t csum_offset; 117 }; 118 119 #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* flags */ 120 #define VIRTIO_NET_HDR_GSO_NONE 0 /* gso_type */ 121 #define VIRTIO_NET_HDR_GSO_TCPV4 1 /* gso_type */ 122 #define VIRTIO_NET_HDR_GSO_UDP 3 /* gso_type */ 123 #define VIRTIO_NET_HDR_GSO_TCPV6 4 /* gso_type */ 124 #define VIRTIO_NET_HDR_GSO_ECN 0x80 /* gso_type, |'ed */ 125 126 127 /* Control virtqueue */ 128 struct virtio_net_ctrl_cmd { 129 uint8_t class; 130 uint8_t command; 131 } __packed; 132 133 #define VIRTIO_NET_CTRL_RX 0 134 #define VIRTIO_NET_CTRL_RX_PROMISC 0 135 #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 136 137 #define VIRTIO_NET_CTRL_MAC 1 138 #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 139 140 #define VIRTIO_NET_CTRL_VLAN 2 141 #define VIRTIO_NET_CTRL_VLAN_ADD 0 142 #define VIRTIO_NET_CTRL_VLAN_DEL 1 143 144 struct virtio_net_ctrl_status { 145 uint8_t ack; 146 } __packed; 147 148 struct virtio_net_ctrl_rx { 149 uint8_t onoff; 150 } __packed; 151 152 struct virtio_net_ctrl_mac_tbl { 153 uint32_t nentries; 154 uint8_t macs[][ETHERADDRL]; 155 } __packed; 156 157 struct virtio_net_ctrl_vlan { 158 uint16_t id; 159 } __packed; 160 161 static int vioif_quiesce(dev_info_t *); 162 static int vioif_attach(dev_info_t *, ddi_attach_cmd_t); 163 static int vioif_detach(dev_info_t *, ddi_detach_cmd_t); 164 165 DDI_DEFINE_STREAM_OPS(vioif_ops, 166 nulldev, /* identify */ 167 nulldev, /* probe */ 168 vioif_attach, /* attach */ 169 vioif_detach, /* detach */ 170 nodev, /* reset */ 171 NULL, /* cb_ops */ 172 D_MP, /* bus_ops */ 173 NULL, /* power */ 174 vioif_quiesce /* quiesce */ 175 ); 176 177 static char vioif_ident[] = "VirtIO ethernet driver"; 178 179 /* Standard Module linkage initialization for a Streams driver */ 180 extern struct mod_ops mod_driverops; 181 182 static struct modldrv modldrv = { 183 &mod_driverops, /* Type of module. This one is a driver */ 184 vioif_ident, /* short description */ 185 &vioif_ops /* driver specific ops */ 186 }; 187 188 static struct modlinkage modlinkage = { 189 MODREV_1, 190 { 191 (void *)&modldrv, 192 NULL, 193 }, 194 }; 195 196 ddi_device_acc_attr_t vioif_attr = { 197 DDI_DEVICE_ATTR_V0, 198 DDI_NEVERSWAP_ACC, /* virtio is always native byte order */ 199 DDI_STORECACHING_OK_ACC, 200 DDI_DEFAULT_ACC 201 }; 202 203 /* 204 * A mapping represents a binding for a single buffer that is contiguous in the 205 * virtual address space. 206 */ 207 struct vioif_buf_mapping { 208 caddr_t vbm_buf; 209 ddi_dma_handle_t vbm_dmah; 210 ddi_acc_handle_t vbm_acch; 211 ddi_dma_cookie_t vbm_dmac; 212 unsigned int vbm_ncookies; 213 }; 214 215 /* 216 * Rx buffers can be loaned upstream, so the code has 217 * to allocate them dynamically. 218 */ 219 struct vioif_rx_buf { 220 struct vioif_softc *rb_sc; 221 frtn_t rb_frtn; 222 223 struct vioif_buf_mapping rb_mapping; 224 }; 225 226 /* 227 * Tx buffers have two mapping types. One, "inline", is pre-allocated and is 228 * used to hold the virtio_net_header. Small packets also get copied there, as 229 * it's faster then mapping them. Bigger packets get mapped using the "external" 230 * mapping array. An array is used, because a packet may consist of muptiple 231 * fragments, so each fragment gets bound to an entry. According to my 232 * observations, the number of fragments does not exceed 2, but just in case, 233 * a bigger, up to VIOIF_INDIRECT_MAX - 1 array is allocated. To save resources, 234 * the dma handles are allocated lazily in the tx path. 235 */ 236 struct vioif_tx_buf { 237 mblk_t *tb_mp; 238 239 /* inline buffer */ 240 struct vioif_buf_mapping tb_inline_mapping; 241 242 /* External buffers */ 243 struct vioif_buf_mapping *tb_external_mapping; 244 unsigned int tb_external_num; 245 }; 246 247 struct vioif_softc { 248 dev_info_t *sc_dev; /* mirrors virtio_softc->sc_dev */ 249 struct virtio_softc sc_virtio; 250 251 mac_handle_t sc_mac_handle; 252 mac_register_t *sc_macp; 253 254 struct virtqueue *sc_rx_vq; 255 struct virtqueue *sc_tx_vq; 256 struct virtqueue *sc_ctrl_vq; 257 258 unsigned int sc_tx_stopped:1; 259 260 /* Feature bits. */ 261 unsigned int sc_rx_csum:1; 262 unsigned int sc_tx_csum:1; 263 unsigned int sc_tx_tso4:1; 264 265 int sc_mtu; 266 uint8_t sc_mac[ETHERADDRL]; 267 /* 268 * For rx buffers, we keep a pointer array, because the buffers 269 * can be loaned upstream, and we have to repopulate the array with 270 * new members. 271 */ 272 struct vioif_rx_buf **sc_rxbufs; 273 274 /* 275 * For tx, we just allocate an array of buffers. The packet can 276 * either be copied into the inline buffer, or the external mapping 277 * could be used to map the packet 278 */ 279 struct vioif_tx_buf *sc_txbufs; 280 281 kstat_t *sc_intrstat; 282 /* 283 * We "loan" rx buffers upstream and reuse them after they are 284 * freed. This lets us avoid allocations in the hot path. 285 */ 286 kmem_cache_t *sc_rxbuf_cache; 287 ulong_t sc_rxloan; 288 289 /* Copying small packets turns out to be faster then mapping them. */ 290 unsigned long sc_rxcopy_thresh; 291 unsigned long sc_txcopy_thresh; 292 /* Some statistic coming here */ 293 uint64_t sc_ipackets; 294 uint64_t sc_opackets; 295 uint64_t sc_rbytes; 296 uint64_t sc_obytes; 297 uint64_t sc_brdcstxmt; 298 uint64_t sc_brdcstrcv; 299 uint64_t sc_multixmt; 300 uint64_t sc_multircv; 301 uint64_t sc_norecvbuf; 302 uint64_t sc_notxbuf; 303 uint64_t sc_toolongerr; 304 uint64_t sc_ierrors; 305 uint64_t sc_oerrors; 306 }; 307 308 #define ETHER_HEADER_LEN sizeof (struct ether_header) 309 310 /* MTU + the ethernet header. */ 311 #define MAX_PAYLOAD 65535 312 #define MAX_MTU (MAX_PAYLOAD - ETHER_HEADER_LEN) 313 #define DEFAULT_MTU ETHERMTU 314 315 /* 316 * Yeah, we spend 8M per device. Turns out, there is no point 317 * being smart and using merged rx buffers (VIRTIO_NET_F_MRG_RXBUF), 318 * because vhost does not support them, and we expect to be used with 319 * vhost in production environment. 320 */ 321 /* The buffer keeps both the packet data and the virtio_net_header. */ 322 #define VIOIF_RX_SIZE (MAX_PAYLOAD + sizeof (struct virtio_net_hdr)) 323 324 /* 325 * We win a bit on header alignment, but the host wins a lot 326 * more on moving aligned buffers. Might need more thought. 327 */ 328 #define VIOIF_IP_ALIGN 0 329 330 /* Maximum number of indirect descriptors, somewhat arbitrary. */ 331 #define VIOIF_INDIRECT_MAX 128 332 333 /* 334 * We pre-allocate a reasonably large buffer to copy small packets 335 * there. Bigger packets are mapped, packets with multiple 336 * cookies are mapped as indirect buffers. 337 */ 338 #define VIOIF_TX_INLINE_SIZE 2048 339 340 /* Native queue size for all queues */ 341 #define VIOIF_RX_QLEN 0 342 #define VIOIF_TX_QLEN 0 343 #define VIOIF_CTRL_QLEN 0 344 345 static uchar_t vioif_broadcast[ETHERADDRL] = { 346 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 347 }; 348 349 #define VIOIF_TX_THRESH_MAX 640 350 #define VIOIF_RX_THRESH_MAX 640 351 352 static char vioif_txcopy_thresh[] = 353 "vioif_txcopy_thresh"; 354 static char vioif_rxcopy_thresh[] = 355 "vioif_rxcopy_thresh"; 356 357 static char *vioif_priv_props[] = { 358 vioif_txcopy_thresh, 359 vioif_rxcopy_thresh, 360 NULL 361 }; 362 363 /* Add up to ddi? */ 364 static ddi_dma_cookie_t * 365 vioif_dma_curr_cookie(ddi_dma_handle_t dmah) 366 { 367 ddi_dma_impl_t *dmah_impl = (void *) dmah; 368 ASSERT(dmah_impl->dmai_cookie); 369 return (dmah_impl->dmai_cookie); 370 } 371 372 static void 373 vioif_dma_reset_cookie(ddi_dma_handle_t dmah, ddi_dma_cookie_t *dmac) 374 { 375 ddi_dma_impl_t *dmah_impl = (void *) dmah; 376 dmah_impl->dmai_cookie = dmac; 377 } 378 379 static link_state_t 380 vioif_link_state(struct vioif_softc *sc) 381 { 382 if (sc->sc_virtio.sc_features & VIRTIO_NET_F_STATUS) { 383 if (virtio_read_device_config_2(&sc->sc_virtio, 384 VIRTIO_NET_CONFIG_STATUS) & VIRTIO_NET_S_LINK_UP) { 385 386 dev_err(sc->sc_dev, CE_NOTE, "Link up\n"); 387 return (LINK_STATE_UP); 388 } else { 389 dev_err(sc->sc_dev, CE_NOTE, "Link down\n"); 390 return (LINK_STATE_DOWN); 391 } 392 } 393 394 dev_err(sc->sc_dev, CE_NOTE, "Link assumed up\n"); 395 396 return (LINK_STATE_UP); 397 } 398 399 static ddi_dma_attr_t vioif_inline_buf_dma_attr = { 400 DMA_ATTR_V0, /* Version number */ 401 0, /* low address */ 402 0xFFFFFFFFFFFFFFFF, /* high address */ 403 0xFFFFFFFF, /* counter register max */ 404 1, /* page alignment */ 405 1, /* burst sizes: 1 - 32 */ 406 1, /* minimum transfer size */ 407 0xFFFFFFFF, /* max transfer size */ 408 0xFFFFFFFFFFFFFFF, /* address register max */ 409 1, /* scatter-gather capacity */ 410 1, /* device operates on bytes */ 411 0, /* attr flag: set to 0 */ 412 }; 413 414 static ddi_dma_attr_t vioif_mapped_buf_dma_attr = { 415 DMA_ATTR_V0, /* Version number */ 416 0, /* low address */ 417 0xFFFFFFFFFFFFFFFF, /* high address */ 418 0xFFFFFFFF, /* counter register max */ 419 1, /* page alignment */ 420 1, /* burst sizes: 1 - 32 */ 421 1, /* minimum transfer size */ 422 0xFFFFFFFF, /* max transfer size */ 423 0xFFFFFFFFFFFFFFF, /* address register max */ 424 425 /* One entry is used for the virtio_net_hdr on the tx path */ 426 VIOIF_INDIRECT_MAX - 1, /* scatter-gather capacity */ 427 1, /* device operates on bytes */ 428 0, /* attr flag: set to 0 */ 429 }; 430 431 static ddi_device_acc_attr_t vioif_bufattr = { 432 DDI_DEVICE_ATTR_V0, 433 DDI_NEVERSWAP_ACC, 434 DDI_STORECACHING_OK_ACC, 435 DDI_DEFAULT_ACC 436 }; 437 438 static void 439 vioif_rx_free(caddr_t free_arg) 440 { 441 struct vioif_rx_buf *buf = (void *) free_arg; 442 struct vioif_softc *sc = buf->rb_sc; 443 444 kmem_cache_free(sc->sc_rxbuf_cache, buf); 445 atomic_dec_ulong(&sc->sc_rxloan); 446 } 447 448 static int 449 vioif_rx_construct(void *buffer, void *user_arg, int kmflags) 450 { 451 _NOTE(ARGUNUSED(kmflags)); 452 struct vioif_softc *sc = user_arg; 453 struct vioif_rx_buf *buf = buffer; 454 size_t len; 455 456 if (ddi_dma_alloc_handle(sc->sc_dev, &vioif_mapped_buf_dma_attr, 457 DDI_DMA_SLEEP, NULL, &buf->rb_mapping.vbm_dmah)) { 458 dev_err(sc->sc_dev, CE_WARN, 459 "Can't allocate dma handle for rx buffer"); 460 goto exit_handle; 461 } 462 463 if (ddi_dma_mem_alloc(buf->rb_mapping.vbm_dmah, 464 VIOIF_RX_SIZE + sizeof (struct virtio_net_hdr), 465 &vioif_bufattr, DDI_DMA_STREAMING, DDI_DMA_SLEEP, 466 NULL, &buf->rb_mapping.vbm_buf, &len, &buf->rb_mapping.vbm_acch)) { 467 dev_err(sc->sc_dev, CE_WARN, 468 "Can't allocate rx buffer"); 469 goto exit_alloc; 470 } 471 ASSERT(len >= VIOIF_RX_SIZE); 472 473 if (ddi_dma_addr_bind_handle(buf->rb_mapping.vbm_dmah, NULL, 474 buf->rb_mapping.vbm_buf, len, DDI_DMA_READ | DDI_DMA_STREAMING, 475 DDI_DMA_SLEEP, NULL, &buf->rb_mapping.vbm_dmac, 476 &buf->rb_mapping.vbm_ncookies)) { 477 dev_err(sc->sc_dev, CE_WARN, "Can't bind tx buffer"); 478 479 goto exit_bind; 480 } 481 482 ASSERT(buf->rb_mapping.vbm_ncookies <= VIOIF_INDIRECT_MAX); 483 484 buf->rb_sc = sc; 485 buf->rb_frtn.free_arg = (void *) buf; 486 buf->rb_frtn.free_func = vioif_rx_free; 487 488 return (0); 489 exit_bind: 490 ddi_dma_mem_free(&buf->rb_mapping.vbm_acch); 491 exit_alloc: 492 ddi_dma_free_handle(&buf->rb_mapping.vbm_dmah); 493 exit_handle: 494 495 return (ENOMEM); 496 } 497 498 static void 499 vioif_rx_destruct(void *buffer, void *user_arg) 500 { 501 _NOTE(ARGUNUSED(user_arg)); 502 struct vioif_rx_buf *buf = buffer; 503 504 ASSERT(buf->rb_mapping.vbm_acch); 505 ASSERT(buf->rb_mapping.vbm_acch); 506 507 (void) ddi_dma_unbind_handle(buf->rb_mapping.vbm_dmah); 508 ddi_dma_mem_free(&buf->rb_mapping.vbm_acch); 509 ddi_dma_free_handle(&buf->rb_mapping.vbm_dmah); 510 } 511 512 static void 513 vioif_free_mems(struct vioif_softc *sc) 514 { 515 int i; 516 517 for (i = 0; i < sc->sc_tx_vq->vq_num; i++) { 518 struct vioif_tx_buf *buf = &sc->sc_txbufs[i]; 519 int j; 520 521 /* Tear down the internal mapping. */ 522 523 ASSERT(buf->tb_inline_mapping.vbm_acch); 524 ASSERT(buf->tb_inline_mapping.vbm_dmah); 525 526 (void) ddi_dma_unbind_handle(buf->tb_inline_mapping.vbm_dmah); 527 ddi_dma_mem_free(&buf->tb_inline_mapping.vbm_acch); 528 ddi_dma_free_handle(&buf->tb_inline_mapping.vbm_dmah); 529 530 /* We should not see any in-flight buffers at this point. */ 531 ASSERT(!buf->tb_mp); 532 533 /* Free all the dma hdnales we allocated lazily. */ 534 for (j = 0; buf->tb_external_mapping[j].vbm_dmah; j++) 535 ddi_dma_free_handle( 536 &buf->tb_external_mapping[j].vbm_dmah); 537 /* Free the external mapping array. */ 538 kmem_free(buf->tb_external_mapping, 539 sizeof (struct vioif_tx_buf) * VIOIF_INDIRECT_MAX - 1); 540 } 541 542 kmem_free(sc->sc_txbufs, sizeof (struct vioif_tx_buf) * 543 sc->sc_tx_vq->vq_num); 544 545 for (i = 0; i < sc->sc_rx_vq->vq_num; i++) { 546 struct vioif_rx_buf *buf = sc->sc_rxbufs[i]; 547 548 if (buf) 549 kmem_cache_free(sc->sc_rxbuf_cache, buf); 550 } 551 kmem_free(sc->sc_rxbufs, sizeof (struct vioif_rx_buf *) * 552 sc->sc_rx_vq->vq_num); 553 } 554 555 static int 556 vioif_alloc_mems(struct vioif_softc *sc) 557 { 558 int i, txqsize, rxqsize; 559 size_t len; 560 unsigned int nsegments; 561 562 txqsize = sc->sc_tx_vq->vq_num; 563 rxqsize = sc->sc_rx_vq->vq_num; 564 565 sc->sc_txbufs = kmem_zalloc(sizeof (struct vioif_tx_buf) * txqsize, 566 KM_SLEEP); 567 if (sc->sc_txbufs == NULL) { 568 dev_err(sc->sc_dev, CE_WARN, 569 "Failed to allocate the tx buffers array"); 570 goto exit_txalloc; 571 } 572 573 /* 574 * We don't allocate the rx vioif_buffs, just the pointers, as 575 * rx vioif_bufs can be loaned upstream, and we don't know the 576 * total number we need. 577 */ 578 sc->sc_rxbufs = kmem_zalloc(sizeof (struct vioif_rx_buf *) * rxqsize, 579 KM_SLEEP); 580 if (sc->sc_rxbufs == NULL) { 581 dev_err(sc->sc_dev, CE_WARN, 582 "Failed to allocate the rx buffers pointer array"); 583 goto exit_rxalloc; 584 } 585 586 for (i = 0; i < txqsize; i++) { 587 struct vioif_tx_buf *buf = &sc->sc_txbufs[i]; 588 589 /* Allocate and bind an inline mapping. */ 590 591 if (ddi_dma_alloc_handle(sc->sc_dev, 592 &vioif_inline_buf_dma_attr, 593 DDI_DMA_SLEEP, NULL, &buf->tb_inline_mapping.vbm_dmah)) { 594 595 dev_err(sc->sc_dev, CE_WARN, 596 "Can't allocate dma handle for tx buffer %d", i); 597 goto exit_tx; 598 } 599 600 if (ddi_dma_mem_alloc(buf->tb_inline_mapping.vbm_dmah, 601 VIOIF_TX_INLINE_SIZE, &vioif_bufattr, DDI_DMA_STREAMING, 602 DDI_DMA_SLEEP, NULL, &buf->tb_inline_mapping.vbm_buf, 603 &len, &buf->tb_inline_mapping.vbm_acch)) { 604 605 dev_err(sc->sc_dev, CE_WARN, 606 "Can't allocate tx buffer %d", i); 607 goto exit_tx; 608 } 609 ASSERT(len >= VIOIF_TX_INLINE_SIZE); 610 611 if (ddi_dma_addr_bind_handle(buf->tb_inline_mapping.vbm_dmah, 612 NULL, buf->tb_inline_mapping.vbm_buf, len, 613 DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, 614 &buf->tb_inline_mapping.vbm_dmac, &nsegments)) { 615 616 dev_err(sc->sc_dev, CE_WARN, 617 "Can't bind tx buffer %d", i); 618 goto exit_tx; 619 } 620 621 /* We asked for a single segment */ 622 ASSERT(nsegments == 1); 623 624 /* 625 * We allow up to VIOIF_INDIRECT_MAX - 1 external mappings. 626 * In reality, I don't expect more then 2-3 used, but who 627 * knows. 628 */ 629 buf->tb_external_mapping = kmem_zalloc( 630 sizeof (struct vioif_tx_buf) * VIOIF_INDIRECT_MAX - 1, 631 KM_SLEEP); 632 633 /* 634 * The external mapping's dma handles are allocate lazily, 635 * as we don't expect most of them to be used.. 636 */ 637 } 638 639 return (0); 640 641 exit_tx: 642 for (i = 0; i < txqsize; i++) { 643 struct vioif_tx_buf *buf = &sc->sc_txbufs[i]; 644 645 if (buf->tb_inline_mapping.vbm_dmah) 646 (void) ddi_dma_unbind_handle( 647 buf->tb_inline_mapping.vbm_dmah); 648 649 if (buf->tb_inline_mapping.vbm_acch) 650 ddi_dma_mem_free( 651 &buf->tb_inline_mapping.vbm_acch); 652 653 if (buf->tb_inline_mapping.vbm_dmah) 654 ddi_dma_free_handle( 655 &buf->tb_inline_mapping.vbm_dmah); 656 657 if (buf->tb_external_mapping) 658 kmem_free(buf->tb_external_mapping, 659 sizeof (struct vioif_tx_buf) * 660 VIOIF_INDIRECT_MAX - 1); 661 } 662 663 kmem_free(sc->sc_rxbufs, sizeof (struct vioif_rx_buf) * rxqsize); 664 665 exit_rxalloc: 666 kmem_free(sc->sc_txbufs, sizeof (struct vioif_tx_buf) * txqsize); 667 exit_txalloc: 668 return (ENOMEM); 669 } 670 671 /* ARGSUSED */ 672 int 673 vioif_multicst(void *arg, boolean_t add, const uint8_t *macaddr) 674 { 675 return (DDI_SUCCESS); 676 } 677 678 /* ARGSUSED */ 679 int 680 vioif_promisc(void *arg, boolean_t on) 681 { 682 return (DDI_SUCCESS); 683 } 684 685 /* ARGSUSED */ 686 int 687 vioif_unicst(void *arg, const uint8_t *macaddr) 688 { 689 return (DDI_FAILURE); 690 } 691 692 693 static int 694 vioif_add_rx(struct vioif_softc *sc, int kmflag) 695 { 696 struct vq_entry *ve; 697 struct vioif_rx_buf *buf; 698 699 ve = vq_alloc_entry(sc->sc_rx_vq); 700 if (!ve) { 701 /* Out of free descriptors - ring already full. */ 702 /* would be better to update sc_norxdescavail */ 703 /* but MAC does not ask for this info */ 704 /* hence update sc_norecvbuf */ 705 sc->sc_norecvbuf ++; 706 goto exit_vq; 707 } 708 buf = sc->sc_rxbufs[ve->qe_index]; 709 710 if (!buf) { 711 /* First run, allocate the buffer. */ 712 buf = kmem_cache_alloc(sc->sc_rxbuf_cache, kmflag); 713 sc->sc_rxbufs[ve->qe_index] = buf; 714 } 715 716 /* Still nothing? Bye. */ 717 if (!buf) { 718 dev_err(sc->sc_dev, CE_WARN, "Can't allocate rx buffer"); 719 sc->sc_norecvbuf ++; 720 goto exit_buf; 721 } 722 723 ASSERT(buf->rb_mapping.vbm_ncookies >= 1); 724 725 /* 726 * For an unknown reason, the virtio_net_hdr must be placed 727 * as a separate virtio queue entry. 728 */ 729 virtio_ve_add_indirect_buf(ve, buf->rb_mapping.vbm_dmac.dmac_laddress, 730 sizeof (struct virtio_net_hdr), B_FALSE); 731 732 /* Add the rest of the first cookie. */ 733 virtio_ve_add_indirect_buf(ve, 734 buf->rb_mapping.vbm_dmac.dmac_laddress + 735 sizeof (struct virtio_net_hdr), 736 buf->rb_mapping.vbm_dmac.dmac_size - 737 sizeof (struct virtio_net_hdr), B_FALSE); 738 739 /* 740 * If the buffer consists of a single cookie (unlikely for a 741 * 64-k buffer), we are done. Otherwise, add the rest of the cookies 742 * using indirect entries. 743 */ 744 if (buf->rb_mapping.vbm_ncookies > 1) { 745 ddi_dma_cookie_t *first_extra_dmac; 746 ddi_dma_cookie_t dmac; 747 first_extra_dmac = 748 vioif_dma_curr_cookie(buf->rb_mapping.vbm_dmah); 749 750 ddi_dma_nextcookie(buf->rb_mapping.vbm_dmah, &dmac); 751 virtio_ve_add_cookie(ve, buf->rb_mapping.vbm_dmah, 752 dmac, buf->rb_mapping.vbm_ncookies - 1, B_FALSE); 753 vioif_dma_reset_cookie(buf->rb_mapping.vbm_dmah, 754 first_extra_dmac); 755 } 756 757 virtio_push_chain(ve, B_FALSE); 758 759 return (DDI_SUCCESS); 760 761 exit_buf: 762 vq_free_entry(sc->sc_rx_vq, ve); 763 exit_vq: 764 return (DDI_FAILURE); 765 } 766 767 static int 768 vioif_populate_rx(struct vioif_softc *sc, int kmflag) 769 { 770 int i = 0; 771 int ret; 772 773 for (;;) { 774 ret = vioif_add_rx(sc, kmflag); 775 if (ret) 776 /* 777 * We could not allocate some memory. Try to work with 778 * what we've got. 779 */ 780 break; 781 i++; 782 } 783 784 if (i) 785 virtio_sync_vq(sc->sc_rx_vq); 786 787 return (i); 788 } 789 790 static int 791 vioif_process_rx(struct vioif_softc *sc) 792 { 793 struct vq_entry *ve; 794 struct vioif_rx_buf *buf; 795 mblk_t *mp; 796 uint32_t len; 797 int i = 0; 798 799 while ((ve = virtio_pull_chain(sc->sc_rx_vq, &len))) { 800 801 buf = sc->sc_rxbufs[ve->qe_index]; 802 ASSERT(buf); 803 804 if (len < sizeof (struct virtio_net_hdr)) { 805 dev_err(sc->sc_dev, CE_WARN, "RX: Cnain too small: %u", 806 len - (uint32_t)sizeof (struct virtio_net_hdr)); 807 sc->sc_ierrors ++; 808 virtio_free_chain(ve); 809 continue; 810 } 811 812 len -= sizeof (struct virtio_net_hdr); 813 /* 814 * We copy small packets that happenned to fit into a single 815 * cookie and reuse the buffers. For bigger ones, we loan 816 * the buffers upstream. 817 */ 818 if (len < sc->sc_rxcopy_thresh) { 819 mp = allocb(len, 0); 820 if (!mp) { 821 cmn_err(CE_WARN, "Failed to allocale mblock!"); 822 sc->sc_norecvbuf ++; 823 sc->sc_ierrors ++; 824 825 virtio_free_chain(ve); 826 break; 827 } 828 829 bcopy((char *)buf->rb_mapping.vbm_buf + 830 sizeof (struct virtio_net_hdr), mp->b_rptr, len); 831 mp->b_wptr = mp->b_rptr + len; 832 833 } else { 834 mp = desballoc((unsigned char *) 835 buf->rb_mapping.vbm_buf + 836 sizeof (struct virtio_net_hdr) + 837 VIOIF_IP_ALIGN, len, 0, &buf->rb_frtn); 838 if (!mp) { 839 cmn_err(CE_WARN, "Failed to allocale mblock!"); 840 sc->sc_norecvbuf ++; 841 sc->sc_ierrors ++; 842 843 virtio_free_chain(ve); 844 break; 845 } 846 mp->b_wptr = mp->b_rptr + len; 847 848 atomic_inc_ulong(&sc->sc_rxloan); 849 /* 850 * Buffer loanded, we will have to allocte a new one 851 * for this slot. 852 */ 853 sc->sc_rxbufs[ve->qe_index] = NULL; 854 } 855 /* virtio-net does not provide the info if this packet */ 856 /* is multicast or broadcast. So we have to check it */ 857 if (mp->b_rptr[0] & 0x1) { 858 if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0) 859 sc->sc_multircv ++; 860 else 861 sc->sc_brdcstrcv ++; 862 } 863 864 sc->sc_rbytes += len; 865 sc->sc_ipackets ++; 866 867 virtio_free_chain(ve); 868 mac_rx(sc->sc_mac_handle, NULL, mp); 869 i++; 870 } 871 872 return (i); 873 } 874 875 static void 876 vioif_reclaim_used_tx(struct vioif_softc *sc) 877 { 878 struct vq_entry *ve; 879 struct vioif_tx_buf *buf; 880 uint32_t len; 881 mblk_t *mp; 882 int i = 0; 883 884 while ((ve = virtio_pull_chain(sc->sc_tx_vq, &len))) { 885 /* We don't chain descriptors for tx, so don't expect any. */ 886 ASSERT(!ve->qe_next); 887 888 buf = &sc->sc_txbufs[ve->qe_index]; 889 mp = buf->tb_mp; 890 buf->tb_mp = NULL; 891 892 if (mp) { 893 for (i = 0; i < buf->tb_external_num; i++) 894 (void) ddi_dma_unbind_handle( 895 buf->tb_external_mapping[i].vbm_dmah); 896 } 897 898 virtio_free_chain(ve); 899 900 /* External mapping used, mp was not freed in vioif_send() */ 901 if (mp) 902 freemsg(mp); 903 i++; 904 } 905 906 if (sc->sc_tx_stopped && i) { 907 sc->sc_tx_stopped = 0; 908 mac_tx_update(sc->sc_mac_handle); 909 } 910 } 911 912 /* sc will be used to update stat counters. */ 913 /* ARGSUSED */ 914 static inline void 915 vioif_tx_inline(struct vioif_softc *sc, struct vq_entry *ve, mblk_t *mp, 916 size_t msg_size) 917 { 918 struct vioif_tx_buf *buf; 919 buf = &sc->sc_txbufs[ve->qe_index]; 920 921 ASSERT(buf); 922 923 /* Frees mp */ 924 mcopymsg(mp, buf->tb_inline_mapping.vbm_buf + 925 sizeof (struct virtio_net_hdr)); 926 927 virtio_ve_add_indirect_buf(ve, 928 buf->tb_inline_mapping.vbm_dmac.dmac_laddress + 929 sizeof (struct virtio_net_hdr), msg_size, B_TRUE); 930 } 931 932 static inline int 933 vioif_tx_lazy_handle_alloc(struct vioif_softc *sc, struct vioif_tx_buf *buf, 934 int i) 935 { 936 int ret = DDI_SUCCESS; 937 938 if (!buf->tb_external_mapping[i].vbm_dmah) { 939 ret = ddi_dma_alloc_handle(sc->sc_dev, 940 &vioif_mapped_buf_dma_attr, DDI_DMA_SLEEP, NULL, 941 &buf->tb_external_mapping[i].vbm_dmah); 942 if (ret != DDI_SUCCESS) { 943 dev_err(sc->sc_dev, CE_WARN, 944 "Can't allocate dma handle for external tx buffer"); 945 } 946 } 947 948 return (ret); 949 } 950 951 static inline int 952 vioif_tx_external(struct vioif_softc *sc, struct vq_entry *ve, mblk_t *mp, 953 size_t msg_size) 954 { 955 _NOTE(ARGUNUSED(msg_size)); 956 957 struct vioif_tx_buf *buf; 958 mblk_t *nmp; 959 int i, j; 960 int ret = DDI_SUCCESS; 961 962 buf = &sc->sc_txbufs[ve->qe_index]; 963 964 ASSERT(buf); 965 966 buf->tb_external_num = 0; 967 i = 0; 968 nmp = mp; 969 970 while (nmp) { 971 size_t len; 972 ddi_dma_cookie_t dmac; 973 unsigned int ncookies; 974 975 len = MBLKL(nmp); 976 /* 977 * For some reason, the network stack can 978 * actually send us zero-length fragments. 979 */ 980 if (len == 0) { 981 nmp = nmp->b_cont; 982 continue; 983 } 984 985 ret = vioif_tx_lazy_handle_alloc(sc, buf, i); 986 if (ret != DDI_SUCCESS) { 987 sc->sc_notxbuf ++; 988 sc->sc_oerrors ++; 989 goto exit_lazy_alloc; 990 } 991 ret = ddi_dma_addr_bind_handle( 992 buf->tb_external_mapping[i].vbm_dmah, NULL, 993 (caddr_t)nmp->b_rptr, len, 994 DDI_DMA_WRITE | DDI_DMA_STREAMING, 995 DDI_DMA_SLEEP, NULL, &dmac, &ncookies); 996 997 if (ret != DDI_SUCCESS) { 998 sc->sc_oerrors ++; 999 dev_err(sc->sc_dev, CE_NOTE, 1000 "TX: Failed to bind external handle"); 1001 goto exit_bind; 1002 } 1003 1004 /* Check if we still fit into the indirect table. */ 1005 if (virtio_ve_indirect_available(ve) < ncookies) { 1006 dev_err(sc->sc_dev, CE_NOTE, 1007 "TX: Indirect descriptor table limit reached." 1008 " It took %d fragments.", i); 1009 sc->sc_notxbuf ++; 1010 sc->sc_oerrors ++; 1011 1012 ret = DDI_FAILURE; 1013 goto exit_limit; 1014 } 1015 1016 virtio_ve_add_cookie(ve, buf->tb_external_mapping[i].vbm_dmah, 1017 dmac, ncookies, B_TRUE); 1018 1019 nmp = nmp->b_cont; 1020 i++; 1021 } 1022 1023 buf->tb_external_num = i; 1024 /* Save the mp to free it when the packet is sent. */ 1025 buf->tb_mp = mp; 1026 1027 return (DDI_SUCCESS); 1028 1029 exit_limit: 1030 exit_bind: 1031 exit_lazy_alloc: 1032 1033 for (j = 0; j < i; j++) { 1034 (void) ddi_dma_unbind_handle( 1035 buf->tb_external_mapping[j].vbm_dmah); 1036 } 1037 1038 return (ret); 1039 } 1040 1041 static boolean_t 1042 vioif_send(struct vioif_softc *sc, mblk_t *mp) 1043 { 1044 struct vq_entry *ve; 1045 struct vioif_tx_buf *buf; 1046 struct virtio_net_hdr *net_header = NULL; 1047 size_t msg_size = 0; 1048 uint32_t csum_start; 1049 uint32_t csum_stuff; 1050 uint32_t csum_flags; 1051 uint32_t lso_flags; 1052 uint32_t lso_mss; 1053 mblk_t *nmp; 1054 int ret; 1055 boolean_t lso_required = B_FALSE; 1056 1057 for (nmp = mp; nmp; nmp = nmp->b_cont) 1058 msg_size += MBLKL(nmp); 1059 1060 if (sc->sc_tx_tso4) { 1061 mac_lso_get(mp, &lso_mss, &lso_flags); 1062 lso_required = (lso_flags & HW_LSO); 1063 } 1064 if (!lso_required && msg_size > sc->sc_mtu) { 1065 dev_err(sc->sc_dev, CE_WARN, "Message too big"); 1066 freemsg(mp); 1067 1068 sc->sc_toolongerr ++; 1069 sc->sc_oerrors ++; 1070 return (B_FALSE); 1071 } 1072 ve = vq_alloc_entry(sc->sc_tx_vq); 1073 1074 if (!ve) { 1075 sc->sc_notxbuf ++; 1076 /* Out of free descriptors - try later. */ 1077 return (B_FALSE); 1078 } 1079 buf = &sc->sc_txbufs[ve->qe_index]; 1080 1081 /* Use the inline buffer of the first entry for the virtio_net_hdr. */ 1082 (void) memset(buf->tb_inline_mapping.vbm_buf, 0, 1083 sizeof (struct virtio_net_hdr)); 1084 1085 /* LINTED E_BAD_PTR_CAST_ALIGN */ 1086 net_header = (struct virtio_net_hdr *) 1087 buf->tb_inline_mapping.vbm_buf; 1088 1089 mac_hcksum_get(mp, &csum_start, &csum_stuff, NULL, 1090 NULL, &csum_flags); 1091 1092 /* They want us to do the TCP/UDP csum calculation. */ 1093 if (csum_flags & HCK_PARTIALCKSUM) { 1094 struct ether_header *eth_header; 1095 int eth_hsize; 1096 1097 /* Did we ask for it? */ 1098 ASSERT(sc->sc_tx_csum); 1099 1100 /* We only asked for partial csum packets. */ 1101 ASSERT(!(csum_flags & HCK_IPV4_HDRCKSUM)); 1102 ASSERT(!(csum_flags & HCK_FULLCKSUM)); 1103 1104 eth_header = (void *) mp->b_rptr; 1105 if (eth_header->ether_type == htons(ETHERTYPE_VLAN)) { 1106 eth_hsize = sizeof (struct ether_vlan_header); 1107 } else { 1108 eth_hsize = sizeof (struct ether_header); 1109 } 1110 net_header->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; 1111 net_header->csum_start = eth_hsize + csum_start; 1112 net_header->csum_offset = csum_stuff - csum_start; 1113 } 1114 1115 /* setup LSO fields if required */ 1116 if (lso_required) { 1117 net_header->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; 1118 net_header->gso_size = (uint16_t)lso_mss; 1119 } 1120 1121 virtio_ve_add_indirect_buf(ve, 1122 buf->tb_inline_mapping.vbm_dmac.dmac_laddress, 1123 sizeof (struct virtio_net_hdr), B_TRUE); 1124 1125 /* 1126 * We copy small packets into the inline buffer. The bigger ones 1127 * get mapped using the mapped buffer. 1128 */ 1129 if (msg_size < sc->sc_txcopy_thresh) { 1130 vioif_tx_inline(sc, ve, mp, msg_size); 1131 } else { 1132 /* statistic gets updated by vioif_tx_external when fail */ 1133 ret = vioif_tx_external(sc, ve, mp, msg_size); 1134 if (ret != DDI_SUCCESS) 1135 goto exit_tx_external; 1136 } 1137 1138 virtio_push_chain(ve, B_TRUE); 1139 /* meanwhile update the statistic */ 1140 if (mp->b_rptr[0] & 0x1) { 1141 if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0) 1142 sc->sc_multixmt ++; 1143 else 1144 sc->sc_brdcstxmt ++; 1145 } 1146 sc->sc_opackets ++; 1147 sc->sc_obytes += msg_size; 1148 1149 return (B_TRUE); 1150 1151 exit_tx_external: 1152 1153 vq_free_entry(sc->sc_tx_vq, ve); 1154 /* 1155 * vioif_tx_external can fail when the buffer does not fit into the 1156 * indirect descriptor table. Free the mp. I don't expect this ever 1157 * to happen. 1158 */ 1159 freemsg(mp); 1160 1161 return (B_TRUE); 1162 } 1163 1164 mblk_t * 1165 vioif_tx(void *arg, mblk_t *mp) 1166 { 1167 struct vioif_softc *sc = arg; 1168 mblk_t *nmp; 1169 1170 while (mp != NULL) { 1171 nmp = mp->b_next; 1172 mp->b_next = NULL; 1173 1174 if (!vioif_send(sc, mp)) { 1175 sc->sc_tx_stopped = 1; 1176 mp->b_next = nmp; 1177 break; 1178 } 1179 mp = nmp; 1180 } 1181 1182 return (mp); 1183 } 1184 1185 int 1186 vioif_start(void *arg) 1187 { 1188 struct vioif_softc *sc = arg; 1189 1190 mac_link_update(sc->sc_mac_handle, 1191 vioif_link_state(sc)); 1192 1193 virtio_start_vq_intr(sc->sc_rx_vq); 1194 1195 return (DDI_SUCCESS); 1196 } 1197 1198 void 1199 vioif_stop(void *arg) 1200 { 1201 struct vioif_softc *sc = arg; 1202 1203 virtio_stop_vq_intr(sc->sc_rx_vq); 1204 } 1205 1206 /* ARGSUSED */ 1207 static int 1208 vioif_stat(void *arg, uint_t stat, uint64_t *val) 1209 { 1210 struct vioif_softc *sc = arg; 1211 1212 switch (stat) { 1213 case MAC_STAT_IERRORS: 1214 *val = sc->sc_ierrors; 1215 break; 1216 case MAC_STAT_OERRORS: 1217 *val = sc->sc_oerrors; 1218 break; 1219 case MAC_STAT_MULTIRCV: 1220 *val = sc->sc_multircv; 1221 break; 1222 case MAC_STAT_BRDCSTRCV: 1223 *val = sc->sc_brdcstrcv; 1224 break; 1225 case MAC_STAT_MULTIXMT: 1226 *val = sc->sc_multixmt; 1227 break; 1228 case MAC_STAT_BRDCSTXMT: 1229 *val = sc->sc_brdcstxmt; 1230 break; 1231 case MAC_STAT_IPACKETS: 1232 *val = sc->sc_ipackets; 1233 break; 1234 case MAC_STAT_RBYTES: 1235 *val = sc->sc_rbytes; 1236 break; 1237 case MAC_STAT_OPACKETS: 1238 *val = sc->sc_opackets; 1239 break; 1240 case MAC_STAT_OBYTES: 1241 *val = sc->sc_obytes; 1242 break; 1243 case MAC_STAT_NORCVBUF: 1244 *val = sc->sc_norecvbuf; 1245 break; 1246 case MAC_STAT_NOXMTBUF: 1247 *val = sc->sc_notxbuf; 1248 break; 1249 case MAC_STAT_IFSPEED: 1250 /* always 1 Gbit */ 1251 *val = 1000000000ULL; 1252 break; 1253 case ETHER_STAT_LINK_DUPLEX: 1254 /* virtual device, always full-duplex */ 1255 *val = LINK_DUPLEX_FULL; 1256 break; 1257 1258 default: 1259 return (ENOTSUP); 1260 } 1261 1262 return (DDI_SUCCESS); 1263 } 1264 1265 static int 1266 vioif_set_prop_private(struct vioif_softc *sc, const char *pr_name, 1267 uint_t pr_valsize, const void *pr_val) 1268 { 1269 _NOTE(ARGUNUSED(pr_valsize)); 1270 1271 long result; 1272 1273 if (strcmp(pr_name, vioif_txcopy_thresh) == 0) { 1274 1275 if (pr_val == NULL) 1276 return (EINVAL); 1277 1278 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1279 1280 if (result < 0 || result > VIOIF_TX_THRESH_MAX) 1281 return (EINVAL); 1282 sc->sc_txcopy_thresh = result; 1283 } 1284 if (strcmp(pr_name, vioif_rxcopy_thresh) == 0) { 1285 1286 if (pr_val == NULL) 1287 return (EINVAL); 1288 1289 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1290 1291 if (result < 0 || result > VIOIF_RX_THRESH_MAX) 1292 return (EINVAL); 1293 sc->sc_rxcopy_thresh = result; 1294 } 1295 return (0); 1296 } 1297 1298 static int 1299 vioif_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 1300 uint_t pr_valsize, const void *pr_val) 1301 { 1302 struct vioif_softc *sc = arg; 1303 const uint32_t *new_mtu; 1304 int err; 1305 1306 switch (pr_num) { 1307 case MAC_PROP_MTU: 1308 new_mtu = pr_val; 1309 1310 if (*new_mtu > MAX_MTU) { 1311 dev_err(sc->sc_dev, CE_WARN, 1312 "Requested mtu (%d) out of range", 1313 *new_mtu); 1314 return (EINVAL); 1315 } 1316 1317 err = mac_maxsdu_update(sc->sc_mac_handle, *new_mtu); 1318 if (err) { 1319 dev_err(sc->sc_dev, CE_WARN, 1320 "Failed to set the requested mtu (%d)", 1321 *new_mtu); 1322 return (err); 1323 } 1324 break; 1325 case MAC_PROP_PRIVATE: 1326 err = vioif_set_prop_private(sc, pr_name, 1327 pr_valsize, pr_val); 1328 if (err) 1329 return (err); 1330 default: 1331 return (ENOTSUP); 1332 } 1333 1334 return (0); 1335 } 1336 1337 static int 1338 vioif_get_prop_private(struct vioif_softc *sc, const char *pr_name, 1339 uint_t pr_valsize, void *pr_val) 1340 { 1341 int err = ENOTSUP; 1342 int value; 1343 1344 if (strcmp(pr_name, vioif_txcopy_thresh) == 0) { 1345 1346 value = sc->sc_txcopy_thresh; 1347 err = 0; 1348 goto done; 1349 } 1350 if (strcmp(pr_name, vioif_rxcopy_thresh) == 0) { 1351 1352 value = sc->sc_rxcopy_thresh; 1353 err = 0; 1354 goto done; 1355 } 1356 done: 1357 if (err == 0) { 1358 (void) snprintf(pr_val, pr_valsize, "%d", value); 1359 } 1360 return (err); 1361 } 1362 1363 static int 1364 vioif_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 1365 uint_t pr_valsize, void *pr_val) 1366 { 1367 struct vioif_softc *sc = arg; 1368 int err = ENOTSUP; 1369 1370 switch (pr_num) { 1371 case MAC_PROP_PRIVATE: 1372 err = vioif_get_prop_private(sc, pr_name, 1373 pr_valsize, pr_val); 1374 break; 1375 default: 1376 break; 1377 } 1378 return (err); 1379 } 1380 1381 static void 1382 vioif_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num, 1383 mac_prop_info_handle_t prh) 1384 { 1385 struct vioif_softc *sc = arg; 1386 1387 switch (pr_num) { 1388 1389 case MAC_PROP_MTU: 1390 mac_prop_info_set_range_uint32(prh, ETHERMIN, MAX_MTU); 1391 break; 1392 1393 case MAC_PROP_PRIVATE: { 1394 char valstr[64]; 1395 int value; 1396 1397 bzero(valstr, sizeof (valstr)); 1398 if (strcmp(pr_name, vioif_txcopy_thresh) == 0) { 1399 1400 value = sc->sc_txcopy_thresh; 1401 } else if (strcmp(pr_name, 1402 vioif_rxcopy_thresh) == 0) { 1403 value = sc->sc_rxcopy_thresh; 1404 } else { 1405 return; 1406 } 1407 (void) snprintf(valstr, sizeof (valstr), "%d", value); 1408 } 1409 default: 1410 break; 1411 } 1412 } 1413 1414 static boolean_t 1415 vioif_getcapab(void *arg, mac_capab_t cap, void *cap_data) 1416 { 1417 struct vioif_softc *sc = arg; 1418 1419 switch (cap) { 1420 case MAC_CAPAB_HCKSUM: 1421 if (sc->sc_tx_csum) { 1422 uint32_t *txflags = cap_data; 1423 1424 *txflags = HCKSUM_INET_PARTIAL; 1425 return (B_TRUE); 1426 } 1427 return (B_FALSE); 1428 case MAC_CAPAB_LSO: 1429 if (sc->sc_tx_tso4) { 1430 mac_capab_lso_t *cap_lso = cap_data; 1431 1432 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 1433 cap_lso->lso_basic_tcp_ipv4.lso_max = MAX_MTU; 1434 return (B_TRUE); 1435 } 1436 return (B_FALSE); 1437 default: 1438 break; 1439 } 1440 return (B_FALSE); 1441 } 1442 1443 static mac_callbacks_t vioif_m_callbacks = { 1444 .mc_callbacks = MC_GETCAPAB, 1445 .mc_getstat = vioif_stat, 1446 .mc_start = vioif_start, 1447 .mc_stop = vioif_stop, 1448 .mc_setpromisc = vioif_promisc, 1449 .mc_multicst = vioif_multicst, 1450 .mc_unicst = vioif_unicst, 1451 .mc_tx = vioif_tx, 1452 /* Optional callbacks */ 1453 .mc_reserved = NULL, /* reserved */ 1454 .mc_ioctl = NULL, /* mc_ioctl */ 1455 .mc_getcapab = vioif_getcapab, /* mc_getcapab */ 1456 .mc_open = NULL, /* mc_open */ 1457 .mc_close = NULL, /* mc_close */ 1458 .mc_setprop = vioif_setprop, 1459 .mc_getprop = vioif_getprop, 1460 .mc_propinfo = vioif_propinfo, 1461 }; 1462 1463 static void 1464 vioif_show_features(struct vioif_softc *sc, const char *prefix, 1465 uint32_t features) 1466 { 1467 char buf[512]; 1468 char *bufp = buf; 1469 char *bufend = buf + sizeof (buf); 1470 1471 /* LINTED E_PTRDIFF_OVERFLOW */ 1472 bufp += snprintf(bufp, bufend - bufp, prefix); 1473 1474 /* LINTED E_PTRDIFF_OVERFLOW */ 1475 bufp += virtio_show_features(features, bufp, bufend - bufp); 1476 1477 /* LINTED E_PTRDIFF_OVERFLOW */ 1478 bufp += snprintf(bufp, bufend - bufp, "Vioif ( "); 1479 1480 if (features & VIRTIO_NET_F_CSUM) 1481 /* LINTED E_PTRDIFF_OVERFLOW */ 1482 bufp += snprintf(bufp, bufend - bufp, "CSUM "); 1483 if (features & VIRTIO_NET_F_GUEST_CSUM) 1484 /* LINTED E_PTRDIFF_OVERFLOW */ 1485 bufp += snprintf(bufp, bufend - bufp, "GUEST_CSUM "); 1486 if (features & VIRTIO_NET_F_MAC) 1487 /* LINTED E_PTRDIFF_OVERFLOW */ 1488 bufp += snprintf(bufp, bufend - bufp, "MAC "); 1489 if (features & VIRTIO_NET_F_GSO) 1490 /* LINTED E_PTRDIFF_OVERFLOW */ 1491 bufp += snprintf(bufp, bufend - bufp, "GSO "); 1492 if (features & VIRTIO_NET_F_GUEST_TSO4) 1493 /* LINTED E_PTRDIFF_OVERFLOW */ 1494 bufp += snprintf(bufp, bufend - bufp, "GUEST_TSO4 "); 1495 if (features & VIRTIO_NET_F_GUEST_TSO6) 1496 /* LINTED E_PTRDIFF_OVERFLOW */ 1497 bufp += snprintf(bufp, bufend - bufp, "GUEST_TSO6 "); 1498 if (features & VIRTIO_NET_F_GUEST_ECN) 1499 /* LINTED E_PTRDIFF_OVERFLOW */ 1500 bufp += snprintf(bufp, bufend - bufp, "GUEST_ECN "); 1501 if (features & VIRTIO_NET_F_GUEST_UFO) 1502 /* LINTED E_PTRDIFF_OVERFLOW */ 1503 bufp += snprintf(bufp, bufend - bufp, "GUEST_UFO "); 1504 if (features & VIRTIO_NET_F_HOST_TSO4) 1505 /* LINTED E_PTRDIFF_OVERFLOW */ 1506 bufp += snprintf(bufp, bufend - bufp, "HOST_TSO4 "); 1507 if (features & VIRTIO_NET_F_HOST_TSO6) 1508 /* LINTED E_PTRDIFF_OVERFLOW */ 1509 bufp += snprintf(bufp, bufend - bufp, "HOST_TSO6 "); 1510 if (features & VIRTIO_NET_F_HOST_ECN) 1511 /* LINTED E_PTRDIFF_OVERFLOW */ 1512 bufp += snprintf(bufp, bufend - bufp, "HOST_ECN "); 1513 if (features & VIRTIO_NET_F_HOST_UFO) 1514 /* LINTED E_PTRDIFF_OVERFLOW */ 1515 bufp += snprintf(bufp, bufend - bufp, "HOST_UFO "); 1516 if (features & VIRTIO_NET_F_MRG_RXBUF) 1517 /* LINTED E_PTRDIFF_OVERFLOW */ 1518 bufp += snprintf(bufp, bufend - bufp, "MRG_RXBUF "); 1519 if (features & VIRTIO_NET_F_STATUS) 1520 /* LINTED E_PTRDIFF_OVERFLOW */ 1521 bufp += snprintf(bufp, bufend - bufp, "STATUS "); 1522 if (features & VIRTIO_NET_F_CTRL_VQ) 1523 /* LINTED E_PTRDIFF_OVERFLOW */ 1524 bufp += snprintf(bufp, bufend - bufp, "CTRL_VQ "); 1525 if (features & VIRTIO_NET_F_CTRL_RX) 1526 /* LINTED E_PTRDIFF_OVERFLOW */ 1527 bufp += snprintf(bufp, bufend - bufp, "CTRL_RX "); 1528 if (features & VIRTIO_NET_F_CTRL_VLAN) 1529 /* LINTED E_PTRDIFF_OVERFLOW */ 1530 bufp += snprintf(bufp, bufend - bufp, "CTRL_VLAN "); 1531 if (features & VIRTIO_NET_F_CTRL_RX_EXTRA) 1532 /* LINTED E_PTRDIFF_OVERFLOW */ 1533 bufp += snprintf(bufp, bufend - bufp, "CTRL_RX_EXTRA "); 1534 1535 /* LINTED E_PTRDIFF_OVERFLOW */ 1536 bufp += snprintf(bufp, bufend - bufp, ")"); 1537 *bufp = '\0'; 1538 1539 dev_err(sc->sc_dev, CE_NOTE, "%s", buf); 1540 } 1541 1542 /* 1543 * Find out which features are supported by the device and 1544 * choose which ones we wish to use. 1545 */ 1546 static int 1547 vioif_dev_features(struct vioif_softc *sc) 1548 { 1549 uint32_t host_features; 1550 1551 host_features = virtio_negotiate_features(&sc->sc_virtio, 1552 VIRTIO_NET_F_CSUM | 1553 VIRTIO_NET_F_HOST_TSO4 | 1554 VIRTIO_NET_F_HOST_ECN | 1555 VIRTIO_NET_F_MAC | 1556 VIRTIO_NET_F_STATUS | 1557 VIRTIO_F_RING_INDIRECT_DESC | 1558 VIRTIO_F_NOTIFY_ON_EMPTY); 1559 1560 vioif_show_features(sc, "Host features: ", host_features); 1561 vioif_show_features(sc, "Negotiated features: ", 1562 sc->sc_virtio.sc_features); 1563 1564 if (!(sc->sc_virtio.sc_features & VIRTIO_F_RING_INDIRECT_DESC)) { 1565 dev_err(sc->sc_dev, CE_NOTE, 1566 "Host does not support RING_INDIRECT_DESC, bye."); 1567 return (DDI_FAILURE); 1568 } 1569 1570 return (DDI_SUCCESS); 1571 } 1572 1573 static int 1574 vioif_has_feature(struct vioif_softc *sc, uint32_t feature) 1575 { 1576 return (virtio_has_feature(&sc->sc_virtio, feature)); 1577 } 1578 1579 static void 1580 vioif_set_mac(struct vioif_softc *sc) 1581 { 1582 int i; 1583 1584 for (i = 0; i < ETHERADDRL; i++) { 1585 virtio_write_device_config_1(&sc->sc_virtio, 1586 VIRTIO_NET_CONFIG_MAC + i, sc->sc_mac[i]); 1587 } 1588 } 1589 1590 /* Get the mac address out of the hardware, or make up one. */ 1591 static void 1592 vioif_get_mac(struct vioif_softc *sc) 1593 { 1594 int i; 1595 if (sc->sc_virtio.sc_features & VIRTIO_NET_F_MAC) { 1596 for (i = 0; i < ETHERADDRL; i++) { 1597 sc->sc_mac[i] = virtio_read_device_config_1( 1598 &sc->sc_virtio, 1599 VIRTIO_NET_CONFIG_MAC + i); 1600 } 1601 dev_err(sc->sc_dev, CE_NOTE, "Got MAC address from host: %s", 1602 ether_sprintf((struct ether_addr *)sc->sc_mac)); 1603 } else { 1604 /* Get a few random bytes */ 1605 (void) random_get_pseudo_bytes(sc->sc_mac, ETHERADDRL); 1606 /* Make sure it's a unicast MAC */ 1607 sc->sc_mac[0] &= ~1; 1608 /* Set the "locally administered" bit */ 1609 sc->sc_mac[1] |= 2; 1610 1611 vioif_set_mac(sc); 1612 1613 dev_err(sc->sc_dev, CE_NOTE, 1614 "Generated a random MAC address: %s", 1615 ether_sprintf((struct ether_addr *)sc->sc_mac)); 1616 } 1617 } 1618 1619 /* 1620 * Virtqueue interrupt handlers 1621 */ 1622 /* ARGSUSED */ 1623 uint_t 1624 vioif_rx_handler(caddr_t arg1, caddr_t arg2) 1625 { 1626 struct virtio_softc *vsc = (void *) arg1; 1627 struct vioif_softc *sc = container_of(vsc, 1628 struct vioif_softc, sc_virtio); 1629 1630 (void) vioif_process_rx(sc); 1631 1632 (void) vioif_populate_rx(sc, KM_NOSLEEP); 1633 1634 return (DDI_INTR_CLAIMED); 1635 } 1636 1637 /* ARGSUSED */ 1638 uint_t 1639 vioif_tx_handler(caddr_t arg1, caddr_t arg2) 1640 { 1641 struct virtio_softc *vsc = (void *)arg1; 1642 struct vioif_softc *sc = container_of(vsc, 1643 struct vioif_softc, sc_virtio); 1644 1645 vioif_reclaim_used_tx(sc); 1646 return (DDI_INTR_CLAIMED); 1647 } 1648 1649 static int 1650 vioif_register_ints(struct vioif_softc *sc) 1651 { 1652 int ret; 1653 1654 struct virtio_int_handler vioif_vq_h[] = { 1655 { vioif_rx_handler }, 1656 { vioif_tx_handler }, 1657 { NULL } 1658 }; 1659 1660 ret = virtio_register_ints(&sc->sc_virtio, NULL, vioif_vq_h); 1661 1662 return (ret); 1663 } 1664 1665 1666 static void 1667 vioif_check_features(struct vioif_softc *sc) 1668 { 1669 if (vioif_has_feature(sc, VIRTIO_NET_F_CSUM)) { 1670 /* The GSO/GRO featured depend on CSUM, check them here. */ 1671 sc->sc_tx_csum = 1; 1672 sc->sc_rx_csum = 1; 1673 1674 if (!vioif_has_feature(sc, VIRTIO_NET_F_GUEST_CSUM)) { 1675 sc->sc_rx_csum = 0; 1676 } 1677 cmn_err(CE_NOTE, "Csum enabled."); 1678 1679 if (vioif_has_feature(sc, VIRTIO_NET_F_HOST_TSO4)) { 1680 1681 sc->sc_tx_tso4 = 1; 1682 /* 1683 * We don't seem to have a way to ask the system 1684 * not to send us LSO packets with Explicit 1685 * Congestion Notification bit set, so we require 1686 * the device to support it in order to do 1687 * LSO. 1688 */ 1689 if (!vioif_has_feature(sc, VIRTIO_NET_F_HOST_ECN)) { 1690 dev_err(sc->sc_dev, CE_NOTE, 1691 "TSO4 supported, but not ECN. " 1692 "Not using LSO."); 1693 sc->sc_tx_tso4 = 0; 1694 } else { 1695 cmn_err(CE_NOTE, "LSO enabled"); 1696 } 1697 } 1698 } 1699 } 1700 1701 static int 1702 vioif_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 1703 { 1704 int ret, instance; 1705 struct vioif_softc *sc; 1706 struct virtio_softc *vsc; 1707 mac_register_t *macp; 1708 1709 instance = ddi_get_instance(devinfo); 1710 1711 switch (cmd) { 1712 case DDI_ATTACH: 1713 break; 1714 1715 case DDI_RESUME: 1716 case DDI_PM_RESUME: 1717 dev_err(devinfo, CE_WARN, "resume not supported yet"); 1718 goto exit; 1719 1720 default: 1721 dev_err(devinfo, CE_WARN, "cmd 0x%x unrecognized", cmd); 1722 goto exit; 1723 } 1724 1725 sc = kmem_zalloc(sizeof (struct vioif_softc), KM_SLEEP); 1726 ddi_set_driver_private(devinfo, sc); 1727 1728 vsc = &sc->sc_virtio; 1729 1730 /* Duplicate for less typing */ 1731 sc->sc_dev = devinfo; 1732 vsc->sc_dev = devinfo; 1733 1734 /* 1735 * Initialize interrupt kstat. 1736 */ 1737 sc->sc_intrstat = kstat_create("vioif", instance, "intr", "controller", 1738 KSTAT_TYPE_INTR, 1, 0); 1739 if (sc->sc_intrstat == NULL) { 1740 dev_err(devinfo, CE_WARN, "kstat_create failed"); 1741 goto exit_intrstat; 1742 } 1743 kstat_install(sc->sc_intrstat); 1744 1745 /* map BAR 0 */ 1746 ret = ddi_regs_map_setup(devinfo, 1, 1747 (caddr_t *)&sc->sc_virtio.sc_io_addr, 1748 0, 0, &vioif_attr, &sc->sc_virtio.sc_ioh); 1749 if (ret != DDI_SUCCESS) { 1750 dev_err(devinfo, CE_WARN, "unable to map bar 0: %d", ret); 1751 goto exit_map; 1752 } 1753 1754 virtio_device_reset(&sc->sc_virtio); 1755 virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_ACK); 1756 virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER); 1757 1758 ret = vioif_dev_features(sc); 1759 if (ret) 1760 goto exit_features; 1761 1762 vsc->sc_nvqs = vioif_has_feature(sc, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2; 1763 1764 sc->sc_rxbuf_cache = kmem_cache_create("vioif_rx", 1765 sizeof (struct vioif_rx_buf), 0, vioif_rx_construct, 1766 vioif_rx_destruct, NULL, sc, NULL, KM_SLEEP); 1767 if (sc->sc_rxbuf_cache == NULL) { 1768 cmn_err(CE_NOTE, "Can't allocate the buffer cache"); 1769 goto exit_cache; 1770 } 1771 1772 ret = vioif_register_ints(sc); 1773 if (ret) { 1774 dev_err(sc->sc_dev, CE_WARN, 1775 "Failed to allocate interrupt(s)!"); 1776 goto exit_ints; 1777 } 1778 1779 /* 1780 * Register layout determined, can now access the 1781 * device-speciffic bits 1782 */ 1783 vioif_get_mac(sc); 1784 1785 sc->sc_rx_vq = virtio_alloc_vq(&sc->sc_virtio, 0, 1786 VIOIF_RX_QLEN, VIOIF_INDIRECT_MAX, "rx"); 1787 if (!sc->sc_rx_vq) 1788 goto exit_alloc1; 1789 virtio_stop_vq_intr(sc->sc_rx_vq); 1790 1791 sc->sc_tx_vq = virtio_alloc_vq(&sc->sc_virtio, 1, 1792 VIOIF_TX_QLEN, VIOIF_INDIRECT_MAX, "tx"); 1793 if (!sc->sc_rx_vq) 1794 goto exit_alloc2; 1795 virtio_stop_vq_intr(sc->sc_tx_vq); 1796 1797 if (vioif_has_feature(sc, VIRTIO_NET_F_CTRL_VQ)) { 1798 sc->sc_ctrl_vq = virtio_alloc_vq(&sc->sc_virtio, 2, 1799 VIOIF_CTRL_QLEN, 0, "ctrl"); 1800 if (!sc->sc_ctrl_vq) { 1801 goto exit_alloc3; 1802 } 1803 virtio_stop_vq_intr(sc->sc_ctrl_vq); 1804 } 1805 1806 virtio_set_status(&sc->sc_virtio, 1807 VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK); 1808 1809 sc->sc_rxloan = 0; 1810 1811 /* set some reasonable-small default values */ 1812 sc->sc_rxcopy_thresh = 300; 1813 sc->sc_txcopy_thresh = 300; 1814 sc->sc_mtu = ETHERMTU; 1815 1816 vioif_check_features(sc); 1817 1818 if (vioif_alloc_mems(sc)) 1819 goto exit_alloc_mems; 1820 1821 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 1822 dev_err(devinfo, CE_WARN, "Failed to alocate a mac_register"); 1823 goto exit_macalloc; 1824 } 1825 1826 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1827 macp->m_driver = sc; 1828 macp->m_dip = devinfo; 1829 macp->m_src_addr = sc->sc_mac; 1830 macp->m_callbacks = &vioif_m_callbacks; 1831 macp->m_min_sdu = 0; 1832 macp->m_max_sdu = sc->sc_mtu; 1833 macp->m_margin = VLAN_TAGSZ; 1834 macp->m_priv_props = vioif_priv_props; 1835 1836 sc->sc_macp = macp; 1837 1838 /* Pre-fill the rx ring. */ 1839 (void) vioif_populate_rx(sc, KM_SLEEP); 1840 1841 ret = mac_register(macp, &sc->sc_mac_handle); 1842 if (ret != 0) { 1843 dev_err(devinfo, CE_WARN, "vioif_attach: " 1844 "mac_register() failed, ret=%d", ret); 1845 goto exit_register; 1846 } 1847 1848 ret = virtio_enable_ints(&sc->sc_virtio); 1849 if (ret) { 1850 dev_err(devinfo, CE_WARN, "Failed to enable interrupts"); 1851 goto exit_enable_ints; 1852 } 1853 1854 mac_link_update(sc->sc_mac_handle, LINK_STATE_UP); 1855 return (DDI_SUCCESS); 1856 1857 exit_enable_ints: 1858 (void) mac_unregister(sc->sc_mac_handle); 1859 exit_register: 1860 mac_free(macp); 1861 exit_macalloc: 1862 vioif_free_mems(sc); 1863 exit_alloc_mems: 1864 virtio_release_ints(&sc->sc_virtio); 1865 if (sc->sc_ctrl_vq) 1866 virtio_free_vq(sc->sc_ctrl_vq); 1867 exit_alloc3: 1868 virtio_free_vq(sc->sc_tx_vq); 1869 exit_alloc2: 1870 virtio_free_vq(sc->sc_rx_vq); 1871 exit_alloc1: 1872 exit_ints: 1873 kmem_cache_destroy(sc->sc_rxbuf_cache); 1874 exit_cache: 1875 exit_features: 1876 virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); 1877 ddi_regs_map_free(&sc->sc_virtio.sc_ioh); 1878 exit_intrstat: 1879 exit_map: 1880 kstat_delete(sc->sc_intrstat); 1881 kmem_free(sc, sizeof (struct vioif_softc)); 1882 exit: 1883 return (DDI_FAILURE); 1884 } 1885 1886 static int 1887 vioif_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 1888 { 1889 struct vioif_softc *sc; 1890 1891 if ((sc = ddi_get_driver_private(devinfo)) == NULL) 1892 return (DDI_FAILURE); 1893 1894 switch (cmd) { 1895 case DDI_DETACH: 1896 break; 1897 1898 case DDI_PM_SUSPEND: 1899 cmn_err(CE_WARN, "suspend not supported yet"); 1900 return (DDI_FAILURE); 1901 1902 default: 1903 cmn_err(CE_WARN, "cmd 0x%x unrecognized", cmd); 1904 return (DDI_FAILURE); 1905 } 1906 1907 if (sc->sc_rxloan) { 1908 cmn_err(CE_NOTE, "Some rx buffers are still upstream, " 1909 "Not detaching"); 1910 return (DDI_FAILURE); 1911 } 1912 1913 virtio_stop_vq_intr(sc->sc_rx_vq); 1914 virtio_stop_vq_intr(sc->sc_tx_vq); 1915 1916 virtio_release_ints(&sc->sc_virtio); 1917 1918 if (mac_unregister(sc->sc_mac_handle)) { 1919 return (DDI_FAILURE); 1920 } 1921 1922 mac_free(sc->sc_macp); 1923 1924 vioif_free_mems(sc); 1925 virtio_free_vq(sc->sc_rx_vq); 1926 virtio_free_vq(sc->sc_tx_vq); 1927 1928 virtio_device_reset(&sc->sc_virtio); 1929 1930 ddi_regs_map_free(&sc->sc_virtio.sc_ioh); 1931 1932 kmem_cache_destroy(sc->sc_rxbuf_cache); 1933 kstat_delete(sc->sc_intrstat); 1934 kmem_free(sc, sizeof (struct vioif_softc)); 1935 1936 return (DDI_SUCCESS); 1937 } 1938 1939 static int 1940 vioif_quiesce(dev_info_t *devinfo) 1941 { 1942 struct vioif_softc *sc; 1943 1944 if ((sc = ddi_get_driver_private(devinfo)) == NULL) 1945 return (DDI_FAILURE); 1946 1947 virtio_stop_vq_intr(sc->sc_rx_vq); 1948 virtio_stop_vq_intr(sc->sc_tx_vq); 1949 virtio_device_reset(&sc->sc_virtio); 1950 1951 return (DDI_SUCCESS); 1952 } 1953 1954 int 1955 _init(void) 1956 { 1957 int ret = 0; 1958 1959 mac_init_ops(&vioif_ops, "vioif"); 1960 1961 ret = mod_install(&modlinkage); 1962 if (ret != DDI_SUCCESS) { 1963 mac_fini_ops(&vioif_ops); 1964 cmn_err(CE_WARN, "Unable to install the driver"); 1965 return (ret); 1966 } 1967 1968 return (0); 1969 } 1970 1971 int 1972 _fini(void) 1973 { 1974 int ret; 1975 1976 ret = mod_remove(&modlinkage); 1977 if (ret == DDI_SUCCESS) { 1978 mac_fini_ops(&vioif_ops); 1979 } 1980 1981 return (ret); 1982 } 1983 1984 int 1985 _info(struct modinfo *pModinfo) 1986 { 1987 return (mod_info(&modlinkage, pModinfo)); 1988 }