1 /* $NetBSD: if_hvn.c,v 1.18 2020/05/24 10:31:59 nonaka Exp $ */ 2 /* $OpenBSD: if_hvn.c,v 1.39 2018/03/11 14:31:34 mikeb Exp $ */ 3 4 /*- 5 * Copyright (c) 2009-2012,2016 Microsoft Corp. 6 * Copyright (c) 2010-2012 Citrix Inc. 7 * Copyright (c) 2012 NetApp Inc. 8 * Copyright (c) 2016 Mike Belopuhov <mike@esdenera.com> 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice unmodified, this list of conditions, and the following 16 * disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * The OpenBSD port was done under funding by Esdenera Networks GmbH. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: if_hvn.c,v 1.18 2020/05/24 10:31:59 nonaka Exp $"); 39 40 #ifdef _KERNEL_OPT 41 #include "opt_inet.h" 42 #include "opt_inet6.h" 43 #include "opt_net_mpsafe.h" 44 #endif 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/device.h> 50 #include <sys/atomic.h> 51 #include <sys/bus.h> 52 #include <sys/intr.h> 53 #include <sys/kmem.h> 54 55 #include <net/if.h> 56 #include <net/if_ether.h> 57 #include <net/if_media.h> 58 59 #include <net/bpf.h> 60 61 #include <dev/ic/ndisreg.h> 62 #include <dev/ic/rndisreg.h> 63 64 #include <dev/hyperv/vmbusvar.h> 65 #include <dev/hyperv/if_hvnreg.h> 66 67 #ifndef EVL_PRIO_BITS 68 #define EVL_PRIO_BITS 13 69 #endif 70 #ifndef EVL_CFI_BITS 71 #define EVL_CFI_BITS 12 72 #endif 73 74 #define HVN_NVS_MSGSIZE 32 75 #define HVN_NVS_BUFSIZE PAGE_SIZE 76 77 /* 78 * RNDIS control interface 79 */ 80 #define HVN_RNDIS_CTLREQS 4 81 #define HVN_RNDIS_BUFSIZE 512 82 83 struct rndis_cmd { 84 uint32_t rc_id; 85 struct hvn_nvs_rndis rc_msg; 86 void *rc_req; 87 bus_dmamap_t rc_dmap; 88 bus_dma_segment_t rc_segs; 89 int rc_nsegs; 90 uint64_t rc_gpa; 91 struct rndis_packet_msg rc_cmp; 92 uint32_t rc_cmplen; 93 uint8_t rc_cmpbuf[HVN_RNDIS_BUFSIZE]; 94 int rc_done; 95 TAILQ_ENTRY(rndis_cmd) rc_entry; 96 }; 97 TAILQ_HEAD(rndis_queue, rndis_cmd); 98 99 #define HVN_MAXMTU (9 * 1024) 100 101 #define HVN_RNDIS_XFER_SIZE 2048 102 103 /* 104 * Tx ring 105 */ 106 #define HVN_TX_DESC 256 107 #define HVN_TX_FRAGS 15 /* 31 is the max */ 108 #define HVN_TX_FRAG_SIZE PAGE_SIZE 109 #define HVN_TX_PKT_SIZE 16384 110 111 #define HVN_RNDIS_PKT_LEN \ 112 (sizeof(struct rndis_packet_msg) + \ 113 sizeof(struct rndis_pktinfo) + NDIS_VLAN_INFO_SIZE + \ 114 sizeof(struct rndis_pktinfo) + NDIS_TXCSUM_INFO_SIZE) 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 rndis_packet_msg *txd_req; 125 }; 126 127 struct hvn_softc { 128 device_t sc_dev; 129 130 struct vmbus_softc *sc_vmbus; 131 struct vmbus_channel *sc_chan; 132 bus_dma_tag_t sc_dmat; 133 134 struct ethercom sc_ec; 135 struct ifmedia sc_media; 136 kmutex_t sc_media_lock; /* XXX */ 137 struct if_percpuq *sc_ipq; 138 int sc_link_state; 139 int sc_promisc; 140 141 uint32_t sc_flags; 142 #define HVN_SCF_ATTACHED __BIT(0) 143 144 /* NVS protocol */ 145 int sc_proto; 146 uint32_t sc_nvstid; 147 uint8_t sc_nvsrsp[HVN_NVS_MSGSIZE]; 148 uint8_t *sc_nvsbuf; 149 int sc_nvsdone; 150 151 /* RNDIS protocol */ 152 int sc_ndisver; 153 uint32_t sc_rndisrid; 154 struct rndis_queue sc_cntl_sq; /* submission queue */ 155 kmutex_t sc_cntl_sqlck; 156 struct rndis_queue sc_cntl_cq; /* completion queue */ 157 kmutex_t sc_cntl_cqlck; 158 struct rndis_queue sc_cntl_fq; /* free queue */ 159 kmutex_t sc_cntl_fqlck; 160 struct rndis_cmd sc_cntl_msgs[HVN_RNDIS_CTLREQS]; 161 struct hvn_nvs_rndis sc_data_msg; 162 163 /* Rx ring */ 164 uint8_t *sc_rx_ring; 165 int sc_rx_size; 166 uint32_t sc_rx_hndl; 167 struct hyperv_dma sc_rx_dma; 168 169 /* Tx ring */ 170 uint32_t sc_tx_next; 171 uint32_t sc_tx_avail; 172 struct hvn_tx_desc sc_tx_desc[HVN_TX_DESC]; 173 bus_dmamap_t sc_tx_rmap; 174 uint8_t *sc_tx_msgs; 175 bus_dma_segment_t sc_tx_mseg; 176 }; 177 178 #define SC2IFP(_sc_) (&(_sc_)->sc_ec.ec_if) 179 #define IFP2SC(_ifp_) ((_ifp_)->if_softc) 180 181 182 static int hvn_match(device_t, cfdata_t, void *); 183 static void hvn_attach(device_t, device_t, void *); 184 static int hvn_detach(device_t, int); 185 186 CFATTACH_DECL_NEW(hvn, sizeof(struct hvn_softc), 187 hvn_match, hvn_attach, hvn_detach, NULL); 188 189 static int hvn_ioctl(struct ifnet *, u_long, void *); 190 static int hvn_media_change(struct ifnet *); 191 static void hvn_media_status(struct ifnet *, struct ifmediareq *); 192 static int hvn_iff(struct hvn_softc *); 193 static int hvn_init(struct ifnet *); 194 static void hvn_stop(struct ifnet *, int); 195 static void hvn_start(struct ifnet *); 196 static int hvn_encap(struct hvn_softc *, struct mbuf *, 197 struct hvn_tx_desc **); 198 static void hvn_decap(struct hvn_softc *, struct hvn_tx_desc *); 199 static void hvn_txeof(struct hvn_softc *, uint64_t); 200 static int hvn_rx_ring_create(struct hvn_softc *); 201 static int hvn_rx_ring_destroy(struct hvn_softc *); 202 static int hvn_tx_ring_create(struct hvn_softc *); 203 static void hvn_tx_ring_destroy(struct hvn_softc *); 204 static int hvn_set_capabilities(struct hvn_softc *); 205 static int hvn_get_lladdr(struct hvn_softc *, uint8_t *); 206 static void hvn_get_link_status(struct hvn_softc *); 207 208 /* NSVP */ 209 static int hvn_nvs_attach(struct hvn_softc *); 210 static void hvn_nvs_intr(void *); 211 static int hvn_nvs_cmd(struct hvn_softc *, void *, size_t, uint64_t, int); 212 static int hvn_nvs_ack(struct hvn_softc *, uint64_t); 213 static void hvn_nvs_detach(struct hvn_softc *); 214 215 /* RNDIS */ 216 static int hvn_rndis_attach(struct hvn_softc *); 217 static int hvn_rndis_cmd(struct hvn_softc *, struct rndis_cmd *, int); 218 static void hvn_rndis_input(struct hvn_softc *, uint64_t, void *); 219 static void hvn_rxeof(struct hvn_softc *, uint8_t *, uint32_t); 220 static void hvn_rndis_complete(struct hvn_softc *, uint8_t *, uint32_t); 221 static int hvn_rndis_output(struct hvn_softc *, struct hvn_tx_desc *); 222 static void hvn_rndis_status(struct hvn_softc *, uint8_t *, uint32_t); 223 static int hvn_rndis_query(struct hvn_softc *, uint32_t, void *, size_t *); 224 static int hvn_rndis_set(struct hvn_softc *, uint32_t, void *, size_t); 225 static int hvn_rndis_open(struct hvn_softc *); 226 static int hvn_rndis_close(struct hvn_softc *); 227 static void hvn_rndis_detach(struct hvn_softc *); 228 229 static int 230 hvn_match(device_t parent, cfdata_t match, void *aux) 231 { 232 struct vmbus_attach_args *aa = aux; 233 234 if (memcmp(aa->aa_type, &hyperv_guid_network, sizeof(*aa->aa_type))) 235 return 0; 236 return 1; 237 } 238 239 static void 240 hvn_attach(device_t parent, device_t self, void *aux) 241 { 242 struct hvn_softc *sc = device_private(self); 243 struct vmbus_attach_args *aa = aux; 244 struct ifnet *ifp = SC2IFP(sc); 245 uint8_t enaddr[ETHER_ADDR_LEN]; 246 int error; 247 248 sc->sc_dev = self; 249 sc->sc_vmbus = (struct vmbus_softc *)device_private(parent); 250 sc->sc_chan = aa->aa_chan; 251 sc->sc_dmat = sc->sc_vmbus->sc_dmat; 252 253 aprint_naive("\n"); 254 aprint_normal(": Hyper-V NetVSC\n"); 255 256 if (hvn_nvs_attach(sc)) { 257 aprint_error_dev(self, "failed to init NVSP\n"); 258 return; 259 } 260 261 if (hvn_rx_ring_create(sc)) { 262 aprint_error_dev(self, "failed to create Rx ring\n"); 263 goto fail1; 264 } 265 266 if (hvn_tx_ring_create(sc)) { 267 aprint_error_dev(self, "failed to create Tx ring\n"); 268 goto fail2; 269 } 270 271 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 272 ifp->if_softc = sc; 273 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 274 ifp->if_ioctl = hvn_ioctl; 275 ifp->if_start = hvn_start; 276 ifp->if_init = hvn_init; 277 ifp->if_stop = hvn_stop; 278 ifp->if_capabilities = IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx; 279 ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx; 280 ifp->if_capabilities |= IFCAP_CSUM_TCPv6_Tx | IFCAP_CSUM_TCPv6_Rx; 281 if (sc->sc_ndisver > NDIS_VERSION_6_30) { 282 ifp->if_capabilities |= IFCAP_CSUM_UDPv4_Tx; 283 ifp->if_capabilities |= IFCAP_CSUM_UDPv4_Rx; 284 ifp->if_capabilities |= IFCAP_CSUM_UDPv6_Tx; 285 ifp->if_capabilities |= IFCAP_CSUM_UDPv6_Rx; 286 } 287 if (sc->sc_proto >= HVN_NVS_PROTO_VERSION_2) { 288 sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_HWTAGGING; 289 sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU; 290 sc->sc_ec.ec_capenable |= ETHERCAP_VLAN_HWTAGGING; 291 } 292 293 IFQ_SET_MAXLEN(&ifp->if_snd, HVN_TX_DESC - 1); 294 IFQ_SET_READY(&ifp->if_snd); 295 296 /* Initialize ifmedia structures. */ 297 sc->sc_ec.ec_ifmedia = &sc->sc_media; 298 /* XXX media locking needs revisiting */ 299 mutex_init(&sc->sc_media_lock, MUTEX_DEFAULT, IPL_SOFTNET); 300 ifmedia_init_with_lock(&sc->sc_media, IFM_IMASK, 301 hvn_media_change, hvn_media_status, &sc->sc_media_lock); 302 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 303 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); 304 305 error = if_initialize(ifp); 306 if (error) { 307 aprint_error_dev(self, "if_initialize failed(%d)\n", error); 308 goto fail3; 309 } 310 sc->sc_ipq = if_percpuq_create(ifp); 311 if_deferred_start_init(ifp, NULL); 312 313 if (hvn_rndis_attach(sc)) { 314 aprint_error_dev(self, "failed to init RNDIS\n"); 315 goto fail3; 316 } 317 318 aprint_normal_dev(self, "NVS %d.%d NDIS %d.%d\n", 319 sc->sc_proto >> 16, sc->sc_proto & 0xffff, 320 sc->sc_ndisver >> 16 , sc->sc_ndisver & 0xffff); 321 322 if (hvn_set_capabilities(sc)) { 323 aprint_error_dev(self, "failed to setup offloading\n"); 324 goto fail4; 325 } 326 327 if (hvn_get_lladdr(sc, enaddr)) { 328 aprint_error_dev(self, 329 "failed to obtain an ethernet address\n"); 330 goto fail4; 331 } 332 aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(enaddr)); 333 334 ether_ifattach(ifp, enaddr); 335 if_register(ifp); 336 337 if (pmf_device_register(self, NULL, NULL)) 338 pmf_class_network_register(self, ifp); 339 else 340 aprint_error_dev(self, "couldn't establish power handler\n"); 341 342 SET(sc->sc_flags, HVN_SCF_ATTACHED); 343 return; 344 345 fail4: hvn_rndis_detach(sc); 346 if_percpuq_destroy(sc->sc_ipq); 347 fail3: ifmedia_fini(&sc->sc_media); 348 mutex_destroy(&sc->sc_media_lock); 349 hvn_tx_ring_destroy(sc); 350 fail2: hvn_rx_ring_destroy(sc); 351 fail1: hvn_nvs_detach(sc); 352 } 353 354 static int 355 hvn_detach(device_t self, int flags) 356 { 357 struct hvn_softc *sc = device_private(self); 358 struct ifnet *ifp = SC2IFP(sc); 359 360 if (!ISSET(sc->sc_flags, HVN_SCF_ATTACHED)) 361 return 0; 362 363 if (ifp->if_flags & IFF_RUNNING) 364 hvn_stop(ifp, 1); 365 366 pmf_device_deregister(self); 367 368 ether_ifdetach(ifp); 369 if_detach(ifp); 370 ifmedia_fini(&sc->sc_media); 371 mutex_destroy(&sc->sc_media_lock); 372 if_percpuq_destroy(sc->sc_ipq); 373 374 hvn_rndis_detach(sc); 375 hvn_rx_ring_destroy(sc); 376 hvn_tx_ring_destroy(sc); 377 hvn_nvs_detach(sc); 378 379 return 0; 380 } 381 382 static int 383 hvn_ioctl(struct ifnet *ifp, u_long command, void * data) 384 { 385 struct hvn_softc *sc = IFP2SC(ifp); 386 int s, error = 0; 387 388 s = splnet(); 389 390 switch (command) { 391 case SIOCSIFFLAGS: 392 if (ifp->if_flags & IFF_UP) { 393 if (ifp->if_flags & IFF_RUNNING) 394 error = ENETRESET; 395 else { 396 error = hvn_init(ifp); 397 if (error) 398 ifp->if_flags &= ~IFF_UP; 399 } 400 } else { 401 if (ifp->if_flags & IFF_RUNNING) 402 hvn_stop(ifp, 1); 403 } 404 break; 405 default: 406 error = ether_ioctl(ifp, command, data); 407 break; 408 } 409 410 if (error == ENETRESET) { 411 if (ifp->if_flags & IFF_RUNNING) 412 hvn_iff(sc); 413 error = 0; 414 } 415 416 splx(s); 417 418 return error; 419 } 420 421 static int 422 hvn_media_change(struct ifnet *ifp) 423 { 424 425 return 0; 426 } 427 428 static void 429 hvn_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 430 { 431 struct hvn_softc *sc = IFP2SC(ifp); 432 int link_state; 433 434 link_state = sc->sc_link_state; 435 hvn_get_link_status(sc); 436 if (link_state != sc->sc_link_state) 437 if_link_state_change(ifp, sc->sc_link_state); 438 439 ifmr->ifm_status = IFM_AVALID; 440 ifmr->ifm_active = IFM_ETHER | IFM_MANUAL; 441 if (sc->sc_link_state == LINK_STATE_UP) 442 ifmr->ifm_status |= IFM_ACTIVE; 443 } 444 445 static int 446 hvn_iff(struct hvn_softc *sc) 447 { 448 449 /* XXX */ 450 sc->sc_promisc = 0; 451 452 return 0; 453 } 454 455 static int 456 hvn_init(struct ifnet *ifp) 457 { 458 struct hvn_softc *sc = IFP2SC(ifp); 459 int error; 460 461 hvn_stop(ifp, 0); 462 463 error = hvn_iff(sc); 464 if (error) 465 return error; 466 467 error = hvn_rndis_open(sc); 468 if (error == 0) { 469 ifp->if_flags |= IFF_RUNNING; 470 ifp->if_flags &= ~IFF_OACTIVE; 471 } 472 return error; 473 } 474 475 static void 476 hvn_stop(struct ifnet *ifp, int disable) 477 { 478 struct hvn_softc *sc = IFP2SC(ifp); 479 480 hvn_rndis_close(sc); 481 482 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 483 } 484 485 static void 486 hvn_start(struct ifnet *ifp) 487 { 488 struct hvn_softc *sc = IFP2SC(ifp); 489 struct hvn_tx_desc *txd; 490 struct mbuf *m; 491 492 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 493 return; 494 495 for (;;) { 496 if (!sc->sc_tx_avail) { 497 /* transient */ 498 ifp->if_flags |= IFF_OACTIVE; 499 break; 500 } 501 502 IFQ_DEQUEUE(&ifp->if_snd, m); 503 if (m == NULL) 504 break; 505 506 if (hvn_encap(sc, m, &txd)) { 507 /* the chain is too large */ 508 if_statinc(ifp, if_oerrors); 509 m_freem(m); 510 continue; 511 } 512 513 bpf_mtap(ifp, m, BPF_D_OUT); 514 515 if (hvn_rndis_output(sc, txd)) { 516 hvn_decap(sc, txd); 517 if_statinc(ifp, if_oerrors); 518 m_freem(m); 519 continue; 520 } 521 522 sc->sc_tx_next++; 523 } 524 } 525 526 static inline char * 527 hvn_rndis_pktinfo_append(struct rndis_packet_msg *pkt, size_t pktsize, 528 size_t datalen, uint32_t type) 529 { 530 struct rndis_pktinfo *pi; 531 size_t pi_size = sizeof(*pi) + datalen; 532 char *cp; 533 534 KASSERT(pkt->rm_pktinfooffset + pkt->rm_pktinfolen + pi_size <= 535 pktsize); 536 537 cp = (char *)pkt + pkt->rm_pktinfooffset + pkt->rm_pktinfolen; 538 pi = (struct rndis_pktinfo *)cp; 539 pi->rm_size = pi_size; 540 pi->rm_type = type; 541 pi->rm_pktinfooffset = sizeof(*pi); 542 pkt->rm_pktinfolen += pi_size; 543 pkt->rm_dataoffset += pi_size; 544 pkt->rm_len += pi_size; 545 546 return (char *)pi->rm_data; 547 } 548 549 static int 550 hvn_encap(struct hvn_softc *sc, struct mbuf *m, struct hvn_tx_desc **txd0) 551 { 552 struct hvn_tx_desc *txd; 553 struct rndis_packet_msg *pkt; 554 bus_dma_segment_t *seg; 555 size_t pktlen; 556 int i, rv; 557 558 do { 559 txd = &sc->sc_tx_desc[sc->sc_tx_next % HVN_TX_DESC]; 560 sc->sc_tx_next++; 561 } while (!txd->txd_ready); 562 txd->txd_ready = 0; 563 564 pkt = txd->txd_req; 565 memset(pkt, 0, HVN_RNDIS_PKT_LEN); 566 pkt->rm_type = REMOTE_NDIS_PACKET_MSG; 567 pkt->rm_len = sizeof(*pkt) + m->m_pkthdr.len; 568 pkt->rm_dataoffset = RNDIS_DATA_OFFSET; 569 pkt->rm_datalen = m->m_pkthdr.len; 570 pkt->rm_pktinfooffset = sizeof(*pkt); /* adjusted below */ 571 pkt->rm_pktinfolen = 0; 572 573 rv = bus_dmamap_load_mbuf(sc->sc_dmat, txd->txd_dmap, m, BUS_DMA_READ | 574 BUS_DMA_NOWAIT); 575 switch (rv) { 576 case 0: 577 break; 578 case EFBIG: 579 if (m_defrag(m, M_NOWAIT) != NULL && 580 bus_dmamap_load_mbuf(sc->sc_dmat, txd->txd_dmap, m, 581 BUS_DMA_READ | BUS_DMA_NOWAIT) == 0) 582 break; 583 /* FALLTHROUGH */ 584 default: 585 DPRINTF("%s: failed to load mbuf\n", device_xname(sc->sc_dev)); 586 return -1; 587 } 588 txd->txd_buf = m; 589 590 if (vlan_has_tag(m)) { 591 uint32_t vlan; 592 char *cp; 593 uint16_t tag; 594 595 tag = vlan_get_tag(m); 596 vlan = NDIS_VLAN_INFO_MAKE(EVL_VLANOFTAG(tag), 597 EVL_PRIOFTAG(tag), EVL_CFIOFTAG(tag)); 598 cp = hvn_rndis_pktinfo_append(pkt, HVN_RNDIS_PKT_LEN, 599 NDIS_VLAN_INFO_SIZE, NDIS_PKTINFO_TYPE_VLAN); 600 memcpy(cp, &vlan, NDIS_VLAN_INFO_SIZE); 601 } 602 603 if (m->m_pkthdr.csum_flags & (M_CSUM_IPv4 | M_CSUM_UDPv4 | 604 M_CSUM_TCPv4)) { 605 uint32_t csum = NDIS_TXCSUM_INFO_IPV4; 606 char *cp; 607 608 if (m->m_pkthdr.csum_flags & M_CSUM_IPv4) 609 csum |= NDIS_TXCSUM_INFO_IPCS; 610 if (m->m_pkthdr.csum_flags & M_CSUM_TCPv4) 611 csum |= NDIS_TXCSUM_INFO_TCPCS; 612 if (m->m_pkthdr.csum_flags & M_CSUM_UDPv4) 613 csum |= NDIS_TXCSUM_INFO_UDPCS; 614 cp = hvn_rndis_pktinfo_append(pkt, HVN_RNDIS_PKT_LEN, 615 NDIS_TXCSUM_INFO_SIZE, NDIS_PKTINFO_TYPE_CSUM); 616 memcpy(cp, &csum, NDIS_TXCSUM_INFO_SIZE); 617 } 618 619 pktlen = pkt->rm_pktinfooffset + pkt->rm_pktinfolen; 620 pkt->rm_pktinfooffset -= RNDIS_HEADER_OFFSET; 621 622 /* Attach an RNDIS message to the first slot */ 623 txd->txd_sgl[0].gpa_page = txd->txd_gpa.gpa_page; 624 txd->txd_sgl[0].gpa_ofs = txd->txd_gpa.gpa_ofs; 625 txd->txd_sgl[0].gpa_len = pktlen; 626 txd->txd_nsge = txd->txd_dmap->dm_nsegs + 1; 627 628 for (i = 0; i < txd->txd_dmap->dm_nsegs; i++) { 629 seg = &txd->txd_dmap->dm_segs[i]; 630 txd->txd_sgl[1 + i].gpa_page = atop(seg->ds_addr); 631 txd->txd_sgl[1 + i].gpa_ofs = seg->ds_addr & PAGE_MASK; 632 txd->txd_sgl[1 + i].gpa_len = seg->ds_len; 633 } 634 635 *txd0 = txd; 636 637 atomic_dec_uint(&sc->sc_tx_avail); 638 639 return 0; 640 } 641 642 static void 643 hvn_decap(struct hvn_softc *sc, struct hvn_tx_desc *txd) 644 { 645 struct ifnet *ifp = SC2IFP(sc); 646 647 bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 648 0, txd->txd_dmap->dm_mapsize, 649 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 650 bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap); 651 txd->txd_buf = NULL; 652 txd->txd_nsge = 0; 653 txd->txd_ready = 1; 654 atomic_inc_uint(&sc->sc_tx_avail); 655 ifp->if_flags &= ~IFF_OACTIVE; 656 } 657 658 static void 659 hvn_txeof(struct hvn_softc *sc, uint64_t tid) 660 { 661 struct ifnet *ifp = SC2IFP(sc); 662 struct hvn_tx_desc *txd; 663 struct mbuf *m; 664 uint32_t id = tid >> 32; 665 666 if ((tid & 0xffffffffU) != 0) 667 return; 668 669 id -= HVN_NVS_CHIM_SIG; 670 if (id >= HVN_TX_DESC) { 671 device_printf(sc->sc_dev, "tx packet index too large: %u", id); 672 return; 673 } 674 675 txd = &sc->sc_tx_desc[id]; 676 677 if ((m = txd->txd_buf) == NULL) { 678 device_printf(sc->sc_dev, "no mbuf @%u\n", id); 679 return; 680 } 681 txd->txd_buf = NULL; 682 683 bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 684 0, txd->txd_dmap->dm_mapsize, 685 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 686 bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap); 687 m_freem(m); 688 if_statinc(ifp, if_opackets); 689 690 txd->txd_ready = 1; 691 692 atomic_inc_uint(&sc->sc_tx_avail); 693 ifp->if_flags &= ~IFF_OACTIVE; 694 } 695 696 static int 697 hvn_rx_ring_create(struct hvn_softc *sc) 698 { 699 struct hvn_nvs_rxbuf_conn cmd; 700 struct hvn_nvs_rxbuf_conn_resp *rsp; 701 uint64_t tid; 702 703 if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_2) 704 sc->sc_rx_size = 15 * 1024 * 1024; /* 15MB */ 705 else 706 sc->sc_rx_size = 16 * 1024 * 1024; /* 16MB */ 707 sc->sc_rx_ring = hyperv_dma_alloc(sc->sc_dmat, &sc->sc_rx_dma, 708 sc->sc_rx_size, PAGE_SIZE, PAGE_SIZE, sc->sc_rx_size / PAGE_SIZE, 709 HYPERV_DMA_SLEEPOK); 710 if (sc->sc_rx_ring == NULL) { 711 DPRINTF("%s: failed to allocate Rx ring buffer\n", 712 device_xname(sc->sc_dev)); 713 return -1; 714 } 715 if (vmbus_handle_alloc(sc->sc_chan, &sc->sc_rx_dma, sc->sc_rx_size, 716 &sc->sc_rx_hndl)) { 717 DPRINTF("%s: failed to obtain a PA handle\n", 718 device_xname(sc->sc_dev)); 719 goto errout; 720 } 721 722 memset(&cmd, 0, sizeof(cmd)); 723 cmd.nvs_type = HVN_NVS_TYPE_RXBUF_CONN; 724 cmd.nvs_gpadl = sc->sc_rx_hndl; 725 cmd.nvs_sig = HVN_NVS_RXBUF_SIG; 726 727 tid = atomic_inc_uint_nv(&sc->sc_nvstid); 728 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) 729 goto errout; 730 731 rsp = (struct hvn_nvs_rxbuf_conn_resp *)&sc->sc_nvsrsp; 732 if (rsp->nvs_status != HVN_NVS_STATUS_OK) { 733 DPRINTF("%s: failed to set up the Rx ring\n", 734 device_xname(sc->sc_dev)); 735 goto errout; 736 } 737 if (rsp->nvs_nsect > 1) { 738 DPRINTF("%s: invalid number of Rx ring sections: %u\n", 739 device_xname(sc->sc_dev), rsp->nvs_nsect); 740 hvn_rx_ring_destroy(sc); 741 return -1; 742 } 743 return 0; 744 745 errout: 746 if (sc->sc_rx_hndl) { 747 vmbus_handle_free(sc->sc_chan, sc->sc_rx_hndl); 748 sc->sc_rx_hndl = 0; 749 } 750 if (sc->sc_rx_ring) { 751 hyperv_dma_free(sc->sc_dmat, &sc->sc_rx_dma); 752 sc->sc_rx_ring = NULL; 753 } 754 return -1; 755 } 756 757 static int 758 hvn_rx_ring_destroy(struct hvn_softc *sc) 759 { 760 struct hvn_nvs_rxbuf_disconn cmd; 761 uint64_t tid; 762 763 if (sc->sc_rx_ring == NULL) 764 return 0; 765 766 memset(&cmd, 0, sizeof(cmd)); 767 cmd.nvs_type = HVN_NVS_TYPE_RXBUF_DISCONN; 768 cmd.nvs_sig = HVN_NVS_RXBUF_SIG; 769 770 tid = atomic_inc_uint_nv(&sc->sc_nvstid); 771 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 0)) 772 return -1; 773 774 delay(100); 775 776 vmbus_handle_free(sc->sc_chan, sc->sc_rx_hndl); 777 sc->sc_rx_hndl = 0; 778 779 hyperv_dma_free(sc->sc_dmat, &sc->sc_rx_dma); 780 sc->sc_rx_ring = NULL; 781 782 return 0; 783 } 784 785 static int 786 hvn_tx_ring_create(struct hvn_softc *sc) 787 { 788 const int dmaflags = cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK; 789 struct hvn_tx_desc *txd; 790 bus_dma_segment_t *seg; 791 size_t msgsize; 792 int i, rsegs; 793 paddr_t pa; 794 795 msgsize = roundup(HVN_RNDIS_PKT_LEN, 128); 796 797 /* Allocate memory to store RNDIS messages */ 798 if (bus_dmamem_alloc(sc->sc_dmat, msgsize * HVN_TX_DESC, PAGE_SIZE, 0, 799 &sc->sc_tx_mseg, 1, &rsegs, dmaflags)) { 800 DPRINTF("%s: failed to allocate memory for RDNIS messages\n", 801 device_xname(sc->sc_dev)); 802 goto errout; 803 } 804 if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tx_mseg, 1, msgsize * 805 HVN_TX_DESC, (void **)&sc->sc_tx_msgs, dmaflags)) { 806 DPRINTF("%s: failed to establish mapping for RDNIS messages\n", 807 device_xname(sc->sc_dev)); 808 goto errout; 809 } 810 memset(sc->sc_tx_msgs, 0, msgsize * HVN_TX_DESC); 811 if (bus_dmamap_create(sc->sc_dmat, msgsize * HVN_TX_DESC, 1, 812 msgsize * HVN_TX_DESC, 0, dmaflags, &sc->sc_tx_rmap)) { 813 DPRINTF("%s: failed to create map for RDNIS messages\n", 814 device_xname(sc->sc_dev)); 815 goto errout; 816 } 817 if (bus_dmamap_load(sc->sc_dmat, sc->sc_tx_rmap, sc->sc_tx_msgs, 818 msgsize * HVN_TX_DESC, NULL, dmaflags)) { 819 DPRINTF("%s: failed to create map for RDNIS messages\n", 820 device_xname(sc->sc_dev)); 821 goto errout; 822 } 823 824 for (i = 0; i < HVN_TX_DESC; i++) { 825 txd = &sc->sc_tx_desc[i]; 826 if (bus_dmamap_create(sc->sc_dmat, HVN_TX_PKT_SIZE, 827 HVN_TX_FRAGS, HVN_TX_FRAG_SIZE, PAGE_SIZE, dmaflags, 828 &txd->txd_dmap)) { 829 DPRINTF("%s: failed to create map for TX descriptors\n", 830 device_xname(sc->sc_dev)); 831 goto errout; 832 } 833 seg = &sc->sc_tx_rmap->dm_segs[0]; 834 pa = seg->ds_addr + (msgsize * i); 835 txd->txd_gpa.gpa_page = atop(pa); 836 txd->txd_gpa.gpa_ofs = pa & PAGE_MASK; 837 txd->txd_gpa.gpa_len = msgsize; 838 txd->txd_req = (void *)(sc->sc_tx_msgs + (msgsize * i)); 839 txd->txd_id = i + HVN_NVS_CHIM_SIG; 840 txd->txd_ready = 1; 841 } 842 sc->sc_tx_avail = HVN_TX_DESC; 843 844 return 0; 845 846 errout: 847 hvn_tx_ring_destroy(sc); 848 return -1; 849 } 850 851 static void 852 hvn_tx_ring_destroy(struct hvn_softc *sc) 853 { 854 struct hvn_tx_desc *txd; 855 int i; 856 857 for (i = 0; i < HVN_TX_DESC; i++) { 858 txd = &sc->sc_tx_desc[i]; 859 if (txd->txd_dmap == NULL) 860 continue; 861 bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 862 0, txd->txd_dmap->dm_mapsize, 863 BUS_DMASYNC_POSTWRITE); 864 bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap); 865 bus_dmamap_destroy(sc->sc_dmat, txd->txd_dmap); 866 txd->txd_dmap = NULL; 867 if (txd->txd_buf == NULL) 868 continue; 869 m_freem(txd->txd_buf); 870 txd->txd_buf = NULL; 871 } 872 if (sc->sc_tx_rmap != NULL) { 873 bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_rmap, 874 0, sc->sc_tx_rmap->dm_mapsize, 875 BUS_DMASYNC_POSTWRITE); 876 bus_dmamap_unload(sc->sc_dmat, sc->sc_tx_rmap); 877 bus_dmamap_destroy(sc->sc_dmat, sc->sc_tx_rmap); 878 sc->sc_tx_rmap = NULL; 879 } 880 if (sc->sc_tx_msgs != NULL) { 881 size_t msgsize = roundup(HVN_RNDIS_PKT_LEN, 128); 882 883 bus_dmamem_unmap(sc->sc_dmat, sc->sc_tx_msgs, 884 msgsize * HVN_TX_DESC); 885 bus_dmamem_free(sc->sc_dmat, &sc->sc_tx_mseg, 1); 886 sc->sc_tx_msgs = NULL; 887 } 888 } 889 890 static int 891 hvn_get_lladdr(struct hvn_softc *sc, uint8_t *enaddr) 892 { 893 size_t addrlen = ETHER_ADDR_LEN; 894 int rv; 895 896 rv = hvn_rndis_query(sc, OID_802_3_PERMANENT_ADDRESS, enaddr, &addrlen); 897 if (rv == 0 && addrlen != ETHER_ADDR_LEN) 898 rv = -1; 899 return rv; 900 } 901 902 static void 903 hvn_get_link_status(struct hvn_softc *sc) 904 { 905 uint32_t state; 906 size_t len = sizeof(state); 907 908 if (hvn_rndis_query(sc, OID_GEN_MEDIA_CONNECT_STATUS, 909 &state, &len) == 0) 910 sc->sc_link_state = (state == NDIS_MEDIA_STATE_CONNECTED) ? 911 LINK_STATE_UP : LINK_STATE_DOWN; 912 } 913 914 static int 915 hvn_nvs_attach(struct hvn_softc *sc) 916 { 917 static const uint32_t protos[] = { 918 HVN_NVS_PROTO_VERSION_5, 919 HVN_NVS_PROTO_VERSION_4, 920 HVN_NVS_PROTO_VERSION_2, 921 HVN_NVS_PROTO_VERSION_1 922 }; 923 struct hvn_nvs_init cmd; 924 struct hvn_nvs_init_resp *rsp; 925 struct hvn_nvs_ndis_init ncmd; 926 struct hvn_nvs_ndis_conf ccmd; 927 uint32_t ndisver, ringsize; 928 uint64_t tid; 929 int i; 930 931 sc->sc_nvsbuf = kmem_zalloc(HVN_NVS_BUFSIZE, KM_SLEEP); 932 933 /* We need to be able to fit all RNDIS control and data messages */ 934 ringsize = HVN_RNDIS_CTLREQS * 935 (sizeof(struct hvn_nvs_rndis) + sizeof(struct vmbus_gpa)) + 936 HVN_TX_DESC * (sizeof(struct hvn_nvs_rndis) + 937 (HVN_TX_FRAGS + 1) * sizeof(struct vmbus_gpa)); 938 939 sc->sc_chan->ch_flags &= ~CHF_BATCHED; 940 941 /* Associate our interrupt handler with the channel */ 942 if (vmbus_channel_open(sc->sc_chan, ringsize, NULL, 0, 943 hvn_nvs_intr, sc)) { 944 DPRINTF("%s: failed to open channel\n", 945 device_xname(sc->sc_dev)); 946 kmem_free(sc->sc_nvsbuf, HVN_NVS_BUFSIZE); 947 return -1; 948 } 949 950 memset(&cmd, 0, sizeof(cmd)); 951 cmd.nvs_type = HVN_NVS_TYPE_INIT; 952 for (i = 0; i < __arraycount(protos); i++) { 953 cmd.nvs_ver_min = cmd.nvs_ver_max = protos[i]; 954 tid = atomic_inc_uint_nv(&sc->sc_nvstid); 955 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) 956 return -1; 957 958 rsp = (struct hvn_nvs_init_resp *)&sc->sc_nvsrsp; 959 if (rsp->nvs_status == HVN_NVS_STATUS_OK) { 960 sc->sc_proto = protos[i]; 961 break; 962 } 963 } 964 if (i == __arraycount(protos)) { 965 DPRINTF("%s: failed to negotiate NVSP version\n", 966 device_xname(sc->sc_dev)); 967 return -1; 968 } 969 970 if (sc->sc_proto >= HVN_NVS_PROTO_VERSION_2) { 971 memset(&ccmd, 0, sizeof(ccmd)); 972 ccmd.nvs_type = HVN_NVS_TYPE_NDIS_CONF; 973 ccmd.nvs_mtu = HVN_MAXMTU; 974 ccmd.nvs_caps = HVN_NVS_NDIS_CONF_VLAN; 975 976 tid = atomic_inc_uint_nv(&sc->sc_nvstid); 977 if (hvn_nvs_cmd(sc, &ccmd, sizeof(ccmd), tid, 100)) 978 return -1; 979 } 980 981 memset(&ncmd, 0, sizeof(ncmd)); 982 ncmd.nvs_type = HVN_NVS_TYPE_NDIS_INIT; 983 if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_4) 984 ndisver = NDIS_VERSION_6_1; 985 else 986 ndisver = NDIS_VERSION_6_30; 987 ncmd.nvs_ndis_major = (ndisver & 0xffff0000) >> 16; 988 ncmd.nvs_ndis_minor = ndisver & 0x0000ffff; 989 990 tid = atomic_inc_uint_nv(&sc->sc_nvstid); 991 if (hvn_nvs_cmd(sc, &ncmd, sizeof(ncmd), tid, 100)) 992 return -1; 993 994 sc->sc_ndisver = ndisver; 995 996 return 0; 997 } 998 999 static void 1000 hvn_nvs_intr(void *arg) 1001 { 1002 struct hvn_softc *sc = arg; 1003 struct ifnet *ifp = SC2IFP(sc); 1004 struct vmbus_chanpkt_hdr *cph; 1005 const struct hvn_nvs_hdr *nvs; 1006 uint64_t rid; 1007 uint32_t rlen; 1008 int rv; 1009 bool dotx = false; 1010 1011 for (;;) { 1012 rv = vmbus_channel_recv(sc->sc_chan, sc->sc_nvsbuf, 1013 HVN_NVS_BUFSIZE, &rlen, &rid, 1); 1014 if (rv != 0 || rlen == 0) { 1015 if (rv != EAGAIN) 1016 device_printf(sc->sc_dev, 1017 "failed to receive an NVSP packet\n"); 1018 break; 1019 } 1020 cph = (struct vmbus_chanpkt_hdr *)sc->sc_nvsbuf; 1021 nvs = (const struct hvn_nvs_hdr *)VMBUS_CHANPKT_CONST_DATA(cph); 1022 1023 if (cph->cph_type == VMBUS_CHANPKT_TYPE_COMP) { 1024 switch (nvs->nvs_type) { 1025 case HVN_NVS_TYPE_INIT_RESP: 1026 case HVN_NVS_TYPE_RXBUF_CONNRESP: 1027 case HVN_NVS_TYPE_CHIM_CONNRESP: 1028 case HVN_NVS_TYPE_SUBCH_RESP: 1029 /* copy the response back */ 1030 memcpy(&sc->sc_nvsrsp, nvs, HVN_NVS_MSGSIZE); 1031 sc->sc_nvsdone = 1; 1032 wakeup(&sc->sc_nvsrsp); 1033 break; 1034 case HVN_NVS_TYPE_RNDIS_ACK: 1035 dotx = true; 1036 hvn_txeof(sc, cph->cph_tid); 1037 break; 1038 default: 1039 device_printf(sc->sc_dev, 1040 "unhandled NVSP packet type %u " 1041 "on completion\n", nvs->nvs_type); 1042 break; 1043 } 1044 } else if (cph->cph_type == VMBUS_CHANPKT_TYPE_RXBUF) { 1045 switch (nvs->nvs_type) { 1046 case HVN_NVS_TYPE_RNDIS: 1047 hvn_rndis_input(sc, cph->cph_tid, cph); 1048 break; 1049 default: 1050 device_printf(sc->sc_dev, 1051 "unhandled NVSP packet type %u " 1052 "on receive\n", nvs->nvs_type); 1053 break; 1054 } 1055 } else if (cph->cph_type == VMBUS_CHANPKT_TYPE_INBAND) { 1056 switch (nvs->nvs_type) { 1057 case HVN_NVS_TYPE_TXTBL_NOTE: 1058 /* Useless; ignore */ 1059 break; 1060 default: 1061 device_printf(sc->sc_dev, 1062 "got notify, nvs type %u\n", nvs->nvs_type); 1063 break; 1064 } 1065 } else 1066 device_printf(sc->sc_dev, 1067 "unknown NVSP packet type %u\n", cph->cph_type); 1068 } 1069 1070 if (dotx) 1071 if_schedule_deferred_start(ifp); 1072 } 1073 1074 static int 1075 hvn_nvs_cmd(struct hvn_softc *sc, void *cmd, size_t cmdsize, uint64_t tid, 1076 int timo) 1077 { 1078 struct hvn_nvs_hdr *hdr = cmd; 1079 int tries = 10; 1080 int rv, s; 1081 1082 sc->sc_nvsdone = 0; 1083 1084 do { 1085 rv = vmbus_channel_send(sc->sc_chan, cmd, cmdsize, 1086 tid, VMBUS_CHANPKT_TYPE_INBAND, 1087 timo ? VMBUS_CHANPKT_FLAG_RC : 0); 1088 if (rv == EAGAIN) { 1089 if (cold) 1090 delay(1000); 1091 else 1092 tsleep(cmd, PRIBIO, "nvsout", mstohz(1)); 1093 } else if (rv) { 1094 DPRINTF("%s: NVSP operation %u send error %d\n", 1095 device_xname(sc->sc_dev), hdr->nvs_type, rv); 1096 return rv; 1097 } 1098 } while (rv != 0 && --tries > 0); 1099 1100 if (tries == 0 && rv != 0) { 1101 device_printf(sc->sc_dev, 1102 "NVSP operation %u send error %d\n", hdr->nvs_type, rv); 1103 return rv; 1104 } 1105 1106 if (timo == 0) 1107 return 0; 1108 1109 do { 1110 if (cold) { 1111 delay(1000); 1112 s = splnet(); 1113 hvn_nvs_intr(sc); 1114 splx(s); 1115 } else 1116 tsleep(sc->sc_nvsrsp, PRIBIO | PCATCH, "nvscmd", 1117 mstohz(1)); 1118 } while (--timo > 0 && sc->sc_nvsdone != 1); 1119 1120 if (timo == 0 && sc->sc_nvsdone != 1) { 1121 device_printf(sc->sc_dev, "NVSP operation %u timed out\n", 1122 hdr->nvs_type); 1123 return ETIMEDOUT; 1124 } 1125 return 0; 1126 } 1127 1128 static int 1129 hvn_nvs_ack(struct hvn_softc *sc, uint64_t tid) 1130 { 1131 struct hvn_nvs_rndis_ack cmd; 1132 int tries = 5; 1133 int rv; 1134 1135 cmd.nvs_type = HVN_NVS_TYPE_RNDIS_ACK; 1136 cmd.nvs_status = HVN_NVS_STATUS_OK; 1137 do { 1138 rv = vmbus_channel_send(sc->sc_chan, &cmd, sizeof(cmd), 1139 tid, VMBUS_CHANPKT_TYPE_COMP, 0); 1140 if (rv == EAGAIN) 1141 delay(10); 1142 else if (rv) { 1143 DPRINTF("%s: NVSP acknowledgement error %d\n", 1144 device_xname(sc->sc_dev), rv); 1145 return rv; 1146 } 1147 } while (rv != 0 && --tries > 0); 1148 return rv; 1149 } 1150 1151 static void 1152 hvn_nvs_detach(struct hvn_softc *sc) 1153 { 1154 1155 if (vmbus_channel_close(sc->sc_chan) == 0) { 1156 kmem_free(sc->sc_nvsbuf, HVN_NVS_BUFSIZE); 1157 sc->sc_nvsbuf = NULL; 1158 } 1159 } 1160 1161 static inline struct rndis_cmd * 1162 hvn_alloc_cmd(struct hvn_softc *sc) 1163 { 1164 struct rndis_cmd *rc; 1165 1166 mutex_enter(&sc->sc_cntl_fqlck); 1167 while ((rc = TAILQ_FIRST(&sc->sc_cntl_fq)) == NULL) 1168 /* XXX use condvar(9) instead of mtsleep */ 1169 mtsleep(&sc->sc_cntl_fq, PRIBIO, "nvsalloc", 1, 1170 &sc->sc_cntl_fqlck); 1171 TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry); 1172 mutex_exit(&sc->sc_cntl_fqlck); 1173 return rc; 1174 } 1175 1176 static inline void 1177 hvn_submit_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 1178 { 1179 1180 mutex_enter(&sc->sc_cntl_sqlck); 1181 TAILQ_INSERT_TAIL(&sc->sc_cntl_sq, rc, rc_entry); 1182 mutex_exit(&sc->sc_cntl_sqlck); 1183 } 1184 1185 static inline struct rndis_cmd * 1186 hvn_complete_cmd(struct hvn_softc *sc, uint32_t id) 1187 { 1188 struct rndis_cmd *rc; 1189 1190 mutex_enter(&sc->sc_cntl_sqlck); 1191 TAILQ_FOREACH(rc, &sc->sc_cntl_sq, rc_entry) { 1192 if (rc->rc_id == id) { 1193 TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry); 1194 break; 1195 } 1196 } 1197 mutex_exit(&sc->sc_cntl_sqlck); 1198 if (rc != NULL) { 1199 mutex_enter(&sc->sc_cntl_cqlck); 1200 TAILQ_INSERT_TAIL(&sc->sc_cntl_cq, rc, rc_entry); 1201 mutex_exit(&sc->sc_cntl_cqlck); 1202 } 1203 return rc; 1204 } 1205 1206 static inline void 1207 hvn_release_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 1208 { 1209 1210 mutex_enter(&sc->sc_cntl_cqlck); 1211 TAILQ_REMOVE(&sc->sc_cntl_cq, rc, rc_entry); 1212 mutex_exit(&sc->sc_cntl_cqlck); 1213 } 1214 1215 static inline int 1216 hvn_rollback_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 1217 { 1218 struct rndis_cmd *rn; 1219 1220 mutex_enter(&sc->sc_cntl_sqlck); 1221 TAILQ_FOREACH(rn, &sc->sc_cntl_sq, rc_entry) { 1222 if (rn == rc) { 1223 TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry); 1224 mutex_exit(&sc->sc_cntl_sqlck); 1225 return 0; 1226 } 1227 } 1228 mutex_exit(&sc->sc_cntl_sqlck); 1229 return -1; 1230 } 1231 1232 static inline void 1233 hvn_free_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) 1234 { 1235 1236 memset(rc->rc_req, 0, sizeof(struct rndis_packet_msg)); 1237 memset(&rc->rc_cmp, 0, sizeof(rc->rc_cmp)); 1238 memset(&rc->rc_msg, 0, sizeof(rc->rc_msg)); 1239 mutex_enter(&sc->sc_cntl_fqlck); 1240 TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry); 1241 mutex_exit(&sc->sc_cntl_fqlck); 1242 wakeup(&sc->sc_cntl_fq); 1243 } 1244 1245 static int 1246 hvn_rndis_attach(struct hvn_softc *sc) 1247 { 1248 const int dmaflags = cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK; 1249 struct rndis_init_req *req; 1250 struct rndis_init_comp *cmp; 1251 struct rndis_cmd *rc; 1252 int i, rv; 1253 1254 /* RNDIS control message queues */ 1255 TAILQ_INIT(&sc->sc_cntl_sq); 1256 TAILQ_INIT(&sc->sc_cntl_cq); 1257 TAILQ_INIT(&sc->sc_cntl_fq); 1258 mutex_init(&sc->sc_cntl_sqlck, MUTEX_DEFAULT, IPL_NET); 1259 mutex_init(&sc->sc_cntl_cqlck, MUTEX_DEFAULT, IPL_NET); 1260 mutex_init(&sc->sc_cntl_fqlck, MUTEX_DEFAULT, IPL_NET); 1261 1262 for (i = 0; i < HVN_RNDIS_CTLREQS; i++) { 1263 rc = &sc->sc_cntl_msgs[i]; 1264 if (bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0, 1265 dmaflags, &rc->rc_dmap)) { 1266 DPRINTF("%s: failed to create RNDIS command map\n", 1267 device_xname(sc->sc_dev)); 1268 goto errout; 1269 } 1270 if (bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 1271 0, &rc->rc_segs, 1, &rc->rc_nsegs, dmaflags)) { 1272 DPRINTF("%s: failed to allocate RNDIS command\n", 1273 device_xname(sc->sc_dev)); 1274 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 1275 goto errout; 1276 } 1277 if (bus_dmamem_map(sc->sc_dmat, &rc->rc_segs, rc->rc_nsegs, 1278 PAGE_SIZE, (void **)&rc->rc_req, dmaflags)) { 1279 DPRINTF("%s: failed to allocate RNDIS command\n", 1280 device_xname(sc->sc_dev)); 1281 bus_dmamem_free(sc->sc_dmat, &rc->rc_segs, 1282 rc->rc_nsegs); 1283 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 1284 goto errout; 1285 } 1286 memset(rc->rc_req, 0, PAGE_SIZE); 1287 if (bus_dmamap_load(sc->sc_dmat, rc->rc_dmap, rc->rc_req, 1288 PAGE_SIZE, NULL, dmaflags)) { 1289 DPRINTF("%s: failed to load RNDIS command map\n", 1290 device_xname(sc->sc_dev)); 1291 bus_dmamem_free(sc->sc_dmat, &rc->rc_segs, 1292 rc->rc_nsegs); 1293 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 1294 goto errout; 1295 } 1296 rc->rc_gpa = atop(rc->rc_dmap->dm_segs[0].ds_addr); 1297 TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry); 1298 } 1299 1300 rc = hvn_alloc_cmd(sc); 1301 1302 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1303 BUS_DMASYNC_PREREAD); 1304 1305 rc->rc_id = atomic_inc_uint_nv(&sc->sc_rndisrid); 1306 1307 req = rc->rc_req; 1308 req->rm_type = REMOTE_NDIS_INITIALIZE_MSG; 1309 req->rm_len = sizeof(*req); 1310 req->rm_rid = rc->rc_id; 1311 req->rm_ver_major = RNDIS_VERSION_MAJOR; 1312 req->rm_ver_minor = RNDIS_VERSION_MINOR; 1313 req->rm_max_xfersz = HVN_RNDIS_XFER_SIZE; 1314 1315 rc->rc_cmplen = sizeof(*cmp); 1316 1317 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1318 BUS_DMASYNC_PREWRITE); 1319 1320 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 1321 DPRINTF("%s: INITIALIZE_MSG failed, error %d\n", 1322 device_xname(sc->sc_dev), rv); 1323 hvn_free_cmd(sc, rc); 1324 goto errout; 1325 } 1326 cmp = (struct rndis_init_comp *)&rc->rc_cmp; 1327 if (cmp->rm_status != RNDIS_STATUS_SUCCESS) { 1328 DPRINTF("%s: failed to init RNDIS, error %#x\n", 1329 device_xname(sc->sc_dev), cmp->rm_status); 1330 hvn_free_cmd(sc, rc); 1331 goto errout; 1332 } 1333 1334 hvn_free_cmd(sc, rc); 1335 1336 /* Initialize RNDIS Data command */ 1337 memset(&sc->sc_data_msg, 0, sizeof(sc->sc_data_msg)); 1338 sc->sc_data_msg.nvs_type = HVN_NVS_TYPE_RNDIS; 1339 sc->sc_data_msg.nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_DATA; 1340 sc->sc_data_msg.nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID; 1341 1342 return 0; 1343 1344 errout: 1345 for (i = 0; i < HVN_RNDIS_CTLREQS; i++) { 1346 rc = &sc->sc_cntl_msgs[i]; 1347 if (rc->rc_req == NULL) 1348 continue; 1349 TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry); 1350 bus_dmamem_free(sc->sc_dmat, &rc->rc_segs, rc->rc_nsegs); 1351 rc->rc_req = NULL; 1352 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap); 1353 } 1354 return -1; 1355 } 1356 1357 static int 1358 hvn_set_capabilities(struct hvn_softc *sc) 1359 { 1360 struct ndis_offload_params params; 1361 size_t len = sizeof(params); 1362 1363 memset(¶ms, 0, sizeof(params)); 1364 1365 params.ndis_hdr.ndis_type = NDIS_OBJTYPE_DEFAULT; 1366 if (sc->sc_ndisver < NDIS_VERSION_6_30) { 1367 params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_2; 1368 len = params.ndis_hdr.ndis_size = NDIS_OFFLOAD_PARAMS_SIZE_6_1; 1369 } else { 1370 params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_3; 1371 len = params.ndis_hdr.ndis_size = NDIS_OFFLOAD_PARAMS_SIZE; 1372 } 1373 1374 params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX; 1375 params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX; 1376 params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX; 1377 if (sc->sc_ndisver >= NDIS_VERSION_6_30) { 1378 params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX; 1379 params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX; 1380 } 1381 1382 return hvn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS, ¶ms, len); 1383 } 1384 1385 static int 1386 hvn_rndis_cmd(struct hvn_softc *sc, struct rndis_cmd *rc, int timo) 1387 { 1388 struct hvn_nvs_rndis *msg = &rc->rc_msg; 1389 struct rndis_msghdr *hdr = rc->rc_req; 1390 struct vmbus_gpa sgl[1]; 1391 int tries = 10; 1392 int rv, s; 1393 1394 KASSERT(timo > 0); 1395 1396 msg->nvs_type = HVN_NVS_TYPE_RNDIS; 1397 msg->nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_CTRL; 1398 msg->nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID; 1399 1400 sgl[0].gpa_page = rc->rc_gpa; 1401 sgl[0].gpa_len = hdr->rm_len; 1402 sgl[0].gpa_ofs = 0; 1403 1404 rc->rc_done = 0; 1405 1406 hvn_submit_cmd(sc, rc); 1407 1408 do { 1409 rv = vmbus_channel_send_sgl(sc->sc_chan, sgl, 1, &rc->rc_msg, 1410 sizeof(*msg), rc->rc_id); 1411 if (rv == EAGAIN) { 1412 if (cold) 1413 delay(1000); 1414 else 1415 tsleep(rc, PRIBIO, "rndisout", mstohz(1)); 1416 } else if (rv) { 1417 DPRINTF("%s: RNDIS operation %u send error %d\n", 1418 device_xname(sc->sc_dev), hdr->rm_type, rv); 1419 hvn_rollback_cmd(sc, rc); 1420 return rv; 1421 } 1422 } while (rv != 0 && --tries > 0); 1423 1424 if (tries == 0 && rv != 0) { 1425 device_printf(sc->sc_dev, 1426 "RNDIS operation %u send error %d\n", hdr->rm_type, rv); 1427 return rv; 1428 } 1429 if (vmbus_channel_is_revoked(sc->sc_chan)) { 1430 /* No response */ 1431 return 0; 1432 } 1433 1434 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1435 BUS_DMASYNC_POSTWRITE); 1436 1437 do { 1438 if (cold) { 1439 delay(1000); 1440 s = splnet(); 1441 hvn_nvs_intr(sc); 1442 splx(s); 1443 } else 1444 tsleep(rc, PRIBIO | PCATCH, "rndiscmd", mstohz(1)); 1445 } while (--timo > 0 && rc->rc_done != 1); 1446 1447 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1448 BUS_DMASYNC_POSTREAD); 1449 1450 if (rc->rc_done != 1) { 1451 rv = timo == 0 ? ETIMEDOUT : EINTR; 1452 if (hvn_rollback_cmd(sc, rc)) { 1453 hvn_release_cmd(sc, rc); 1454 rv = 0; 1455 } else if (rv == ETIMEDOUT) { 1456 device_printf(sc->sc_dev, 1457 "RNDIS operation %u timed out\n", hdr->rm_type); 1458 } 1459 return rv; 1460 } 1461 1462 hvn_release_cmd(sc, rc); 1463 return 0; 1464 } 1465 1466 static void 1467 hvn_rndis_input(struct hvn_softc *sc, uint64_t tid, void *arg) 1468 { 1469 struct vmbus_chanpkt_prplist *cp = arg; 1470 uint32_t off, len, type; 1471 int i; 1472 1473 if (sc->sc_rx_ring == NULL) { 1474 DPRINTF("%s: invalid rx ring\n", device_xname(sc->sc_dev)); 1475 return; 1476 } 1477 1478 for (i = 0; i < cp->cp_range_cnt; i++) { 1479 off = cp->cp_range[i].gpa_ofs; 1480 len = cp->cp_range[i].gpa_len; 1481 1482 KASSERT(off + len <= sc->sc_rx_size); 1483 KASSERT(len >= RNDIS_HEADER_OFFSET + 4); 1484 1485 memcpy(&type, sc->sc_rx_ring + off, sizeof(type)); 1486 switch (type) { 1487 /* data message */ 1488 case REMOTE_NDIS_PACKET_MSG: 1489 hvn_rxeof(sc, sc->sc_rx_ring + off, len); 1490 break; 1491 /* completion messages */ 1492 case REMOTE_NDIS_INITIALIZE_CMPLT: 1493 case REMOTE_NDIS_QUERY_CMPLT: 1494 case REMOTE_NDIS_SET_CMPLT: 1495 case REMOTE_NDIS_RESET_CMPLT: 1496 case REMOTE_NDIS_KEEPALIVE_CMPLT: 1497 hvn_rndis_complete(sc, sc->sc_rx_ring + off, len); 1498 break; 1499 /* notification message */ 1500 case REMOTE_NDIS_INDICATE_STATUS_MSG: 1501 hvn_rndis_status(sc, sc->sc_rx_ring + off, len); 1502 break; 1503 default: 1504 device_printf(sc->sc_dev, 1505 "unhandled RNDIS message type %u\n", type); 1506 break; 1507 } 1508 } 1509 1510 hvn_nvs_ack(sc, tid); 1511 } 1512 1513 static inline struct mbuf * 1514 hvn_devget(struct hvn_softc *sc, void *buf, uint32_t len) 1515 { 1516 struct ifnet *ifp = SC2IFP(sc); 1517 struct mbuf *m; 1518 size_t size = len + ETHER_ALIGN; 1519 1520 MGETHDR(m, M_NOWAIT, MT_DATA); 1521 if (m == NULL) 1522 return NULL; 1523 1524 if (size > MHLEN) { 1525 if (size <= MCLBYTES) 1526 MCLGET(m, M_NOWAIT); 1527 else 1528 MEXTMALLOC(m, size, M_NOWAIT); 1529 if ((m->m_flags & M_EXT) == 0) { 1530 m_freem(m); 1531 return NULL; 1532 } 1533 } 1534 1535 m->m_len = m->m_pkthdr.len = size; 1536 m_adj(m, ETHER_ALIGN); 1537 m_copyback(m, 0, len, buf); 1538 m_set_rcvif(m, ifp); 1539 return m; 1540 } 1541 1542 static void 1543 hvn_rxeof(struct hvn_softc *sc, uint8_t *buf, uint32_t len) 1544 { 1545 struct ifnet *ifp = SC2IFP(sc); 1546 struct rndis_packet_msg *pkt; 1547 struct rndis_pktinfo *pi; 1548 uint32_t csum, vlan; 1549 struct mbuf *m; 1550 1551 if (!(ifp->if_flags & IFF_RUNNING)) 1552 return; 1553 1554 if (len < sizeof(*pkt)) { 1555 device_printf(sc->sc_dev, "data packet too short: %u\n", 1556 len); 1557 return; 1558 } 1559 1560 pkt = (struct rndis_packet_msg *)buf; 1561 if (pkt->rm_dataoffset + pkt->rm_datalen > len) { 1562 device_printf(sc->sc_dev, 1563 "data packet out of bounds: %u@%u\n", pkt->rm_dataoffset, 1564 pkt->rm_datalen); 1565 return; 1566 } 1567 1568 if ((m = hvn_devget(sc, buf + RNDIS_HEADER_OFFSET + pkt->rm_dataoffset, 1569 pkt->rm_datalen)) == NULL) { 1570 if_statinc(ifp, if_ierrors); 1571 return; 1572 } 1573 1574 if (pkt->rm_pktinfooffset + pkt->rm_pktinfolen > len) { 1575 device_printf(sc->sc_dev, 1576 "pktinfo is out of bounds: %u@%u vs %u\n", 1577 pkt->rm_pktinfolen, pkt->rm_pktinfooffset, len); 1578 goto done; 1579 } 1580 1581 pi = (struct rndis_pktinfo *)(buf + RNDIS_HEADER_OFFSET + 1582 pkt->rm_pktinfooffset); 1583 while (pkt->rm_pktinfolen > 0) { 1584 if (pi->rm_size > pkt->rm_pktinfolen) { 1585 device_printf(sc->sc_dev, 1586 "invalid pktinfo size: %u/%u\n", pi->rm_size, 1587 pkt->rm_pktinfolen); 1588 break; 1589 } 1590 1591 switch (pi->rm_type) { 1592 case NDIS_PKTINFO_TYPE_CSUM: 1593 memcpy(&csum, pi->rm_data, sizeof(csum)); 1594 if (csum & NDIS_RXCSUM_INFO_IPCS_OK) 1595 m->m_pkthdr.csum_flags |= M_CSUM_IPv4; 1596 if (csum & NDIS_RXCSUM_INFO_TCPCS_OK) 1597 m->m_pkthdr.csum_flags |= M_CSUM_TCPv4; 1598 if (csum & NDIS_RXCSUM_INFO_UDPCS_OK) 1599 m->m_pkthdr.csum_flags |= M_CSUM_UDPv4; 1600 break; 1601 case NDIS_PKTINFO_TYPE_VLAN: 1602 memcpy(&vlan, pi->rm_data, sizeof(vlan)); 1603 if (vlan != 0xffffffff) { 1604 uint16_t t = NDIS_VLAN_INFO_ID(vlan); 1605 t |= NDIS_VLAN_INFO_PRI(vlan) << EVL_PRIO_BITS; 1606 t |= NDIS_VLAN_INFO_CFI(vlan) << EVL_CFI_BITS; 1607 vlan_set_tag(m, t); 1608 } 1609 break; 1610 default: 1611 DPRINTF("%s: unhandled pktinfo type %u\n", 1612 device_xname(sc->sc_dev), pi->rm_type); 1613 break; 1614 } 1615 1616 pkt->rm_pktinfolen -= pi->rm_size; 1617 pi = (struct rndis_pktinfo *)((char *)pi + pi->rm_size); 1618 } 1619 1620 done: 1621 if_percpuq_enqueue(sc->sc_ipq, m); 1622 } 1623 1624 static void 1625 hvn_rndis_complete(struct hvn_softc *sc, uint8_t *buf, uint32_t len) 1626 { 1627 struct rndis_cmd *rc; 1628 uint32_t id; 1629 1630 memcpy(&id, buf + RNDIS_HEADER_OFFSET, sizeof(id)); 1631 if ((rc = hvn_complete_cmd(sc, id)) != NULL) { 1632 if (len < rc->rc_cmplen) 1633 device_printf(sc->sc_dev, 1634 "RNDIS response %u too short: %u\n", id, len); 1635 else 1636 memcpy(&rc->rc_cmp, buf, rc->rc_cmplen); 1637 if (len > rc->rc_cmplen && 1638 len - rc->rc_cmplen > HVN_RNDIS_BUFSIZE) 1639 device_printf(sc->sc_dev, 1640 "RNDIS response %u too large: %u\n", id, len); 1641 else if (len > rc->rc_cmplen) 1642 memcpy(&rc->rc_cmpbuf, buf + rc->rc_cmplen, 1643 len - rc->rc_cmplen); 1644 rc->rc_done = 1; 1645 wakeup(rc); 1646 } else { 1647 DPRINTF("%s: failed to complete RNDIS request id %u\n", 1648 device_xname(sc->sc_dev), id); 1649 } 1650 } 1651 1652 static int 1653 hvn_rndis_output(struct hvn_softc *sc, struct hvn_tx_desc *txd) 1654 { 1655 uint64_t rid = (uint64_t)txd->txd_id << 32; 1656 int rv; 1657 1658 rv = vmbus_channel_send_sgl(sc->sc_chan, txd->txd_sgl, txd->txd_nsge, 1659 &sc->sc_data_msg, sizeof(sc->sc_data_msg), rid); 1660 if (rv) { 1661 DPRINTF("%s: RNDIS data send error %d\n", 1662 device_xname(sc->sc_dev), rv); 1663 return rv; 1664 } 1665 return 0; 1666 } 1667 1668 static void 1669 hvn_rndis_status(struct hvn_softc *sc, uint8_t *buf, uint32_t len) 1670 { 1671 struct ifnet *ifp = SC2IFP(sc); 1672 uint32_t status; 1673 int link_state = sc->sc_link_state; 1674 1675 memcpy(&status, buf + RNDIS_HEADER_OFFSET, sizeof(status)); 1676 switch (status) { 1677 case RNDIS_STATUS_MEDIA_CONNECT: 1678 sc->sc_link_state = LINK_STATE_UP; 1679 break; 1680 case RNDIS_STATUS_MEDIA_DISCONNECT: 1681 sc->sc_link_state = LINK_STATE_DOWN; 1682 break; 1683 /* Ignore these */ 1684 case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG: 1685 return; 1686 default: 1687 DPRINTF("%s: unhandled status %#x\n", device_xname(sc->sc_dev), 1688 status); 1689 return; 1690 } 1691 if (link_state != sc->sc_link_state) 1692 if_link_state_change(ifp, sc->sc_link_state); 1693 } 1694 1695 static int 1696 hvn_rndis_query(struct hvn_softc *sc, uint32_t oid, void *res, size_t *length) 1697 { 1698 struct rndis_cmd *rc; 1699 struct rndis_query_req *req; 1700 struct rndis_query_comp *cmp; 1701 size_t olength = *length; 1702 int rv; 1703 1704 rc = hvn_alloc_cmd(sc); 1705 1706 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1707 BUS_DMASYNC_PREREAD); 1708 1709 rc->rc_id = atomic_inc_uint_nv(&sc->sc_rndisrid); 1710 1711 req = rc->rc_req; 1712 req->rm_type = REMOTE_NDIS_QUERY_MSG; 1713 req->rm_len = sizeof(*req); 1714 req->rm_rid = rc->rc_id; 1715 req->rm_oid = oid; 1716 req->rm_infobufoffset = sizeof(*req) - RNDIS_HEADER_OFFSET; 1717 1718 rc->rc_cmplen = sizeof(*cmp); 1719 1720 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1721 BUS_DMASYNC_PREWRITE); 1722 1723 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 1724 DPRINTF("%s: QUERY_MSG failed, error %d\n", 1725 device_xname(sc->sc_dev), rv); 1726 hvn_free_cmd(sc, rc); 1727 return rv; 1728 } 1729 1730 cmp = (struct rndis_query_comp *)&rc->rc_cmp; 1731 switch (cmp->rm_status) { 1732 case RNDIS_STATUS_SUCCESS: 1733 if (cmp->rm_infobuflen > olength) { 1734 rv = EINVAL; 1735 break; 1736 } 1737 memcpy(res, rc->rc_cmpbuf, cmp->rm_infobuflen); 1738 *length = cmp->rm_infobuflen; 1739 break; 1740 default: 1741 *length = 0; 1742 rv = EIO; 1743 break; 1744 } 1745 1746 hvn_free_cmd(sc, rc); 1747 return rv; 1748 } 1749 1750 static int 1751 hvn_rndis_set(struct hvn_softc *sc, uint32_t oid, void *data, size_t length) 1752 { 1753 struct rndis_cmd *rc; 1754 struct rndis_set_req *req; 1755 struct rndis_set_comp *cmp; 1756 int rv; 1757 1758 rc = hvn_alloc_cmd(sc); 1759 1760 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1761 BUS_DMASYNC_PREREAD); 1762 1763 rc->rc_id = atomic_inc_uint_nv(&sc->sc_rndisrid); 1764 1765 req = rc->rc_req; 1766 req->rm_type = REMOTE_NDIS_SET_MSG; 1767 req->rm_len = sizeof(*req) + length; 1768 req->rm_rid = rc->rc_id; 1769 req->rm_oid = oid; 1770 req->rm_infobufoffset = sizeof(*req) - RNDIS_HEADER_OFFSET; 1771 1772 rc->rc_cmplen = sizeof(*cmp); 1773 1774 if (length > 0) { 1775 KASSERT(sizeof(*req) + length < PAGE_SIZE); 1776 req->rm_infobuflen = length; 1777 memcpy(req + 1, data, length); 1778 } 1779 1780 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1781 BUS_DMASYNC_PREWRITE); 1782 1783 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 1784 DPRINTF("%s: SET_MSG failed, error %d\n", 1785 device_xname(sc->sc_dev), rv); 1786 hvn_free_cmd(sc, rc); 1787 return rv; 1788 } 1789 1790 cmp = (struct rndis_set_comp *)&rc->rc_cmp; 1791 if (cmp->rm_status != RNDIS_STATUS_SUCCESS) 1792 rv = EIO; 1793 1794 hvn_free_cmd(sc, rc); 1795 return rv; 1796 } 1797 1798 static int 1799 hvn_rndis_open(struct hvn_softc *sc) 1800 { 1801 uint32_t filter; 1802 int rv; 1803 1804 if (sc->sc_promisc) 1805 filter = RNDIS_PACKET_TYPE_PROMISCUOUS; 1806 else 1807 filter = RNDIS_PACKET_TYPE_BROADCAST | 1808 RNDIS_PACKET_TYPE_ALL_MULTICAST | 1809 RNDIS_PACKET_TYPE_DIRECTED; 1810 1811 rv = hvn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER, 1812 &filter, sizeof(filter)); 1813 if (rv) { 1814 DPRINTF("%s: failed to set RNDIS filter to %#x\n", 1815 device_xname(sc->sc_dev), filter); 1816 } 1817 return rv; 1818 } 1819 1820 static int 1821 hvn_rndis_close(struct hvn_softc *sc) 1822 { 1823 uint32_t filter = 0; 1824 int rv; 1825 1826 rv = hvn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER, 1827 &filter, sizeof(filter)); 1828 if (rv) { 1829 DPRINTF("%s: failed to clear RNDIS filter\n", 1830 device_xname(sc->sc_dev)); 1831 } 1832 return rv; 1833 } 1834 1835 static void 1836 hvn_rndis_detach(struct hvn_softc *sc) 1837 { 1838 struct rndis_cmd *rc; 1839 struct rndis_halt_req *req; 1840 int rv; 1841 1842 rc = hvn_alloc_cmd(sc); 1843 1844 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1845 BUS_DMASYNC_PREREAD); 1846 1847 rc->rc_id = atomic_inc_uint_nv(&sc->sc_rndisrid); 1848 1849 req = rc->rc_req; 1850 req->rm_type = REMOTE_NDIS_HALT_MSG; 1851 req->rm_len = sizeof(*req); 1852 req->rm_rid = rc->rc_id; 1853 1854 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, 1855 BUS_DMASYNC_PREWRITE); 1856 1857 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { 1858 DPRINTF("%s: HALT_MSG failed, error %d\n", 1859 device_xname(sc->sc_dev), rv); 1860 } 1861 hvn_free_cmd(sc, rc); 1862 1863 mutex_destroy(&sc->sc_cntl_sqlck); 1864 mutex_destroy(&sc->sc_cntl_cqlck); 1865 mutex_destroy(&sc->sc_cntl_fqlck); 1866 } 1867