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