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