if_vioif.c revision 1.8
1/* $NetBSD: if_vioif.c,v 1.8 2014/08/13 14:35:46 pooka 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: if_vioif.c,v 1.8 2014/08/13 14:35:46 pooka Exp $"); 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/kernel.h> 34#include <sys/bus.h> 35#include <sys/condvar.h> 36#include <sys/device.h> 37#include <sys/intr.h> 38#include <sys/kmem.h> 39#include <sys/mbuf.h> 40#include <sys/mutex.h> 41#include <sys/sockio.h> 42 43#include <dev/pci/pcidevs.h> 44#include <dev/pci/pcireg.h> 45#include <dev/pci/pcivar.h> 46#include <dev/pci/virtioreg.h> 47#include <dev/pci/virtiovar.h> 48 49#include <net/if.h> 50#include <net/if_media.h> 51#include <net/if_ether.h> 52 53#include <net/bpf.h> 54 55 56#ifdef NET_MPSAFE 57#define VIOIF_MPSAFE 1 58#endif 59 60/* 61 * if_vioifreg.h: 62 */ 63/* Configuration registers */ 64#define VIRTIO_NET_CONFIG_MAC 0 /* 8bit x 6byte */ 65#define VIRTIO_NET_CONFIG_STATUS 6 /* 16bit */ 66 67/* Feature bits */ 68#define VIRTIO_NET_F_CSUM (1<<0) 69#define VIRTIO_NET_F_GUEST_CSUM (1<<1) 70#define VIRTIO_NET_F_MAC (1<<5) 71#define VIRTIO_NET_F_GSO (1<<6) 72#define VIRTIO_NET_F_GUEST_TSO4 (1<<7) 73#define VIRTIO_NET_F_GUEST_TSO6 (1<<8) 74#define VIRTIO_NET_F_GUEST_ECN (1<<9) 75#define VIRTIO_NET_F_GUEST_UFO (1<<10) 76#define VIRTIO_NET_F_HOST_TSO4 (1<<11) 77#define VIRTIO_NET_F_HOST_TSO6 (1<<12) 78#define VIRTIO_NET_F_HOST_ECN (1<<13) 79#define VIRTIO_NET_F_HOST_UFO (1<<14) 80#define VIRTIO_NET_F_MRG_RXBUF (1<<15) 81#define VIRTIO_NET_F_STATUS (1<<16) 82#define VIRTIO_NET_F_CTRL_VQ (1<<17) 83#define VIRTIO_NET_F_CTRL_RX (1<<18) 84#define VIRTIO_NET_F_CTRL_VLAN (1<<19) 85 86/* Status */ 87#define VIRTIO_NET_S_LINK_UP 1 88 89/* Packet header structure */ 90struct virtio_net_hdr { 91 uint8_t flags; 92 uint8_t gso_type; 93 uint16_t hdr_len; 94 uint16_t gso_size; 95 uint16_t csum_start; 96 uint16_t csum_offset; 97#if 0 98 uint16_t num_buffers; /* if VIRTIO_NET_F_MRG_RXBUF enabled */ 99#endif 100} __packed; 101 102#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* flags */ 103#define VIRTIO_NET_HDR_GSO_NONE 0 /* gso_type */ 104#define VIRTIO_NET_HDR_GSO_TCPV4 1 /* gso_type */ 105#define VIRTIO_NET_HDR_GSO_UDP 3 /* gso_type */ 106#define VIRTIO_NET_HDR_GSO_TCPV6 4 /* gso_type */ 107#define VIRTIO_NET_HDR_GSO_ECN 0x80 /* gso_type, |'ed */ 108 109#define VIRTIO_NET_MAX_GSO_LEN (65536+ETHER_HDR_LEN) 110 111/* Control virtqueue */ 112struct virtio_net_ctrl_cmd { 113 uint8_t class; 114 uint8_t command; 115} __packed; 116#define VIRTIO_NET_CTRL_RX 0 117# define VIRTIO_NET_CTRL_RX_PROMISC 0 118# define VIRTIO_NET_CTRL_RX_ALLMULTI 1 119 120#define VIRTIO_NET_CTRL_MAC 1 121# define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 122 123#define VIRTIO_NET_CTRL_VLAN 2 124# define VIRTIO_NET_CTRL_VLAN_ADD 0 125# define VIRTIO_NET_CTRL_VLAN_DEL 1 126 127struct virtio_net_ctrl_status { 128 uint8_t ack; 129} __packed; 130#define VIRTIO_NET_OK 0 131#define VIRTIO_NET_ERR 1 132 133struct virtio_net_ctrl_rx { 134 uint8_t onoff; 135} __packed; 136 137struct virtio_net_ctrl_mac_tbl { 138 uint32_t nentries; 139 uint8_t macs[][ETHER_ADDR_LEN]; 140} __packed; 141 142struct virtio_net_ctrl_vlan { 143 uint16_t id; 144} __packed; 145 146 147/* 148 * if_vioifvar.h: 149 */ 150struct vioif_softc { 151 device_t sc_dev; 152 153 struct virtio_softc *sc_virtio; 154 struct virtqueue sc_vq[3]; 155 156 uint8_t sc_mac[ETHER_ADDR_LEN]; 157 struct ethercom sc_ethercom; 158 short sc_deferred_init_done; 159 160 /* bus_dmamem */ 161 bus_dma_segment_t sc_hdr_segs[1]; 162 struct virtio_net_hdr *sc_hdrs; 163#define sc_rx_hdrs sc_hdrs 164 struct virtio_net_hdr *sc_tx_hdrs; 165 struct virtio_net_ctrl_cmd *sc_ctrl_cmd; 166 struct virtio_net_ctrl_status *sc_ctrl_status; 167 struct virtio_net_ctrl_rx *sc_ctrl_rx; 168 struct virtio_net_ctrl_mac_tbl *sc_ctrl_mac_tbl_uc; 169 struct virtio_net_ctrl_mac_tbl *sc_ctrl_mac_tbl_mc; 170 171 /* kmem */ 172 bus_dmamap_t *sc_arrays; 173#define sc_rxhdr_dmamaps sc_arrays 174 bus_dmamap_t *sc_txhdr_dmamaps; 175 bus_dmamap_t *sc_rx_dmamaps; 176 bus_dmamap_t *sc_tx_dmamaps; 177 struct mbuf **sc_rx_mbufs; 178 struct mbuf **sc_tx_mbufs; 179 180 bus_dmamap_t sc_ctrl_cmd_dmamap; 181 bus_dmamap_t sc_ctrl_status_dmamap; 182 bus_dmamap_t sc_ctrl_rx_dmamap; 183 bus_dmamap_t sc_ctrl_tbl_uc_dmamap; 184 bus_dmamap_t sc_ctrl_tbl_mc_dmamap; 185 186 void *sc_rx_softint; 187 188 enum { 189 FREE, INUSE, DONE 190 } sc_ctrl_inuse; 191 kcondvar_t sc_ctrl_wait; 192 kmutex_t sc_ctrl_wait_lock; 193 kmutex_t *sc_tx_lock; 194 kmutex_t *sc_rx_lock; 195 bool sc_stopping; 196}; 197#define VIRTIO_NET_TX_MAXNSEGS (16) /* XXX */ 198#define VIRTIO_NET_CTRL_MAC_MAXENTRIES (64) /* XXX */ 199 200#define VIOIF_TX_LOCK(_sc) if ((_sc)->sc_tx_lock) mutex_enter((_sc)->sc_tx_lock) 201#define VIOIF_TX_UNLOCK(_sc) if ((_sc)->sc_tx_lock) mutex_exit((_sc)->sc_tx_lock) 202#define VIOIF_TX_LOCKED(_sc) (!(_sc)->sc_tx_lock || mutex_owned((_sc)->sc_tx_lock)) 203#define VIOIF_RX_LOCK(_sc) if ((_sc)->sc_rx_lock) mutex_enter((_sc)->sc_rx_lock) 204#define VIOIF_RX_UNLOCK(_sc) if ((_sc)->sc_rx_lock) mutex_exit((_sc)->sc_rx_lock) 205#define VIOIF_RX_LOCKED(_sc) (!(_sc)->sc_rx_lock || mutex_owned((_sc)->sc_rx_lock)) 206 207/* cfattach interface functions */ 208static int vioif_match(device_t, cfdata_t, void *); 209static void vioif_attach(device_t, device_t, void *); 210static void vioif_deferred_init(device_t); 211 212/* ifnet interface functions */ 213static int vioif_init(struct ifnet *); 214static void vioif_stop(struct ifnet *, int); 215static void vioif_start(struct ifnet *); 216static int vioif_ioctl(struct ifnet *, u_long, void *); 217static void vioif_watchdog(struct ifnet *); 218 219/* rx */ 220static int vioif_add_rx_mbuf(struct vioif_softc *, int); 221static void vioif_free_rx_mbuf(struct vioif_softc *, int); 222static void vioif_populate_rx_mbufs(struct vioif_softc *); 223static int vioif_rx_deq(struct vioif_softc *); 224static int vioif_rx_deq_locked(struct vioif_softc *); 225static int vioif_rx_vq_done(struct virtqueue *); 226static void vioif_rx_softint(void *); 227static void vioif_rx_drain(struct vioif_softc *); 228 229/* tx */ 230static int vioif_tx_vq_done(struct virtqueue *); 231static int vioif_tx_vq_done_locked(struct virtqueue *); 232static void vioif_tx_drain(struct vioif_softc *); 233 234/* other control */ 235static int vioif_updown(struct vioif_softc *, bool); 236static int vioif_ctrl_rx(struct vioif_softc *, int, bool); 237static int vioif_set_promisc(struct vioif_softc *, bool); 238static int vioif_set_allmulti(struct vioif_softc *, bool); 239static int vioif_set_rx_filter(struct vioif_softc *); 240static int vioif_rx_filter(struct vioif_softc *); 241static int vioif_ctrl_vq_done(struct virtqueue *); 242 243CFATTACH_DECL_NEW(vioif, sizeof(struct vioif_softc), 244 vioif_match, vioif_attach, NULL, NULL); 245 246static int 247vioif_match(device_t parent, cfdata_t match, void *aux) 248{ 249 struct virtio_softc *va = aux; 250 251 if (va->sc_childdevid == PCI_PRODUCT_VIRTIO_NETWORK) 252 return 1; 253 254 return 0; 255} 256 257/* allocate memory */ 258/* 259 * dma memory is used for: 260 * sc_rx_hdrs[slot]: metadata array for recieved frames (READ) 261 * sc_tx_hdrs[slot]: metadata array for frames to be sent (WRITE) 262 * sc_ctrl_cmd: command to be sent via ctrl vq (WRITE) 263 * sc_ctrl_status: return value for a command via ctrl vq (READ) 264 * sc_ctrl_rx: parameter for a VIRTIO_NET_CTRL_RX class command 265 * (WRITE) 266 * sc_ctrl_mac_tbl_uc: unicast MAC address filter for a VIRTIO_NET_CTRL_MAC 267 * class command (WRITE) 268 * sc_ctrl_mac_tbl_mc: multicast MAC address filter for a VIRTIO_NET_CTRL_MAC 269 * class command (WRITE) 270 * sc_ctrl_* structures are allocated only one each; they are protected by 271 * sc_ctrl_inuse variable and sc_ctrl_wait condvar. 272 */ 273/* 274 * dynamically allocated memory is used for: 275 * sc_rxhdr_dmamaps[slot]: bus_dmamap_t array for sc_rx_hdrs[slot] 276 * sc_txhdr_dmamaps[slot]: bus_dmamap_t array for sc_tx_hdrs[slot] 277 * sc_rx_dmamaps[slot]: bus_dmamap_t array for recieved payload 278 * sc_tx_dmamaps[slot]: bus_dmamap_t array for sent payload 279 * sc_rx_mbufs[slot]: mbuf pointer array for recieved frames 280 * sc_tx_mbufs[slot]: mbuf pointer array for sent frames 281 */ 282static int 283vioif_alloc_mems(struct vioif_softc *sc) 284{ 285 struct virtio_softc *vsc = sc->sc_virtio; 286 int allocsize, allocsize2, r, rsegs, i; 287 void *vaddr; 288 intptr_t p; 289 int rxqsize, txqsize; 290 291 rxqsize = vsc->sc_vqs[0].vq_num; 292 txqsize = vsc->sc_vqs[1].vq_num; 293 294 allocsize = sizeof(struct virtio_net_hdr) * rxqsize; 295 allocsize += sizeof(struct virtio_net_hdr) * txqsize; 296 if (vsc->sc_nvqs == 3) { 297 allocsize += sizeof(struct virtio_net_ctrl_cmd) * 1; 298 allocsize += sizeof(struct virtio_net_ctrl_status) * 1; 299 allocsize += sizeof(struct virtio_net_ctrl_rx) * 1; 300 allocsize += sizeof(struct virtio_net_ctrl_mac_tbl) 301 + sizeof(struct virtio_net_ctrl_mac_tbl) 302 + ETHER_ADDR_LEN * VIRTIO_NET_CTRL_MAC_MAXENTRIES; 303 } 304 r = bus_dmamem_alloc(vsc->sc_dmat, allocsize, 0, 0, 305 &sc->sc_hdr_segs[0], 1, &rsegs, BUS_DMA_NOWAIT); 306 if (r != 0) { 307 aprint_error_dev(sc->sc_dev, 308 "DMA memory allocation failed, size %d, " 309 "error code %d\n", allocsize, r); 310 goto err_none; 311 } 312 r = bus_dmamem_map(vsc->sc_dmat, 313 &sc->sc_hdr_segs[0], 1, allocsize, 314 &vaddr, BUS_DMA_NOWAIT); 315 if (r != 0) { 316 aprint_error_dev(sc->sc_dev, 317 "DMA memory map failed, " 318 "error code %d\n", r); 319 goto err_dmamem_alloc; 320 } 321 sc->sc_hdrs = vaddr; 322 memset(vaddr, 0, allocsize); 323 p = (intptr_t) vaddr; 324 p += sizeof(struct virtio_net_hdr) * rxqsize; 325#define P(name,size) do { sc->sc_ ##name = (void*) p; \ 326 p += size; } while (0) 327 P(tx_hdrs, sizeof(struct virtio_net_hdr) * txqsize); 328 if (vsc->sc_nvqs == 3) { 329 P(ctrl_cmd, sizeof(struct virtio_net_ctrl_cmd)); 330 P(ctrl_status, sizeof(struct virtio_net_ctrl_status)); 331 P(ctrl_rx, sizeof(struct virtio_net_ctrl_rx)); 332 P(ctrl_mac_tbl_uc, sizeof(struct virtio_net_ctrl_mac_tbl)); 333 P(ctrl_mac_tbl_mc, 334 (sizeof(struct virtio_net_ctrl_mac_tbl) 335 + ETHER_ADDR_LEN * VIRTIO_NET_CTRL_MAC_MAXENTRIES)); 336 } 337#undef P 338 339 allocsize2 = sizeof(bus_dmamap_t) * (rxqsize + txqsize); 340 allocsize2 += sizeof(bus_dmamap_t) * (rxqsize + txqsize); 341 allocsize2 += sizeof(struct mbuf*) * (rxqsize + txqsize); 342 sc->sc_arrays = kmem_zalloc(allocsize2, KM_SLEEP); 343 if (sc->sc_arrays == NULL) 344 goto err_dmamem_map; 345 sc->sc_txhdr_dmamaps = sc->sc_arrays + rxqsize; 346 sc->sc_rx_dmamaps = sc->sc_txhdr_dmamaps + txqsize; 347 sc->sc_tx_dmamaps = sc->sc_rx_dmamaps + rxqsize; 348 sc->sc_rx_mbufs = (void*) (sc->sc_tx_dmamaps + txqsize); 349 sc->sc_tx_mbufs = sc->sc_rx_mbufs + rxqsize; 350 351#define C(map, buf, size, nsegs, rw, usage) \ 352 do { \ 353 r = bus_dmamap_create(vsc->sc_dmat, size, nsegs, size, 0, \ 354 BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, \ 355 &sc->sc_ ##map); \ 356 if (r != 0) { \ 357 aprint_error_dev(sc->sc_dev, \ 358 usage " dmamap creation failed, " \ 359 "error code %d\n", r); \ 360 goto err_reqs; \ 361 } \ 362 } while (0) 363#define C_L1(map, buf, size, nsegs, rw, usage) \ 364 C(map, buf, size, nsegs, rw, usage); \ 365 do { \ 366 r = bus_dmamap_load(vsc->sc_dmat, sc->sc_ ##map, \ 367 &sc->sc_ ##buf, size, NULL, \ 368 BUS_DMA_ ##rw | BUS_DMA_NOWAIT); \ 369 if (r != 0) { \ 370 aprint_error_dev(sc->sc_dev, \ 371 usage " dmamap load failed, " \ 372 "error code %d\n", r); \ 373 goto err_reqs; \ 374 } \ 375 } while (0) 376#define C_L2(map, buf, size, nsegs, rw, usage) \ 377 C(map, buf, size, nsegs, rw, usage); \ 378 do { \ 379 r = bus_dmamap_load(vsc->sc_dmat, sc->sc_ ##map, \ 380 sc->sc_ ##buf, size, NULL, \ 381 BUS_DMA_ ##rw | BUS_DMA_NOWAIT); \ 382 if (r != 0) { \ 383 aprint_error_dev(sc->sc_dev, \ 384 usage " dmamap load failed, " \ 385 "error code %d\n", r); \ 386 goto err_reqs; \ 387 } \ 388 } while (0) 389 for (i = 0; i < rxqsize; i++) { 390 C_L1(rxhdr_dmamaps[i], rx_hdrs[i], 391 sizeof(struct virtio_net_hdr), 1, 392 READ, "rx header"); 393 C(rx_dmamaps[i], NULL, MCLBYTES, 1, 0, "rx payload"); 394 } 395 396 for (i = 0; i < txqsize; i++) { 397 C_L1(txhdr_dmamaps[i], rx_hdrs[i], 398 sizeof(struct virtio_net_hdr), 1, 399 WRITE, "tx header"); 400 C(tx_dmamaps[i], NULL, ETHER_MAX_LEN, 256 /* XXX */, 0, 401 "tx payload"); 402 } 403 404 if (vsc->sc_nvqs == 3) { 405 /* control vq class & command */ 406 C_L2(ctrl_cmd_dmamap, ctrl_cmd, 407 sizeof(struct virtio_net_ctrl_cmd), 1, WRITE, 408 "control command"); 409 410 /* control vq status */ 411 C_L2(ctrl_status_dmamap, ctrl_status, 412 sizeof(struct virtio_net_ctrl_status), 1, READ, 413 "control status"); 414 415 /* control vq rx mode command parameter */ 416 C_L2(ctrl_rx_dmamap, ctrl_rx, 417 sizeof(struct virtio_net_ctrl_rx), 1, WRITE, 418 "rx mode control command"); 419 420 /* control vq MAC filter table for unicast */ 421 /* do not load now since its length is variable */ 422 C(ctrl_tbl_uc_dmamap, NULL, 423 sizeof(struct virtio_net_ctrl_mac_tbl) + 0, 1, WRITE, 424 "unicast MAC address filter command"); 425 426 /* control vq MAC filter table for multicast */ 427 C(ctrl_tbl_mc_dmamap, NULL, 428 (sizeof(struct virtio_net_ctrl_mac_tbl) 429 + ETHER_ADDR_LEN * VIRTIO_NET_CTRL_MAC_MAXENTRIES), 430 1, WRITE, "multicast MAC address filter command"); 431 } 432#undef C_L2 433#undef C_L1 434#undef C 435 436 return 0; 437 438err_reqs: 439#define D(map) \ 440 do { \ 441 if (sc->sc_ ##map) { \ 442 bus_dmamap_destroy(vsc->sc_dmat, sc->sc_ ##map); \ 443 sc->sc_ ##map = NULL; \ 444 } \ 445 } while (0) 446 D(ctrl_tbl_mc_dmamap); 447 D(ctrl_tbl_uc_dmamap); 448 D(ctrl_rx_dmamap); 449 D(ctrl_status_dmamap); 450 D(ctrl_cmd_dmamap); 451 for (i = 0; i < txqsize; i++) { 452 D(tx_dmamaps[i]); 453 D(txhdr_dmamaps[i]); 454 } 455 for (i = 0; i < rxqsize; i++) { 456 D(rx_dmamaps[i]); 457 D(rxhdr_dmamaps[i]); 458 } 459#undef D 460 if (sc->sc_arrays) { 461 kmem_free(sc->sc_arrays, allocsize2); 462 sc->sc_arrays = 0; 463 } 464err_dmamem_map: 465 bus_dmamem_unmap(vsc->sc_dmat, sc->sc_hdrs, allocsize); 466err_dmamem_alloc: 467 bus_dmamem_free(vsc->sc_dmat, &sc->sc_hdr_segs[0], 1); 468err_none: 469 return -1; 470} 471 472static void 473vioif_attach(device_t parent, device_t self, void *aux) 474{ 475 struct vioif_softc *sc = device_private(self); 476 struct virtio_softc *vsc = device_private(parent); 477 uint32_t features; 478 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 479 u_int flags; 480 481 if (vsc->sc_child != NULL) { 482 aprint_normal(": child already attached for %s; " 483 "something wrong...\n", 484 device_xname(parent)); 485 return; 486 } 487 488 sc->sc_dev = self; 489 sc->sc_virtio = vsc; 490 491 vsc->sc_child = self; 492 vsc->sc_ipl = IPL_NET; 493 vsc->sc_vqs = &sc->sc_vq[0]; 494 vsc->sc_config_change = 0; 495 vsc->sc_intrhand = virtio_vq_intr; 496 vsc->sc_flags = 0; 497 498#ifdef VIOIF_MPSAFE 499 vsc->sc_flags |= VIRTIO_F_PCI_INTR_MPSAFE; 500#endif 501 502 features = virtio_negotiate_features(vsc, 503 (VIRTIO_NET_F_MAC | 504 VIRTIO_NET_F_STATUS | 505 VIRTIO_NET_F_CTRL_VQ | 506 VIRTIO_NET_F_CTRL_RX | 507 VIRTIO_F_NOTIFY_ON_EMPTY)); 508 if (features & VIRTIO_NET_F_MAC) { 509 sc->sc_mac[0] = virtio_read_device_config_1(vsc, 510 VIRTIO_NET_CONFIG_MAC+0); 511 sc->sc_mac[1] = virtio_read_device_config_1(vsc, 512 VIRTIO_NET_CONFIG_MAC+1); 513 sc->sc_mac[2] = virtio_read_device_config_1(vsc, 514 VIRTIO_NET_CONFIG_MAC+2); 515 sc->sc_mac[3] = virtio_read_device_config_1(vsc, 516 VIRTIO_NET_CONFIG_MAC+3); 517 sc->sc_mac[4] = virtio_read_device_config_1(vsc, 518 VIRTIO_NET_CONFIG_MAC+4); 519 sc->sc_mac[5] = virtio_read_device_config_1(vsc, 520 VIRTIO_NET_CONFIG_MAC+5); 521 } else { 522 /* code stolen from sys/net/if_tap.c */ 523 struct timeval tv; 524 uint32_t ui; 525 getmicrouptime(&tv); 526 ui = (tv.tv_sec ^ tv.tv_usec) & 0xffffff; 527 memcpy(sc->sc_mac+3, (uint8_t *)&ui, 3); 528 virtio_write_device_config_1(vsc, 529 VIRTIO_NET_CONFIG_MAC+0, 530 sc->sc_mac[0]); 531 virtio_write_device_config_1(vsc, 532 VIRTIO_NET_CONFIG_MAC+1, 533 sc->sc_mac[1]); 534 virtio_write_device_config_1(vsc, 535 VIRTIO_NET_CONFIG_MAC+2, 536 sc->sc_mac[2]); 537 virtio_write_device_config_1(vsc, 538 VIRTIO_NET_CONFIG_MAC+3, 539 sc->sc_mac[3]); 540 virtio_write_device_config_1(vsc, 541 VIRTIO_NET_CONFIG_MAC+4, 542 sc->sc_mac[4]); 543 virtio_write_device_config_1(vsc, 544 VIRTIO_NET_CONFIG_MAC+5, 545 sc->sc_mac[5]); 546 } 547 aprint_normal(": Ethernet address %s\n", ether_sprintf(sc->sc_mac)); 548 aprint_naive("\n"); 549 550 if (virtio_alloc_vq(vsc, &sc->sc_vq[0], 0, 551 MCLBYTES+sizeof(struct virtio_net_hdr), 2, 552 "rx") != 0) { 553 goto err; 554 } 555 vsc->sc_nvqs = 1; 556 sc->sc_vq[0].vq_done = vioif_rx_vq_done; 557 if (virtio_alloc_vq(vsc, &sc->sc_vq[1], 1, 558 (sizeof(struct virtio_net_hdr) 559 + (ETHER_MAX_LEN - ETHER_HDR_LEN)), 560 VIRTIO_NET_TX_MAXNSEGS + 1, 561 "tx") != 0) { 562 goto err; 563 } 564 565#ifdef VIOIF_MPSAFE 566 sc->sc_tx_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET); 567 sc->sc_rx_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET); 568#else 569 sc->sc_tx_lock = NULL; 570 sc->sc_rx_lock = NULL; 571#endif 572 sc->sc_stopping = false; 573 574 vsc->sc_nvqs = 2; 575 sc->sc_vq[1].vq_done = vioif_tx_vq_done; 576 virtio_start_vq_intr(vsc, &sc->sc_vq[0]); 577 virtio_stop_vq_intr(vsc, &sc->sc_vq[1]); /* not urgent; do it later */ 578 if ((features & VIRTIO_NET_F_CTRL_VQ) 579 && (features & VIRTIO_NET_F_CTRL_RX)) { 580 if (virtio_alloc_vq(vsc, &sc->sc_vq[2], 2, 581 NBPG, 1, "control") == 0) { 582 sc->sc_vq[2].vq_done = vioif_ctrl_vq_done; 583 cv_init(&sc->sc_ctrl_wait, "ctrl_vq"); 584 mutex_init(&sc->sc_ctrl_wait_lock, 585 MUTEX_DEFAULT, IPL_NET); 586 sc->sc_ctrl_inuse = FREE; 587 virtio_start_vq_intr(vsc, &sc->sc_vq[2]); 588 vsc->sc_nvqs = 3; 589 } 590 } 591 592#ifdef VIOIF_MPSAFE 593 flags = SOFTINT_NET | SOFTINT_MPSAFE; 594#else 595 flags = SOFTINT_NET; 596#endif 597 sc->sc_rx_softint = softint_establish(flags, vioif_rx_softint, sc); 598 if (sc->sc_rx_softint == NULL) { 599 aprint_error_dev(self, "cannot establish softint\n"); 600 goto err; 601 } 602 603 if (vioif_alloc_mems(sc) < 0) 604 goto err; 605 606 strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); 607 ifp->if_softc = sc; 608 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 609 ifp->if_start = vioif_start; 610 ifp->if_ioctl = vioif_ioctl; 611 ifp->if_init = vioif_init; 612 ifp->if_stop = vioif_stop; 613 ifp->if_capabilities = 0; 614 ifp->if_watchdog = vioif_watchdog; 615 616 if_attach(ifp); 617 ether_ifattach(ifp, sc->sc_mac); 618 619 return; 620 621err: 622 if (sc->sc_tx_lock) 623 mutex_obj_free(sc->sc_tx_lock); 624 if (sc->sc_rx_lock) 625 mutex_obj_free(sc->sc_rx_lock); 626 627 if (vsc->sc_nvqs == 3) { 628 virtio_free_vq(vsc, &sc->sc_vq[2]); 629 cv_destroy(&sc->sc_ctrl_wait); 630 mutex_destroy(&sc->sc_ctrl_wait_lock); 631 vsc->sc_nvqs = 2; 632 } 633 if (vsc->sc_nvqs == 2) { 634 virtio_free_vq(vsc, &sc->sc_vq[1]); 635 vsc->sc_nvqs = 1; 636 } 637 if (vsc->sc_nvqs == 1) { 638 virtio_free_vq(vsc, &sc->sc_vq[0]); 639 vsc->sc_nvqs = 0; 640 } 641 vsc->sc_child = (void*)1; 642 return; 643} 644 645/* we need interrupts to make promiscuous mode off */ 646static void 647vioif_deferred_init(device_t self) 648{ 649 struct vioif_softc *sc = device_private(self); 650 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 651 int r; 652 653 r = vioif_set_promisc(sc, false); 654 if (r != 0) 655 aprint_error_dev(self, "resetting promisc mode failed, " 656 "errror code %d\n", r); 657 else 658 ifp->if_flags &= ~IFF_PROMISC; 659} 660 661/* 662 * Interface functions for ifnet 663 */ 664static int 665vioif_init(struct ifnet *ifp) 666{ 667 struct vioif_softc *sc = ifp->if_softc; 668 669 vioif_stop(ifp, 0); 670 671 if (!sc->sc_deferred_init_done) { 672 struct virtio_softc *vsc = sc->sc_virtio; 673 674 sc->sc_deferred_init_done = 1; 675 if (vsc->sc_nvqs == 3) 676 vioif_deferred_init(sc->sc_dev); 677 } 678 679 /* Have to set false before vioif_populate_rx_mbufs */ 680 sc->sc_stopping = false; 681 682 vioif_populate_rx_mbufs(sc); 683 684 vioif_updown(sc, true); 685 ifp->if_flags |= IFF_RUNNING; 686 ifp->if_flags &= ~IFF_OACTIVE; 687 vioif_rx_filter(sc); 688 689 return 0; 690} 691 692static void 693vioif_stop(struct ifnet *ifp, int disable) 694{ 695 struct vioif_softc *sc = ifp->if_softc; 696 struct virtio_softc *vsc = sc->sc_virtio; 697 698 sc->sc_stopping = true; 699 700 /* only way to stop I/O and DMA is resetting... */ 701 virtio_reset(vsc); 702 vioif_rx_deq(sc); 703 vioif_tx_drain(sc); 704 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 705 706 if (disable) 707 vioif_rx_drain(sc); 708 709 virtio_reinit_start(vsc); 710 virtio_negotiate_features(vsc, vsc->sc_features); 711 virtio_start_vq_intr(vsc, &sc->sc_vq[0]); 712 virtio_stop_vq_intr(vsc, &sc->sc_vq[1]); 713 if (vsc->sc_nvqs >= 3) 714 virtio_start_vq_intr(vsc, &sc->sc_vq[2]); 715 virtio_reinit_end(vsc); 716 vioif_updown(sc, false); 717} 718 719static void 720vioif_start(struct ifnet *ifp) 721{ 722 struct vioif_softc *sc = ifp->if_softc; 723 struct virtio_softc *vsc = sc->sc_virtio; 724 struct virtqueue *vq = &sc->sc_vq[1]; /* tx vq */ 725 struct mbuf *m; 726 int queued = 0, retry = 0; 727 728 VIOIF_TX_LOCK(sc); 729 730 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) 731 goto out; 732 733 if (sc->sc_stopping) 734 goto out; 735 736 for (;;) { 737 int slot, r; 738 739 IFQ_DEQUEUE(&ifp->if_snd, m); 740 741 if (m == NULL) 742 break; 743 744 r = virtio_enqueue_prep(vsc, vq, &slot); 745 if (r == EAGAIN) { 746 ifp->if_flags |= IFF_OACTIVE; 747 vioif_tx_vq_done_locked(vq); 748 if (retry++ == 0) 749 continue; 750 else 751 break; 752 } 753 if (r != 0) 754 panic("enqueue_prep for a tx buffer"); 755 r = bus_dmamap_load_mbuf(vsc->sc_dmat, 756 sc->sc_tx_dmamaps[slot], 757 m, BUS_DMA_WRITE|BUS_DMA_NOWAIT); 758 if (r != 0) { 759 virtio_enqueue_abort(vsc, vq, slot); 760 printf("%s: tx dmamap load failed, error code %d\n", 761 device_xname(sc->sc_dev), r); 762 break; 763 } 764 r = virtio_enqueue_reserve(vsc, vq, slot, 765 sc->sc_tx_dmamaps[slot]->dm_nsegs + 1); 766 if (r != 0) { 767 bus_dmamap_unload(vsc->sc_dmat, 768 sc->sc_tx_dmamaps[slot]); 769 ifp->if_flags |= IFF_OACTIVE; 770 vioif_tx_vq_done_locked(vq); 771 if (retry++ == 0) 772 continue; 773 else 774 break; 775 } 776 777 sc->sc_tx_mbufs[slot] = m; 778 779 memset(&sc->sc_tx_hdrs[slot], 0, sizeof(struct virtio_net_hdr)); 780 bus_dmamap_sync(vsc->sc_dmat, sc->sc_tx_dmamaps[slot], 781 0, sc->sc_tx_dmamaps[slot]->dm_mapsize, 782 BUS_DMASYNC_PREWRITE); 783 bus_dmamap_sync(vsc->sc_dmat, sc->sc_txhdr_dmamaps[slot], 784 0, sc->sc_txhdr_dmamaps[slot]->dm_mapsize, 785 BUS_DMASYNC_PREWRITE); 786 virtio_enqueue(vsc, vq, slot, sc->sc_txhdr_dmamaps[slot], true); 787 virtio_enqueue(vsc, vq, slot, sc->sc_tx_dmamaps[slot], true); 788 virtio_enqueue_commit(vsc, vq, slot, false); 789 queued++; 790 bpf_mtap(ifp, m); 791 } 792 793 if (m != NULL) { 794 ifp->if_flags |= IFF_OACTIVE; 795 m_freem(m); 796 } 797 798 if (queued > 0) { 799 virtio_enqueue_commit(vsc, vq, -1, true); 800 ifp->if_timer = 5; 801 } 802 803out: 804 VIOIF_TX_UNLOCK(sc); 805} 806 807static int 808vioif_ioctl(struct ifnet *ifp, u_long cmd, void *data) 809{ 810 int s, r; 811 812 s = splnet(); 813 814 r = ether_ioctl(ifp, cmd, data); 815 if ((r == 0 && cmd == SIOCSIFFLAGS) || 816 (r == ENETRESET && (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI))) { 817 if (ifp->if_flags & IFF_RUNNING) 818 r = vioif_rx_filter(ifp->if_softc); 819 else 820 r = 0; 821 } 822 823 splx(s); 824 825 return r; 826} 827 828void 829vioif_watchdog(struct ifnet *ifp) 830{ 831 struct vioif_softc *sc = ifp->if_softc; 832 833 if (ifp->if_flags & IFF_RUNNING) 834 vioif_tx_vq_done(&sc->sc_vq[1]); 835} 836 837 838/* 839 * Recieve implementation 840 */ 841/* allocate and initialize a mbuf for recieve */ 842static int 843vioif_add_rx_mbuf(struct vioif_softc *sc, int i) 844{ 845 struct mbuf *m; 846 int r; 847 848 MGETHDR(m, M_DONTWAIT, MT_DATA); 849 if (m == NULL) 850 return ENOBUFS; 851 MCLGET(m, M_DONTWAIT); 852 if ((m->m_flags & M_EXT) == 0) { 853 m_freem(m); 854 return ENOBUFS; 855 } 856 sc->sc_rx_mbufs[i] = m; 857 m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 858 r = bus_dmamap_load_mbuf(sc->sc_virtio->sc_dmat, 859 sc->sc_rx_dmamaps[i], 860 m, BUS_DMA_READ|BUS_DMA_NOWAIT); 861 if (r) { 862 m_freem(m); 863 sc->sc_rx_mbufs[i] = 0; 864 return r; 865 } 866 867 return 0; 868} 869 870/* free a mbuf for recieve */ 871static void 872vioif_free_rx_mbuf(struct vioif_softc *sc, int i) 873{ 874 bus_dmamap_unload(sc->sc_virtio->sc_dmat, sc->sc_rx_dmamaps[i]); 875 m_freem(sc->sc_rx_mbufs[i]); 876 sc->sc_rx_mbufs[i] = NULL; 877} 878 879/* add mbufs for all the empty recieve slots */ 880static void 881vioif_populate_rx_mbufs(struct vioif_softc *sc) 882{ 883 struct virtio_softc *vsc = sc->sc_virtio; 884 int i, r, ndone = 0; 885 struct virtqueue *vq = &sc->sc_vq[0]; /* rx vq */ 886 887 VIOIF_RX_LOCK(sc); 888 889 if (sc->sc_stopping) 890 goto out; 891 892 for (i = 0; i < vq->vq_num; i++) { 893 int slot; 894 r = virtio_enqueue_prep(vsc, vq, &slot); 895 if (r == EAGAIN) 896 break; 897 if (r != 0) 898 panic("enqueue_prep for rx buffers"); 899 if (sc->sc_rx_mbufs[slot] == NULL) { 900 r = vioif_add_rx_mbuf(sc, slot); 901 if (r != 0) { 902 printf("%s: rx mbuf allocation failed, " 903 "error code %d\n", 904 device_xname(sc->sc_dev), r); 905 break; 906 } 907 } 908 r = virtio_enqueue_reserve(vsc, vq, slot, 909 sc->sc_rx_dmamaps[slot]->dm_nsegs + 1); 910 if (r != 0) { 911 vioif_free_rx_mbuf(sc, slot); 912 break; 913 } 914 bus_dmamap_sync(vsc->sc_dmat, sc->sc_rxhdr_dmamaps[slot], 915 0, sizeof(struct virtio_net_hdr), BUS_DMASYNC_PREREAD); 916 bus_dmamap_sync(vsc->sc_dmat, sc->sc_rx_dmamaps[slot], 917 0, MCLBYTES, BUS_DMASYNC_PREREAD); 918 virtio_enqueue(vsc, vq, slot, sc->sc_rxhdr_dmamaps[slot], false); 919 virtio_enqueue(vsc, vq, slot, sc->sc_rx_dmamaps[slot], false); 920 virtio_enqueue_commit(vsc, vq, slot, false); 921 ndone++; 922 } 923 if (ndone > 0) 924 virtio_enqueue_commit(vsc, vq, -1, true); 925 926out: 927 VIOIF_RX_UNLOCK(sc); 928} 929 930/* dequeue recieved packets */ 931static int 932vioif_rx_deq(struct vioif_softc *sc) 933{ 934 int r; 935 936 KASSERT(sc->sc_stopping); 937 938 VIOIF_RX_LOCK(sc); 939 r = vioif_rx_deq_locked(sc); 940 VIOIF_RX_UNLOCK(sc); 941 942 return r; 943} 944 945/* dequeue recieved packets */ 946static int 947vioif_rx_deq_locked(struct vioif_softc *sc) 948{ 949 struct virtio_softc *vsc = sc->sc_virtio; 950 struct virtqueue *vq = &sc->sc_vq[0]; 951 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 952 struct mbuf *m; 953 int r = 0; 954 int slot, len; 955 956 KASSERT(VIOIF_RX_LOCKED(sc)); 957 958 while (virtio_dequeue(vsc, vq, &slot, &len) == 0) { 959 len -= sizeof(struct virtio_net_hdr); 960 r = 1; 961 bus_dmamap_sync(vsc->sc_dmat, sc->sc_rxhdr_dmamaps[slot], 962 0, sizeof(struct virtio_net_hdr), 963 BUS_DMASYNC_POSTREAD); 964 bus_dmamap_sync(vsc->sc_dmat, sc->sc_rx_dmamaps[slot], 965 0, MCLBYTES, 966 BUS_DMASYNC_POSTREAD); 967 m = sc->sc_rx_mbufs[slot]; 968 KASSERT(m != NULL); 969 bus_dmamap_unload(vsc->sc_dmat, sc->sc_rx_dmamaps[slot]); 970 sc->sc_rx_mbufs[slot] = 0; 971 virtio_dequeue_commit(vsc, vq, slot); 972 m->m_pkthdr.rcvif = ifp; 973 m->m_len = m->m_pkthdr.len = len; 974 ifp->if_ipackets++; 975 bpf_mtap(ifp, m); 976 977 VIOIF_RX_UNLOCK(sc); 978 (*ifp->if_input)(ifp, m); 979 VIOIF_RX_LOCK(sc); 980 981 if (sc->sc_stopping) 982 break; 983 } 984 985 return r; 986} 987 988/* rx interrupt; call _dequeue above and schedule a softint */ 989static int 990vioif_rx_vq_done(struct virtqueue *vq) 991{ 992 struct virtio_softc *vsc = vq->vq_owner; 993 struct vioif_softc *sc = device_private(vsc->sc_child); 994 int r = 0; 995 996 VIOIF_RX_LOCK(sc); 997 998 if (sc->sc_stopping) 999 goto out; 1000 1001 r = vioif_rx_deq_locked(sc); 1002 if (r) 1003 softint_schedule(sc->sc_rx_softint); 1004 1005out: 1006 VIOIF_RX_UNLOCK(sc); 1007 return r; 1008} 1009 1010/* softint: enqueue recieve requests for new incoming packets */ 1011static void 1012vioif_rx_softint(void *arg) 1013{ 1014 struct vioif_softc *sc = arg; 1015 1016 vioif_populate_rx_mbufs(sc); 1017} 1018 1019/* free all the mbufs; called from if_stop(disable) */ 1020static void 1021vioif_rx_drain(struct vioif_softc *sc) 1022{ 1023 struct virtqueue *vq = &sc->sc_vq[0]; 1024 int i; 1025 1026 for (i = 0; i < vq->vq_num; i++) { 1027 if (sc->sc_rx_mbufs[i] == NULL) 1028 continue; 1029 vioif_free_rx_mbuf(sc, i); 1030 } 1031} 1032 1033 1034/* 1035 * Transmition implementation 1036 */ 1037/* actual transmission is done in if_start */ 1038/* tx interrupt; dequeue and free mbufs */ 1039/* 1040 * tx interrupt is actually disabled; this should be called upon 1041 * tx vq full and watchdog 1042 */ 1043static int 1044vioif_tx_vq_done(struct virtqueue *vq) 1045{ 1046 struct virtio_softc *vsc = vq->vq_owner; 1047 struct vioif_softc *sc = device_private(vsc->sc_child); 1048 int r = 0; 1049 1050 VIOIF_TX_LOCK(sc); 1051 1052 if (sc->sc_stopping) 1053 goto out; 1054 1055 r = vioif_tx_vq_done_locked(vq); 1056 1057out: 1058 VIOIF_TX_UNLOCK(sc); 1059 return r; 1060} 1061 1062static int 1063vioif_tx_vq_done_locked(struct virtqueue *vq) 1064{ 1065 struct virtio_softc *vsc = vq->vq_owner; 1066 struct vioif_softc *sc = device_private(vsc->sc_child); 1067 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1068 struct mbuf *m; 1069 int r = 0; 1070 int slot, len; 1071 1072 KASSERT(VIOIF_TX_LOCKED(sc)); 1073 1074 while (virtio_dequeue(vsc, vq, &slot, &len) == 0) { 1075 r++; 1076 bus_dmamap_sync(vsc->sc_dmat, sc->sc_txhdr_dmamaps[slot], 1077 0, sizeof(struct virtio_net_hdr), 1078 BUS_DMASYNC_POSTWRITE); 1079 bus_dmamap_sync(vsc->sc_dmat, sc->sc_tx_dmamaps[slot], 1080 0, sc->sc_tx_dmamaps[slot]->dm_mapsize, 1081 BUS_DMASYNC_POSTWRITE); 1082 m = sc->sc_tx_mbufs[slot]; 1083 bus_dmamap_unload(vsc->sc_dmat, sc->sc_tx_dmamaps[slot]); 1084 sc->sc_tx_mbufs[slot] = 0; 1085 virtio_dequeue_commit(vsc, vq, slot); 1086 ifp->if_opackets++; 1087 m_freem(m); 1088 } 1089 1090 if (r) 1091 ifp->if_flags &= ~IFF_OACTIVE; 1092 return r; 1093} 1094 1095/* free all the mbufs already put on vq; called from if_stop(disable) */ 1096static void 1097vioif_tx_drain(struct vioif_softc *sc) 1098{ 1099 struct virtio_softc *vsc = sc->sc_virtio; 1100 struct virtqueue *vq = &sc->sc_vq[1]; 1101 int i; 1102 1103 KASSERT(sc->sc_stopping); 1104 1105 for (i = 0; i < vq->vq_num; i++) { 1106 if (sc->sc_tx_mbufs[i] == NULL) 1107 continue; 1108 bus_dmamap_unload(vsc->sc_dmat, sc->sc_tx_dmamaps[i]); 1109 m_freem(sc->sc_tx_mbufs[i]); 1110 sc->sc_tx_mbufs[i] = NULL; 1111 } 1112} 1113 1114/* 1115 * Control vq 1116 */ 1117/* issue a VIRTIO_NET_CTRL_RX class command and wait for completion */ 1118static int 1119vioif_ctrl_rx(struct vioif_softc *sc, int cmd, bool onoff) 1120{ 1121 struct virtio_softc *vsc = sc->sc_virtio; 1122 struct virtqueue *vq = &sc->sc_vq[2]; 1123 int r, slot; 1124 1125 if (vsc->sc_nvqs < 3) 1126 return ENOTSUP; 1127 1128 mutex_enter(&sc->sc_ctrl_wait_lock); 1129 while (sc->sc_ctrl_inuse != FREE) 1130 cv_wait(&sc->sc_ctrl_wait, &sc->sc_ctrl_wait_lock); 1131 sc->sc_ctrl_inuse = INUSE; 1132 mutex_exit(&sc->sc_ctrl_wait_lock); 1133 1134 sc->sc_ctrl_cmd->class = VIRTIO_NET_CTRL_RX; 1135 sc->sc_ctrl_cmd->command = cmd; 1136 sc->sc_ctrl_rx->onoff = onoff; 1137 1138 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_cmd_dmamap, 1139 0, sizeof(struct virtio_net_ctrl_cmd), 1140 BUS_DMASYNC_PREWRITE); 1141 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_rx_dmamap, 1142 0, sizeof(struct virtio_net_ctrl_rx), 1143 BUS_DMASYNC_PREWRITE); 1144 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_status_dmamap, 1145 0, sizeof(struct virtio_net_ctrl_status), 1146 BUS_DMASYNC_PREREAD); 1147 1148 r = virtio_enqueue_prep(vsc, vq, &slot); 1149 if (r != 0) 1150 panic("%s: control vq busy!?", device_xname(sc->sc_dev)); 1151 r = virtio_enqueue_reserve(vsc, vq, slot, 3); 1152 if (r != 0) 1153 panic("%s: control vq busy!?", device_xname(sc->sc_dev)); 1154 virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_cmd_dmamap, true); 1155 virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_rx_dmamap, true); 1156 virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_status_dmamap, false); 1157 virtio_enqueue_commit(vsc, vq, slot, true); 1158 1159 /* wait for done */ 1160 mutex_enter(&sc->sc_ctrl_wait_lock); 1161 while (sc->sc_ctrl_inuse != DONE) 1162 cv_wait(&sc->sc_ctrl_wait, &sc->sc_ctrl_wait_lock); 1163 mutex_exit(&sc->sc_ctrl_wait_lock); 1164 /* already dequeueued */ 1165 1166 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_cmd_dmamap, 0, 1167 sizeof(struct virtio_net_ctrl_cmd), 1168 BUS_DMASYNC_POSTWRITE); 1169 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_rx_dmamap, 0, 1170 sizeof(struct virtio_net_ctrl_rx), 1171 BUS_DMASYNC_POSTWRITE); 1172 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_status_dmamap, 0, 1173 sizeof(struct virtio_net_ctrl_status), 1174 BUS_DMASYNC_POSTREAD); 1175 1176 if (sc->sc_ctrl_status->ack == VIRTIO_NET_OK) 1177 r = 0; 1178 else { 1179 printf("%s: failed setting rx mode\n", 1180 device_xname(sc->sc_dev)); 1181 r = EIO; 1182 } 1183 1184 mutex_enter(&sc->sc_ctrl_wait_lock); 1185 sc->sc_ctrl_inuse = FREE; 1186 cv_signal(&sc->sc_ctrl_wait); 1187 mutex_exit(&sc->sc_ctrl_wait_lock); 1188 1189 return r; 1190} 1191 1192static int 1193vioif_set_promisc(struct vioif_softc *sc, bool onoff) 1194{ 1195 int r; 1196 1197 r = vioif_ctrl_rx(sc, VIRTIO_NET_CTRL_RX_PROMISC, onoff); 1198 1199 return r; 1200} 1201 1202static int 1203vioif_set_allmulti(struct vioif_softc *sc, bool onoff) 1204{ 1205 int r; 1206 1207 r = vioif_ctrl_rx(sc, VIRTIO_NET_CTRL_RX_ALLMULTI, onoff); 1208 1209 return r; 1210} 1211 1212/* issue VIRTIO_NET_CTRL_MAC_TABLE_SET command and wait for completion */ 1213static int 1214vioif_set_rx_filter(struct vioif_softc *sc) 1215{ 1216 /* filter already set in sc_ctrl_mac_tbl */ 1217 struct virtio_softc *vsc = sc->sc_virtio; 1218 struct virtqueue *vq = &sc->sc_vq[2]; 1219 int r, slot; 1220 1221 if (vsc->sc_nvqs < 3) 1222 return ENOTSUP; 1223 1224 mutex_enter(&sc->sc_ctrl_wait_lock); 1225 while (sc->sc_ctrl_inuse != FREE) 1226 cv_wait(&sc->sc_ctrl_wait, &sc->sc_ctrl_wait_lock); 1227 sc->sc_ctrl_inuse = INUSE; 1228 mutex_exit(&sc->sc_ctrl_wait_lock); 1229 1230 sc->sc_ctrl_cmd->class = VIRTIO_NET_CTRL_MAC; 1231 sc->sc_ctrl_cmd->command = VIRTIO_NET_CTRL_MAC_TABLE_SET; 1232 1233 r = bus_dmamap_load(vsc->sc_dmat, sc->sc_ctrl_tbl_uc_dmamap, 1234 sc->sc_ctrl_mac_tbl_uc, 1235 (sizeof(struct virtio_net_ctrl_mac_tbl) 1236 + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_uc->nentries), 1237 NULL, BUS_DMA_WRITE|BUS_DMA_NOWAIT); 1238 if (r) { 1239 printf("%s: control command dmamap load failed, " 1240 "error code %d\n", device_xname(sc->sc_dev), r); 1241 goto out; 1242 } 1243 r = bus_dmamap_load(vsc->sc_dmat, sc->sc_ctrl_tbl_mc_dmamap, 1244 sc->sc_ctrl_mac_tbl_mc, 1245 (sizeof(struct virtio_net_ctrl_mac_tbl) 1246 + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_mc->nentries), 1247 NULL, BUS_DMA_WRITE|BUS_DMA_NOWAIT); 1248 if (r) { 1249 printf("%s: control command dmamap load failed, " 1250 "error code %d\n", device_xname(sc->sc_dev), r); 1251 bus_dmamap_unload(vsc->sc_dmat, sc->sc_ctrl_tbl_uc_dmamap); 1252 goto out; 1253 } 1254 1255 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_cmd_dmamap, 1256 0, sizeof(struct virtio_net_ctrl_cmd), 1257 BUS_DMASYNC_PREWRITE); 1258 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_tbl_uc_dmamap, 0, 1259 (sizeof(struct virtio_net_ctrl_mac_tbl) 1260 + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_uc->nentries), 1261 BUS_DMASYNC_PREWRITE); 1262 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_tbl_mc_dmamap, 0, 1263 (sizeof(struct virtio_net_ctrl_mac_tbl) 1264 + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_mc->nentries), 1265 BUS_DMASYNC_PREWRITE); 1266 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_status_dmamap, 1267 0, sizeof(struct virtio_net_ctrl_status), 1268 BUS_DMASYNC_PREREAD); 1269 1270 r = virtio_enqueue_prep(vsc, vq, &slot); 1271 if (r != 0) 1272 panic("%s: control vq busy!?", device_xname(sc->sc_dev)); 1273 r = virtio_enqueue_reserve(vsc, vq, slot, 4); 1274 if (r != 0) 1275 panic("%s: control vq busy!?", device_xname(sc->sc_dev)); 1276 virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_cmd_dmamap, true); 1277 virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_tbl_uc_dmamap, true); 1278 virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_tbl_mc_dmamap, true); 1279 virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_status_dmamap, false); 1280 virtio_enqueue_commit(vsc, vq, slot, true); 1281 1282 /* wait for done */ 1283 mutex_enter(&sc->sc_ctrl_wait_lock); 1284 while (sc->sc_ctrl_inuse != DONE) 1285 cv_wait(&sc->sc_ctrl_wait, &sc->sc_ctrl_wait_lock); 1286 mutex_exit(&sc->sc_ctrl_wait_lock); 1287 /* already dequeueued */ 1288 1289 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_cmd_dmamap, 0, 1290 sizeof(struct virtio_net_ctrl_cmd), 1291 BUS_DMASYNC_POSTWRITE); 1292 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_tbl_uc_dmamap, 0, 1293 (sizeof(struct virtio_net_ctrl_mac_tbl) 1294 + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_uc->nentries), 1295 BUS_DMASYNC_POSTWRITE); 1296 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_tbl_mc_dmamap, 0, 1297 (sizeof(struct virtio_net_ctrl_mac_tbl) 1298 + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_mc->nentries), 1299 BUS_DMASYNC_POSTWRITE); 1300 bus_dmamap_sync(vsc->sc_dmat, sc->sc_ctrl_status_dmamap, 0, 1301 sizeof(struct virtio_net_ctrl_status), 1302 BUS_DMASYNC_POSTREAD); 1303 bus_dmamap_unload(vsc->sc_dmat, sc->sc_ctrl_tbl_uc_dmamap); 1304 bus_dmamap_unload(vsc->sc_dmat, sc->sc_ctrl_tbl_mc_dmamap); 1305 1306 if (sc->sc_ctrl_status->ack == VIRTIO_NET_OK) 1307 r = 0; 1308 else { 1309 printf("%s: failed setting rx filter\n", 1310 device_xname(sc->sc_dev)); 1311 r = EIO; 1312 } 1313 1314out: 1315 mutex_enter(&sc->sc_ctrl_wait_lock); 1316 sc->sc_ctrl_inuse = FREE; 1317 cv_signal(&sc->sc_ctrl_wait); 1318 mutex_exit(&sc->sc_ctrl_wait_lock); 1319 1320 return r; 1321} 1322 1323/* ctrl vq interrupt; wake up the command issuer */ 1324static int 1325vioif_ctrl_vq_done(struct virtqueue *vq) 1326{ 1327 struct virtio_softc *vsc = vq->vq_owner; 1328 struct vioif_softc *sc = device_private(vsc->sc_child); 1329 int r, slot; 1330 1331 r = virtio_dequeue(vsc, vq, &slot, NULL); 1332 if (r == ENOENT) 1333 return 0; 1334 virtio_dequeue_commit(vsc, vq, slot); 1335 1336 mutex_enter(&sc->sc_ctrl_wait_lock); 1337 sc->sc_ctrl_inuse = DONE; 1338 cv_signal(&sc->sc_ctrl_wait); 1339 mutex_exit(&sc->sc_ctrl_wait_lock); 1340 1341 return 1; 1342} 1343 1344/* 1345 * If IFF_PROMISC requested, set promiscuous 1346 * If multicast filter small enough (<=MAXENTRIES) set rx filter 1347 * If large multicast filter exist use ALLMULTI 1348 */ 1349/* 1350 * If setting rx filter fails fall back to ALLMULTI 1351 * If ALLMULTI fails fall back to PROMISC 1352 */ 1353static int 1354vioif_rx_filter(struct vioif_softc *sc) 1355{ 1356 struct virtio_softc *vsc = sc->sc_virtio; 1357 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1358 struct ether_multi *enm; 1359 struct ether_multistep step; 1360 int nentries; 1361 int promisc = 0, allmulti = 0, rxfilter = 0; 1362 int r; 1363 1364 if (vsc->sc_nvqs < 3) { /* no ctrl vq; always promisc */ 1365 ifp->if_flags |= IFF_PROMISC; 1366 return 0; 1367 } 1368 1369 if (ifp->if_flags & IFF_PROMISC) { 1370 promisc = 1; 1371 goto set; 1372 } 1373 1374 nentries = -1; 1375 ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm); 1376 while (nentries++, enm != NULL) { 1377 if (nentries >= VIRTIO_NET_CTRL_MAC_MAXENTRIES) { 1378 allmulti = 1; 1379 goto set; 1380 } 1381 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 1382 ETHER_ADDR_LEN)) { 1383 allmulti = 1; 1384 goto set; 1385 } 1386 memcpy(sc->sc_ctrl_mac_tbl_mc->macs[nentries], 1387 enm->enm_addrlo, ETHER_ADDR_LEN); 1388 ETHER_NEXT_MULTI(step, enm); 1389 } 1390 rxfilter = 1; 1391 1392set: 1393 if (rxfilter) { 1394 sc->sc_ctrl_mac_tbl_uc->nentries = 0; 1395 sc->sc_ctrl_mac_tbl_mc->nentries = nentries; 1396 r = vioif_set_rx_filter(sc); 1397 if (r != 0) { 1398 rxfilter = 0; 1399 allmulti = 1; /* fallback */ 1400 } 1401 } else { 1402 /* remove rx filter */ 1403 sc->sc_ctrl_mac_tbl_uc->nentries = 0; 1404 sc->sc_ctrl_mac_tbl_mc->nentries = 0; 1405 r = vioif_set_rx_filter(sc); 1406 /* what to do on failure? */ 1407 } 1408 if (allmulti) { 1409 r = vioif_set_allmulti(sc, true); 1410 if (r != 0) { 1411 allmulti = 0; 1412 promisc = 1; /* fallback */ 1413 } 1414 } else { 1415 r = vioif_set_allmulti(sc, false); 1416 /* what to do on failure? */ 1417 } 1418 if (promisc) { 1419 r = vioif_set_promisc(sc, true); 1420 } else { 1421 r = vioif_set_promisc(sc, false); 1422 } 1423 1424 return r; 1425} 1426 1427/* change link status */ 1428static int 1429vioif_updown(struct vioif_softc *sc, bool isup) 1430{ 1431 struct virtio_softc *vsc = sc->sc_virtio; 1432 1433 if (!(vsc->sc_features & VIRTIO_NET_F_STATUS)) 1434 return ENODEV; 1435 virtio_write_device_config_1(vsc, 1436 VIRTIO_NET_CONFIG_STATUS, 1437 isup?VIRTIO_NET_S_LINK_UP:0); 1438 return 0; 1439} 1440