hn_nvs.c revision 307081
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 307081 2016-10-12 02:15:06Z 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 "hv_net_vsc.h" 48#include "hv_rndis.h" 49#include "hv_rndis_filter.h" 50 51/* priv1 and priv2 are consumed by the main driver */ 52#define hv_chan_rdbuf hv_chan_priv3 53 54MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver"); 55 56/* 57 * Forward declarations 58 */ 59static void hv_nv_on_channel_callback(void *xchan); 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 hv_vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt); 67static void hv_nv_on_receive_completion(struct hv_vmbus_channel *chan, 68 uint64_t tid, uint32_t status); 69static void hv_nv_on_receive(netvsc_dev *net_dev, 70 struct hn_softc *sc, struct hv_vmbus_channel *chan, 71 const struct vmbus_chanpkt_hdr *pkt); 72 73/* 74 * 75 */ 76static inline netvsc_dev * 77hv_nv_alloc_net_device(struct hn_softc *sc) 78{ 79 netvsc_dev *net_dev; 80 81 net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_WAITOK | M_ZERO); 82 83 net_dev->sc = sc; 84 net_dev->destroy = FALSE; 85 sc->net_dev = net_dev; 86 87 return (net_dev); 88} 89 90/* 91 * XXX unnecessary; nuke it. 92 */ 93static inline netvsc_dev * 94hv_nv_get_outbound_net_device(struct hn_softc *sc) 95{ 96 return sc->net_dev; 97} 98 99/* 100 * XXX unnecessary; nuke it. 101 */ 102static inline netvsc_dev * 103hv_nv_get_inbound_net_device(struct hn_softc *sc) 104{ 105 return sc->net_dev; 106} 107 108int 109hv_nv_get_next_send_section(netvsc_dev *net_dev) 110{ 111 unsigned long bitsmap_words = net_dev->bitsmap_words; 112 unsigned long *bitsmap = net_dev->send_section_bitsmap; 113 unsigned long idx; 114 int ret = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; 115 int i; 116 117 for (i = 0; i < bitsmap_words; i++) { 118 idx = ffsl(~bitsmap[i]); 119 if (0 == idx) 120 continue; 121 122 idx--; 123 KASSERT(i * BITS_PER_LONG + idx < net_dev->send_section_count, 124 ("invalid i %d and idx %lu", i, idx)); 125 126 if (atomic_testandset_long(&bitsmap[i], idx)) 127 continue; 128 129 ret = i * BITS_PER_LONG + idx; 130 break; 131 } 132 133 return (ret); 134} 135 136/* 137 * Net VSC initialize receive buffer with net VSP 138 * 139 * Net VSP: Network virtual services client, also known as the 140 * Hyper-V extensible switch and the synthetic data path. 141 */ 142static int 143hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) 144{ 145 netvsc_dev *net_dev; 146 nvsp_msg *init_pkt; 147 int ret = 0; 148 149 net_dev = hv_nv_get_outbound_net_device(sc); 150 if (!net_dev) { 151 return (ENODEV); 152 } 153 154 net_dev->rx_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), 155 PAGE_SIZE, 0, net_dev->rx_buf_size, &net_dev->rxbuf_dma, 156 BUS_DMA_WAITOK | BUS_DMA_ZERO); 157 if (net_dev->rx_buf == NULL) { 158 device_printf(sc->hn_dev, "allocate rxbuf failed\n"); 159 return ENOMEM; 160 } 161 162 /* 163 * Connect the RXBUF GPADL to the primary channel. 164 * 165 * NOTE: 166 * Only primary channel has RXBUF connected to it. Sub-channels 167 * just share this RXBUF. 168 */ 169 ret = vmbus_chan_gpadl_connect(sc->hn_prichan, 170 net_dev->rxbuf_dma.hv_paddr, net_dev->rx_buf_size, 171 &net_dev->rx_buf_gpadl_handle); 172 if (ret != 0) { 173 device_printf(sc->hn_dev, "rxbuf gpadl connect failed: %d\n", 174 ret); 175 goto cleanup; 176 } 177 178 /* sema_wait(&ext->channel_init_sema); KYS CHECK */ 179 180 /* Notify the NetVsp of the gpadl handle */ 181 init_pkt = &net_dev->channel_init_packet; 182 183 memset(init_pkt, 0, sizeof(nvsp_msg)); 184 185 init_pkt->hdr.msg_type = nvsp_msg_1_type_send_rx_buf; 186 init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle = 187 net_dev->rx_buf_gpadl_handle; 188 init_pkt->msgs.vers_1_msgs.send_rx_buf.id = 189 NETVSC_RECEIVE_BUFFER_ID; 190 191 /* Send the gpadl notification request */ 192 193 ret = vmbus_chan_send(sc->hn_prichan, 194 VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, 195 init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt); 196 if (ret != 0) { 197 goto cleanup; 198 } 199 200 sema_wait(&net_dev->channel_init_sema); 201 202 /* Check the response */ 203 if (init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.status 204 != nvsp_status_success) { 205 ret = EINVAL; 206 goto cleanup; 207 } 208 209 net_dev->rx_section_count = 210 init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections; 211 212 net_dev->rx_sections = malloc(net_dev->rx_section_count * 213 sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_WAITOK); 214 memcpy(net_dev->rx_sections, 215 init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections, 216 net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section)); 217 218 219 /* 220 * For first release, there should only be 1 section that represents 221 * the entire receive buffer 222 */ 223 if (net_dev->rx_section_count != 1 224 || net_dev->rx_sections->offset != 0) { 225 ret = EINVAL; 226 goto cleanup; 227 } 228 229 goto exit; 230 231cleanup: 232 hv_nv_destroy_rx_buffer(net_dev); 233 234exit: 235 return (ret); 236} 237 238/* 239 * Net VSC initialize send buffer with net VSP 240 */ 241static int 242hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) 243{ 244 netvsc_dev *net_dev; 245 nvsp_msg *init_pkt; 246 int ret = 0; 247 248 net_dev = hv_nv_get_outbound_net_device(sc); 249 if (!net_dev) { 250 return (ENODEV); 251 } 252 253 net_dev->send_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), 254 PAGE_SIZE, 0, net_dev->send_buf_size, &net_dev->txbuf_dma, 255 BUS_DMA_WAITOK | BUS_DMA_ZERO); 256 if (net_dev->send_buf == NULL) { 257 device_printf(sc->hn_dev, "allocate chimney txbuf failed\n"); 258 return ENOMEM; 259 } 260 261 /* 262 * Connect chimney sending buffer GPADL to the primary channel. 263 * 264 * NOTE: 265 * Only primary channel has chimney sending buffer connected to it. 266 * Sub-channels just share this chimney sending buffer. 267 */ 268 ret = vmbus_chan_gpadl_connect(sc->hn_prichan, 269 net_dev->txbuf_dma.hv_paddr, net_dev->send_buf_size, 270 &net_dev->send_buf_gpadl_handle); 271 if (ret != 0) { 272 device_printf(sc->hn_dev, "chimney sending buffer gpadl " 273 "connect failed: %d\n", ret); 274 goto cleanup; 275 } 276 277 /* Notify the NetVsp of the gpadl handle */ 278 279 init_pkt = &net_dev->channel_init_packet; 280 281 memset(init_pkt, 0, sizeof(nvsp_msg)); 282 283 init_pkt->hdr.msg_type = nvsp_msg_1_type_send_send_buf; 284 init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle = 285 net_dev->send_buf_gpadl_handle; 286 init_pkt->msgs.vers_1_msgs.send_rx_buf.id = 287 NETVSC_SEND_BUFFER_ID; 288 289 /* Send the gpadl notification request */ 290 291 ret = vmbus_chan_send(sc->hn_prichan, 292 VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, 293 init_pkt, sizeof(nvsp_msg), (uint64_t)init_pkt); 294 if (ret != 0) { 295 goto cleanup; 296 } 297 298 sema_wait(&net_dev->channel_init_sema); 299 300 /* Check the response */ 301 if (init_pkt->msgs.vers_1_msgs.send_send_buf_complete.status 302 != nvsp_status_success) { 303 ret = EINVAL; 304 goto cleanup; 305 } 306 307 net_dev->send_section_size = 308 init_pkt->msgs.vers_1_msgs.send_send_buf_complete.section_size; 309 net_dev->send_section_count = 310 net_dev->send_buf_size / net_dev->send_section_size; 311 net_dev->bitsmap_words = howmany(net_dev->send_section_count, 312 BITS_PER_LONG); 313 net_dev->send_section_bitsmap = 314 malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC, 315 M_WAITOK | M_ZERO); 316 317 goto exit; 318 319cleanup: 320 hv_nv_destroy_send_buffer(net_dev); 321 322exit: 323 return (ret); 324} 325 326/* 327 * Net VSC destroy receive buffer 328 */ 329static int 330hv_nv_destroy_rx_buffer(netvsc_dev *net_dev) 331{ 332 nvsp_msg *revoke_pkt; 333 int ret = 0; 334 335 /* 336 * If we got a section count, it means we received a 337 * send_rx_buf_complete msg 338 * (ie sent nvsp_msg_1_type_send_rx_buf msg) therefore, 339 * we need to send a revoke msg here 340 */ 341 if (net_dev->rx_section_count) { 342 /* Send the revoke receive buffer */ 343 revoke_pkt = &net_dev->revoke_packet; 344 memset(revoke_pkt, 0, sizeof(nvsp_msg)); 345 346 revoke_pkt->hdr.msg_type = nvsp_msg_1_type_revoke_rx_buf; 347 revoke_pkt->msgs.vers_1_msgs.revoke_rx_buf.id = 348 NETVSC_RECEIVE_BUFFER_ID; 349 350 ret = vmbus_chan_send(net_dev->sc->hn_prichan, 351 VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg), 352 (uint64_t)(uintptr_t)revoke_pkt); 353 354 /* 355 * If we failed here, we might as well return and have a leak 356 * rather than continue and a bugchk 357 */ 358 if (ret != 0) { 359 return (ret); 360 } 361 } 362 363 /* Tear down the gpadl on the vsp end */ 364 if (net_dev->rx_buf_gpadl_handle) { 365 ret = hv_vmbus_channel_teardown_gpdal(net_dev->sc->hn_prichan, 366 net_dev->rx_buf_gpadl_handle); 367 /* 368 * If we failed here, we might as well return and have a leak 369 * rather than continue and a bugchk 370 */ 371 if (ret != 0) { 372 return (ret); 373 } 374 net_dev->rx_buf_gpadl_handle = 0; 375 } 376 377 if (net_dev->rx_buf) { 378 /* Free up the receive buffer */ 379 hyperv_dmamem_free(&net_dev->rxbuf_dma, net_dev->rx_buf); 380 net_dev->rx_buf = NULL; 381 } 382 383 if (net_dev->rx_sections) { 384 free(net_dev->rx_sections, M_NETVSC); 385 net_dev->rx_sections = NULL; 386 net_dev->rx_section_count = 0; 387 } 388 389 return (ret); 390} 391 392/* 393 * Net VSC destroy send buffer 394 */ 395static int 396hv_nv_destroy_send_buffer(netvsc_dev *net_dev) 397{ 398 nvsp_msg *revoke_pkt; 399 int ret = 0; 400 401 /* 402 * If we got a section count, it means we received a 403 * send_rx_buf_complete msg 404 * (ie sent nvsp_msg_1_type_send_rx_buf msg) therefore, 405 * we need to send a revoke msg here 406 */ 407 if (net_dev->send_section_size) { 408 /* Send the revoke send buffer */ 409 revoke_pkt = &net_dev->revoke_packet; 410 memset(revoke_pkt, 0, sizeof(nvsp_msg)); 411 412 revoke_pkt->hdr.msg_type = 413 nvsp_msg_1_type_revoke_send_buf; 414 revoke_pkt->msgs.vers_1_msgs.revoke_send_buf.id = 415 NETVSC_SEND_BUFFER_ID; 416 417 ret = vmbus_chan_send(net_dev->sc->hn_prichan, 418 VMBUS_CHANPKT_TYPE_INBAND, 0, 419 revoke_pkt, sizeof(nvsp_msg), 420 (uint64_t)(uintptr_t)revoke_pkt); 421 /* 422 * If we failed here, we might as well return and have a leak 423 * rather than continue and a bugchk 424 */ 425 if (ret != 0) { 426 return (ret); 427 } 428 } 429 430 /* Tear down the gpadl on the vsp end */ 431 if (net_dev->send_buf_gpadl_handle) { 432 ret = hv_vmbus_channel_teardown_gpdal(net_dev->sc->hn_prichan, 433 net_dev->send_buf_gpadl_handle); 434 435 /* 436 * If we failed here, we might as well return and have a leak 437 * rather than continue and a bugchk 438 */ 439 if (ret != 0) { 440 return (ret); 441 } 442 net_dev->send_buf_gpadl_handle = 0; 443 } 444 445 if (net_dev->send_buf) { 446 /* Free up the receive buffer */ 447 hyperv_dmamem_free(&net_dev->txbuf_dma, net_dev->send_buf); 448 net_dev->send_buf = NULL; 449 } 450 451 if (net_dev->send_section_bitsmap) { 452 free(net_dev->send_section_bitsmap, M_NETVSC); 453 } 454 455 return (ret); 456} 457 458 459/* 460 * Attempt to negotiate the caller-specified NVSP version 461 * 462 * For NVSP v2, Server 2008 R2 does not set 463 * init_pkt->msgs.init_msgs.init_compl.negotiated_prot_vers 464 * to the negotiated version, so we cannot rely on that. 465 */ 466static int 467hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev, 468 uint32_t nvsp_ver) 469{ 470 nvsp_msg *init_pkt; 471 int ret; 472 473 init_pkt = &net_dev->channel_init_packet; 474 memset(init_pkt, 0, sizeof(nvsp_msg)); 475 init_pkt->hdr.msg_type = nvsp_msg_type_init; 476 477 /* 478 * Specify parameter as the only acceptable protocol version 479 */ 480 init_pkt->msgs.init_msgs.init.p1.protocol_version = nvsp_ver; 481 init_pkt->msgs.init_msgs.init.protocol_version_2 = nvsp_ver; 482 483 /* Send the init request */ 484 ret = vmbus_chan_send(sc->hn_prichan, 485 VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, 486 init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt); 487 if (ret != 0) 488 return (-1); 489 490 sema_wait(&net_dev->channel_init_sema); 491 492 if (init_pkt->msgs.init_msgs.init_compl.status != nvsp_status_success) 493 return (EINVAL); 494 495 return (0); 496} 497 498/* 499 * Send NDIS version 2 config packet containing MTU. 500 * 501 * Not valid for NDIS version 1. 502 */ 503static int 504hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu) 505{ 506 netvsc_dev *net_dev; 507 nvsp_msg *init_pkt; 508 int ret; 509 510 net_dev = hv_nv_get_outbound_net_device(sc); 511 if (!net_dev) 512 return (-ENODEV); 513 514 /* 515 * Set up configuration packet, write MTU 516 * Indicate we are capable of handling VLAN tags 517 */ 518 init_pkt = &net_dev->channel_init_packet; 519 memset(init_pkt, 0, sizeof(nvsp_msg)); 520 init_pkt->hdr.msg_type = nvsp_msg_2_type_send_ndis_config; 521 init_pkt->msgs.vers_2_msgs.send_ndis_config.mtu = mtu; 522 init_pkt-> 523 msgs.vers_2_msgs.send_ndis_config.capabilities.u1.u2.ieee8021q 524 = 1; 525 526 /* Send the configuration packet */ 527 ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, 528 init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt); 529 if (ret != 0) 530 return (-EINVAL); 531 532 return (0); 533} 534 535/* 536 * Net VSC connect to VSP 537 */ 538static int 539hv_nv_connect_to_vsp(struct hn_softc *sc) 540{ 541 netvsc_dev *net_dev; 542 nvsp_msg *init_pkt; 543 uint32_t ndis_version; 544 uint32_t protocol_list[] = { NVSP_PROTOCOL_VERSION_1, 545 NVSP_PROTOCOL_VERSION_2, 546 NVSP_PROTOCOL_VERSION_4, 547 NVSP_PROTOCOL_VERSION_5 }; 548 int i; 549 int protocol_number = nitems(protocol_list); 550 int ret = 0; 551 device_t dev = sc->hn_dev; 552 struct ifnet *ifp = sc->arpcom.ac_ifp; 553 554 net_dev = hv_nv_get_outbound_net_device(sc); 555 556 /* 557 * Negotiate the NVSP version. Try the latest NVSP first. 558 */ 559 for (i = protocol_number - 1; i >= 0; i--) { 560 if (hv_nv_negotiate_nvsp_protocol(sc, net_dev, 561 protocol_list[i]) == 0) { 562 net_dev->nvsp_version = protocol_list[i]; 563 if (bootverbose) 564 device_printf(dev, "Netvsc: got version 0x%x\n", 565 net_dev->nvsp_version); 566 break; 567 } 568 } 569 570 if (i < 0) { 571 if (bootverbose) 572 device_printf(dev, "failed to negotiate a valid " 573 "protocol.\n"); 574 return (EPROTO); 575 } 576 577 /* 578 * Set the MTU if supported by this NVSP protocol version 579 * This needs to be right after the NVSP init message per Haiyang 580 */ 581 if (net_dev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) 582 ret = hv_nv_send_ndis_config(sc, ifp->if_mtu); 583 584 /* 585 * Send the NDIS version 586 */ 587 init_pkt = &net_dev->channel_init_packet; 588 589 memset(init_pkt, 0, sizeof(nvsp_msg)); 590 591 if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_4) { 592 ndis_version = NDIS_VERSION_6_1; 593 } else { 594 ndis_version = NDIS_VERSION_6_30; 595 } 596 597 init_pkt->hdr.msg_type = nvsp_msg_1_type_send_ndis_vers; 598 init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_major_vers = 599 (ndis_version & 0xFFFF0000) >> 16; 600 init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_minor_vers = 601 ndis_version & 0xFFFF; 602 603 /* Send the init request */ 604 605 ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, 606 init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt); 607 if (ret != 0) { 608 goto cleanup; 609 } 610 /* 611 * TODO: BUGBUG - We have to wait for the above msg since the netvsp 612 * uses KMCL which acknowledges packet (completion packet) 613 * since our Vmbus always set the VMBUS_CHANPKT_FLAG_RC flag 614 */ 615 /* sema_wait(&NetVscChannel->channel_init_sema); */ 616 617 /* Post the big receive buffer to NetVSP */ 618 if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_2) 619 net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; 620 else 621 net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; 622 net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE; 623 624 ret = hv_nv_init_rx_buffer_with_net_vsp(sc); 625 if (ret == 0) 626 ret = hv_nv_init_send_buffer_with_net_vsp(sc); 627 628cleanup: 629 return (ret); 630} 631 632/* 633 * Net VSC disconnect from VSP 634 */ 635static void 636hv_nv_disconnect_from_vsp(netvsc_dev *net_dev) 637{ 638 hv_nv_destroy_rx_buffer(net_dev); 639 hv_nv_destroy_send_buffer(net_dev); 640} 641 642void 643hv_nv_subchan_attach(struct hv_vmbus_channel *chan) 644{ 645 646 chan->hv_chan_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK); 647 hv_vmbus_channel_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE, 648 NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, 649 hv_nv_on_channel_callback, chan); 650} 651 652/* 653 * Net VSC on device add 654 * 655 * Callback when the device belonging to this driver is added 656 */ 657netvsc_dev * 658hv_nv_on_device_add(struct hn_softc *sc, void *additional_info) 659{ 660 struct hv_vmbus_channel *chan = sc->hn_prichan; 661 netvsc_dev *net_dev; 662 int ret = 0; 663 664 net_dev = hv_nv_alloc_net_device(sc); 665 if (net_dev == NULL) 666 return NULL; 667 668 /* Initialize the NetVSC channel extension */ 669 670 sema_init(&net_dev->channel_init_sema, 0, "netdev_sema"); 671 672 chan->hv_chan_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK); 673 674 /* 675 * Open the channel 676 */ 677 ret = hv_vmbus_channel_open(chan, 678 NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE, 679 NULL, 0, hv_nv_on_channel_callback, chan); 680 if (ret != 0) { 681 free(chan->hv_chan_rdbuf, M_NETVSC); 682 goto cleanup; 683 } 684 685 /* 686 * Connect with the NetVsp 687 */ 688 ret = hv_nv_connect_to_vsp(sc); 689 if (ret != 0) 690 goto close; 691 692 return (net_dev); 693 694close: 695 /* Now, we can close the channel safely */ 696 free(chan->hv_chan_rdbuf, M_NETVSC); 697 hv_vmbus_channel_close(chan); 698 699cleanup: 700 /* 701 * Free the packet buffers on the netvsc device packet queue. 702 * Release other resources. 703 */ 704 sema_destroy(&net_dev->channel_init_sema); 705 free(net_dev, M_NETVSC); 706 707 return (NULL); 708} 709 710/* 711 * Net VSC on device remove 712 */ 713int 714hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) 715{ 716 netvsc_dev *net_dev = sc->net_dev;; 717 718 /* Stop outbound traffic ie sends and receives completions */ 719 net_dev->destroy = TRUE; 720 721 hv_nv_disconnect_from_vsp(net_dev); 722 723 /* At this point, no one should be accessing net_dev except in here */ 724 725 /* Now, we can close the channel safely */ 726 727 free(sc->hn_prichan->hv_chan_rdbuf, M_NETVSC); 728 hv_vmbus_channel_close(sc->hn_prichan); 729 730 sema_destroy(&net_dev->channel_init_sema); 731 free(net_dev, M_NETVSC); 732 733 return (0); 734} 735 736/* 737 * Net VSC on send completion 738 */ 739static void 740hv_nv_on_send_completion(netvsc_dev *net_dev, struct hv_vmbus_channel *chan, 741 const struct vmbus_chanpkt_hdr *pkt) 742{ 743 const nvsp_msg *nvsp_msg_pkt; 744 netvsc_packet *net_vsc_pkt; 745 746 nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkt); 747 748 if (nvsp_msg_pkt->hdr.msg_type == nvsp_msg_type_init_complete 749 || nvsp_msg_pkt->hdr.msg_type 750 == nvsp_msg_1_type_send_rx_buf_complete 751 || nvsp_msg_pkt->hdr.msg_type 752 == nvsp_msg_1_type_send_send_buf_complete 753 || nvsp_msg_pkt->hdr.msg_type 754 == nvsp_msg5_type_subchannel) { 755 /* Copy the response back */ 756 memcpy(&net_dev->channel_init_packet, nvsp_msg_pkt, 757 sizeof(nvsp_msg)); 758 sema_post(&net_dev->channel_init_sema); 759 } else if (nvsp_msg_pkt->hdr.msg_type == 760 nvsp_msg_1_type_send_rndis_pkt_complete) { 761 /* Get the send context */ 762 net_vsc_pkt = 763 (netvsc_packet *)(unsigned long)pkt->cph_xactid; 764 if (NULL != net_vsc_pkt) { 765 if (net_vsc_pkt->send_buf_section_idx != 766 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { 767 u_long mask; 768 int idx; 769 770 idx = net_vsc_pkt->send_buf_section_idx / 771 BITS_PER_LONG; 772 KASSERT(idx < net_dev->bitsmap_words, 773 ("invalid section index %u", 774 net_vsc_pkt->send_buf_section_idx)); 775 mask = 1UL << 776 (net_vsc_pkt->send_buf_section_idx % 777 BITS_PER_LONG); 778 779 KASSERT(net_dev->send_section_bitsmap[idx] & 780 mask, 781 ("index bitmap 0x%lx, section index %u, " 782 "bitmap idx %d, bitmask 0x%lx", 783 net_dev->send_section_bitsmap[idx], 784 net_vsc_pkt->send_buf_section_idx, 785 idx, mask)); 786 atomic_clear_long( 787 &net_dev->send_section_bitsmap[idx], mask); 788 } 789 790 /* Notify the layer above us */ 791 net_vsc_pkt->compl.send.on_send_completion(chan, 792 net_vsc_pkt->compl.send.send_completion_context); 793 794 } 795 } 796} 797 798/* 799 * Net VSC on send 800 * Sends a packet on the specified Hyper-V device. 801 * Returns 0 on success, non-zero on failure. 802 */ 803int 804hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt) 805{ 806 nvsp_msg send_msg; 807 int ret; 808 809 send_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt; 810 if (pkt->is_data_pkt) { 811 /* 0 is RMC_DATA */ 812 send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 0; 813 } else { 814 /* 1 is RMC_CONTROL */ 815 send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 1; 816 } 817 818 send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_idx = 819 pkt->send_buf_section_idx; 820 send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size = 821 pkt->send_buf_section_size; 822 823 if (pkt->gpa_cnt) { 824 ret = vmbus_chan_send_sglist(chan, pkt->gpa, pkt->gpa_cnt, 825 &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt); 826 } else { 827 ret = vmbus_chan_send(chan, 828 VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, 829 &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt); 830 } 831 832 return (ret); 833} 834 835/* 836 * Net VSC on receive 837 * 838 * In the FreeBSD Hyper-V virtual world, this function deals exclusively 839 * with virtual addresses. 840 */ 841static void 842hv_nv_on_receive(netvsc_dev *net_dev, struct hn_softc *sc, 843 struct hv_vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) 844{ 845 const struct vmbus_chanpkt_rxbuf *pkt; 846 const nvsp_msg *nvsp_msg_pkt; 847 netvsc_packet vsc_pkt; 848 netvsc_packet *net_vsc_pkt = &vsc_pkt; 849 device_t dev = sc->hn_dev; 850 int count = 0; 851 int i = 0; 852 int status = nvsp_status_success; 853 854 nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkthdr); 855 856 /* Make sure this is a valid nvsp packet */ 857 if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) { 858 device_printf(dev, "packet hdr type %u is invalid!\n", 859 nvsp_msg_pkt->hdr.msg_type); 860 return; 861 } 862 863 pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr; 864 865 if (pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID) { 866 device_printf(dev, "rxbuf_id %d is invalid!\n", 867 pkt->cp_rxbuf_id); 868 return; 869 } 870 871 count = pkt->cp_rxbuf_cnt; 872 873 /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */ 874 for (i = 0; i < count; i++) { 875 net_vsc_pkt->status = nvsp_status_success; 876 net_vsc_pkt->data = ((uint8_t *)net_dev->rx_buf + 877 pkt->cp_rxbuf[i].rb_ofs); 878 net_vsc_pkt->tot_data_buf_len = pkt->cp_rxbuf[i].rb_len; 879 880 hv_rf_on_receive(net_dev, chan, net_vsc_pkt); 881 if (net_vsc_pkt->status != nvsp_status_success) { 882 status = nvsp_status_failure; 883 } 884 } 885 886 /* 887 * Moved completion call back here so that all received 888 * messages (not just data messages) will trigger a response 889 * message back to the host. 890 */ 891 hv_nv_on_receive_completion(chan, pkt->cp_hdr.cph_xactid, status); 892} 893 894/* 895 * Net VSC on receive completion 896 * 897 * Send a receive completion packet to RNDIS device (ie NetVsp) 898 */ 899static void 900hv_nv_on_receive_completion(struct hv_vmbus_channel *chan, uint64_t tid, 901 uint32_t status) 902{ 903 nvsp_msg rx_comp_msg; 904 int retries = 0; 905 int ret = 0; 906 907 rx_comp_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt_complete; 908 909 /* Pass in the status */ 910 rx_comp_msg.msgs.vers_1_msgs.send_rndis_pkt_complete.status = 911 status; 912 913retry_send_cmplt: 914 /* Send the completion */ 915 ret = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_COMP, 0, 916 &rx_comp_msg, sizeof(nvsp_msg), tid); 917 if (ret == 0) { 918 /* success */ 919 /* no-op */ 920 } else if (ret == EAGAIN) { 921 /* no more room... wait a bit and attempt to retry 3 times */ 922 retries++; 923 924 if (retries < 4) { 925 DELAY(100); 926 goto retry_send_cmplt; 927 } 928 } 929} 930 931/* 932 * Net VSC receiving vRSS send table from VSP 933 */ 934static void 935hv_nv_send_table(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt) 936{ 937 netvsc_dev *net_dev; 938 const nvsp_msg *nvsp_msg_pkt; 939 int i; 940 uint32_t count; 941 const uint32_t *table; 942 943 net_dev = hv_nv_get_inbound_net_device(sc); 944 if (!net_dev) 945 return; 946 947 nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkt); 948 949 if (nvsp_msg_pkt->hdr.msg_type != 950 nvsp_msg5_type_send_indirection_table) { 951 printf("Netvsc: !Warning! receive msg type not " 952 "send_indirection_table. type = %d\n", 953 nvsp_msg_pkt->hdr.msg_type); 954 return; 955 } 956 957 count = nvsp_msg_pkt->msgs.vers_5_msgs.send_table.count; 958 if (count != VRSS_SEND_TABLE_SIZE) { 959 printf("Netvsc: Received wrong send table size: %u\n", count); 960 return; 961 } 962 963 table = (const uint32_t *) 964 ((const uint8_t *)&nvsp_msg_pkt->msgs.vers_5_msgs.send_table + 965 nvsp_msg_pkt->msgs.vers_5_msgs.send_table.offset); 966 967 for (i = 0; i < count; i++) 968 net_dev->vrss_send_table[i] = table[i]; 969} 970 971/* 972 * Net VSC on channel callback 973 */ 974static void 975hv_nv_on_channel_callback(void *xchan) 976{ 977 struct hv_vmbus_channel *chan = xchan; 978 device_t dev = chan->ch_dev; 979 struct hn_softc *sc = device_get_softc(dev); 980 netvsc_dev *net_dev; 981 void *buffer; 982 int bufferlen = NETVSC_PACKET_SIZE; 983 984 net_dev = hv_nv_get_inbound_net_device(sc); 985 if (net_dev == NULL) 986 return; 987 988 buffer = chan->hv_chan_rdbuf; 989 do { 990 struct vmbus_chanpkt_hdr *pkt = buffer; 991 uint32_t bytes_rxed; 992 int ret; 993 994 bytes_rxed = bufferlen; 995 ret = vmbus_chan_recv_pkt(chan, pkt, &bytes_rxed); 996 if (ret == 0) { 997 if (bytes_rxed > 0) { 998 switch (pkt->cph_type) { 999 case VMBUS_CHANPKT_TYPE_COMP: 1000 hv_nv_on_send_completion(net_dev, chan, 1001 pkt); 1002 break; 1003 case VMBUS_CHANPKT_TYPE_RXBUF: 1004 hv_nv_on_receive(net_dev, sc, chan, pkt); 1005 break; 1006 case VMBUS_CHANPKT_TYPE_INBAND: 1007 hv_nv_send_table(sc, pkt); 1008 break; 1009 default: 1010 device_printf(dev, 1011 "unknown chan pkt %u\n", 1012 pkt->cph_type); 1013 break; 1014 } 1015 } 1016 } else if (ret == ENOBUFS) { 1017 /* Handle large packet */ 1018 if (bufferlen > NETVSC_PACKET_SIZE) { 1019 free(buffer, M_NETVSC); 1020 buffer = NULL; 1021 } 1022 1023 /* alloc new buffer */ 1024 buffer = malloc(bytes_rxed, M_NETVSC, M_NOWAIT); 1025 if (buffer == NULL) { 1026 device_printf(dev, 1027 "hv_cb malloc buffer failed, len=%u\n", 1028 bytes_rxed); 1029 bufferlen = 0; 1030 break; 1031 } 1032 bufferlen = bytes_rxed; 1033 } else { 1034 /* No more packets */ 1035 break; 1036 } 1037 } while (1); 1038 1039 if (bufferlen > NETVSC_PACKET_SIZE) 1040 free(buffer, M_NETVSC); 1041 1042 hv_rf_channel_rollup(chan); 1043} 1044