hn_nvs.c revision 307167
1/*- 2 * Copyright (c) 2009-2012,2016 Microsoft Corp. 3 * Copyright (c) 2010-2012 Citrix Inc. 4 * Copyright (c) 2012 NetApp Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c 307167 2016-10-13 02:38:46Z sephe $ 29 */ 30 31/** 32 * HyperV vmbus network VSC (virtual services client) module 33 * 34 */ 35 36 37#include <sys/param.h> 38#include <sys/kernel.h> 39#include <sys/socket.h> 40#include <sys/lock.h> 41#include <net/if.h> 42#include <net/if_arp.h> 43#include <machine/bus.h> 44#include <machine/atomic.h> 45 46#include <dev/hyperv/include/hyperv.h> 47#include <dev/hyperv/include/vmbus_xact.h> 48#include <dev/hyperv/netvsc/hv_net_vsc.h> 49#include <dev/hyperv/netvsc/hv_rndis.h> 50#include <dev/hyperv/netvsc/hv_rndis_filter.h> 51#include <dev/hyperv/netvsc/if_hnreg.h> 52 53MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver"); 54 55/* 56 * Forward declarations 57 */ 58static void hv_nv_on_channel_callback(struct vmbus_channel *chan, 59 void *xrxr); 60static int hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc); 61static int hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *); 62static int hv_nv_destroy_send_buffer(netvsc_dev *net_dev); 63static int hv_nv_destroy_rx_buffer(netvsc_dev *net_dev); 64static int hv_nv_connect_to_vsp(struct hn_softc *sc); 65static void hv_nv_on_send_completion(netvsc_dev *net_dev, 66 struct vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt); 67static void hv_nv_on_receive_completion(struct vmbus_channel *chan, 68 uint64_t tid, uint32_t status); 69static void hv_nv_on_receive(netvsc_dev *net_dev, 70 struct hn_rx_ring *rxr, struct vmbus_channel *chan, 71 const struct vmbus_chanpkt_hdr *pkt); 72static void hn_nvs_sent_none(struct hn_send_ctx *sndc, 73 struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, 74 const void *, int); 75 76static struct hn_send_ctx hn_send_ctx_none = 77 HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL); 78 79/* 80 * 81 */ 82static inline netvsc_dev * 83hv_nv_alloc_net_device(struct hn_softc *sc) 84{ 85 netvsc_dev *net_dev; 86 87 net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_WAITOK | M_ZERO); 88 89 net_dev->sc = sc; 90 net_dev->destroy = FALSE; 91 sc->net_dev = net_dev; 92 93 return (net_dev); 94} 95 96/* 97 * XXX unnecessary; nuke it. 98 */ 99static inline netvsc_dev * 100hv_nv_get_outbound_net_device(struct hn_softc *sc) 101{ 102 return sc->net_dev; 103} 104 105/* 106 * XXX unnecessary; nuke it. 107 */ 108static inline netvsc_dev * 109hv_nv_get_inbound_net_device(struct hn_softc *sc) 110{ 111 return sc->net_dev; 112} 113 114int 115hv_nv_get_next_send_section(netvsc_dev *net_dev) 116{ 117 unsigned long bitsmap_words = net_dev->bitsmap_words; 118 unsigned long *bitsmap = net_dev->send_section_bitsmap; 119 unsigned long idx; 120 int ret = HN_NVS_CHIM_IDX_INVALID; 121 int i; 122 123 for (i = 0; i < bitsmap_words; i++) { 124 idx = ffsl(~bitsmap[i]); 125 if (0 == idx) 126 continue; 127 128 idx--; 129 KASSERT(i * BITS_PER_LONG + idx < net_dev->send_section_count, 130 ("invalid i %d and idx %lu", i, idx)); 131 132 if (atomic_testandset_long(&bitsmap[i], idx)) 133 continue; 134 135 ret = i * BITS_PER_LONG + idx; 136 break; 137 } 138 139 return (ret); 140} 141 142/* 143 * Net VSC initialize receive buffer with net VSP 144 * 145 * Net VSP: Network virtual services client, also known as the 146 * Hyper-V extensible switch and the synthetic data path. 147 */ 148static int 149hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) 150{ 151 struct vmbus_xact *xact; 152 struct hn_nvs_rxbuf_conn *conn; 153 const struct hn_nvs_rxbuf_connresp *resp; 154 size_t resp_len; 155 struct hn_send_ctx sndc; 156 netvsc_dev *net_dev; 157 uint32_t status; 158 int error; 159 160 net_dev = hv_nv_get_outbound_net_device(sc); 161 if (!net_dev) { 162 return (ENODEV); 163 } 164 165 net_dev->rx_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), 166 PAGE_SIZE, 0, net_dev->rx_buf_size, &net_dev->rxbuf_dma, 167 BUS_DMA_WAITOK | BUS_DMA_ZERO); 168 if (net_dev->rx_buf == NULL) { 169 device_printf(sc->hn_dev, "allocate rxbuf failed\n"); 170 return (ENOMEM); 171 } 172 173 /* 174 * Connect the RXBUF GPADL to the primary channel. 175 * 176 * NOTE: 177 * Only primary channel has RXBUF connected to it. Sub-channels 178 * just share this RXBUF. 179 */ 180 error = vmbus_chan_gpadl_connect(sc->hn_prichan, 181 net_dev->rxbuf_dma.hv_paddr, net_dev->rx_buf_size, 182 &net_dev->rx_buf_gpadl_handle); 183 if (error) { 184 if_printf(sc->hn_ifp, "rxbuf gpadl connect failed: %d\n", 185 error); 186 goto cleanup; 187 } 188 189 /* 190 * Connect RXBUF to NVS. 191 */ 192 193 xact = vmbus_xact_get(sc->hn_xact, sizeof(*conn)); 194 if (xact == NULL) { 195 if_printf(sc->hn_ifp, "no xact for nvs rxbuf conn\n"); 196 error = ENXIO; 197 goto cleanup; 198 } 199 200 conn = vmbus_xact_req_data(xact); 201 conn->nvs_type = HN_NVS_TYPE_RXBUF_CONN; 202 conn->nvs_gpadl = net_dev->rx_buf_gpadl_handle; 203 conn->nvs_sig = HN_NVS_RXBUF_SIG; 204 205 hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); 206 vmbus_xact_activate(xact); 207 208 error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, 209 conn, sizeof(*conn), &sndc); 210 if (error != 0) { 211 if_printf(sc->hn_ifp, "send nvs rxbuf conn failed: %d\n", 212 error); 213 vmbus_xact_deactivate(xact); 214 vmbus_xact_put(xact); 215 goto cleanup; 216 } 217 218 resp = vmbus_xact_wait(xact, &resp_len); 219 if (resp_len < sizeof(*resp)) { 220 if_printf(sc->hn_ifp, "invalid rxbuf conn resp length %zu\n", 221 resp_len); 222 vmbus_xact_put(xact); 223 error = EINVAL; 224 goto cleanup; 225 } 226 if (resp->nvs_type != HN_NVS_TYPE_RXBUF_CONNRESP) { 227 if_printf(sc->hn_ifp, "not rxbuf conn resp, type %u\n", 228 resp->nvs_type); 229 vmbus_xact_put(xact); 230 error = EINVAL; 231 goto cleanup; 232 } 233 234 status = resp->nvs_status; 235 vmbus_xact_put(xact); 236 237 if (status != HN_NVS_STATUS_OK) { 238 if_printf(sc->hn_ifp, "rxbuf conn failed: %x\n", status); 239 error = EIO; 240 goto cleanup; 241 } 242 net_dev->rx_section_count = 1; 243 244 return (0); 245 246cleanup: 247 hv_nv_destroy_rx_buffer(net_dev); 248 return (error); 249} 250 251/* 252 * Net VSC initialize send buffer with net VSP 253 */ 254static int 255hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) 256{ 257 struct hn_send_ctx sndc; 258 struct vmbus_xact *xact; 259 struct hn_nvs_chim_conn *chim; 260 const struct hn_nvs_chim_connresp *resp; 261 size_t resp_len; 262 uint32_t status, sectsz; 263 netvsc_dev *net_dev; 264 int error; 265 266 net_dev = hv_nv_get_outbound_net_device(sc); 267 if (!net_dev) { 268 return (ENODEV); 269 } 270 271 net_dev->send_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), 272 PAGE_SIZE, 0, net_dev->send_buf_size, &net_dev->txbuf_dma, 273 BUS_DMA_WAITOK | BUS_DMA_ZERO); 274 if (net_dev->send_buf == NULL) { 275 device_printf(sc->hn_dev, "allocate chimney txbuf failed\n"); 276 return (ENOMEM); 277 } 278 279 /* 280 * Connect chimney sending buffer GPADL to the primary channel. 281 * 282 * NOTE: 283 * Only primary channel has chimney sending buffer connected to it. 284 * Sub-channels just share this chimney sending buffer. 285 */ 286 error = vmbus_chan_gpadl_connect(sc->hn_prichan, 287 net_dev->txbuf_dma.hv_paddr, net_dev->send_buf_size, 288 &net_dev->send_buf_gpadl_handle); 289 if (error) { 290 if_printf(sc->hn_ifp, "chimney sending buffer gpadl " 291 "connect failed: %d\n", error); 292 goto cleanup; 293 } 294 295 /* 296 * Connect chimney sending buffer to NVS 297 */ 298 299 xact = vmbus_xact_get(sc->hn_xact, sizeof(*chim)); 300 if (xact == NULL) { 301 if_printf(sc->hn_ifp, "no xact for nvs chim conn\n"); 302 error = ENXIO; 303 goto cleanup; 304 } 305 306 chim = vmbus_xact_req_data(xact); 307 chim->nvs_type = HN_NVS_TYPE_CHIM_CONN; 308 chim->nvs_gpadl = net_dev->send_buf_gpadl_handle; 309 chim->nvs_sig = HN_NVS_CHIM_SIG; 310 311 hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); 312 vmbus_xact_activate(xact); 313 314 error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, 315 chim, sizeof(*chim), &sndc); 316 if (error) { 317 if_printf(sc->hn_ifp, "send nvs chim conn failed: %d\n", 318 error); 319 vmbus_xact_deactivate(xact); 320 vmbus_xact_put(xact); 321 goto cleanup; 322 } 323 324 resp = vmbus_xact_wait(xact, &resp_len); 325 if (resp_len < sizeof(*resp)) { 326 if_printf(sc->hn_ifp, "invalid chim conn resp length %zu\n", 327 resp_len); 328 vmbus_xact_put(xact); 329 error = EINVAL; 330 goto cleanup; 331 } 332 if (resp->nvs_type != HN_NVS_TYPE_CHIM_CONNRESP) { 333 if_printf(sc->hn_ifp, "not chim conn resp, type %u\n", 334 resp->nvs_type); 335 vmbus_xact_put(xact); 336 error = EINVAL; 337 goto cleanup; 338 } 339 340 status = resp->nvs_status; 341 sectsz = resp->nvs_sectsz; 342 vmbus_xact_put(xact); 343 344 if (status != HN_NVS_STATUS_OK) { 345 if_printf(sc->hn_ifp, "chim conn failed: %x\n", status); 346 error = EIO; 347 goto cleanup; 348 } 349 if (sectsz == 0) { 350 if_printf(sc->hn_ifp, "zero chimney sending buffer " 351 "section size\n"); 352 return 0; 353 } 354 355 net_dev->send_section_size = sectsz; 356 net_dev->send_section_count = 357 net_dev->send_buf_size / net_dev->send_section_size; 358 net_dev->bitsmap_words = howmany(net_dev->send_section_count, 359 BITS_PER_LONG); 360 net_dev->send_section_bitsmap = 361 malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC, 362 M_WAITOK | M_ZERO); 363 364 if (bootverbose) { 365 if_printf(sc->hn_ifp, "chimney sending buffer %u/%u\n", 366 net_dev->send_section_size, net_dev->send_section_count); 367 } 368 return 0; 369 370cleanup: 371 hv_nv_destroy_send_buffer(net_dev); 372 return (error); 373} 374 375/* 376 * Net VSC destroy receive buffer 377 */ 378static int 379hv_nv_destroy_rx_buffer(netvsc_dev *net_dev) 380{ 381 int ret = 0; 382 383 if (net_dev->rx_section_count) { 384 struct hn_nvs_rxbuf_disconn disconn; 385 386 /* 387 * Disconnect RXBUF from NVS. 388 */ 389 memset(&disconn, 0, sizeof(disconn)); 390 disconn.nvs_type = HN_NVS_TYPE_RXBUF_DISCONN; 391 disconn.nvs_sig = HN_NVS_RXBUF_SIG; 392 393 /* NOTE: No response. */ 394 ret = hn_nvs_send(net_dev->sc->hn_prichan, 395 VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn), 396 &hn_send_ctx_none); 397 if (ret != 0) { 398 if_printf(net_dev->sc->hn_ifp, 399 "send rxbuf disconn failed: %d\n", ret); 400 return (ret); 401 } 402 net_dev->rx_section_count = 0; 403 } 404 405 /* Tear down the gpadl on the vsp end */ 406 if (net_dev->rx_buf_gpadl_handle) { 407 ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan, 408 net_dev->rx_buf_gpadl_handle); 409 /* 410 * If we failed here, we might as well return and have a leak 411 * rather than continue and a bugchk 412 */ 413 if (ret != 0) { 414 return (ret); 415 } 416 net_dev->rx_buf_gpadl_handle = 0; 417 } 418 419 if (net_dev->rx_buf) { 420 /* Free up the receive buffer */ 421 hyperv_dmamem_free(&net_dev->rxbuf_dma, net_dev->rx_buf); 422 net_dev->rx_buf = NULL; 423 } 424 425 return (ret); 426} 427 428/* 429 * Net VSC destroy send buffer 430 */ 431static int 432hv_nv_destroy_send_buffer(netvsc_dev *net_dev) 433{ 434 int ret = 0; 435 436 if (net_dev->send_section_size) { 437 struct hn_nvs_chim_disconn disconn; 438 439 /* 440 * Disconnect chimney sending buffer from NVS. 441 */ 442 memset(&disconn, 0, sizeof(disconn)); 443 disconn.nvs_type = HN_NVS_TYPE_CHIM_DISCONN; 444 disconn.nvs_sig = HN_NVS_CHIM_SIG; 445 446 /* NOTE: No response. */ 447 ret = hn_nvs_send(net_dev->sc->hn_prichan, 448 VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn), 449 &hn_send_ctx_none); 450 if (ret != 0) { 451 if_printf(net_dev->sc->hn_ifp, 452 "send chim disconn failed: %d\n", ret); 453 return (ret); 454 } 455 } 456 457 /* Tear down the gpadl on the vsp end */ 458 if (net_dev->send_buf_gpadl_handle) { 459 ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan, 460 net_dev->send_buf_gpadl_handle); 461 462 /* 463 * If we failed here, we might as well return and have a leak 464 * rather than continue and a bugchk 465 */ 466 if (ret != 0) { 467 return (ret); 468 } 469 net_dev->send_buf_gpadl_handle = 0; 470 } 471 472 if (net_dev->send_buf) { 473 /* Free up the receive buffer */ 474 hyperv_dmamem_free(&net_dev->txbuf_dma, net_dev->send_buf); 475 net_dev->send_buf = NULL; 476 } 477 478 if (net_dev->send_section_bitsmap) { 479 free(net_dev->send_section_bitsmap, M_NETVSC); 480 } 481 482 return (ret); 483} 484 485static int 486hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev, 487 uint32_t nvs_ver) 488{ 489 struct hn_send_ctx sndc; 490 struct vmbus_xact *xact; 491 struct hn_nvs_init *init; 492 const struct hn_nvs_init_resp *resp; 493 size_t resp_len; 494 uint32_t status; 495 int error; 496 497 xact = vmbus_xact_get(sc->hn_xact, sizeof(*init)); 498 if (xact == NULL) { 499 if_printf(sc->hn_ifp, "no xact for nvs init\n"); 500 return (ENXIO); 501 } 502 503 init = vmbus_xact_req_data(xact); 504 init->nvs_type = HN_NVS_TYPE_INIT; 505 init->nvs_ver_min = nvs_ver; 506 init->nvs_ver_max = nvs_ver; 507 508 vmbus_xact_activate(xact); 509 hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); 510 511 error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, 512 init, sizeof(*init), &sndc); 513 if (error) { 514 if_printf(sc->hn_ifp, "send nvs init failed: %d\n", error); 515 vmbus_xact_deactivate(xact); 516 vmbus_xact_put(xact); 517 return (error); 518 } 519 520 resp = vmbus_xact_wait(xact, &resp_len); 521 if (resp_len < sizeof(*resp)) { 522 if_printf(sc->hn_ifp, "invalid init resp length %zu\n", 523 resp_len); 524 vmbus_xact_put(xact); 525 return (EINVAL); 526 } 527 if (resp->nvs_type != HN_NVS_TYPE_INIT_RESP) { 528 if_printf(sc->hn_ifp, "not init resp, type %u\n", 529 resp->nvs_type); 530 vmbus_xact_put(xact); 531 return (EINVAL); 532 } 533 534 status = resp->nvs_status; 535 vmbus_xact_put(xact); 536 537 if (status != HN_NVS_STATUS_OK) { 538 if_printf(sc->hn_ifp, "nvs init failed for ver 0x%x\n", 539 nvs_ver); 540 return (EINVAL); 541 } 542 return (0); 543} 544 545/* 546 * Send NDIS version 2 config packet containing MTU. 547 * 548 * Not valid for NDIS version 1. 549 */ 550static int 551hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu) 552{ 553 struct hn_nvs_ndis_conf conf; 554 int error; 555 556 memset(&conf, 0, sizeof(conf)); 557 conf.nvs_type = HN_NVS_TYPE_NDIS_CONF; 558 conf.nvs_mtu = mtu; 559 conf.nvs_caps = HN_NVS_NDIS_CONF_VLAN; 560 561 /* NOTE: No response. */ 562 error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE, 563 &conf, sizeof(conf), &hn_send_ctx_none); 564 if (error) 565 if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error); 566 return (error); 567} 568 569/* 570 * Net VSC connect to VSP 571 */ 572static int 573hv_nv_connect_to_vsp(struct hn_softc *sc) 574{ 575 netvsc_dev *net_dev; 576 uint32_t protocol_list[] = { NVSP_PROTOCOL_VERSION_1, 577 NVSP_PROTOCOL_VERSION_2, 578 NVSP_PROTOCOL_VERSION_4, 579 NVSP_PROTOCOL_VERSION_5 }; 580 int i; 581 int protocol_number = nitems(protocol_list); 582 int ret = 0; 583 device_t dev = sc->hn_dev; 584 struct ifnet *ifp = sc->arpcom.ac_ifp; 585 struct hn_nvs_ndis_init ndis; 586 587 net_dev = hv_nv_get_outbound_net_device(sc); 588 589 /* 590 * Negotiate the NVSP version. Try the latest NVSP first. 591 */ 592 for (i = protocol_number - 1; i >= 0; i--) { 593 if (hv_nv_negotiate_nvsp_protocol(sc, net_dev, 594 protocol_list[i]) == 0) { 595 net_dev->nvsp_version = protocol_list[i]; 596 if (bootverbose) 597 device_printf(dev, "Netvsc: got version 0x%x\n", 598 net_dev->nvsp_version); 599 break; 600 } 601 } 602 603 if (i < 0) { 604 if (bootverbose) 605 device_printf(dev, "failed to negotiate a valid " 606 "protocol.\n"); 607 return (EPROTO); 608 } 609 610 /* 611 * Set the MTU if supported by this NVSP protocol version 612 * This needs to be right after the NVSP init message per Haiyang 613 */ 614 if (net_dev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) 615 ret = hv_nv_send_ndis_config(sc, ifp->if_mtu); 616 617 /* 618 * Initialize NDIS. 619 */ 620 621 memset(&ndis, 0, sizeof(ndis)); 622 ndis.nvs_type = HN_NVS_TYPE_NDIS_INIT; 623 ndis.nvs_ndis_major = NDIS_VERSION_MAJOR_6; 624 if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_4) 625 ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_1; 626 else 627 ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_30; 628 629 /* NOTE: No response. */ 630 ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE, 631 &ndis, sizeof(ndis), &hn_send_ctx_none); 632 if (ret != 0) { 633 if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", ret); 634 goto cleanup; 635 } 636 637 /* Post the big receive buffer to NetVSP */ 638 if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_2) 639 net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; 640 else 641 net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; 642 net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE; 643 644 ret = hv_nv_init_rx_buffer_with_net_vsp(sc); 645 if (ret == 0) 646 ret = hv_nv_init_send_buffer_with_net_vsp(sc); 647 648cleanup: 649 return (ret); 650} 651 652/* 653 * Net VSC disconnect from VSP 654 */ 655static void 656hv_nv_disconnect_from_vsp(netvsc_dev *net_dev) 657{ 658 hv_nv_destroy_rx_buffer(net_dev); 659 hv_nv_destroy_send_buffer(net_dev); 660} 661 662void 663hv_nv_subchan_attach(struct vmbus_channel *chan, struct hn_rx_ring *rxr) 664{ 665 KASSERT(rxr->hn_rx_idx == vmbus_chan_subidx(chan), 666 ("chan%u subidx %u, rxr%d mismatch", 667 vmbus_chan_id(chan), vmbus_chan_subidx(chan), rxr->hn_rx_idx)); 668 vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE, 669 NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, 670 hv_nv_on_channel_callback, rxr); 671} 672 673/* 674 * Net VSC on device add 675 * 676 * Callback when the device belonging to this driver is added 677 */ 678netvsc_dev * 679hv_nv_on_device_add(struct hn_softc *sc, void *additional_info, 680 struct hn_rx_ring *rxr) 681{ 682 struct vmbus_channel *chan = sc->hn_prichan; 683 netvsc_dev *net_dev; 684 int ret = 0; 685 686 net_dev = hv_nv_alloc_net_device(sc); 687 if (net_dev == NULL) 688 return NULL; 689 690 /* Initialize the NetVSC channel extension */ 691 692 /* 693 * Open the channel 694 */ 695 KASSERT(rxr->hn_rx_idx == vmbus_chan_subidx(chan), 696 ("chan%u subidx %u, rxr%d mismatch", 697 vmbus_chan_id(chan), vmbus_chan_subidx(chan), rxr->hn_rx_idx)); 698 ret = vmbus_chan_open(chan, 699 NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE, 700 NULL, 0, hv_nv_on_channel_callback, rxr); 701 if (ret != 0) 702 goto cleanup; 703 704 /* 705 * Connect with the NetVsp 706 */ 707 ret = hv_nv_connect_to_vsp(sc); 708 if (ret != 0) 709 goto close; 710 711 return (net_dev); 712 713close: 714 /* Now, we can close the channel safely */ 715 vmbus_chan_close(chan); 716 717cleanup: 718 /* 719 * Free the packet buffers on the netvsc device packet queue. 720 * Release other resources. 721 */ 722 free(net_dev, M_NETVSC); 723 724 return (NULL); 725} 726 727/* 728 * Net VSC on device remove 729 */ 730int 731hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) 732{ 733 netvsc_dev *net_dev = sc->net_dev;; 734 735 /* Stop outbound traffic ie sends and receives completions */ 736 net_dev->destroy = TRUE; 737 738 hv_nv_disconnect_from_vsp(net_dev); 739 740 /* At this point, no one should be accessing net_dev except in here */ 741 742 /* Now, we can close the channel safely */ 743 744 vmbus_chan_close(sc->hn_prichan); 745 746 free(net_dev, M_NETVSC); 747 748 return (0); 749} 750 751void 752hn_nvs_sent_xact(struct hn_send_ctx *sndc, 753 struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused, 754 const void *data, int dlen) 755{ 756 757 vmbus_xact_wakeup(sndc->hn_cbarg, data, dlen); 758} 759 760static void 761hn_nvs_sent_none(struct hn_send_ctx *sndc __unused, 762 struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused, 763 const void *data __unused, int dlen __unused) 764{ 765 /* EMPTY */ 766} 767 768void 769hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx) 770{ 771 u_long mask; 772 uint32_t idx; 773 774 idx = chim_idx / BITS_PER_LONG; 775 KASSERT(idx < net_dev->bitsmap_words, 776 ("invalid chimney index 0x%x", chim_idx)); 777 778 mask = 1UL << (chim_idx % BITS_PER_LONG); 779 KASSERT(net_dev->send_section_bitsmap[idx] & mask, 780 ("index bitmap 0x%lx, chimney index %u, " 781 "bitmap idx %d, bitmask 0x%lx", 782 net_dev->send_section_bitsmap[idx], chim_idx, idx, mask)); 783 784 atomic_clear_long(&net_dev->send_section_bitsmap[idx], mask); 785} 786 787/* 788 * Net VSC on send completion 789 */ 790static void 791hv_nv_on_send_completion(netvsc_dev *net_dev, struct vmbus_channel *chan, 792 const struct vmbus_chanpkt_hdr *pkt) 793{ 794 struct hn_send_ctx *sndc; 795 796 sndc = (struct hn_send_ctx *)(uintptr_t)pkt->cph_xactid; 797 sndc->hn_cb(sndc, net_dev, chan, VMBUS_CHANPKT_CONST_DATA(pkt), 798 VMBUS_CHANPKT_DATALEN(pkt)); 799 /* 800 * NOTE: 801 * 'sndc' CAN NOT be accessed anymore, since it can be freed by 802 * its callback. 803 */ 804} 805 806/* 807 * Net VSC on send 808 * Sends a packet on the specified Hyper-V device. 809 * Returns 0 on success, non-zero on failure. 810 */ 811int 812hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, 813 struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt) 814{ 815 struct hn_nvs_rndis rndis; 816 int ret; 817 818 rndis.nvs_type = HN_NVS_TYPE_RNDIS; 819 rndis.nvs_rndis_mtype = rndis_mtype; 820 rndis.nvs_chim_idx = sndc->hn_chim_idx; 821 rndis.nvs_chim_sz = sndc->hn_chim_sz; 822 823 if (gpa_cnt) { 824 ret = hn_nvs_send_sglist(chan, gpa, gpa_cnt, 825 &rndis, sizeof(rndis), sndc); 826 } else { 827 ret = hn_nvs_send(chan, VMBUS_CHANPKT_FLAG_RC, 828 &rndis, sizeof(rndis), sndc); 829 } 830 831 return (ret); 832} 833 834/* 835 * Net VSC on receive 836 * 837 * In the FreeBSD Hyper-V virtual world, this function deals exclusively 838 * with virtual addresses. 839 */ 840static void 841hv_nv_on_receive(netvsc_dev *net_dev, struct hn_rx_ring *rxr, 842 struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) 843{ 844 const struct vmbus_chanpkt_rxbuf *pkt; 845 const struct hn_nvs_hdr *nvs_hdr; 846 netvsc_packet vsc_pkt; 847 netvsc_packet *net_vsc_pkt = &vsc_pkt; 848 int count = 0; 849 int i = 0; 850 int status = HN_NVS_STATUS_OK; 851 852 /* Make sure that this is a RNDIS message. */ 853 nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr); 854 if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) { 855 if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n", 856 nvs_hdr->nvs_type); 857 return; 858 } 859 860 pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr; 861 862 if (pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID) { 863 if_printf(rxr->hn_ifp, "rxbuf_id %d is invalid!\n", 864 pkt->cp_rxbuf_id); 865 return; 866 } 867 868 count = pkt->cp_rxbuf_cnt; 869 870 /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */ 871 for (i = 0; i < count; i++) { 872 net_vsc_pkt->status = HN_NVS_STATUS_OK; 873 net_vsc_pkt->data = ((uint8_t *)net_dev->rx_buf + 874 pkt->cp_rxbuf[i].rb_ofs); 875 net_vsc_pkt->tot_data_buf_len = pkt->cp_rxbuf[i].rb_len; 876 877 hv_rf_on_receive(net_dev, rxr, net_vsc_pkt); 878 879 /* XXX pretty broken; whack it */ 880 if (net_vsc_pkt->status != HN_NVS_STATUS_OK) 881 status = HN_NVS_STATUS_FAILED; 882 } 883 884 /* 885 * Moved completion call back here so that all received 886 * messages (not just data messages) will trigger a response 887 * message back to the host. 888 */ 889 hv_nv_on_receive_completion(chan, pkt->cp_hdr.cph_xactid, status); 890} 891 892/* 893 * Net VSC on receive completion 894 * 895 * Send a receive completion packet to RNDIS device (ie NetVsp) 896 */ 897static void 898hv_nv_on_receive_completion(struct vmbus_channel *chan, uint64_t tid, 899 uint32_t status) 900{ 901 struct hn_nvs_rndis_ack ack; 902 int retries = 0; 903 int ret = 0; 904 905 ack.nvs_type = HN_NVS_TYPE_RNDIS_ACK; 906 ack.nvs_status = status; 907 908retry_send_cmplt: 909 /* Send the completion */ 910 ret = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_COMP, 911 VMBUS_CHANPKT_FLAG_NONE, &ack, sizeof(ack), tid); 912 if (ret == 0) { 913 /* success */ 914 /* no-op */ 915 } else if (ret == EAGAIN) { 916 /* no more room... wait a bit and attempt to retry 3 times */ 917 retries++; 918 919 if (retries < 4) { 920 DELAY(100); 921 goto retry_send_cmplt; 922 } 923 } 924} 925 926static void 927hn_proc_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt) 928{ 929 const struct hn_nvs_hdr *hdr; 930 931 hdr = VMBUS_CHANPKT_CONST_DATA(pkt); 932 if (hdr->nvs_type == HN_NVS_TYPE_TXTBL_NOTE) { 933 /* Useless; ignore */ 934 return; 935 } 936 if_printf(sc->hn_ifp, "got notify, nvs type %u\n", hdr->nvs_type); 937} 938 939/* 940 * Net VSC on channel callback 941 */ 942static void 943hv_nv_on_channel_callback(struct vmbus_channel *chan, void *xrxr) 944{ 945 struct hn_rx_ring *rxr = xrxr; 946 struct hn_softc *sc = rxr->hn_ifp->if_softc; 947 netvsc_dev *net_dev; 948 void *buffer; 949 int bufferlen = NETVSC_PACKET_SIZE; 950 951 net_dev = hv_nv_get_inbound_net_device(sc); 952 if (net_dev == NULL) 953 return; 954 955 buffer = rxr->hn_rdbuf; 956 do { 957 struct vmbus_chanpkt_hdr *pkt = buffer; 958 uint32_t bytes_rxed; 959 int ret; 960 961 bytes_rxed = bufferlen; 962 ret = vmbus_chan_recv_pkt(chan, pkt, &bytes_rxed); 963 if (ret == 0) { 964 if (bytes_rxed > 0) { 965 switch (pkt->cph_type) { 966 case VMBUS_CHANPKT_TYPE_COMP: 967 hv_nv_on_send_completion(net_dev, chan, 968 pkt); 969 break; 970 case VMBUS_CHANPKT_TYPE_RXBUF: 971 hv_nv_on_receive(net_dev, rxr, chan, pkt); 972 break; 973 case VMBUS_CHANPKT_TYPE_INBAND: 974 hn_proc_notify(sc, pkt); 975 break; 976 default: 977 if_printf(rxr->hn_ifp, 978 "unknown chan pkt %u\n", 979 pkt->cph_type); 980 break; 981 } 982 } 983 } else if (ret == ENOBUFS) { 984 /* Handle large packet */ 985 if (bufferlen > NETVSC_PACKET_SIZE) { 986 free(buffer, M_NETVSC); 987 buffer = NULL; 988 } 989 990 /* alloc new buffer */ 991 buffer = malloc(bytes_rxed, M_NETVSC, M_NOWAIT); 992 if (buffer == NULL) { 993 if_printf(rxr->hn_ifp, 994 "hv_cb malloc buffer failed, len=%u\n", 995 bytes_rxed); 996 bufferlen = 0; 997 break; 998 } 999 bufferlen = bytes_rxed; 1000 } else { 1001 /* No more packets */ 1002 break; 1003 } 1004 } while (1); 1005 1006 if (bufferlen > NETVSC_PACKET_SIZE) 1007 free(buffer, M_NETVSC); 1008 1009 hv_rf_channel_rollup(rxr, rxr->hn_txr); 1010} 1011