1 /*- 2 * Copyright (c) 2009-2012 Microsoft Corp. 3 * Copyright (c) 2010-2012 Citrix Inc. 4 * Copyright (c) 2012 NetApp Inc. 5 * Copyright (c) 2016 Mike Belopuhov <mike@esdenera.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice unmodified, this list of conditions, and the following 13 * disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * The OpenBSD port was done under funding by Esdenera Networks GmbH. 32 */ 33 34 #include "bpfilter.h" 35 #include "vlan.h" 36 #include "hyperv.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/atomic.h> 41 #include <sys/device.h> 42 #include <sys/kernel.h> 43 #include <sys/malloc.h> 44 #include <sys/mbuf.h> 45 #include <sys/pool.h> 46 #include <sys/queue.h> 47 #include <sys/socket.h> 48 #include <sys/sockio.h> 49 #include <sys/task.h> 50 #include <sys/timeout.h> 51 52 #include <machine/bus.h> 53 54 #include <uvm/uvm_extern.h> 55 56 #include <dev/pv/hypervreg.h> 57 #include <dev/pv/hypervvar.h> 58 #include <dev/pv/rndisreg.h> 59 #include <dev/pv/if_hvnreg.h> 60 61 #include <net/if.h> 62 #include <net/if_media.h> 63 64 #include <netinet/in.h> 65 #include <netinet/if_ether.h> 66 67 #ifdef INET6 68 #include <netinet/ip6.h> 69 #endif 70 71 #if NBPFILTER > 0 72 #include <net/bpf.h> 73 #endif 74 75 #define HVN_DEBUG 1 76 77 #define HVN_NVS_BUFSIZE PAGE_SIZE 78 #define HVN_NVS_MSGSIZE 32 79 80 /* 81 * RNDIS control interface 82 */ 83 #define HVN_RNDIS_CTLREQS 4 84 #define HVN_RNDIS_CMPBUFSZ 512 85 86 struct rndis_cmd { 87 uint32_t rc_id; 88 struct hvn_nvs_rndis rc_msg; 89 struct rndis *rc_req; 90 bus_dmamap_t rc_dmap; 91 uint64_t rc_pfn; 92 struct rndis rc_cmp; 93 uint32_t rc_cmplen; 94 uint8_t rc_cmpbuf[HVN_RNDIS_CMPBUFSZ]; 95 struct mutex rc_mtx; 96 TAILQ_ENTRY(rndis_cmd) rc_entry; 97 }; 98 TAILQ_HEAD(rndis_queue, rndis_cmd); 99 100 /* 101 * Tx ring 102 */ 103 #define HVN_TX_DESC 128 104 105 struct hvn_softc { 106 struct device sc_dev; 107 struct hv_softc *sc_hvsc; 108 struct hv_channel *sc_chan; 109 bus_dma_tag_t sc_dmat; 110 111 struct arpcom sc_ac; 112 struct ifmedia sc_media; 113 int sc_link_state; 114 int sc_promisc; 115 116 /* NVS protocol */ 117 int sc_proto; 118 uint32_t sc_nvstid; 119 uint8_t sc_nvsrsp[HVN_NVS_MSGSIZE]; 120 uint8_t *sc_nvsbuf; 121 struct mutex sc_nvslck; 122 123 /* RNDIS protocol */ 124 uint32_t sc_rndisrid; 125 struct rndis_queue sc_cntl_sq; /* submission queue */ 126 struct mutex sc_cntl_sqlck; 127 struct rndis_queue sc_cntl_cq; /* completion queue */ 128 struct mutex sc_cntl_cqlck; 129 struct rndis_queue sc_cntl_fq; /* free queue */ 130 struct mutex sc_cntl_fqlck; 131 struct rndis_cmd sc_cntl_msgs[HVN_RNDIS_CTLREQS]; 132 133 /* Rx ring */ 134 void *sc_rx_ring; 135 int sc_rx_size; 136 uint32_t sc_rx_hndl; 137 138 /* Tx ring */ 139 void *sc_tx_ring; 140 int sc_tx_size; 141 uint32_t sc_tx_hndl; 142 }; 143 144 int hvn_match(struct device *, void *, void *); 145 void hvn_attach(struct device *, struct device *, void *); 146 int hvn_ioctl(struct ifnet *, u_long, caddr_t); 147 int hvn_media_change(struct ifnet *); 148 void hvn_media_status(struct ifnet *, struct ifmediareq *); 149 int hvn_iff(struct hvn_softc *); 150 void hvn_init(struct hvn_softc *); 151 void hvn_stop(struct hvn_softc *); 152 void hvn_start(struct ifnet *); 153 void hvn_txeof(struct hvn_softc *, uint64_t); 154 void hvn_rxeof(struct hvn_softc *, void *); 155 int hvn_rx_ring_create(struct hvn_softc *); 156 int hvn_rx_ring_destroy(struct hvn_softc *); 157 int hvn_tx_ring_create(struct hvn_softc *); 158 int hvn_tx_ring_destroy(struct hvn_softc *); 159 int hvn_get_lladdr(struct hvn_softc *); 160 int hvn_set_lladdr(struct hvn_softc *); 161 void hvn_get_link_status(struct hvn_softc *); 162 void hvn_link_status(struct hvn_softc *); 163 164 /* NSVP */ 165 int hvn_nvs_attach(struct hvn_softc *); 166 void hvn_nvs_intr(void *); 167 int hvn_nvs_cmd(struct hvn_softc *, void *, size_t, uint64_t, int); 168 int hvn_nvs_ack(struct hvn_softc *, uint64_t); 169 void hvn_nvs_detach(struct hvn_softc *); 170 171 /* RNDIS */ 172 int hvn_rndis_attach(struct hvn_softc *); 173 int hvn_rndis_cmd(struct hvn_softc *, struct rndis_cmd *, int); 174 void hvn_rndis_filter(struct hvn_softc *sc, uint64_t, void *); 175 void hvn_rndis_input(struct hvn_softc *, caddr_t, uint32_t, 176 struct mbuf_list *); 177 void hvn_rndis_complete(struct hvn_softc *, caddr_t, uint32_t); 178 void hvn_rndis_status(struct hvn_softc *, caddr_t, uint32_t); 179 int hvn_rndis_query(struct hvn_softc *, uint32_t, void *, size_t *); 180 int hvn_rndis_set(struct hvn_softc *, uint32_t, void *, size_t); 181 int hvn_rndis_open(struct hvn_softc *); 182 int hvn_rndis_close(struct hvn_softc *); 183 void hvn_rndis_detach(struct hvn_softc *); 184 185 struct cfdriver hvn_cd = { 186 NULL, "hvn", DV_IFNET 187 }; 188 189 const struct cfattach hvn_ca = { 190 sizeof(struct hvn_softc), hvn_match, hvn_attach 191 }; 192 193 int 194 hvn_match(struct device *parent, void *match, void *aux) 195 { 196 struct hv_attach_args *aa = aux; 197 198 if (strcmp("network", aa->aa_ident)) 199 return (0); 200 201 return (1); 202 } 203 204 void 205 hvn_attach(struct device *parent, struct device *self, void *aux) 206 { 207 struct hv_attach_args *aa = aux; 208 struct hvn_softc *sc = (struct hvn_softc *)self; 209 struct ifnet *ifp = &sc->sc_ac.ac_if; 210 211 sc->sc_hvsc = (struct hv_softc *)parent; 212 sc->sc_chan = aa->aa_chan; 213 sc->sc_dmat = aa->aa_dmat; 214 215 strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); 216 217 DPRINTF("\n"); 218 219 if (hvn_nvs_attach(sc)) { 220 printf(": failed to init NVSP\n"); 221 return; 222 } 223 224 if (hvn_rx_ring_create(sc)) { 225 printf(": failed to create Rx ring\n"); 226 goto detach; 227 } 228 229 if (hvn_tx_ring_create(sc)) { 230 printf(": failed to create Tx ring\n"); 231 goto detach; 232 } 233 234 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 235 ifp->if_xflags = IFXF_MPSAFE; 236 ifp->if_ioctl = hvn_ioctl; 237 ifp->if_start = hvn_start; 238 ifp->if_softc = sc; 239 240 ifp->if_capabilities = IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | 241 IFCAP_CSUM_UDPv4; 242 #if NVLAN > 0 243 ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 244 #endif 245 246 IFQ_SET_MAXLEN(&ifp->if_snd, HVN_TX_DESC - 1); 247 248 ifmedia_init(&sc->sc_media, IFM_IMASK, hvn_media_change, 249 hvn_media_status); 250 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 251 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); 252 253 if_attach(ifp); 254 255 if (hvn_rndis_attach(sc)) { 256 printf(": failed to init RNDIS\n"); 257 goto detach; 258 } 259 260 if (hvn_get_lladdr(sc)) { 261 printf(": failed to obtain an ethernet address\n"); 262 hvn_rndis_detach(sc); 263 goto detach; 264 } 265 266 DPRINTF("%s", sc->sc_dev.dv_xname); 267 printf(": channel %u, address %s\n", sc->sc_chan->ch_id, 268 ether_sprintf(sc->sc_ac.ac_enaddr)); 269 270 ether_ifattach(ifp); 271 return; 272 273 detach: 274 hvn_rx_ring_destroy(sc); 275 hvn_tx_ring_destroy(sc); 276 hvn_nvs_detach(sc); 277 if (ifp->if_start) 278 if_detach(ifp); 279 } 280 281 int 282 hvn_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 283 { 284 struct hvn_softc *sc = ifp->if_softc; 285 struct ifreq *ifr = (struct ifreq *)data; 286 int s, error = 0; 287 288 s = splnet(); 289 290 switch (command) { 291 case SIOCSIFADDR: 292 ifp->if_flags |= IFF_UP; 293 if (!(ifp->if_flags & IFF_RUNNING)) 294 hvn_init(sc); 295 break; 296 case SIOCSIFFLAGS: 297 if (ifp->if_flags & IFF_UP) { 298 if (ifp->if_flags & IFF_RUNNING) 299 error = ENETRESET; 300 else 301 hvn_init(sc); 302 } else { 303 if (ifp->if_flags & IFF_RUNNING) 304 hvn_stop(sc); 305 } 306 break; 307 case SIOCGIFMEDIA: 308 case SIOCSIFMEDIA: 309 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command); 310 break; 311 default: 312 error = ether_ioctl(ifp, &sc->sc_ac, command, data); 313 } 314 315 if (error == ENETRESET) { 316 if (ifp->if_flags & IFF_RUNNING) 317 hvn_iff(sc); 318 error = 0; 319 } 320 321 splx(s); 322 323 return (error); 324 } 325 326 int 327 hvn_media_change(struct ifnet *ifp) 328 { 329 return (0); 330 } 331 332 void 333 hvn_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 334 { 335 struct hvn_softc *sc = ifp->if_softc; 336 337 hvn_get_link_status(sc); 338 hvn_link_status(sc); 339 340 ifmr->ifm_status = IFM_AVALID; 341 ifmr->ifm_active = IFM_ETHER | IFM_MANUAL; 342 if (sc->sc_link_state == LINK_STATE_UP) 343 ifmr->ifm_status |= IFM_ACTIVE; 344 } 345 346 void 347 hvn_link_status(struct hvn_softc *sc) 348 { 349 struct ifnet *ifp = &sc->sc_ac.ac_if; 350 351 if (sc->sc_link_state != ifp->if_link_state) { 352 ifp->if_link_state = sc->sc_link_state; 353 if_link_state_change(ifp); 354 } 355 } 356 357 int 358 hvn_iff(struct hvn_softc *sc) 359 { 360 /* XXX */ 361 sc->sc_promisc = 0; 362 363 return (0); 364 } 365 366 void 367 hvn_init(struct hvn_softc *sc) 368 { 369 struct ifnet *ifp = &sc->sc_ac.ac_if; 370 371 hvn_stop(sc); 372 373 hvn_iff(sc); 374 375 if (hvn_rndis_open(sc) == 0) { 376 ifp->if_flags |= IFF_RUNNING; 377 ifq_clr_oactive(&ifp->if_snd); 378 } 379 } 380 381 void 382 hvn_stop(struct hvn_softc *sc) 383 { 384 struct ifnet *ifp = &sc->sc_ac.ac_if; 385 386 if (ifp->if_flags & IFF_RUNNING) { 387 ifp->if_flags &= ~IFF_RUNNING; 388 hvn_rndis_close(sc); 389 } 390 391 ifq_barrier(&ifp->if_snd); 392 intr_barrier(sc->sc_chan); 393 394 ifq_clr_oactive(&ifp->if_snd); 395 } 396 397 void 398 hvn_start(struct ifnet *ifp) 399 { 400 struct mbuf *m; 401 402 if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) 403 return; 404 405 for (;;) { 406 m = ifq_deq_begin(&ifp->if_snd); 407 if (m == NULL) 408 break; 409 410 ifq_deq_commit(&ifp->if_snd, m); 411 412 #if NBPFILTER > 0 413 if (ifp->if_bpf) 414 bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT); 415 #endif 416 417 m_freem(m); 418 ifp->if_oerrors++; 419 } 420 } 421 422 void 423 hvn_txeof(struct hvn_softc *sc, uint64_t tid) 424 { 425 struct ifnet *ifp = &sc->sc_ac.ac_if; 426 427 printf("%s: tx tid %llu\n", ifp->if_xname, tid); 428 } 429 430 int 431 hvn_rx_ring_create(struct hvn_softc *sc) 432 { 433 struct hvn_nvs_rxbuf_conn cmd; 434 struct hvn_nvs_rxbuf_conn_resp *rsp; 435 uint64_t tid; 436 437 if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_2) 438 sc->sc_rx_size = 15 * 1024 * 1024; /* 15MB */ 439 else 440 sc->sc_rx_size = 16 * 1024 * 1024; /* 16MB */ 441 sc->sc_rx_ring = km_alloc(sc->sc_rx_size, &kv_any, &kp_zero, 442 cold ? &kd_nowait : &kd_waitok); 443 if (sc->sc_rx_ring == NULL) { 444 DPRINTF("%s: failed to allocate Rx ring buffer\n", 445 sc->sc_dev.dv_xname); 446 return (-1); 447 } 448 if (hv_handle_alloc(sc->sc_chan, sc->sc_rx_ring, sc->sc_rx_size, 449 &sc->sc_rx_hndl)) { 450 DPRINTF("%s: failed to obtain a PA handle\n", 451 sc->sc_dev.dv_xname); 452 goto errout; 453 } 454 455 memset(&cmd, 0, sizeof(cmd)); 456 cmd.nvs_type = HVN_NVS_TYPE_RXBUF_CONN; 457 cmd.nvs_gpadl = sc->sc_rx_hndl; 458 cmd.nvs_sig = HVN_NVS_RXBUF_SIG; 459 460 tid = atomic_inc_int_nv(&sc->sc_nvstid); 461 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) 462 goto errout; 463 464 rsp = (struct hvn_nvs_rxbuf_conn_resp *)&sc->sc_nvsrsp; 465 if (rsp->nvs_status != HVN_NVS_STATUS_OK) { 466 DPRINTF("%s: failed to set up the Rx ring\n", 467 sc->sc_dev.dv_xname); 468 goto errout; 469 } 470 if (rsp->nvs_nsect > 1) { 471 DPRINTF("%s: invalid number of Rx ring sections: %d\n", 472 sc->sc_dev.dv_xname, rsp->nvs_nsect); 473 hvn_rx_ring_destroy(sc); 474 return (-1); 475 } 476 return (0); 477 478 errout: 479 if (sc->sc_rx_hndl) { 480 hv_handle_free(sc->sc_chan, sc->sc_rx_hndl); 481 sc->sc_rx_hndl = 0; 482 } 483 if (sc->sc_rx_ring) { 484 km_free(sc->sc_rx_ring, sc->sc_rx_size, &kv_any, &kp_zero); 485 sc->sc_rx_ring = NULL; 486 } 487 return (-1); 488 } 489 490 int 491 hvn_rx_ring_destroy(struct hvn_softc *sc) 492 { 493 struct hvn_nvs_rxbuf_disconn cmd; 494 uint64_t tid; 495 496 if (sc->sc_rx_ring == NULL) 497 return (0); 498 499 memset(&cmd, 0, sizeof(cmd)); 500 cmd.nvs_type = HVN_NVS_TYPE_RXBUF_DISCONN; 501 cmd.nvs_sig = HVN_NVS_RXBUF_SIG; 502 503 tid = atomic_inc_int_nv(&sc->sc_nvstid); 504 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 0)) 505 return (-1); 506 507 delay(100); 508 509 hv_handle_free(sc->sc_chan, sc->sc_rx_hndl); 510 511 sc->sc_rx_hndl = 0; 512 513 km_free(sc->sc_rx_ring, sc->sc_rx_size, &kv_any, &kp_zero); 514 sc->sc_rx_ring = NULL; 515 516 return (0); 517 } 518 519 int 520 hvn_tx_ring_create(struct hvn_softc *sc) 521 { 522 struct hvn_nvs_chim_conn cmd; 523 struct hvn_nvs_chim_conn_resp *rsp; 524 uint64_t tid; 525 526 sc->sc_tx_size = 15 * 1024 * 1024; /* 15MB */ 527 sc->sc_tx_ring = km_alloc(sc->sc_tx_size, &kv_any, &kp_zero, 528 cold ? &kd_nowait : &kd_waitok); 529 if (sc->sc_tx_ring == NULL) { 530 DPRINTF("%s: failed to allocate Tx ring buffer\n", 531 sc->sc_dev.dv_xname); 532 return (-1); 533 } 534 if (hv_handle_alloc(sc->sc_chan, sc->sc_tx_ring, sc->sc_tx_size, 535 &sc->sc_tx_hndl)) { 536 DPRINTF("%s: failed to obtain a PA handle\n", 537 sc->sc_dev.dv_xname); 538 goto errout; 539 } 540 541 memset(&cmd, 0, sizeof(cmd)); 542 cmd.nvs_type = HVN_NVS_TYPE_CHIM_CONN; 543 cmd.nvs_gpadl = sc->sc_tx_hndl; 544 cmd.nvs_sig = HVN_NVS_CHIM_SIG; 545 546 tid = atomic_inc_int_nv(&sc->sc_nvstid); 547 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) 548 goto errout; 549 550 rsp = (struct hvn_nvs_chim_conn_resp *)&sc->sc_nvsrsp; 551 if (rsp->nvs_status != HVN_NVS_STATUS_OK) { 552 DPRINTF("%s: failed to set up the Tx ring\n", 553 sc->sc_dev.dv_xname); 554 goto errout; 555 } 556 return (0); 557 558 errout: 559 if (sc->sc_tx_hndl) { 560 hv_handle_free(sc->sc_chan, sc->sc_tx_hndl); 561 sc->sc_tx_hndl = 0; 562 } 563 if (sc->sc_tx_ring) { 564 km_free(sc->sc_tx_ring, sc->sc_tx_size, &kv_any, &kp_zero); 565 sc->sc_tx_ring = NULL; 566 } 567 return (-1); 568 } 569 570 int 571 hvn_tx_ring_destroy(struct hvn_softc *sc) 572 { 573 struct hvn_nvs_chim_disconn cmd; 574 uint64_t tid; 575 576 if (sc->sc_tx_ring == NULL) 577 return (0); 578 579 memset(&cmd, 0, sizeof(cmd)); 580 cmd.nvs_type = HVN_NVS_TYPE_CHIM_DISCONN; 581 cmd.nvs_sig = HVN_NVS_CHIM_SIG; 582 583 tid = atomic_inc_int_nv(&sc->sc_nvstid); 584 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 0)) 585 return (-1); 586 587 delay(100); 588 589 hv_handle_free(sc->sc_chan, sc->sc_tx_hndl); 590 591 sc->sc_tx_hndl = 0; 592 593 km_free(sc->sc_tx_ring, sc->sc_tx_size, &kv_any, &kp_zero); 594 sc->sc_tx_ring = NULL; 595 return (0); 596 } 597 598 int 599 hvn_get_lladdr(struct hvn_softc *sc) 600 { 601 char enaddr[ETHER_ADDR_LEN]; 602 size_t addrlen = ETHER_ADDR_LEN; 603 int rv; 604 605 rv = hvn_rndis_query(sc, RNDIS_OID_802_3_PERMANENT_ADDRESS, 606 enaddr, &addrlen); 607 if (rv == 0 && addrlen == ETHER_ADDR_LEN) 608 memcpy(sc->sc_ac.ac_enaddr, enaddr, ETHER_ADDR_LEN); 609 return (rv); 610 } 611 612 int 613 hvn_set_lladdr(struct hvn_softc *sc) 614 { 615 return (hvn_rndis_set(sc, RNDIS_OID_802_3_CURRENT_ADDRESS, 616 sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN)); 617 } 618 619 void 620 hvn_get_link_status(struct hvn_softc *sc) 621 { 622 uint32_t state; 623 size_t len = sizeof(state); 624 625 if (hvn_rndis_query(sc, RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, 626 &state, &len) == 0) 627 sc->sc_link_state = (state == 0) ? LINK_STATE_UP : 628 LINK_STATE_DOWN; 629 } 630 631 int 632 hvn_nvs_attach(struct hvn_softc *sc) 633 { 634 const uint32_t protos[] = { 635 HVN_NVS_PROTO_VERSION_5, HVN_NVS_PROTO_VERSION_4, 636 HVN_NVS_PROTO_VERSION_2, HVN_NVS_PROTO_VERSION_1 637 }; 638 struct hvn_nvs_init cmd; 639 struct hvn_nvs_init_resp *rsp; 640 struct hvn_nvs_ndis_init ncmd; 641 uint64_t tid; 642 uint32_t ndisver; 643 int i; 644 645 /* 4 page sized buffer for channel messages */ 646 sc->sc_nvsbuf = km_alloc(HVN_NVS_BUFSIZE, &kv_any, &kp_zero, 647 (cold ? &kd_nowait : &kd_waitok)); 648 if (sc->sc_nvsbuf == NULL) { 649 DPRINTF("%s: failed to allocate channel data buffer\n", 650 sc->sc_dev.dv_xname); 651 return (-1); 652 } 653 sc->sc_chan->ch_buflen = PAGE_SIZE * 4; 654 655 /* Associate our interrupt handler with the channel */ 656 if (hv_channel_open(sc->sc_chan, NULL, 0, hvn_nvs_intr, sc)) { 657 DPRINTF("%s: failed to open channel\n", sc->sc_dev.dv_xname); 658 km_free(sc->sc_nvsbuf, HVN_NVS_BUFSIZE, &kv_any, &kp_zero); 659 return (-1); 660 } 661 662 mtx_init(&sc->sc_nvslck, IPL_NET); 663 664 memset(&cmd, 0, sizeof(cmd)); 665 cmd.nvs_type = HVN_NVS_TYPE_INIT; 666 for (i = 0; i < nitems(protos); i++) { 667 cmd.nvs_ver_min = cmd.nvs_ver_max = protos[i]; 668 tid = atomic_inc_int_nv(&sc->sc_nvstid); 669 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) 670 return (-1); 671 rsp = (struct hvn_nvs_init_resp *)&sc->sc_nvsrsp; 672 if (rsp->nvs_status == HVN_NVS_STATUS_OK) { 673 sc->sc_proto = protos[i]; 674 break; 675 } 676 } 677 if (!sc->sc_proto) { 678 DPRINTF("%s: failed to negotiate NVSP version\n", 679 sc->sc_dev.dv_xname); 680 return (-1); 681 } 682 683 memset(&ncmd, 0, sizeof(ncmd)); 684 ncmd.nvs_type = HVN_NVS_TYPE_NDIS_INIT; 685 if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_4) 686 ndisver = NDIS_VERSION_6_1; 687 else 688 ndisver = NDIS_VERSION_6_30; 689 ncmd.nvs_ndis_major = (ndisver & 0xffff0000) >> 16; 690 ncmd.nvs_ndis_minor = (ndisver & 0x0000ffff); 691 692 tid = atomic_inc_int_nv(&sc->sc_nvstid); 693 if (hvn_nvs_cmd(sc, &ncmd, sizeof(ncmd), tid, 100)) 694 return (-1); 695 696 DPRINTF("%s: NVSP %u.%u, NDIS %u.%u\n", sc->sc_dev.dv_xname, 697 sc->sc_proto >> 16, sc->sc_proto & 0xffff, 698 ndisver >> 16, ndisver & 0xffff); 699 700 return (0); 701 } 702 703 void 704 hvn_nvs_intr(void *arg) 705 { 706 struct hvn_softc *sc = arg; 707 struct vmbus_chanpkt_hdr *cph; 708 struct hvn_nvs_hdr *nvs; 709 uint64_t rid; 710 uint32_t rlen; 711 int rv; 712 713 for (;;) { 714 rv = hv_channel_recv(sc->sc_chan, sc->sc_nvsbuf, 715 HVN_NVS_BUFSIZE, &rlen, &rid, 1); 716 if (rv != 0 || rlen == 0) { 717 if (rv != EAGAIN) 718 printf("%s: failed to receive an NVSP " 719 "packet\n", sc->sc_dev.dv_xname); 720 break; 721 } 722 cph = (struct vmbus_chanpkt_hdr *)sc->sc_nvsbuf; 723 nvs = (struct hvn_nvs_hdr *)VMBUS_CHANPKT_CONST_DATA(cph); 724 725 if (cph->cph_type == VMBUS_CHANPKT_TYPE_COMP) { 726 switch (nvs->nvs_type) { 727 case HVN_NVS_TYPE_INIT_RESP: 728 case HVN_NVS_TYPE_RXBUF_CONNRESP: 729 case HVN_NVS_TYPE_CHIM_CONNRESP: 730 case HVN_NVS_TYPE_SUBCH_RESP: 731 /* copy the response back */ 732 memcpy(&sc->sc_nvsrsp, nvs, HVN_NVS_MSGSIZE); 733 wakeup_one(&sc->sc_nvsrsp); 734 break; 735 case HVN_NVS_TYPE_RNDIS_ACK: 736 hvn_txeof(sc, cph->cph_tid); 737 break; 738 default: 739 printf("%s: unhandled NVSP packet type %d " 740 "on completion\n", sc->sc_dev.dv_xname, 741 nvs->nvs_type); 742 } 743 } else if (cph->cph_type == VMBUS_CHANPKT_TYPE_RXBUF) { 744 switch (nvs->nvs_type) { 745 case HVN_NVS_TYPE_RNDIS: 746 hvn_rndis_filter(sc, cph->cph_tid, cph); 747 break; 748 default: 749 printf("%s: unhandled NVSP packet type %d " 750 "on receive\n", sc->sc_dev.dv_xname, 751 nvs->nvs_type); 752 } 753 } else 754 printf("%s: unknown NVSP packet type %u\n", 755 sc->sc_dev.dv_xname, cph->cph_type); 756 } 757 } 758 759 int 760 hvn_nvs_cmd(struct hvn_softc *sc, void *cmd, size_t cmdsize, uint64_t tid, 761 int timo) 762 { 763 struct hvn_nvs_hdr *hdr = cmd; 764 int tries = 10; 765 int rv; 766 767 do { 768 rv = hv_channel_send(sc->sc_chan, cmd, cmdsize, 769 tid, VMBUS_CHANPKT_TYPE_INBAND, 770 timo ? VMBUS_CHANPKT_FLAG_RC : 0); 771 if (rv == EAGAIN) { 772 if (timo) 773 tsleep(cmd, PRIBIO, "hvnsend", timo / 10); 774 else 775 delay(100); 776 } else if (rv) { 777 DPRINTF("%s: NVSP operation %d send error %d\n", 778 sc->sc_dev.dv_xname, hdr->nvs_type, rv); 779 return (rv); 780 } 781 } while (rv != 0 && --tries > 0); 782 783 if (timo) { 784 mtx_enter(&sc->sc_nvslck); 785 rv = msleep(&sc->sc_nvsrsp, &sc->sc_nvslck, PRIBIO, "hvnvsp", 786 timo); 787 mtx_leave(&sc->sc_nvslck); 788 #ifdef HVN_DEBUG 789 switch (rv) { 790 case EINTR: 791 rv = 0; 792 break; 793 case EWOULDBLOCK: 794 printf("%s: NVSP opertaion %d timed out\n", 795 sc->sc_dev.dv_xname, hdr->nvs_type); 796 } 797 } 798 #endif 799 return (rv); 800 } 801 802 int 803 hvn_nvs_ack(struct hvn_softc *sc, uint64_t tid) 804 { 805 struct hvn_nvs_rndis_ack cmd; 806 int tries = 5; 807 int rv; 808 809 cmd.nvs_type = HVN_NVS_TYPE_RNDIS_ACK; 810 cmd.nvs_status = HVN_NVS_STATUS_OK; 811 do { 812 rv = hv_channel_send(sc->sc_chan, &cmd, sizeof(cmd), 813 tid, VMBUS_CHANPKT_TYPE_COMP, 0); 814 if (rv == EAGAIN) 815 delay(100); 816 else if (rv) { 817 DPRINTF("%s: NVSP acknowledgement error %d\n", 818 sc->sc_dev.dv_xname, rv); 819 return (rv); 820 } 821 } while (rv != 0 && --tries > 0); 822 return (rv); 823 } 824 825 void 826 hvn_nvs_detach(struct hvn_softc *sc) 827 { 828 if (hv_channel_close(sc->sc_chan) == 0) { 829 km_free(sc->sc_nvsbuf, HVN_NVS_BUFSIZE, &kv_any, &kp_zero); 830 sc->sc_nvsbuf = NULL; 831 } 832 } 833 834 static inline struct rndis_cmd * 835 hvn_alloc_cmd(struct hvn_softc *sc) 836 { 837 struct rndis_cmd *rc; 838 839 mtx_enter(&sc->sc_cntl_fqlck); 840 while ((rc = TAILQ_FIRST(&sc->sc_cntl_fq)) == NULL) 841 msleep(&sc->sc_cntl_fq, &sc->sc_cntl_fqlck, 842 PRIBIO, "hvnrr", 1); 843 TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry); 844 mtx_leave(&sc->sc_cntl_fqlck); 845 return (rc); 846 } 847 848 static inline void 849 hvn_submit_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 850 { 851 mtx_enter(&sc->sc_cntl_sqlck); 852 TAILQ_INSERT_TAIL(&sc->sc_cntl_sq, rc, rc_entry); 853 mtx_leave(&sc->sc_cntl_sqlck); 854 } 855 856 static inline struct rndis_cmd * 857 hvn_complete_cmd(struct hvn_softc *sc, uint32_t id) 858 { 859 struct rndis_cmd *rc; 860 861 mtx_enter(&sc->sc_cntl_sqlck); 862 TAILQ_FOREACH(rc, &sc->sc_cntl_sq, rc_entry) { 863 if (rc->rc_id == id) { 864 TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry); 865 break; 866 } 867 } 868 mtx_leave(&sc->sc_cntl_sqlck); 869 if (rc != NULL) { 870 mtx_enter(&sc->sc_cntl_cqlck); 871 TAILQ_INSERT_TAIL(&sc->sc_cntl_cq, rc, rc_entry); 872 mtx_leave(&sc->sc_cntl_cqlck); 873 } 874 return (rc); 875 } 876 877 static inline int 878 hvn_rollback_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 879 { 880 struct rndis_cmd *rn; 881 882 mtx_enter(&sc->sc_cntl_sqlck); 883 TAILQ_FOREACH(rn, &sc->sc_cntl_sq, rc_entry) { 884 if (rn == rc) { 885 TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry); 886 mtx_leave(&sc->sc_cntl_sqlck); 887 return (0); 888 } 889 } 890 mtx_leave(&sc->sc_cntl_sqlck); 891 return (-1); 892 } 893 894 static inline void 895 hvn_free_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 896 { 897 memset(rc->rc_req, 0, sizeof(*rc->rc_req)); 898 memset(&rc->rc_cmp, 0, sizeof(rc->rc_cmp)); 899 memset(&rc->rc_msg, 0, sizeof(rc->rc_msg)); 900 mtx_enter(&sc->sc_cntl_fqlck); 901 TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry); 902 mtx_leave(&sc->sc_cntl_fqlck); 903 wakeup(&sc->sc_cntl_fq); 904 } 905 906 int 907 hvn_rndis_attach(struct hvn_softc *sc) 908 { 909 struct rndis_init_req *req; 910 struct rndis_init_comp *cmp; 911 struct rndis_cmd *rc; 912 int i, rv; 913 914 /* RNDIS control message queues */ 915 TAILQ_INIT(&sc->sc_cntl_sq); 916 TAILQ_INIT(&sc->sc_cntl_cq); 917 TAILQ_INIT(&sc->sc_cntl_fq); 918 mtx_init(&sc->sc_cntl_sqlck, IPL_NET); 919 mtx_init(&sc->sc_cntl_cqlck, IPL_NET); 920 mtx_init(&sc->sc_cntl_fqlck, IPL_NET); 921 922 for (i = 0; i < HVN_RNDIS_CTLREQS; i++) { 923 rc = &sc->sc_cntl_msgs[i]; 924 if (bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, 925 PAGE_SIZE, 0, BUS_DMA_WAITOK, &rc->rc_dmap)) { 926 DPRINTF("%s: failed to create RNDIS command map\n", 927 sc->sc_dev.dv_xname); 928 goto errout; 929 } 930 rc->rc_req = km_alloc(PAGE_SIZE, &kv_any, &kp_zero, 931 &kd_waitok); 932 if (rc->rc_req == NULL) { 933 DPRINTF("%s: failed to allocate RNDIS command\n", 934 sc->sc_dev.dv_xname); 935 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 936 goto errout; 937 } 938 if (bus_dmamap_load(sc->sc_dmat, rc->rc_dmap, rc->rc_req, 939 PAGE_SIZE, NULL, BUS_DMA_WAITOK)) { 940 DPRINTF("%s: failed to load RNDIS command map\n", 941 sc->sc_dev.dv_xname); 942 km_free(rc->rc_req, PAGE_SIZE, &kv_any, &kp_zero); 943 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 944 goto errout; 945 } 946 rc->rc_pfn = atop(rc->rc_dmap->dm_segs[0].ds_addr); 947 mtx_init(&rc->rc_mtx, IPL_NET); 948 TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry); 949 } 950 951 rc = hvn_alloc_cmd(sc); 952 953 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 954 BUS_DMASYNC_PREREAD); 955 956 rc->rc_req->msg_type = RNDIS_INITIALIZE_MSG; 957 rc->rc_req->msg_len = RNDIS_MESSAGE_SIZE(*req); 958 rc->rc_cmplen = RNDIS_MESSAGE_SIZE(*cmp); 959 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid); 960 req = (struct rndis_init_req *)&rc->rc_req->msg; 961 req->request_id = rc->rc_id; 962 req->major_version = RNDIS_MAJOR_VERSION; 963 req->minor_version = RNDIS_MINOR_VERSION; 964 req->max_xfer_size = 2048; /* XXX */ 965 966 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 967 BUS_DMASYNC_PREWRITE); 968 969 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 970 DPRINTF("%s: INITIALIZE_MSG failed, error %u\n", 971 sc->sc_dev.dv_xname, rv); 972 hvn_free_cmd(sc, rc); 973 goto errout; 974 } 975 cmp = (struct rndis_init_comp *)&rc->rc_cmp.msg; 976 if (cmp->status != RNDIS_STATUS_SUCCESS) { 977 DPRINTF("%s: failed to init RNDIS, error %#x\n", 978 sc->sc_dev.dv_xname, cmp->status); 979 hvn_free_cmd(sc, rc); 980 goto errout; 981 } 982 DPRINTF("%s: RNDIS %u.%u\n", sc->sc_dev.dv_xname, 983 cmp->major_version, cmp->minor_version); 984 985 hvn_free_cmd(sc, rc); 986 987 return (0); 988 989 errout: 990 for (i = 0; i < HVN_RNDIS_CTLREQS; i++) { 991 rc = &sc->sc_cntl_msgs[i]; 992 if (rc->rc_req == NULL) 993 continue; 994 TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry); 995 km_free(rc->rc_req, PAGE_SIZE, &kv_any, &kp_zero); 996 rc->rc_req = NULL; 997 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 998 } 999 return (-1); 1000 } 1001 1002 int 1003 hvn_rndis_cmd(struct hvn_softc *sc, struct rndis_cmd *rc, int timo) 1004 { 1005 struct hvn_nvs_rndis *msg = &rc->rc_msg; 1006 struct vmbus_gpa sgl[1]; 1007 int tries = 10; 1008 int rv; 1009 1010 KASSERT(timo > 0); 1011 1012 msg->nvs_type = HVN_NVS_TYPE_RNDIS; 1013 msg->nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_CTRL; 1014 msg->nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID; 1015 1016 sgl[0].gpa_page = rc->rc_pfn; 1017 sgl[0].gpa_len = rc->rc_req->msg_len; 1018 sgl[0].gpa_ofs = 0; 1019 1020 hvn_submit_cmd(sc, rc); 1021 1022 do { 1023 rv = hv_channel_send_sgl(sc->sc_chan, sgl, 1, &rc->rc_msg, 1024 sizeof(struct hvn_nvs_rndis), rc->rc_id); 1025 if (rv == EAGAIN) 1026 tsleep(rc, PRIBIO, "hvnsendbuf", timo / 10); 1027 else if (rv) { 1028 DPRINTF("%s: RNDIS operation %d send error %d\n", 1029 sc->sc_dev.dv_xname, rc->rc_req->msg_type, rv); 1030 return (rv); 1031 } 1032 } while (rv != 0 && --tries > 0); 1033 1034 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1035 BUS_DMASYNC_POSTWRITE); 1036 1037 mtx_enter(&rc->rc_mtx); 1038 rv = msleep(rc, &rc->rc_mtx, PRIBIO, "rndisctl", timo); 1039 mtx_leave(&rc->rc_mtx); 1040 1041 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1042 BUS_DMASYNC_POSTREAD); 1043 1044 #ifdef HVN_DEBUG 1045 switch (rv) { 1046 case EINTR: 1047 rv = 0; 1048 break; 1049 case EWOULDBLOCK: 1050 if (hvn_rollback_cmd(sc, rc)) { 1051 /* failed to rollback? go for one sleep cycle */ 1052 tsleep(rc, PRIBIO, "rndisctl2", 1); 1053 rv = 0; 1054 break; 1055 } 1056 printf("%s: RNDIS opertaion %d timed out\n", sc->sc_dev.dv_xname, 1057 rc->rc_req->msg_type); 1058 } 1059 #endif 1060 return (rv); 1061 } 1062 1063 void 1064 hvn_rndis_filter(struct hvn_softc *sc, uint64_t tid, void *arg) 1065 { 1066 struct ifnet *ifp = &sc->sc_ac.ac_if; 1067 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 1068 struct vmbus_chanpkt_prplist *cp = arg; 1069 uint32_t off, len, type; 1070 int i; 1071 1072 if (sc->sc_rx_ring == NULL) { 1073 DPRINTF("%s: invalid rx ring\n", sc->sc_dev.dv_xname); 1074 return; 1075 } 1076 for (i = 0; i < cp->cp_range_cnt; i++) { 1077 off = cp->cp_range[i].gpa_ofs; 1078 len = cp->cp_range[i].gpa_len; 1079 1080 KASSERT(off + len <= sc->sc_rx_size); 1081 KASSERT(len >= RNDIS_HEADER_SIZE + 4); 1082 1083 memcpy(&type, (caddr_t)sc->sc_rx_ring + off, sizeof(type)); 1084 switch (type) { 1085 /* data message */ 1086 case RNDIS_PACKET_MSG: 1087 hvn_rndis_input(sc, (caddr_t)sc->sc_rx_ring + 1088 off, len, &ml); 1089 break; 1090 /* completion messages */ 1091 case RNDIS_INITIALIZE_CMPLT: 1092 case RNDIS_QUERY_CMPLT: 1093 case RNDIS_SET_CMPLT: 1094 case RNDIS_RESET_CMPLT: 1095 case RNDIS_KEEPALIVE_CMPLT: 1096 hvn_rndis_complete(sc, (caddr_t)sc->sc_rx_ring + 1097 off, len); 1098 break; 1099 /* notification message */ 1100 case RNDIS_INDICATE_STATUS_MSG: 1101 hvn_rndis_status(sc, (caddr_t)sc->sc_rx_ring + 1102 off, len); 1103 break; 1104 default: 1105 printf("%s: unhandled RNDIS message type %u\n", 1106 sc->sc_dev.dv_xname, type); 1107 } 1108 } 1109 hvn_nvs_ack(sc, tid); 1110 1111 if (MBUF_LIST_FIRST(&ml)) 1112 if_input(ifp, &ml); 1113 } 1114 1115 static inline struct mbuf * 1116 hvn_devget(struct hvn_softc *sc, caddr_t buf, uint32_t len) 1117 { 1118 struct mbuf *m; 1119 1120 if (len + ETHER_ALIGN <= MHLEN) 1121 MGETHDR(m, M_NOWAIT, MT_DATA); 1122 else 1123 m = MCLGETI(NULL, M_NOWAIT, NULL, len + ETHER_ALIGN); 1124 if (m == NULL) 1125 return (NULL); 1126 m->m_len = m->m_pkthdr.len = len; 1127 m_adj(m, ETHER_ALIGN); 1128 1129 if (m_copyback(m, 0, len, buf, M_NOWAIT)) { 1130 m_freem(m); 1131 return (NULL); 1132 } 1133 1134 return (m); 1135 } 1136 1137 void 1138 hvn_rndis_input(struct hvn_softc *sc, caddr_t buf, uint32_t len, 1139 struct mbuf_list *ml) 1140 { 1141 struct ifnet *ifp = &sc->sc_ac.ac_if; 1142 struct rndis_pkt *pkt; 1143 struct rndis_pkt_info *ppi; 1144 struct rndis_tcp_ip_csum_info *csum; 1145 struct ndis_8021q_info *vlan; 1146 struct mbuf *m; 1147 1148 if (!(ifp->if_flags & IFF_RUNNING)) 1149 return; 1150 1151 if (len < RNDIS_HEADER_SIZE + sizeof(*pkt)) { 1152 printf("%s: data packet too short: %u\n", 1153 sc->sc_dev.dv_xname, len); 1154 return; 1155 } 1156 1157 pkt = (struct rndis_pkt *)(buf + RNDIS_HEADER_SIZE); 1158 1159 if (pkt->data_offset + pkt->data_length > len) { 1160 printf("%s: data packet out of bounds: %u@%u\n", 1161 sc->sc_dev.dv_xname, pkt->data_offset, pkt->data_length); 1162 return; 1163 } 1164 1165 if ((m = hvn_devget(sc, buf + RNDIS_HEADER_SIZE + pkt->data_offset, 1166 pkt->data_length)) == NULL) { 1167 ifp->if_ierrors++; 1168 return; 1169 } 1170 1171 while (pkt->pkt_info_length > 0) { 1172 if (pkt->pkt_info_offset + pkt->pkt_info_length > len) { 1173 printf("%s: PPI out of bounds: %u@%u\n", 1174 sc->sc_dev.dv_xname, pkt->pkt_info_length, 1175 pkt->pkt_info_offset); 1176 break; 1177 } 1178 ppi = (struct rndis_pkt_info *)((caddr_t)pkt + 1179 pkt->pkt_info_offset); 1180 if (ppi->size > pkt->pkt_info_length) { 1181 printf("%s: invalid PPI size: %u/%u\n", 1182 sc->sc_dev.dv_xname, ppi->size, 1183 pkt->pkt_info_length); 1184 break; 1185 } 1186 switch (ppi->type) { 1187 case tcpip_chksum_info: 1188 csum = (struct rndis_tcp_ip_csum_info *) 1189 ((caddr_t)ppi + ppi->size); 1190 if (csum->recv.ip_csum_succeeded) 1191 m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; 1192 if (csum->recv.tcp_csum_succeeded) 1193 m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK; 1194 if (csum->recv.udp_csum_succeeded) 1195 m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK; 1196 break; 1197 case ieee_8021q_info: 1198 vlan = (struct ndis_8021q_info *) 1199 ((caddr_t)ppi + ppi->size); 1200 #if NVLAN > 0 1201 m->m_pkthdr.ether_vtag = vlan->vlan_id; 1202 m->m_flags |= M_VLANTAG; 1203 #endif 1204 break; 1205 default: 1206 DPRINTF("%s: unhandled PPI %u\n", sc->sc_dev.dv_xname, 1207 ppi->type); 1208 } 1209 pkt->pkt_info_length -= ppi->size; 1210 } 1211 1212 ml_enqueue(ml, m); 1213 } 1214 1215 void 1216 hvn_rndis_complete(struct hvn_softc *sc, caddr_t buf, uint32_t len) 1217 { 1218 struct rndis_cmd *rc; 1219 uint32_t id; 1220 1221 memcpy(&id, buf + RNDIS_HEADER_SIZE, sizeof(id)); 1222 if ((rc = hvn_complete_cmd(sc, id)) != NULL) { 1223 if (len < rc->rc_cmplen) 1224 printf("%s: RNDIS response %u too short: %u\n", 1225 sc->sc_dev.dv_xname, id, len); 1226 else 1227 memcpy(&rc->rc_cmp, buf, rc->rc_cmplen); 1228 if (len > rc->rc_cmplen && 1229 len - rc->rc_cmplen > HVN_RNDIS_CMPBUFSZ) 1230 printf("%s: RNDIS response %u too large: %u\n", 1231 sc->sc_dev.dv_xname, id, len); 1232 else if (len > rc->rc_cmplen) 1233 memcpy(&rc->rc_cmpbuf, buf + rc->rc_cmplen, 1234 len - rc->rc_cmplen); 1235 wakeup_one(rc); 1236 } else 1237 DPRINTF("%s: failed to complete RNDIS request id %u\n", 1238 sc->sc_dev.dv_xname, id); 1239 } 1240 1241 void 1242 hvn_rndis_status(struct hvn_softc *sc, caddr_t buf, uint32_t len) 1243 { 1244 uint32_t sta; 1245 1246 memcpy(&sta, buf + RNDIS_HEADER_SIZE, sizeof(sta)); 1247 switch (sta) { 1248 case RNDIS_STATUS_MEDIA_CONNECT: 1249 sc->sc_link_state = LINK_STATE_UP; 1250 break; 1251 case RNDIS_STATUS_MEDIA_DISCONNECT: 1252 sc->sc_link_state = LINK_STATE_DOWN; 1253 break; 1254 /* Ignore these */ 1255 case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG: 1256 return; 1257 default: 1258 DPRINTF("%s: unhandled status %#x\n", sc->sc_dev.dv_xname, sta); 1259 return; 1260 } 1261 KERNEL_LOCK(); 1262 hvn_link_status(sc); 1263 KERNEL_UNLOCK(); 1264 } 1265 1266 int 1267 hvn_rndis_query(struct hvn_softc *sc, uint32_t oid, void *res, size_t *length) 1268 { 1269 struct rndis_cmd *rc; 1270 struct rndis_query_req *req; 1271 struct rndis_query_comp *cmp; 1272 size_t olength = *length; 1273 int rv; 1274 1275 rc = hvn_alloc_cmd(sc); 1276 1277 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1278 BUS_DMASYNC_PREREAD); 1279 1280 rc->rc_req->msg_type = RNDIS_QUERY_MSG; 1281 rc->rc_req->msg_len = RNDIS_MESSAGE_SIZE(*req); 1282 rc->rc_cmplen = RNDIS_MESSAGE_SIZE(*cmp); 1283 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid); 1284 req = (struct rndis_query_req *)&rc->rc_req->msg; 1285 req->request_id = rc->rc_id; 1286 req->oid = oid; 1287 req->info_buffer_offset = sizeof(*req); 1288 1289 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1290 BUS_DMASYNC_PREWRITE); 1291 1292 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 1293 DPRINTF("%s: QUERY_MSG failed, error %d\n", 1294 sc->sc_dev.dv_xname, rv); 1295 hvn_free_cmd(sc, rc); 1296 return (rv); 1297 } 1298 1299 cmp = (struct rndis_query_comp *)&rc->rc_cmp.msg; 1300 switch (cmp->status) { 1301 case RNDIS_STATUS_SUCCESS: 1302 if (cmp->info_buffer_length > olength) { 1303 rv = EINVAL; 1304 break; 1305 } 1306 memcpy(res, rc->rc_cmpbuf, cmp->info_buffer_length); 1307 *length = cmp->info_buffer_length; 1308 break; 1309 default: 1310 *length = 0; 1311 rv = EIO; 1312 } 1313 1314 hvn_free_cmd(sc, rc); 1315 1316 return (rv); 1317 } 1318 1319 int 1320 hvn_rndis_set(struct hvn_softc *sc, uint32_t oid, void *data, size_t length) 1321 { 1322 struct rndis_cmd *rc; 1323 struct rndis_set_req *req; 1324 struct rndis_set_comp *cmp; 1325 int rv; 1326 1327 rc = hvn_alloc_cmd(sc); 1328 1329 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1330 BUS_DMASYNC_PREREAD); 1331 1332 rc->rc_req->msg_type = RNDIS_SET_MSG; 1333 rc->rc_req->msg_len = RNDIS_MESSAGE_SIZE(*req) + length; 1334 rc->rc_cmplen = RNDIS_MESSAGE_SIZE(*cmp); 1335 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid); 1336 req = (struct rndis_set_req *)&rc->rc_req->msg; 1337 memset(req, 0, sizeof(*req)); 1338 req->request_id = rc->rc_id; 1339 req->oid = oid; 1340 req->info_buffer_offset = sizeof(*req); 1341 1342 if (length > 0) { 1343 KASSERT(sizeof(*req) + length < sizeof(struct rndis)); 1344 req->info_buffer_length = length; 1345 memcpy((caddr_t)(req + 1), data, length); 1346 } 1347 1348 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1349 BUS_DMASYNC_PREWRITE); 1350 1351 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 1352 DPRINTF("%s: SET_MSG failed, error %u\n", 1353 sc->sc_dev.dv_xname, rv); 1354 hvn_free_cmd(sc, rc); 1355 return (rv); 1356 } 1357 1358 cmp = (struct rndis_set_comp *)&rc->rc_cmp.msg; 1359 if (cmp->status != RNDIS_STATUS_SUCCESS) 1360 rv = EIO; 1361 1362 hvn_free_cmd(sc, rc); 1363 1364 return (rv); 1365 } 1366 1367 int 1368 hvn_rndis_open(struct hvn_softc *sc) 1369 { 1370 uint32_t filter; 1371 int rv; 1372 1373 if (sc->sc_promisc) 1374 filter = NDIS_PACKET_TYPE_PROMISCUOUS; 1375 else 1376 filter = NDIS_PACKET_TYPE_BROADCAST | 1377 NDIS_PACKET_TYPE_ALL_MULTICAST | 1378 NDIS_PACKET_TYPE_DIRECTED; 1379 1380 rv = hvn_rndis_set(sc, RNDIS_OID_GEN_CURRENT_PACKET_FILTER, 1381 &filter, sizeof(filter)); 1382 if (rv) 1383 DPRINTF("%s: failed to set RNDIS filter to %#x\n", 1384 sc->sc_dev.dv_xname, filter); 1385 return (rv); 1386 } 1387 1388 int 1389 hvn_rndis_close(struct hvn_softc *sc) 1390 { 1391 uint32_t filter = 0; 1392 int rv; 1393 1394 rv = hvn_rndis_set(sc, RNDIS_OID_GEN_CURRENT_PACKET_FILTER, 1395 &filter, sizeof(filter)); 1396 if (rv) 1397 DPRINTF("%s: failed to clear RNDIS filter\n", 1398 sc->sc_dev.dv_xname); 1399 return (rv); 1400 } 1401 1402 void 1403 hvn_rndis_detach(struct hvn_softc *sc) 1404 { 1405 struct rndis_cmd *rc; 1406 struct rndis_halt_req *req; 1407 int rv; 1408 1409 rc = hvn_alloc_cmd(sc); 1410 1411 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1412 BUS_DMASYNC_PREREAD); 1413 1414 rc->rc_req->msg_type = RNDIS_HALT_MSG; 1415 rc->rc_req->msg_len = RNDIS_MESSAGE_SIZE(*req); 1416 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid); 1417 req = (struct rndis_halt_req *)&rc->rc_req->msg; 1418 req->request_id = rc->rc_id; 1419 1420 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1421 BUS_DMASYNC_PREWRITE); 1422 1423 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) 1424 DPRINTF("%s: HALT_MSG failed, error %u\n", 1425 sc->sc_dev.dv_xname, rv); 1426 1427 hvn_free_cmd(sc, rc); 1428 } 1429