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 59 #include <dev/rndis.h> 60 #include <dev/pv/ndis.h> 61 #include <dev/pv/if_hvnreg.h> 62 63 #include <net/if.h> 64 #include <net/if_media.h> 65 66 #include <netinet/in.h> 67 #include <netinet/if_ether.h> 68 69 #ifdef INET6 70 #include <netinet/ip6.h> 71 #endif 72 73 #if NBPFILTER > 0 74 #include <net/bpf.h> 75 #endif 76 77 #define HVN_DEBUG 1 78 79 #define HVN_NVS_BUFSIZE PAGE_SIZE 80 #define HVN_NVS_MSGSIZE 32 81 82 /* 83 * RNDIS control interface 84 */ 85 #define HVN_RNDIS_CTLREQS 4 86 #define HVN_RNDIS_CMPBUFSZ 512 87 88 #define HVN_RNDIS_MSG_LEN \ 89 (sizeof(struct rndis_packet_msg) + NDIS_VLAN_INFO_SIZE + \ 90 NDIS_RXCSUM_INFO_SIZE) 91 92 struct rndis_cmd { 93 uint32_t rc_id; 94 struct hvn_nvs_rndis rc_msg; 95 void *rc_req; 96 bus_dmamap_t rc_dmap; 97 bus_dma_segment_t rc_segs; 98 int rc_nsegs; 99 uint64_t rc_gpa; 100 struct rndis_packet_msg rc_cmp; 101 uint32_t rc_cmplen; 102 uint8_t rc_cmpbuf[HVN_RNDIS_CMPBUFSZ]; 103 struct mutex rc_mtx; 104 TAILQ_ENTRY(rndis_cmd) rc_entry; 105 }; 106 TAILQ_HEAD(rndis_queue, rndis_cmd); 107 108 /* 109 * Tx ring 110 */ 111 #define HVN_TX_DESC 128 112 #define HVN_TX_FRAGS 31 113 #define HVN_TX_FRAG_SIZE PAGE_SIZE 114 #define HVN_TX_PKT_SIZE 16384 115 116 struct hvn_tx_desc { 117 uint32_t txd_id; 118 int txd_ready; 119 struct vmbus_gpa txd_sgl[HVN_TX_FRAGS + 1]; 120 int txd_nsge; 121 struct mbuf *txd_buf; 122 bus_dmamap_t txd_dmap; 123 struct vmbus_gpa txd_gpa; 124 struct hvn_nvs_rndis txd_cmd; 125 struct rndis_packet_msg *txd_req; 126 }; 127 128 struct hvn_softc { 129 struct device sc_dev; 130 struct hv_softc *sc_hvsc; 131 struct hv_channel *sc_chan; 132 bus_dma_tag_t sc_dmat; 133 134 struct arpcom sc_ac; 135 struct ifmedia sc_media; 136 int sc_link_state; 137 int sc_promisc; 138 139 /* NVS protocol */ 140 int sc_proto; 141 uint32_t sc_nvstid; 142 uint8_t sc_nvsrsp[HVN_NVS_MSGSIZE]; 143 uint8_t *sc_nvsbuf; 144 struct mutex sc_nvslck; 145 146 /* RNDIS protocol */ 147 int sc_ndisver; 148 uint32_t sc_rndisrid; 149 struct rndis_queue sc_cntl_sq; /* submission queue */ 150 struct mutex sc_cntl_sqlck; 151 struct rndis_queue sc_cntl_cq; /* completion queue */ 152 struct mutex sc_cntl_cqlck; 153 struct rndis_queue sc_cntl_fq; /* free queue */ 154 struct mutex sc_cntl_fqlck; 155 struct rndis_cmd sc_cntl_msgs[HVN_RNDIS_CTLREQS]; 156 157 /* Rx ring */ 158 void *sc_rx_ring; 159 int sc_rx_size; 160 uint32_t sc_rx_hndl; 161 162 /* Tx ring */ 163 uint32_t sc_tx_next; 164 uint32_t sc_tx_avail; 165 struct hvn_tx_desc sc_tx_desc[HVN_TX_DESC]; 166 bus_dmamap_t sc_tx_rmap; 167 void *sc_tx_msgs; 168 bus_dma_segment_t sc_tx_mseg; 169 }; 170 171 int hvn_match(struct device *, void *, void *); 172 void hvn_attach(struct device *, struct device *, void *); 173 int hvn_ioctl(struct ifnet *, u_long, caddr_t); 174 int hvn_media_change(struct ifnet *); 175 void hvn_media_status(struct ifnet *, struct ifmediareq *); 176 int hvn_iff(struct hvn_softc *); 177 void hvn_init(struct hvn_softc *); 178 void hvn_stop(struct hvn_softc *); 179 void hvn_start(struct ifnet *); 180 int hvn_encap(struct hvn_softc *, struct mbuf *, struct hvn_tx_desc **); 181 void hvn_decap(struct hvn_softc *, struct hvn_tx_desc *); 182 void hvn_txeof(struct hvn_softc *, uint64_t); 183 int hvn_rx_ring_create(struct hvn_softc *); 184 int hvn_rx_ring_destroy(struct hvn_softc *); 185 int hvn_tx_ring_create(struct hvn_softc *); 186 void hvn_tx_ring_destroy(struct hvn_softc *); 187 int hvn_get_lladdr(struct hvn_softc *); 188 int hvn_set_lladdr(struct hvn_softc *); 189 void hvn_get_link_status(struct hvn_softc *); 190 void hvn_link_status(struct hvn_softc *); 191 192 /* NSVP */ 193 int hvn_nvs_attach(struct hvn_softc *); 194 void hvn_nvs_intr(void *); 195 int hvn_nvs_cmd(struct hvn_softc *, void *, size_t, uint64_t, int); 196 int hvn_nvs_ack(struct hvn_softc *, uint64_t); 197 void hvn_nvs_detach(struct hvn_softc *); 198 199 /* RNDIS */ 200 int hvn_rndis_attach(struct hvn_softc *); 201 int hvn_rndis_cmd(struct hvn_softc *, struct rndis_cmd *, int); 202 void hvn_rndis_input(struct hvn_softc *, uint64_t, void *); 203 void hvn_rxeof(struct hvn_softc *, caddr_t, uint32_t, struct mbuf_list *); 204 void hvn_rndis_complete(struct hvn_softc *, caddr_t, uint32_t); 205 int hvn_rndis_output(struct hvn_softc *, struct hvn_tx_desc *); 206 void hvn_rndis_status(struct hvn_softc *, caddr_t, uint32_t); 207 int hvn_rndis_query(struct hvn_softc *, uint32_t, void *, size_t *); 208 int hvn_rndis_set(struct hvn_softc *, uint32_t, void *, size_t); 209 int hvn_rndis_open(struct hvn_softc *); 210 int hvn_rndis_close(struct hvn_softc *); 211 void hvn_rndis_detach(struct hvn_softc *); 212 213 struct cfdriver hvn_cd = { 214 NULL, "hvn", DV_IFNET 215 }; 216 217 const struct cfattach hvn_ca = { 218 sizeof(struct hvn_softc), hvn_match, hvn_attach 219 }; 220 221 int 222 hvn_match(struct device *parent, void *match, void *aux) 223 { 224 struct hv_attach_args *aa = aux; 225 226 if (strcmp("network", aa->aa_ident)) 227 return (0); 228 229 return (1); 230 } 231 232 void 233 hvn_attach(struct device *parent, struct device *self, void *aux) 234 { 235 struct hv_attach_args *aa = aux; 236 struct hvn_softc *sc = (struct hvn_softc *)self; 237 struct ifnet *ifp = &sc->sc_ac.ac_if; 238 239 sc->sc_hvsc = (struct hv_softc *)parent; 240 sc->sc_chan = aa->aa_chan; 241 sc->sc_dmat = aa->aa_dmat; 242 243 strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); 244 245 DPRINTF("\n"); 246 247 if (hvn_nvs_attach(sc)) { 248 printf(": failed to init NVSP\n"); 249 return; 250 } 251 252 if (hvn_rx_ring_create(sc)) { 253 printf(": failed to create Rx ring\n"); 254 goto detach; 255 } 256 257 if (hvn_tx_ring_create(sc)) { 258 printf(": failed to create Tx ring\n"); 259 goto detach; 260 } 261 262 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 263 ifp->if_xflags = IFXF_MPSAFE; 264 ifp->if_ioctl = hvn_ioctl; 265 ifp->if_start = hvn_start; 266 ifp->if_softc = sc; 267 268 #ifdef notyet 269 ifp->if_capabilities = IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | 270 IFCAP_CSUM_UDPv4; 271 #endif 272 #if NVLAN > 0 273 ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 274 #endif 275 276 IFQ_SET_MAXLEN(&ifp->if_snd, HVN_TX_DESC - 1); 277 278 ifmedia_init(&sc->sc_media, IFM_IMASK, hvn_media_change, 279 hvn_media_status); 280 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 281 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); 282 283 if_attach(ifp); 284 285 if (hvn_rndis_attach(sc)) { 286 printf(": failed to init RNDIS\n"); 287 goto detach; 288 } 289 290 if (hvn_get_lladdr(sc)) { 291 printf(": failed to obtain an ethernet address\n"); 292 hvn_rndis_detach(sc); 293 goto detach; 294 } 295 296 DPRINTF("%s:", sc->sc_dev.dv_xname); 297 printf(" channel %u: NVS %u.%u NDIS %u.%u, address %s\n", 298 sc->sc_chan->ch_id, sc->sc_proto >> 16, sc->sc_proto & 0xffff, 299 sc->sc_ndisver >> 16 , sc->sc_ndisver & 0xffff, 300 ether_sprintf(sc->sc_ac.ac_enaddr)); 301 302 ether_ifattach(ifp); 303 return; 304 305 detach: 306 hvn_rx_ring_destroy(sc); 307 hvn_tx_ring_destroy(sc); 308 hvn_nvs_detach(sc); 309 if (ifp->if_start) 310 if_detach(ifp); 311 } 312 313 int 314 hvn_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 315 { 316 struct hvn_softc *sc = ifp->if_softc; 317 struct ifreq *ifr = (struct ifreq *)data; 318 int s, error = 0; 319 320 s = splnet(); 321 322 switch (command) { 323 case SIOCSIFADDR: 324 ifp->if_flags |= IFF_UP; 325 if (!(ifp->if_flags & IFF_RUNNING)) 326 hvn_init(sc); 327 break; 328 case SIOCSIFFLAGS: 329 if (ifp->if_flags & IFF_UP) { 330 if (ifp->if_flags & IFF_RUNNING) 331 error = ENETRESET; 332 else 333 hvn_init(sc); 334 } else { 335 if (ifp->if_flags & IFF_RUNNING) 336 hvn_stop(sc); 337 } 338 break; 339 case SIOCGIFMEDIA: 340 case SIOCSIFMEDIA: 341 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command); 342 break; 343 default: 344 error = ether_ioctl(ifp, &sc->sc_ac, command, data); 345 } 346 347 if (error == ENETRESET) { 348 if (ifp->if_flags & IFF_RUNNING) 349 hvn_iff(sc); 350 error = 0; 351 } 352 353 splx(s); 354 355 return (error); 356 } 357 358 int 359 hvn_media_change(struct ifnet *ifp) 360 { 361 return (0); 362 } 363 364 void 365 hvn_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 366 { 367 struct hvn_softc *sc = ifp->if_softc; 368 369 hvn_get_link_status(sc); 370 hvn_link_status(sc); 371 372 ifmr->ifm_status = IFM_AVALID; 373 ifmr->ifm_active = IFM_ETHER | IFM_MANUAL; 374 if (sc->sc_link_state == LINK_STATE_UP) 375 ifmr->ifm_status |= IFM_ACTIVE; 376 } 377 378 void 379 hvn_link_status(struct hvn_softc *sc) 380 { 381 struct ifnet *ifp = &sc->sc_ac.ac_if; 382 383 if (sc->sc_link_state != ifp->if_link_state) { 384 ifp->if_link_state = sc->sc_link_state; 385 if_link_state_change(ifp); 386 } 387 } 388 389 int 390 hvn_iff(struct hvn_softc *sc) 391 { 392 /* XXX */ 393 sc->sc_promisc = 0; 394 395 return (0); 396 } 397 398 void 399 hvn_init(struct hvn_softc *sc) 400 { 401 struct ifnet *ifp = &sc->sc_ac.ac_if; 402 403 hvn_stop(sc); 404 405 hvn_iff(sc); 406 407 if (hvn_rndis_open(sc) == 0) { 408 ifp->if_flags |= IFF_RUNNING; 409 ifq_clr_oactive(&ifp->if_snd); 410 } 411 } 412 413 void 414 hvn_stop(struct hvn_softc *sc) 415 { 416 struct ifnet *ifp = &sc->sc_ac.ac_if; 417 418 if (ifp->if_flags & IFF_RUNNING) { 419 ifp->if_flags &= ~IFF_RUNNING; 420 hvn_rndis_close(sc); 421 } 422 423 ifq_barrier(&ifp->if_snd); 424 intr_barrier(sc->sc_chan); 425 426 ifq_clr_oactive(&ifp->if_snd); 427 } 428 429 void 430 hvn_start(struct ifnet *ifp) 431 { 432 struct hvn_softc *sc = ifp->if_softc; 433 struct hvn_tx_desc *txd; 434 struct mbuf *m; 435 436 if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) 437 return; 438 439 for (;;) { 440 if (!sc->sc_tx_avail) { 441 /* transient */ 442 ifq_set_oactive(&ifp->if_snd); 443 break; 444 } 445 446 m = ifq_dequeue(&ifp->if_snd); 447 if (m == NULL) 448 break; 449 450 if (hvn_encap(sc, m, &txd)) { 451 /* the chain is too large */ 452 ifp->if_oerrors++; 453 m_freem(m); 454 continue; 455 } 456 457 #if NBPFILTER > 0 458 if (ifp->if_bpf) 459 bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT); 460 #endif 461 462 if (hvn_rndis_output(sc, txd)) { 463 hvn_decap(sc, txd); 464 m_freem(m); 465 } 466 467 sc->sc_tx_next++; 468 sc->sc_tx_next %= HVN_TX_DESC; 469 470 atomic_dec_int(&sc->sc_tx_avail); 471 472 ifp->if_opackets++; 473 } 474 } 475 476 int 477 hvn_encap(struct hvn_softc *sc, struct mbuf *m, struct hvn_tx_desc **txd0) 478 { 479 struct hvn_tx_desc *txd; 480 bus_dma_segment_t *seg; 481 size_t rlen; 482 int i; 483 484 /* XXX use queues? */ 485 txd = &sc->sc_tx_desc[sc->sc_tx_next]; 486 while (!txd->txd_ready) { 487 sc->sc_tx_next++; 488 sc->sc_tx_next %= HVN_TX_DESC; 489 txd = &sc->sc_tx_desc[sc->sc_tx_next]; 490 } 491 492 memset(txd->txd_req, 0, sizeof(*txd->txd_req)); 493 txd->txd_req->rm_type = REMOTE_NDIS_PACKET_MSG; 494 txd->txd_req->rm_dataoffset = RNDIS_DATA_OFFSET; 495 txd->txd_req->rm_datalen = m->m_pkthdr.len; 496 txd->txd_req->rm_pktinfooffset = RNDIS_DATA_OFFSET; 497 rlen = sizeof(struct rndis_packet_msg); 498 499 if (bus_dmamap_load_mbuf(sc->sc_dmat, txd->txd_dmap, m, BUS_DMA_READ | 500 BUS_DMA_NOWAIT)) { 501 DPRINTF("%s: failed to load mbuf\n", sc->sc_dev.dv_xname); 502 return (-1); 503 } 504 txd->txd_buf = m; 505 506 /* Per-packet info adjusts rlen */ 507 508 /* Final length value for the RNDIS header and data */ 509 txd->txd_req->rm_len = txd->txd_req->rm_datalen + rlen; 510 511 /* Attach an RNDIS message into the first slot */ 512 txd->txd_sgl[0].gpa_page = txd->txd_gpa.gpa_page; 513 txd->txd_sgl[0].gpa_ofs = txd->txd_gpa.gpa_ofs; 514 txd->txd_sgl[0].gpa_len = rlen; 515 txd->txd_nsge = txd->txd_dmap->dm_nsegs + 1; 516 517 for (i = 0; i < txd->txd_dmap->dm_nsegs; i++) { 518 seg = &txd->txd_dmap->dm_segs[i]; 519 txd->txd_sgl[1 + i].gpa_page = atop(seg->ds_addr); 520 txd->txd_sgl[1 + i].gpa_ofs = seg->ds_addr & PAGE_MASK; 521 txd->txd_sgl[1 + i].gpa_len = seg->ds_len; 522 } 523 524 *txd0 = txd; 525 return (0); 526 } 527 528 void 529 hvn_decap(struct hvn_softc *sc, struct hvn_tx_desc *txd) 530 { 531 bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 0, 0, 532 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 533 bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap); 534 txd->txd_buf = NULL; 535 txd->txd_nsge = 0; 536 } 537 538 void 539 hvn_txeof(struct hvn_softc *sc, uint64_t tid) 540 { 541 struct ifnet *ifp = &sc->sc_ac.ac_if; 542 struct hvn_tx_desc *txd; 543 struct mbuf *m; 544 uint32_t id = tid >> 32; 545 546 if ((tid & 0xffffffff) != 0) 547 return; 548 if (id > HVN_TX_DESC) 549 panic("tx packet index too large: %u", id); 550 551 txd = &sc->sc_tx_desc[id]; 552 553 if ((m = txd->txd_buf) == NULL) 554 panic("%s: no mbuf @%u\n", sc->sc_dev.dv_xname, id); 555 txd->txd_buf = NULL; 556 557 bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 0, 0, 558 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 559 bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap); 560 m_freem(m); 561 562 txd->txd_ready = 1; 563 564 atomic_inc_int(&sc->sc_tx_avail); 565 566 if (ifq_is_oactive(&ifp->if_snd)) 567 ifq_restart(&ifp->if_snd); 568 } 569 570 int 571 hvn_rx_ring_create(struct hvn_softc *sc) 572 { 573 struct hvn_nvs_rxbuf_conn cmd; 574 struct hvn_nvs_rxbuf_conn_resp *rsp; 575 uint64_t tid; 576 577 if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_2) 578 sc->sc_rx_size = 15 * 1024 * 1024; /* 15MB */ 579 else 580 sc->sc_rx_size = 16 * 1024 * 1024; /* 16MB */ 581 sc->sc_rx_ring = km_alloc(sc->sc_rx_size, &kv_any, &kp_zero, 582 cold ? &kd_nowait : &kd_waitok); 583 if (sc->sc_rx_ring == NULL) { 584 DPRINTF("%s: failed to allocate Rx ring buffer\n", 585 sc->sc_dev.dv_xname); 586 return (-1); 587 } 588 if (hv_handle_alloc(sc->sc_chan, sc->sc_rx_ring, sc->sc_rx_size, 589 &sc->sc_rx_hndl)) { 590 DPRINTF("%s: failed to obtain a PA handle\n", 591 sc->sc_dev.dv_xname); 592 goto errout; 593 } 594 595 memset(&cmd, 0, sizeof(cmd)); 596 cmd.nvs_type = HVN_NVS_TYPE_RXBUF_CONN; 597 cmd.nvs_gpadl = sc->sc_rx_hndl; 598 cmd.nvs_sig = HVN_NVS_RXBUF_SIG; 599 600 tid = atomic_inc_int_nv(&sc->sc_nvstid); 601 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) 602 goto errout; 603 604 rsp = (struct hvn_nvs_rxbuf_conn_resp *)&sc->sc_nvsrsp; 605 if (rsp->nvs_status != HVN_NVS_STATUS_OK) { 606 DPRINTF("%s: failed to set up the Rx ring\n", 607 sc->sc_dev.dv_xname); 608 goto errout; 609 } 610 if (rsp->nvs_nsect > 1) { 611 DPRINTF("%s: invalid number of Rx ring sections: %d\n", 612 sc->sc_dev.dv_xname, rsp->nvs_nsect); 613 hvn_rx_ring_destroy(sc); 614 return (-1); 615 } 616 return (0); 617 618 errout: 619 if (sc->sc_rx_hndl) { 620 hv_handle_free(sc->sc_chan, sc->sc_rx_hndl); 621 sc->sc_rx_hndl = 0; 622 } 623 if (sc->sc_rx_ring) { 624 km_free(sc->sc_rx_ring, sc->sc_rx_size, &kv_any, &kp_zero); 625 sc->sc_rx_ring = NULL; 626 } 627 return (-1); 628 } 629 630 int 631 hvn_rx_ring_destroy(struct hvn_softc *sc) 632 { 633 struct hvn_nvs_rxbuf_disconn cmd; 634 uint64_t tid; 635 636 if (sc->sc_rx_ring == NULL) 637 return (0); 638 639 memset(&cmd, 0, sizeof(cmd)); 640 cmd.nvs_type = HVN_NVS_TYPE_RXBUF_DISCONN; 641 cmd.nvs_sig = HVN_NVS_RXBUF_SIG; 642 643 tid = atomic_inc_int_nv(&sc->sc_nvstid); 644 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 0)) 645 return (-1); 646 647 delay(100); 648 649 hv_handle_free(sc->sc_chan, sc->sc_rx_hndl); 650 651 sc->sc_rx_hndl = 0; 652 653 km_free(sc->sc_rx_ring, sc->sc_rx_size, &kv_any, &kp_zero); 654 sc->sc_rx_ring = NULL; 655 656 return (0); 657 } 658 659 int 660 hvn_tx_ring_create(struct hvn_softc *sc) 661 { 662 struct hvn_tx_desc *txd; 663 bus_dma_segment_t *seg; 664 size_t msgsize; 665 int i, rsegs; 666 paddr_t pa; 667 668 msgsize = roundup(HVN_RNDIS_MSG_LEN, 128); 669 670 /* Allocate memory to store RNDIS messages */ 671 if (bus_dmamem_alloc(sc->sc_dmat, msgsize * HVN_TX_DESC, PAGE_SIZE, 0, 672 &sc->sc_tx_mseg, 1, &rsegs, BUS_DMA_ZERO | BUS_DMA_WAITOK)) { 673 DPRINTF("%s: failed to allocate memory for RDNIS messages\n", 674 sc->sc_dev.dv_xname); 675 goto errout; 676 } 677 if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tx_mseg, 1, msgsize * 678 HVN_TX_DESC, (caddr_t *)&sc->sc_tx_msgs, BUS_DMA_WAITOK)) { 679 DPRINTF("%s: failed to establish mapping for RDNIS messages\n", 680 sc->sc_dev.dv_xname); 681 goto errout; 682 } 683 if (bus_dmamap_create(sc->sc_dmat, msgsize * HVN_TX_DESC, 1, 684 msgsize * HVN_TX_DESC, 0, BUS_DMA_WAITOK, &sc->sc_tx_rmap)) { 685 DPRINTF("%s: failed to create map for RDNIS messages\n", 686 sc->sc_dev.dv_xname); 687 goto errout; 688 } 689 if (bus_dmamap_load(sc->sc_dmat, sc->sc_tx_rmap, sc->sc_tx_msgs, 690 msgsize * HVN_TX_DESC, NULL, BUS_DMA_WAITOK)) { 691 DPRINTF("%s: failed to create map for RDNIS messages\n", 692 sc->sc_dev.dv_xname); 693 goto errout; 694 } 695 696 for (i = 0; i < HVN_TX_DESC; i++) { 697 txd = &sc->sc_tx_desc[i]; 698 if (bus_dmamap_create(sc->sc_dmat, HVN_TX_PKT_SIZE, 699 HVN_TX_FRAGS, HVN_TX_FRAG_SIZE, 0, BUS_DMA_WAITOK, 700 &txd->txd_dmap)) { 701 DPRINTF("%s: failed to create map for TX descriptors\n", 702 sc->sc_dev.dv_xname); 703 goto errout; 704 } 705 seg = &sc->sc_tx_rmap->dm_segs[0]; 706 pa = seg->ds_addr + (msgsize * i); 707 txd->txd_gpa.gpa_page = atop(pa); 708 txd->txd_gpa.gpa_ofs = pa & PAGE_MASK; 709 txd->txd_gpa.gpa_len = msgsize; 710 txd->txd_req = (void *)((caddr_t)sc->sc_tx_msgs + 711 (msgsize * i)); 712 txd->txd_id = i; 713 txd->txd_ready = 1; 714 } 715 sc->sc_tx_avail = HVN_TX_DESC; 716 717 return (0); 718 719 errout: 720 hvn_tx_ring_destroy(sc); 721 return (-1); 722 } 723 724 void 725 hvn_tx_ring_destroy(struct hvn_softc *sc) 726 { 727 struct hvn_tx_desc *txd; 728 int i; 729 730 for (i = 0; i < HVN_TX_DESC; i++) { 731 txd = &sc->sc_tx_desc[i]; 732 if (txd->txd_dmap == NULL) 733 continue; 734 bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 0, 0, 735 BUS_DMASYNC_POSTWRITE); 736 bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap); 737 bus_dmamap_destroy(sc->sc_dmat, txd->txd_dmap); 738 txd->txd_dmap = NULL; 739 if (txd->txd_buf == NULL) 740 continue; 741 m_free(txd->txd_buf); 742 txd->txd_buf = NULL; 743 } 744 if (sc->sc_tx_rmap) { 745 bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_rmap, 0, 0, 746 BUS_DMASYNC_POSTWRITE); 747 bus_dmamap_unload(sc->sc_dmat, sc->sc_tx_rmap); 748 bus_dmamap_destroy(sc->sc_dmat, sc->sc_tx_rmap); 749 } 750 if (sc->sc_tx_msgs) { 751 size_t msgsize = roundup(HVN_RNDIS_MSG_LEN, 128); 752 753 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_tx_msgs, 754 msgsize * HVN_TX_DESC); 755 bus_dmamem_free(sc->sc_dmat, &sc->sc_tx_mseg, 1); 756 } 757 sc->sc_tx_rmap = NULL; 758 sc->sc_tx_msgs = NULL; 759 } 760 761 int 762 hvn_get_lladdr(struct hvn_softc *sc) 763 { 764 char enaddr[ETHER_ADDR_LEN]; 765 size_t addrlen = ETHER_ADDR_LEN; 766 int rv; 767 768 rv = hvn_rndis_query(sc, OID_802_3_PERMANENT_ADDRESS, 769 enaddr, &addrlen); 770 if (rv == 0 && addrlen == ETHER_ADDR_LEN) 771 memcpy(sc->sc_ac.ac_enaddr, enaddr, ETHER_ADDR_LEN); 772 return (rv); 773 } 774 775 int 776 hvn_set_lladdr(struct hvn_softc *sc) 777 { 778 return (hvn_rndis_set(sc, OID_802_3_CURRENT_ADDRESS, 779 sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN)); 780 } 781 782 void 783 hvn_get_link_status(struct hvn_softc *sc) 784 { 785 uint32_t state; 786 size_t len = sizeof(state); 787 788 if (hvn_rndis_query(sc, OID_GEN_MEDIA_CONNECT_STATUS, 789 &state, &len) == 0) 790 sc->sc_link_state = (state == NDIS_MEDIA_STATE_CONNECTED) ? 791 LINK_STATE_UP : LINK_STATE_DOWN; 792 } 793 794 int 795 hvn_nvs_attach(struct hvn_softc *sc) 796 { 797 const uint32_t protos[] = { 798 HVN_NVS_PROTO_VERSION_5, HVN_NVS_PROTO_VERSION_4, 799 HVN_NVS_PROTO_VERSION_2, HVN_NVS_PROTO_VERSION_1 800 }; 801 struct hvn_nvs_init cmd; 802 struct hvn_nvs_init_resp *rsp; 803 struct hvn_nvs_ndis_init ncmd; 804 uint64_t tid; 805 uint32_t ndisver; 806 int i; 807 808 /* 4 page sized buffer for channel messages */ 809 sc->sc_nvsbuf = km_alloc(HVN_NVS_BUFSIZE, &kv_any, &kp_zero, 810 (cold ? &kd_nowait : &kd_waitok)); 811 if (sc->sc_nvsbuf == NULL) { 812 DPRINTF("%s: failed to allocate channel data buffer\n", 813 sc->sc_dev.dv_xname); 814 return (-1); 815 } 816 sc->sc_chan->ch_buflen = PAGE_SIZE * 4; 817 818 /* Associate our interrupt handler with the channel */ 819 if (hv_channel_open(sc->sc_chan, NULL, 0, hvn_nvs_intr, sc)) { 820 DPRINTF("%s: failed to open channel\n", sc->sc_dev.dv_xname); 821 km_free(sc->sc_nvsbuf, HVN_NVS_BUFSIZE, &kv_any, &kp_zero); 822 return (-1); 823 } 824 825 hv_evcount_attach(sc->sc_chan, sc->sc_dev.dv_xname); 826 827 mtx_init(&sc->sc_nvslck, IPL_NET); 828 829 memset(&cmd, 0, sizeof(cmd)); 830 cmd.nvs_type = HVN_NVS_TYPE_INIT; 831 for (i = 0; i < nitems(protos); i++) { 832 cmd.nvs_ver_min = cmd.nvs_ver_max = protos[i]; 833 tid = atomic_inc_int_nv(&sc->sc_nvstid); 834 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) 835 return (-1); 836 rsp = (struct hvn_nvs_init_resp *)&sc->sc_nvsrsp; 837 if (rsp->nvs_status == HVN_NVS_STATUS_OK) { 838 sc->sc_proto = protos[i]; 839 break; 840 } 841 } 842 if (!sc->sc_proto) { 843 DPRINTF("%s: failed to negotiate NVSP version\n", 844 sc->sc_dev.dv_xname); 845 return (-1); 846 } 847 848 memset(&ncmd, 0, sizeof(ncmd)); 849 ncmd.nvs_type = HVN_NVS_TYPE_NDIS_INIT; 850 if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_4) 851 ndisver = NDIS_VERSION_6_1; 852 else 853 ndisver = NDIS_VERSION_6_30; 854 ncmd.nvs_ndis_major = (ndisver & 0xffff0000) >> 16; 855 ncmd.nvs_ndis_minor = (ndisver & 0x0000ffff); 856 857 tid = atomic_inc_int_nv(&sc->sc_nvstid); 858 if (hvn_nvs_cmd(sc, &ncmd, sizeof(ncmd), tid, 100)) 859 return (-1); 860 861 sc->sc_ndisver = ndisver; 862 863 return (0); 864 } 865 866 void 867 hvn_nvs_intr(void *arg) 868 { 869 struct hvn_softc *sc = arg; 870 struct vmbus_chanpkt_hdr *cph; 871 struct hvn_nvs_hdr *nvs; 872 uint64_t rid; 873 uint32_t rlen; 874 int rv; 875 876 for (;;) { 877 rv = hv_channel_recv(sc->sc_chan, sc->sc_nvsbuf, 878 HVN_NVS_BUFSIZE, &rlen, &rid, 1); 879 if (rv != 0 || rlen == 0) { 880 if (rv != EAGAIN) 881 printf("%s: failed to receive an NVSP " 882 "packet\n", sc->sc_dev.dv_xname); 883 break; 884 } 885 cph = (struct vmbus_chanpkt_hdr *)sc->sc_nvsbuf; 886 nvs = (struct hvn_nvs_hdr *)VMBUS_CHANPKT_CONST_DATA(cph); 887 888 if (cph->cph_type == VMBUS_CHANPKT_TYPE_COMP) { 889 switch (nvs->nvs_type) { 890 case HVN_NVS_TYPE_INIT_RESP: 891 case HVN_NVS_TYPE_RXBUF_CONNRESP: 892 case HVN_NVS_TYPE_CHIM_CONNRESP: 893 case HVN_NVS_TYPE_SUBCH_RESP: 894 /* copy the response back */ 895 memcpy(&sc->sc_nvsrsp, nvs, HVN_NVS_MSGSIZE); 896 wakeup_one(&sc->sc_nvsrsp); 897 break; 898 case HVN_NVS_TYPE_RNDIS_ACK: 899 hvn_txeof(sc, cph->cph_tid); 900 break; 901 default: 902 printf("%s: unhandled NVSP packet type %d " 903 "on completion\n", sc->sc_dev.dv_xname, 904 nvs->nvs_type); 905 } 906 } else if (cph->cph_type == VMBUS_CHANPKT_TYPE_RXBUF) { 907 switch (nvs->nvs_type) { 908 case HVN_NVS_TYPE_RNDIS: 909 hvn_rndis_input(sc, cph->cph_tid, cph); 910 break; 911 default: 912 printf("%s: unhandled NVSP packet type %d " 913 "on receive\n", sc->sc_dev.dv_xname, 914 nvs->nvs_type); 915 } 916 } else 917 printf("%s: unknown NVSP packet type %u\n", 918 sc->sc_dev.dv_xname, cph->cph_type); 919 } 920 } 921 922 int 923 hvn_nvs_cmd(struct hvn_softc *sc, void *cmd, size_t cmdsize, uint64_t tid, 924 int timo) 925 { 926 struct hvn_nvs_hdr *hdr = cmd; 927 int tries = 10; 928 int rv; 929 930 do { 931 rv = hv_channel_send(sc->sc_chan, cmd, cmdsize, 932 tid, VMBUS_CHANPKT_TYPE_INBAND, 933 timo ? VMBUS_CHANPKT_FLAG_RC : 0); 934 if (rv == EAGAIN) { 935 if (timo) 936 tsleep(cmd, PRIBIO, "hvnsend", timo / 10); 937 else 938 delay(100); 939 } else if (rv) { 940 DPRINTF("%s: NVSP operation %d send error %d\n", 941 sc->sc_dev.dv_xname, hdr->nvs_type, rv); 942 return (rv); 943 } 944 } while (rv != 0 && --tries > 0); 945 946 if (timo) { 947 mtx_enter(&sc->sc_nvslck); 948 rv = msleep(&sc->sc_nvsrsp, &sc->sc_nvslck, PRIBIO, "hvnvsp", 949 timo); 950 mtx_leave(&sc->sc_nvslck); 951 #ifdef HVN_DEBUG 952 switch (rv) { 953 case EINTR: 954 rv = 0; 955 break; 956 case EWOULDBLOCK: 957 printf("%s: NVSP opertaion %d timed out\n", 958 sc->sc_dev.dv_xname, hdr->nvs_type); 959 } 960 } 961 #endif 962 return (rv); 963 } 964 965 int 966 hvn_nvs_ack(struct hvn_softc *sc, uint64_t tid) 967 { 968 struct hvn_nvs_rndis_ack cmd; 969 int tries = 5; 970 int rv; 971 972 cmd.nvs_type = HVN_NVS_TYPE_RNDIS_ACK; 973 cmd.nvs_status = HVN_NVS_STATUS_OK; 974 do { 975 rv = hv_channel_send(sc->sc_chan, &cmd, sizeof(cmd), 976 tid, VMBUS_CHANPKT_TYPE_COMP, 0); 977 if (rv == EAGAIN) 978 delay(100); 979 else if (rv) { 980 DPRINTF("%s: NVSP acknowledgement error %d\n", 981 sc->sc_dev.dv_xname, rv); 982 return (rv); 983 } 984 } while (rv != 0 && --tries > 0); 985 return (rv); 986 } 987 988 void 989 hvn_nvs_detach(struct hvn_softc *sc) 990 { 991 if (hv_channel_close(sc->sc_chan) == 0) { 992 km_free(sc->sc_nvsbuf, HVN_NVS_BUFSIZE, &kv_any, &kp_zero); 993 sc->sc_nvsbuf = NULL; 994 } 995 } 996 997 static inline struct rndis_cmd * 998 hvn_alloc_cmd(struct hvn_softc *sc) 999 { 1000 struct rndis_cmd *rc; 1001 1002 mtx_enter(&sc->sc_cntl_fqlck); 1003 while ((rc = TAILQ_FIRST(&sc->sc_cntl_fq)) == NULL) 1004 msleep(&sc->sc_cntl_fq, &sc->sc_cntl_fqlck, 1005 PRIBIO, "hvnrr", 1); 1006 TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry); 1007 mtx_leave(&sc->sc_cntl_fqlck); 1008 return (rc); 1009 } 1010 1011 static inline void 1012 hvn_submit_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 1013 { 1014 mtx_enter(&sc->sc_cntl_sqlck); 1015 TAILQ_INSERT_TAIL(&sc->sc_cntl_sq, rc, rc_entry); 1016 mtx_leave(&sc->sc_cntl_sqlck); 1017 } 1018 1019 static inline struct rndis_cmd * 1020 hvn_complete_cmd(struct hvn_softc *sc, uint32_t id) 1021 { 1022 struct rndis_cmd *rc; 1023 1024 mtx_enter(&sc->sc_cntl_sqlck); 1025 TAILQ_FOREACH(rc, &sc->sc_cntl_sq, rc_entry) { 1026 if (rc->rc_id == id) { 1027 TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry); 1028 break; 1029 } 1030 } 1031 mtx_leave(&sc->sc_cntl_sqlck); 1032 if (rc != NULL) { 1033 mtx_enter(&sc->sc_cntl_cqlck); 1034 TAILQ_INSERT_TAIL(&sc->sc_cntl_cq, rc, rc_entry); 1035 mtx_leave(&sc->sc_cntl_cqlck); 1036 } 1037 return (rc); 1038 } 1039 1040 static inline int 1041 hvn_rollback_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 1042 { 1043 struct rndis_cmd *rn; 1044 1045 mtx_enter(&sc->sc_cntl_sqlck); 1046 TAILQ_FOREACH(rn, &sc->sc_cntl_sq, rc_entry) { 1047 if (rn == rc) { 1048 TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry); 1049 mtx_leave(&sc->sc_cntl_sqlck); 1050 return (0); 1051 } 1052 } 1053 mtx_leave(&sc->sc_cntl_sqlck); 1054 return (-1); 1055 } 1056 1057 static inline void 1058 hvn_free_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 1059 { 1060 memset(rc->rc_req, 0, sizeof(struct rndis_packet_msg)); 1061 memset(&rc->rc_cmp, 0, sizeof(rc->rc_cmp)); 1062 memset(&rc->rc_msg, 0, sizeof(rc->rc_msg)); 1063 mtx_enter(&sc->sc_cntl_fqlck); 1064 TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry); 1065 mtx_leave(&sc->sc_cntl_fqlck); 1066 wakeup(&sc->sc_cntl_fq); 1067 } 1068 1069 int 1070 hvn_rndis_attach(struct hvn_softc *sc) 1071 { 1072 struct rndis_init_req *req; 1073 struct rndis_init_comp *cmp; 1074 struct rndis_cmd *rc; 1075 int i, rv; 1076 1077 /* RNDIS control message queues */ 1078 TAILQ_INIT(&sc->sc_cntl_sq); 1079 TAILQ_INIT(&sc->sc_cntl_cq); 1080 TAILQ_INIT(&sc->sc_cntl_fq); 1081 mtx_init(&sc->sc_cntl_sqlck, IPL_NET); 1082 mtx_init(&sc->sc_cntl_cqlck, IPL_NET); 1083 mtx_init(&sc->sc_cntl_fqlck, IPL_NET); 1084 1085 for (i = 0; i < HVN_RNDIS_CTLREQS; i++) { 1086 rc = &sc->sc_cntl_msgs[i]; 1087 if (bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, 1088 PAGE_SIZE, 0, BUS_DMA_WAITOK, &rc->rc_dmap)) { 1089 DPRINTF("%s: failed to create RNDIS command map\n", 1090 sc->sc_dev.dv_xname); 1091 goto errout; 1092 } 1093 if (bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 1094 0, &rc->rc_segs, 1, &rc->rc_nsegs, BUS_DMA_NOWAIT | 1095 BUS_DMA_ZERO)) { 1096 DPRINTF("%s: failed to allocate RNDIS command\n", 1097 sc->sc_dev.dv_xname); 1098 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 1099 goto errout; 1100 } 1101 if (bus_dmamem_map(sc->sc_dmat, &rc->rc_segs, rc->rc_nsegs, 1102 PAGE_SIZE, (caddr_t *)&rc->rc_req, BUS_DMA_NOWAIT)) { 1103 DPRINTF("%s: failed to allocate RNDIS command\n", 1104 sc->sc_dev.dv_xname); 1105 bus_dmamem_free(sc->sc_dmat, &rc->rc_segs, 1106 rc->rc_nsegs); 1107 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 1108 goto errout; 1109 } 1110 if (bus_dmamap_load(sc->sc_dmat, rc->rc_dmap, rc->rc_req, 1111 PAGE_SIZE, NULL, BUS_DMA_WAITOK)) { 1112 DPRINTF("%s: failed to load RNDIS command map\n", 1113 sc->sc_dev.dv_xname); 1114 bus_dmamem_free(sc->sc_dmat, &rc->rc_segs, 1115 rc->rc_nsegs); 1116 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 1117 goto errout; 1118 } 1119 rc->rc_gpa = atop(rc->rc_dmap->dm_segs[0].ds_addr); 1120 mtx_init(&rc->rc_mtx, IPL_NET); 1121 TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry); 1122 } 1123 1124 rc = hvn_alloc_cmd(sc); 1125 1126 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1127 BUS_DMASYNC_PREREAD); 1128 1129 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid); 1130 1131 req = rc->rc_req; 1132 req->rm_type = REMOTE_NDIS_INITIALIZE_MSG; 1133 req->rm_len = sizeof(*req); 1134 req->rm_rid = rc->rc_id; 1135 req->rm_ver_major = RNDIS_VERSION_MAJOR; 1136 req->rm_ver_minor = RNDIS_VERSION_MINOR; 1137 req->rm_max_xfersz = 2048; /* XXX */ 1138 1139 rc->rc_cmplen = sizeof(*cmp); 1140 1141 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1142 BUS_DMASYNC_PREWRITE); 1143 1144 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 1145 DPRINTF("%s: INITIALIZE_MSG failed, error %u\n", 1146 sc->sc_dev.dv_xname, rv); 1147 hvn_free_cmd(sc, rc); 1148 goto errout; 1149 } 1150 cmp = (struct rndis_init_comp *)&rc->rc_cmp; 1151 if (cmp->rm_status != RNDIS_STATUS_SUCCESS) { 1152 DPRINTF("%s: failed to init RNDIS, error %#x\n", 1153 sc->sc_dev.dv_xname, cmp->rm_status); 1154 hvn_free_cmd(sc, rc); 1155 goto errout; 1156 } 1157 1158 hvn_free_cmd(sc, rc); 1159 1160 return (0); 1161 1162 errout: 1163 for (i = 0; i < HVN_RNDIS_CTLREQS; i++) { 1164 rc = &sc->sc_cntl_msgs[i]; 1165 if (rc->rc_req == NULL) 1166 continue; 1167 TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry); 1168 bus_dmamem_free(sc->sc_dmat, &rc->rc_segs, rc->rc_nsegs); 1169 rc->rc_req = NULL; 1170 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 1171 } 1172 return (-1); 1173 } 1174 1175 int 1176 hvn_rndis_cmd(struct hvn_softc *sc, struct rndis_cmd *rc, int timo) 1177 { 1178 struct hvn_nvs_rndis *msg = &rc->rc_msg; 1179 struct rndis_msghdr *hdr = rc->rc_req; 1180 struct vmbus_gpa sgl[1]; 1181 int tries = 10; 1182 int rv; 1183 1184 KASSERT(timo > 0); 1185 1186 msg->nvs_type = HVN_NVS_TYPE_RNDIS; 1187 msg->nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_CTRL; 1188 msg->nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID; 1189 1190 sgl[0].gpa_page = rc->rc_gpa; 1191 sgl[0].gpa_len = hdr->rm_len; 1192 sgl[0].gpa_ofs = 0; 1193 1194 hvn_submit_cmd(sc, rc); 1195 1196 do { 1197 rv = hv_channel_send_sgl(sc->sc_chan, sgl, 1, &rc->rc_msg, 1198 sizeof(*msg), rc->rc_id); 1199 if (rv == EAGAIN) 1200 tsleep(rc, PRIBIO, "hvnsendbuf", timo / 10); 1201 else if (rv) { 1202 DPRINTF("%s: RNDIS operation %d send error %d\n", 1203 sc->sc_dev.dv_xname, hdr->rm_type, rv); 1204 return (rv); 1205 } 1206 } while (rv != 0 && --tries > 0); 1207 1208 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1209 BUS_DMASYNC_POSTWRITE); 1210 1211 mtx_enter(&rc->rc_mtx); 1212 rv = msleep(rc, &rc->rc_mtx, PRIBIO, "rndisctl", timo); 1213 mtx_leave(&rc->rc_mtx); 1214 1215 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1216 BUS_DMASYNC_POSTREAD); 1217 1218 #ifdef HVN_DEBUG 1219 switch (rv) { 1220 case EINTR: 1221 rv = 0; 1222 break; 1223 case EWOULDBLOCK: 1224 if (hvn_rollback_cmd(sc, rc)) { 1225 /* failed to rollback? go for one sleep cycle */ 1226 tsleep(rc, PRIBIO, "rndisctl2", 1); 1227 rv = 0; 1228 break; 1229 } 1230 printf("%s: RNDIS opertaion %d timed out\n", sc->sc_dev.dv_xname, 1231 hdr->rm_type); 1232 } 1233 #endif 1234 return (rv); 1235 } 1236 1237 void 1238 hvn_rndis_input(struct hvn_softc *sc, uint64_t tid, void *arg) 1239 { 1240 struct ifnet *ifp = &sc->sc_ac.ac_if; 1241 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 1242 struct vmbus_chanpkt_prplist *cp = arg; 1243 uint32_t off, len, type; 1244 int i; 1245 1246 if (sc->sc_rx_ring == NULL) { 1247 DPRINTF("%s: invalid rx ring\n", sc->sc_dev.dv_xname); 1248 return; 1249 } 1250 for (i = 0; i < cp->cp_range_cnt; i++) { 1251 off = cp->cp_range[i].gpa_ofs; 1252 len = cp->cp_range[i].gpa_len; 1253 1254 KASSERT(off + len <= sc->sc_rx_size); 1255 KASSERT(len >= RNDIS_HEADER_OFFSET + 4); 1256 1257 memcpy(&type, (caddr_t)sc->sc_rx_ring + off, sizeof(type)); 1258 switch (type) { 1259 /* data message */ 1260 case REMOTE_NDIS_PACKET_MSG: 1261 hvn_rxeof(sc, (caddr_t)sc->sc_rx_ring + 1262 off, len, &ml); 1263 break; 1264 /* completion messages */ 1265 case REMOTE_NDIS_INITIALIZE_CMPLT: 1266 case REMOTE_NDIS_QUERY_CMPLT: 1267 case REMOTE_NDIS_SET_CMPLT: 1268 case REMOTE_NDIS_RESET_CMPLT: 1269 case REMOTE_NDIS_KEEPALIVE_CMPLT: 1270 hvn_rndis_complete(sc, (caddr_t)sc->sc_rx_ring + 1271 off, len); 1272 break; 1273 /* notification message */ 1274 case REMOTE_NDIS_INDICATE_STATUS_MSG: 1275 hvn_rndis_status(sc, (caddr_t)sc->sc_rx_ring + 1276 off, len); 1277 break; 1278 default: 1279 printf("%s: unhandled RNDIS message type %u\n", 1280 sc->sc_dev.dv_xname, type); 1281 } 1282 } 1283 hvn_nvs_ack(sc, tid); 1284 1285 if (MBUF_LIST_FIRST(&ml)) 1286 if_input(ifp, &ml); 1287 } 1288 1289 static inline struct mbuf * 1290 hvn_devget(struct hvn_softc *sc, caddr_t buf, uint32_t len) 1291 { 1292 struct mbuf *m; 1293 1294 if (len + ETHER_ALIGN <= MHLEN) 1295 MGETHDR(m, M_NOWAIT, MT_DATA); 1296 else 1297 m = MCLGETI(NULL, M_NOWAIT, NULL, len + ETHER_ALIGN); 1298 if (m == NULL) 1299 return (NULL); 1300 m->m_len = m->m_pkthdr.len = len; 1301 m_adj(m, ETHER_ALIGN); 1302 1303 if (m_copyback(m, 0, len, buf, M_NOWAIT)) { 1304 m_freem(m); 1305 return (NULL); 1306 } 1307 1308 return (m); 1309 } 1310 1311 void 1312 hvn_rxeof(struct hvn_softc *sc, caddr_t buf, uint32_t len, 1313 struct mbuf_list *ml) 1314 { 1315 struct ifnet *ifp = &sc->sc_ac.ac_if; 1316 struct rndis_packet_msg *pkt; 1317 struct rndis_pktinfo *pi; 1318 uint32_t csum, vlan; 1319 struct mbuf *m; 1320 1321 if (!(ifp->if_flags & IFF_RUNNING)) 1322 return; 1323 1324 if (len < RNDIS_HEADER_OFFSET + sizeof(*pkt)) { 1325 printf("%s: data packet too short: %u\n", 1326 sc->sc_dev.dv_xname, len); 1327 return; 1328 } 1329 1330 pkt = (struct rndis_packet_msg *)buf; 1331 1332 if (pkt->rm_dataoffset + pkt->rm_datalen > len) { 1333 printf("%s: data packet out of bounds: %u@%u\n", 1334 sc->sc_dev.dv_xname, pkt->rm_dataoffset, pkt->rm_datalen); 1335 return; 1336 } 1337 1338 if ((m = hvn_devget(sc, buf + RNDIS_HEADER_OFFSET + pkt->rm_dataoffset, 1339 pkt->rm_datalen)) == NULL) { 1340 ifp->if_ierrors++; 1341 return; 1342 } 1343 1344 pi = (struct rndis_pktinfo *)((caddr_t)pkt + RNDIS_HEADER_OFFSET + 1345 pkt->rm_pktinfooffset); 1346 while (pkt->rm_pktinfolen > 0) { 1347 if (pkt->rm_pktinfooffset + pkt->rm_pktinfolen > len) { 1348 printf("%s: PI out of bounds: %u@%u\n", 1349 sc->sc_dev.dv_xname, pkt->rm_pktinfolen, 1350 pkt->rm_pktinfooffset); 1351 break; 1352 } 1353 if (pi->rm_size > pkt->rm_pktinfolen) { 1354 printf("%s: invalid PI size: %u/%u\n", 1355 sc->sc_dev.dv_xname, pi->rm_size, 1356 pkt->rm_pktinfolen); 1357 break; 1358 } 1359 switch (pi->rm_type) { 1360 case NDIS_PKTINFO_TYPE_CSUM: 1361 memcpy(&csum, (caddr_t)pi + pi->rm_size, sizeof(csum)); 1362 if (csum & NDIS_RXCSUM_INFO_IPCS_OK) 1363 m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; 1364 if (csum & NDIS_RXCSUM_INFO_TCPCS_OK) 1365 m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK; 1366 if (csum & NDIS_RXCSUM_INFO_UDPCS_OK) 1367 m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK; 1368 break; 1369 case NDIS_PKTINFO_TYPE_VLAN: 1370 memcpy(&vlan, (caddr_t)pi + pi->rm_size, sizeof(vlan)); 1371 #if NVLAN > 0 1372 m->m_pkthdr.ether_vtag = vlan & 0xffff; 1373 m->m_flags |= M_VLANTAG; 1374 #endif 1375 break; 1376 default: 1377 DPRINTF("%s: unhandled PI %u\n", sc->sc_dev.dv_xname, 1378 pi->rm_type); 1379 } 1380 pkt->rm_pktinfolen -= pi->rm_size; 1381 pi = (struct rndis_pktinfo *)((caddr_t)pi + pi->rm_size); 1382 } 1383 1384 ml_enqueue(ml, m); 1385 } 1386 1387 void 1388 hvn_rndis_complete(struct hvn_softc *sc, caddr_t buf, uint32_t len) 1389 { 1390 struct rndis_cmd *rc; 1391 uint32_t id; 1392 1393 memcpy(&id, buf + RNDIS_HEADER_OFFSET, sizeof(id)); 1394 if ((rc = hvn_complete_cmd(sc, id)) != NULL) { 1395 if (len < rc->rc_cmplen) 1396 printf("%s: RNDIS response %u too short: %u\n", 1397 sc->sc_dev.dv_xname, id, len); 1398 else 1399 memcpy(&rc->rc_cmp, buf, rc->rc_cmplen); 1400 if (len > rc->rc_cmplen && 1401 len - rc->rc_cmplen > HVN_RNDIS_CMPBUFSZ) 1402 printf("%s: RNDIS response %u too large: %u\n", 1403 sc->sc_dev.dv_xname, id, len); 1404 else if (len > rc->rc_cmplen) 1405 memcpy(&rc->rc_cmpbuf, buf + rc->rc_cmplen, 1406 len - rc->rc_cmplen); 1407 wakeup_one(rc); 1408 } else 1409 DPRINTF("%s: failed to complete RNDIS request id %u\n", 1410 sc->sc_dev.dv_xname, id); 1411 } 1412 1413 int 1414 hvn_rndis_output(struct hvn_softc *sc, struct hvn_tx_desc *txd) 1415 { 1416 struct hvn_nvs_rndis *cmd = &txd->txd_cmd; 1417 int rv; 1418 1419 cmd->nvs_type = HVN_NVS_TYPE_RNDIS; 1420 cmd->nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_DATA; 1421 cmd->nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID; 1422 1423 rv = hv_channel_send_sgl(sc->sc_chan, txd->txd_sgl, txd->txd_nsge, 1424 &txd->txd_cmd, sizeof(*cmd), (uint64_t)txd->txd_id << 32); 1425 if (rv) { 1426 DPRINTF("%s: RNDIS data send error %d\n", 1427 sc->sc_dev.dv_xname, rv); 1428 return (rv); 1429 } 1430 1431 return (0); 1432 } 1433 1434 void 1435 hvn_rndis_status(struct hvn_softc *sc, caddr_t buf, uint32_t len) 1436 { 1437 uint32_t sta; 1438 1439 memcpy(&sta, buf + RNDIS_HEADER_OFFSET, sizeof(sta)); 1440 switch (sta) { 1441 case RNDIS_STATUS_MEDIA_CONNECT: 1442 sc->sc_link_state = LINK_STATE_UP; 1443 break; 1444 case RNDIS_STATUS_MEDIA_DISCONNECT: 1445 sc->sc_link_state = LINK_STATE_DOWN; 1446 break; 1447 /* Ignore these */ 1448 case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG: 1449 return; 1450 default: 1451 DPRINTF("%s: unhandled status %#x\n", sc->sc_dev.dv_xname, sta); 1452 return; 1453 } 1454 KERNEL_LOCK(); 1455 hvn_link_status(sc); 1456 KERNEL_UNLOCK(); 1457 } 1458 1459 int 1460 hvn_rndis_query(struct hvn_softc *sc, uint32_t oid, void *res, size_t *length) 1461 { 1462 struct rndis_cmd *rc; 1463 struct rndis_query_req *req; 1464 struct rndis_query_comp *cmp; 1465 size_t olength = *length; 1466 int rv; 1467 1468 rc = hvn_alloc_cmd(sc); 1469 1470 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1471 BUS_DMASYNC_PREREAD); 1472 1473 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid); 1474 1475 req = rc->rc_req; 1476 req->rm_type = REMOTE_NDIS_QUERY_MSG; 1477 req->rm_len = sizeof(*req); 1478 req->rm_rid = rc->rc_id; 1479 req->rm_oid = oid; 1480 req->rm_infobufoffset = sizeof(*req) - RNDIS_HEADER_OFFSET; 1481 1482 rc->rc_cmplen = sizeof(*cmp); 1483 1484 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1485 BUS_DMASYNC_PREWRITE); 1486 1487 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 1488 DPRINTF("%s: QUERY_MSG failed, error %d\n", 1489 sc->sc_dev.dv_xname, rv); 1490 hvn_free_cmd(sc, rc); 1491 return (rv); 1492 } 1493 1494 cmp = (struct rndis_query_comp *)&rc->rc_cmp; 1495 switch (cmp->rm_status) { 1496 case RNDIS_STATUS_SUCCESS: 1497 if (cmp->rm_infobuflen > olength) { 1498 rv = EINVAL; 1499 break; 1500 } 1501 memcpy(res, rc->rc_cmpbuf, cmp->rm_infobuflen); 1502 *length = cmp->rm_infobuflen; 1503 break; 1504 default: 1505 *length = 0; 1506 rv = EIO; 1507 } 1508 1509 hvn_free_cmd(sc, rc); 1510 1511 return (rv); 1512 } 1513 1514 int 1515 hvn_rndis_set(struct hvn_softc *sc, uint32_t oid, void *data, size_t length) 1516 { 1517 struct rndis_cmd *rc; 1518 struct rndis_set_req *req; 1519 struct rndis_set_comp *cmp; 1520 int rv; 1521 1522 rc = hvn_alloc_cmd(sc); 1523 1524 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1525 BUS_DMASYNC_PREREAD); 1526 1527 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid); 1528 1529 req = rc->rc_req; 1530 req->rm_type = REMOTE_NDIS_SET_MSG; 1531 req->rm_len = sizeof(*req) + length; 1532 req->rm_rid = rc->rc_id; 1533 req->rm_oid = oid; 1534 req->rm_infobufoffset = sizeof(*req) - RNDIS_HEADER_OFFSET; 1535 1536 rc->rc_cmplen = sizeof(*cmp); 1537 1538 if (length > 0) { 1539 KASSERT(sizeof(*req) + length < PAGE_SIZE); 1540 req->rm_infobuflen = length; 1541 memcpy((caddr_t)(req + 1), data, length); 1542 } 1543 1544 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1545 BUS_DMASYNC_PREWRITE); 1546 1547 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 1548 DPRINTF("%s: SET_MSG failed, error %u\n", 1549 sc->sc_dev.dv_xname, rv); 1550 hvn_free_cmd(sc, rc); 1551 return (rv); 1552 } 1553 1554 cmp = (struct rndis_set_comp *)&rc->rc_cmp; 1555 if (cmp->rm_status != RNDIS_STATUS_SUCCESS) 1556 rv = EIO; 1557 1558 hvn_free_cmd(sc, rc); 1559 1560 return (rv); 1561 } 1562 1563 int 1564 hvn_rndis_open(struct hvn_softc *sc) 1565 { 1566 uint32_t filter; 1567 int rv; 1568 1569 if (sc->sc_promisc) 1570 filter = NDIS_PACKET_TYPE_PROMISCUOUS; 1571 else 1572 filter = NDIS_PACKET_TYPE_BROADCAST | 1573 NDIS_PACKET_TYPE_ALL_MULTICAST | 1574 NDIS_PACKET_TYPE_DIRECTED; 1575 1576 rv = hvn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER, 1577 &filter, sizeof(filter)); 1578 if (rv) 1579 DPRINTF("%s: failed to set RNDIS filter to %#x\n", 1580 sc->sc_dev.dv_xname, filter); 1581 return (rv); 1582 } 1583 1584 int 1585 hvn_rndis_close(struct hvn_softc *sc) 1586 { 1587 uint32_t filter = 0; 1588 int rv; 1589 1590 rv = hvn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER, 1591 &filter, sizeof(filter)); 1592 if (rv) 1593 DPRINTF("%s: failed to clear RNDIS filter\n", 1594 sc->sc_dev.dv_xname); 1595 return (rv); 1596 } 1597 1598 void 1599 hvn_rndis_detach(struct hvn_softc *sc) 1600 { 1601 struct rndis_cmd *rc; 1602 struct rndis_halt_req *req; 1603 int rv; 1604 1605 rc = hvn_alloc_cmd(sc); 1606 1607 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1608 BUS_DMASYNC_PREREAD); 1609 1610 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid); 1611 1612 req = rc->rc_req; 1613 req->rm_type = REMOTE_NDIS_HALT_MSG; 1614 req->rm_len = sizeof(*req); 1615 req->rm_rid = rc->rc_id; 1616 1617 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1618 BUS_DMASYNC_PREWRITE); 1619 1620 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) 1621 DPRINTF("%s: HALT_MSG failed, error %u\n", 1622 sc->sc_dev.dv_xname, rv); 1623 1624 hvn_free_cmd(sc, rc); 1625 } 1626