hv_netvsc_drv_freebsd.c revision 253869
1/*- 2 * Copyright (c) 2010-2012 Citrix Inc. 3 * Copyright (c) 2009-2012 Microsoft Corp. 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 29/*- 30 * Copyright (c) 2004-2006 Kip Macy 31 * All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 */ 54 55#include <sys/param.h> 56#include <sys/systm.h> 57#include <sys/sockio.h> 58#include <sys/mbuf.h> 59#include <sys/malloc.h> 60#include <sys/module.h> 61#include <sys/kernel.h> 62#include <sys/socket.h> 63#include <sys/queue.h> 64#include <sys/lock.h> 65#include <sys/sx.h> 66 67#include <net/if.h> 68#include <net/if_arp.h> 69#include <net/ethernet.h> 70#include <net/if_dl.h> 71#include <net/if_media.h> 72 73#include <net/bpf.h> 74 75#include <net/if_types.h> 76#include <net/if_vlan_var.h> 77#include <net/if.h> 78 79#include <netinet/in_systm.h> 80#include <netinet/in.h> 81#include <netinet/ip.h> 82#include <netinet/if_ether.h> 83 84#include <vm/vm.h> 85#include <vm/vm_param.h> 86#include <vm/vm_kern.h> 87#include <vm/pmap.h> 88 89#include <machine/bus.h> 90#include <machine/resource.h> 91#include <machine/frame.h> 92#include <machine/vmparam.h> 93 94#include <sys/bus.h> 95#include <sys/rman.h> 96#include <sys/mutex.h> 97#include <sys/errno.h> 98#include <sys/types.h> 99#include <machine/atomic.h> 100 101#include <machine/intr_machdep.h> 102 103#include <dev/hyperv/include/hyperv.h> 104#include "hv_net_vsc.h" 105#include "hv_rndis.h" 106#include "hv_rndis_filter.h" 107 108 109/* Short for Hyper-V network interface */ 110#define NETVSC_DEVNAME "hn" 111 112/* 113 * It looks like offset 0 of buf is reserved to hold the softc pointer. 114 * The sc pointer evidently not needed, and is not presently populated. 115 * The packet offset is where the netvsc_packet starts in the buffer. 116 */ 117#define HV_NV_SC_PTR_OFFSET_IN_BUF 0 118#define HV_NV_PACKET_OFFSET_IN_BUF 16 119 120 121/* 122 * Data types 123 */ 124 125struct hv_netvsc_driver_context { 126 uint32_t drv_inited; 127}; 128 129/* 130 * Be aware that this sleepable mutex will exhibit WITNESS errors when 131 * certain TCP and ARP code paths are taken. This appears to be a 132 * well-known condition, as all other drivers checked use a sleeping 133 * mutex to protect their transmit paths. 134 * Also Be aware that mutexes do not play well with semaphores, and there 135 * is a conflicting semaphore in a certain channel code path. 136 */ 137#define NV_LOCK_INIT(_sc, _name) \ 138 mtx_init(&(_sc)->hn_lock, _name, MTX_NETWORK_LOCK, MTX_DEF) 139#define NV_LOCK(_sc) mtx_lock(&(_sc)->hn_lock) 140#define NV_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->hn_lock, MA_OWNED) 141#define NV_UNLOCK(_sc) mtx_unlock(&(_sc)->hn_lock) 142#define NV_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->hn_lock) 143 144 145/* 146 * Globals 147 */ 148 149int hv_promisc_mode = 0; /* normal mode by default */ 150 151/* The one and only one */ 152static struct hv_netvsc_driver_context g_netvsc_drv; 153 154 155/* 156 * Forward declarations 157 */ 158static void hn_stop(hn_softc_t *sc); 159static void hn_ifinit_locked(hn_softc_t *sc); 160static void hn_ifinit(void *xsc); 161static int hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 162static int hn_start_locked(struct ifnet *ifp); 163static void hn_start(struct ifnet *ifp); 164 165 166/* 167 * NetVsc driver initialization 168 * Note: Filter init is no longer required 169 */ 170static int 171netvsc_drv_init(void) 172{ 173 return (0); 174} 175 176/* 177 * NetVsc global initialization entry point 178 */ 179static void 180netvsc_init(void) 181{ 182 printf("Netvsc initializing... "); 183 184 /* 185 * XXXKYS: cleanup initialization 186 */ 187 if (!cold && !g_netvsc_drv.drv_inited) { 188 g_netvsc_drv.drv_inited = 1; 189 netvsc_drv_init(); 190 } else { 191 printf("Already initialized!\n"); 192 } 193} 194 195/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ 196static const hv_guid g_net_vsc_device_type = { 197 .data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 198 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E} 199}; 200 201/* 202 * Standard probe entry point. 203 * 204 */ 205static int 206netvsc_probe(device_t dev) 207{ 208 const char *p; 209 210 p = vmbus_get_type(dev); 211 if (!memcmp(p, &g_net_vsc_device_type.data, sizeof(hv_guid))) { 212 device_set_desc(dev, "Synthetic Network Interface"); 213 printf("Netvsc probe... DONE \n"); 214 215 return (0); 216 } 217 218 return (ENXIO); 219} 220 221/* 222 * Standard attach entry point. 223 * 224 * Called when the driver is loaded. It allocates needed resources, 225 * and initializes the "hardware" and software. 226 */ 227static int 228netvsc_attach(device_t dev) 229{ 230 struct hv_device *device_ctx = vmbus_get_devctx(dev); 231 netvsc_device_info device_info; 232 hn_softc_t *sc; 233 int unit = device_get_unit(dev); 234 struct ifnet *ifp; 235 int ret; 236 237 netvsc_init(); 238 239 sc = device_get_softc(dev); 240 if (sc == NULL) { 241 return (ENOMEM); 242 } 243 244 bzero(sc, sizeof(hn_softc_t)); 245 sc->hn_unit = unit; 246 sc->hn_dev = dev; 247 248 NV_LOCK_INIT(sc, "NetVSCLock"); 249 250 sc->hn_dev_obj = device_ctx; 251 252 ifp = sc->hn_ifp = sc->arpcom.ac_ifp = if_alloc(IFT_ETHER); 253 ifp->if_softc = sc; 254 255 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 256 ifp->if_dunit = unit; 257 ifp->if_dname = NETVSC_DEVNAME; 258 259 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 260 ifp->if_ioctl = hn_ioctl; 261 ifp->if_start = hn_start; 262 ifp->if_init = hn_ifinit; 263 /* needed by hv_rf_on_device_add() code */ 264 ifp->if_mtu = ETHERMTU; 265 IFQ_SET_MAXLEN(&ifp->if_snd, 512); 266 ifp->if_snd.ifq_drv_maxlen = 511; 267 IFQ_SET_READY(&ifp->if_snd); 268 269 /* 270 * Tell upper layers that we support full VLAN capability. 271 */ 272 ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 273 ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 274 ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 275 276 ret = hv_rf_on_device_add(device_ctx, &device_info); 277 if (ret != 0) { 278 if_free(ifp); 279 280 return (ret); 281 } 282 if (device_info.link_state == 0) { 283 sc->hn_carrier = 1; 284 } 285 286 ether_ifattach(ifp, device_info.mac_addr); 287 288 return (0); 289} 290 291/* 292 * Standard detach entry point 293 */ 294static int 295netvsc_detach(device_t dev) 296{ 297 struct hv_device *hv_device = vmbus_get_devctx(dev); 298 299 printf("netvsc_detach\n"); 300 301 /* 302 * XXXKYS: Need to clean up all our 303 * driver state; this is the driver 304 * unloading. 305 */ 306 307 /* 308 * XXXKYS: Need to stop outgoing traffic and unregister 309 * the netdevice. 310 */ 311 312 hv_rf_on_device_remove(hv_device, HV_RF_NV_DESTROY_CHANNEL); 313 314 return (0); 315} 316 317/* 318 * Standard shutdown entry point 319 */ 320static int 321netvsc_shutdown(device_t dev) 322{ 323 return (0); 324} 325 326/* 327 * Send completion processing 328 * 329 * Note: It looks like offset 0 of buf is reserved to hold the softc 330 * pointer. The sc pointer is not currently needed in this function, and 331 * it is not presently populated by the TX function. 332 */ 333void 334netvsc_xmit_completion(void *context) 335{ 336 netvsc_packet *packet = (netvsc_packet *)context; 337 struct mbuf *mb; 338 uint8_t *buf; 339 340 mb = (struct mbuf *)packet->compl.send.send_completion_tid; 341 buf = ((uint8_t *)packet) - HV_NV_PACKET_OFFSET_IN_BUF; 342 343 free(buf, M_DEVBUF); 344 345 if (mb != NULL) { 346 m_freem(mb); 347 } 348} 349 350/* 351 * Start a transmit of one or more packets 352 */ 353static int 354hn_start_locked(struct ifnet *ifp) 355{ 356 hn_softc_t *sc = ifp->if_softc; 357 struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); 358 uint8_t *buf; 359 netvsc_packet *packet; 360 struct mbuf *m_head, *m; 361 struct mbuf *mc_head = NULL; 362 int i; 363 int num_frags; 364 int len; 365 int xlen; 366 int rppi_size; 367 int retries = 0; 368 int ret = 0; 369 370 while (!IFQ_DRV_IS_EMPTY(&sc->hn_ifp->if_snd)) { 371 IFQ_DRV_DEQUEUE(&sc->hn_ifp->if_snd, m_head); 372 if (m_head == NULL) { 373 break; 374 } 375 376 len = 0; 377 num_frags = 0; 378 xlen = 0; 379 380 /* Walk the mbuf list computing total length and num frags */ 381 for (m = m_head; m != NULL; m = m->m_next) { 382 if (m->m_len != 0) { 383 num_frags++; 384 len += m->m_len; 385 } 386 } 387 388 /* 389 * Reserve the number of pages requested. Currently, 390 * one page is reserved for the message in the RNDIS 391 * filter packet 392 */ 393 num_frags += HV_RF_NUM_TX_RESERVED_PAGE_BUFS; 394 395 /* If exceeds # page_buffers in netvsc_packet */ 396 if (num_frags > NETVSC_PACKET_MAXPAGE) { 397 m_freem(m); 398 399 return (EINVAL); 400 } 401 402 rppi_size = 0; 403 if (m_head->m_flags & M_VLANTAG) { 404 rppi_size = sizeof(rndis_per_packet_info) + 405 sizeof(ndis_8021q_info); 406 } 407 408 /* 409 * Allocate a buffer with space for a netvsc packet plus a 410 * number of reserved areas. First comes a (currently 16 411 * bytes, currently unused) reserved data area. Second is 412 * the netvsc_packet, which includes (currently 4) page 413 * buffers. Third (optional) is a rndis_per_packet_info 414 * struct, but only if a VLAN tag should be inserted into the 415 * Ethernet frame by the Hyper-V infrastructure. Fourth is 416 * an area reserved for an rndis_filter_packet struct. 417 * Changed malloc to M_NOWAIT to avoid sleep under spin lock. 418 * No longer reserving extra space for page buffers, as they 419 * are already part of the netvsc_packet. 420 */ 421 buf = malloc(HV_NV_PACKET_OFFSET_IN_BUF + 422 sizeof(netvsc_packet) + rppi_size + 423 sizeof(rndis_filter_packet), 424 M_DEVBUF, M_ZERO | M_NOWAIT); 425 if (buf == NULL) { 426 m_freem(m); 427 428 return (ENOMEM); 429 } 430 431 packet = (netvsc_packet *)(buf + HV_NV_PACKET_OFFSET_IN_BUF); 432 *(vm_offset_t *)buf = HV_NV_SC_PTR_OFFSET_IN_BUF; 433 434 /* 435 * extension points to the area reserved for the 436 * rndis_filter_packet, which is placed just after 437 * the netvsc_packet (and rppi struct, if present; 438 * length is updated later). 439 */ 440 packet->extension = packet + 1; 441 442 /* Set up the rndis header */ 443 packet->page_buf_count = num_frags; 444 445 /* Initialize it from the mbuf */ 446 packet->tot_data_buf_len = len; 447 448 /* 449 * If the Hyper-V infrastructure needs to embed a VLAN tag, 450 * initialize netvsc_packet and rppi struct values as needed. 451 */ 452 if (rppi_size) { 453 /* Lower layers need the VLAN TCI */ 454 packet->vlan_tci = m_head->m_pkthdr.ether_vtag; 455 } 456 457 /* 458 * Fill the page buffers with mbuf info starting at index 459 * HV_RF_NUM_TX_RESERVED_PAGE_BUFS. 460 */ 461 i = HV_RF_NUM_TX_RESERVED_PAGE_BUFS; 462 for (m = m_head; m != NULL; m = m->m_next) { 463 if (m->m_len) { 464 vm_offset_t paddr = 465 vtophys(mtod(m, vm_offset_t)); 466 packet->page_buffers[i].pfn = 467 paddr >> PAGE_SHIFT; 468 packet->page_buffers[i].offset = 469 paddr & (PAGE_SIZE - 1); 470 packet->page_buffers[i].length = m->m_len; 471 i++; 472 } 473 } 474 475 /* 476 * If bpf, copy the mbuf chain. This is less expensive than 477 * it appears; the mbuf clusters are not copied, only their 478 * reference counts are incremented. 479 * Needed to avoid a race condition where the completion 480 * callback is invoked, freeing the mbuf chain, before the 481 * bpf_mtap code has a chance to run. 482 */ 483 if (ifp->if_bpf) { 484 mc_head = m_copypacket(m_head, M_DONTWAIT); 485 } 486retry_send: 487 /* Set the completion routine */ 488 packet->compl.send.on_send_completion = netvsc_xmit_completion; 489 packet->compl.send.send_completion_context = packet; 490 packet->compl.send.send_completion_tid = (uint64_t)m_head; 491 492 /* Removed critical_enter(), does not appear necessary */ 493 ret = hv_rf_on_send(device_ctx, packet); 494 495 if (ret == 0) { 496 ifp->if_opackets++; 497 /* if bpf && mc_head, call bpf_mtap code */ 498 if (mc_head) { 499 ETHER_BPF_MTAP(ifp, mc_head); 500 } 501 } else { 502 retries++; 503 if (retries < 4) { 504 goto retry_send; 505 } 506 507 IF_PREPEND(&ifp->if_snd, m_head); 508 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 509 510 /* 511 * Null the mbuf pointer so the completion function 512 * does not free the mbuf chain. We just pushed the 513 * mbuf chain back on the if_snd queue. 514 */ 515 packet->compl.send.send_completion_tid = 0; 516 517 /* 518 * Release the resources since we will not get any 519 * send completion 520 */ 521 netvsc_xmit_completion(packet); 522 } 523 524 /* if bpf && mc_head, free the mbuf chain copy */ 525 if (mc_head) { 526 m_freem(mc_head); 527 } 528 } 529 530 return (ret); 531} 532 533/* 534 * Link up/down notification 535 */ 536void 537netvsc_linkstatus_callback(struct hv_device *device_obj, uint32_t status) 538{ 539 hn_softc_t *sc = device_get_softc(device_obj->device); 540 541 if (sc == NULL) { 542 return; 543 } 544 545 if (status == 1) { 546 sc->hn_carrier = 1; 547 } else { 548 sc->hn_carrier = 0; 549 } 550} 551 552/* 553 * Append the specified data to the indicated mbuf chain, 554 * Extend the mbuf chain if the new data does not fit in 555 * existing space. 556 * 557 * This is a minor rewrite of m_append() from sys/kern/uipc_mbuf.c. 558 * There should be an equivalent in the kernel mbuf code, 559 * but there does not appear to be one yet. 560 * 561 * Differs from m_append() in that additional mbufs are 562 * allocated with cluster size MJUMPAGESIZE, and filled 563 * accordingly. 564 * 565 * Return 1 if able to complete the job; otherwise 0. 566 */ 567static int 568hv_m_append(struct mbuf *m0, int len, c_caddr_t cp) 569{ 570 struct mbuf *m, *n; 571 int remainder, space; 572 573 for (m = m0; m->m_next != NULL; m = m->m_next) 574 ; 575 remainder = len; 576 space = M_TRAILINGSPACE(m); 577 if (space > 0) { 578 /* 579 * Copy into available space. 580 */ 581 if (space > remainder) 582 space = remainder; 583 bcopy(cp, mtod(m, caddr_t) + m->m_len, space); 584 m->m_len += space; 585 cp += space; 586 remainder -= space; 587 } 588 while (remainder > 0) { 589 /* 590 * Allocate a new mbuf; could check space 591 * and allocate a cluster instead. 592 */ 593 n = m_getjcl(M_DONTWAIT, m->m_type, 0, MJUMPAGESIZE); 594 if (n == NULL) 595 break; 596 n->m_len = min(MJUMPAGESIZE, remainder); 597 bcopy(cp, mtod(n, caddr_t), n->m_len); 598 cp += n->m_len; 599 remainder -= n->m_len; 600 m->m_next = n; 601 m = n; 602 } 603 if (m0->m_flags & M_PKTHDR) 604 m0->m_pkthdr.len += len - remainder; 605 606 return (remainder == 0); 607} 608 609 610/* 611 * Called when we receive a data packet from the "wire" on the 612 * specified device 613 * 614 * Note: This is no longer used as a callback 615 */ 616int 617netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet) 618{ 619 hn_softc_t *sc = (hn_softc_t *)device_get_softc(device_ctx->device); 620 struct mbuf *m_new; 621 struct ifnet *ifp = sc->hn_ifp; 622 int size; 623 int i; 624 625 if (sc == NULL) { 626 return (0); /* TODO: KYS how can this be! */ 627 } 628 629 ifp = sc->arpcom.ac_ifp; 630 631 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 632 return (0); 633 } 634 635 /* 636 * Bail out if packet contains more data than configured MTU. 637 */ 638 if (packet->tot_data_buf_len > (ifp->if_mtu + ETHER_HDR_LEN)) { 639 return (0); 640 } 641 642 /* 643 * Get an mbuf with a cluster. For packets 2K or less, 644 * get a standard 2K cluster. For anything larger, get a 645 * 4K cluster. Any buffers larger than 4K can cause problems 646 * if looped around to the Hyper-V TX channel, so avoid them. 647 */ 648 size = MCLBYTES; 649 650 if (packet->tot_data_buf_len > MCLBYTES) { 651 /* 4096 */ 652 size = MJUMPAGESIZE; 653 } 654 655 m_new = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, size); 656 657 if (m_new == NULL) 658 return (0); 659 660 /* 661 * Remove trailing junk from RX data buffer. 662 * Fixme: This will not work for multiple Hyper-V RX buffers. 663 * Fortunately, the channel gathers all RX data into one buffer. 664 * 665 * L2 frame length, with L2 header, not including CRC 666 */ 667 packet->page_buffers[0].length = packet->tot_data_buf_len; 668 669 /* 670 * Copy the received packet to one or more mbufs. 671 * The copy is required since the memory pointed to by netvsc_packet 672 * cannot be deallocated 673 */ 674 for (i=0; i < packet->page_buf_count; i++) { 675 /* Shift virtual page number to form virtual page address */ 676 uint8_t *vaddr = (uint8_t *) 677 (packet->page_buffers[i].pfn << PAGE_SHIFT); 678 679 hv_m_append(m_new, packet->page_buffers[i].length, 680 vaddr + packet->page_buffers[i].offset); 681 } 682 683 m_new->m_pkthdr.rcvif = ifp; 684 685 if ((packet->vlan_tci != 0) && 686 (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 687 m_new->m_pkthdr.ether_vtag = packet->vlan_tci; 688 m_new->m_flags |= M_VLANTAG; 689 } 690 691 /* 692 * Note: Moved RX completion back to hv_nv_on_receive() so all 693 * messages (not just data messages) will trigger a response. 694 */ 695 696 ifp->if_ipackets++; 697 698 /* We're not holding the lock here, so don't release it */ 699 (*ifp->if_input)(ifp, m_new); 700 701 return (0); 702} 703 704/* 705 * Standard ioctl entry point. Called when the user wants to configure 706 * the interface. 707 */ 708static int 709hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 710{ 711 hn_softc_t *sc = ifp->if_softc; 712 struct ifreq *ifr = (struct ifreq *)data; 713 netvsc_device_info device_info; 714 struct hv_device *hn_dev; 715 int mask, error = 0; 716 717 switch(cmd) { 718 719 case SIOCSIFADDR: 720 case SIOCGIFADDR: 721 error = ether_ioctl(ifp, cmd, data); 722 break; 723 case SIOCSIFMTU: 724 hn_dev = vmbus_get_devctx(sc->hn_dev); 725 726 NV_LOCK(sc); 727 728 if (ifr->ifr_mtu > NETVSC_MAX_CONFIGURABLE_MTU) { 729 error = EINVAL; 730 NV_UNLOCK(sc); 731 break; 732 } 733 /* Obtain and record requested MTU */ 734 ifp->if_mtu = ifr->ifr_mtu; 735 736 /* 737 * We must remove and add back the device to cause the new 738 * MTU to take effect. This includes tearing down, but not 739 * deleting the channel, then bringing it back up. 740 */ 741 error = hv_rf_on_device_remove(hn_dev, HV_RF_NV_RETAIN_CHANNEL); 742 if (error) { 743 NV_UNLOCK(sc); 744 break; 745 } 746 error = hv_rf_on_device_add(hn_dev, &device_info); 747 if (error) { 748 NV_UNLOCK(sc); 749 break; 750 } 751 752 hn_ifinit_locked(sc); 753 754 NV_UNLOCK(sc); 755 break; 756 case SIOCSIFFLAGS: 757 NV_LOCK(sc); 758 if (ifp->if_flags & IFF_UP) { 759 /* 760 * If only the state of the PROMISC flag changed, 761 * then just use the 'set promisc mode' command 762 * instead of reinitializing the entire NIC. Doing 763 * a full re-init means reloading the firmware and 764 * waiting for it to start up, which may take a 765 * second or two. 766 */ 767#ifdef notyet 768 /* Fixme: Promiscuous mode? */ 769 /* No promiscuous mode with Xen */ 770 if (ifp->if_drv_flags & IFF_DRV_RUNNING && 771 ifp->if_flags & IFF_PROMISC && 772 !(sc->hn_if_flags & IFF_PROMISC)) { 773 /* do something here for Hyper-V */ 774 ; 775/* XN_SETBIT(sc, XN_RX_MODE, */ 776/* XN_RXMODE_RX_PROMISC); */ 777 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && 778 !(ifp->if_flags & IFF_PROMISC) && 779 sc->hn_if_flags & IFF_PROMISC) { 780 /* do something here for Hyper-V */ 781 ; 782/* XN_CLRBIT(sc, XN_RX_MODE, */ 783/* XN_RXMODE_RX_PROMISC); */ 784 } else 785#endif 786 hn_ifinit_locked(sc); 787 } else { 788 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 789 hn_stop(sc); 790 } 791 } 792 sc->hn_if_flags = ifp->if_flags; 793 NV_UNLOCK(sc); 794 error = 0; 795 break; 796 case SIOCSIFCAP: 797 mask = ifr->ifr_reqcap ^ ifp->if_capenable; 798 if (mask & IFCAP_HWCSUM) { 799 if (IFCAP_HWCSUM & ifp->if_capenable) { 800 ifp->if_capenable &= ~IFCAP_HWCSUM; 801 } else { 802 ifp->if_capenable |= IFCAP_HWCSUM; 803 } 804 } 805 error = 0; 806 break; 807 case SIOCADDMULTI: 808 case SIOCDELMULTI: 809#ifdef notyet 810 /* Fixme: Multicast mode? */ 811 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 812 NV_LOCK(sc); 813 netvsc_setmulti(sc); 814 NV_UNLOCK(sc); 815 error = 0; 816 } 817#endif 818 /* FALLTHROUGH */ 819 case SIOCSIFMEDIA: 820 case SIOCGIFMEDIA: 821 error = EINVAL; 822 break; 823 default: 824 error = ether_ioctl(ifp, cmd, data); 825 break; 826 } 827 828 return (error); 829} 830 831/* 832 * 833 */ 834static void 835hn_stop(hn_softc_t *sc) 836{ 837 struct ifnet *ifp; 838 int ret; 839 struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); 840 841 NV_LOCK_ASSERT(sc); 842 ifp = sc->hn_ifp; 843 844 printf(" Closing Device ...\n"); 845 846 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 847 sc->hn_initdone = 0; 848 849 ret = hv_rf_on_close(device_ctx); 850} 851 852/* 853 * FreeBSD transmit entry point 854 */ 855static void 856hn_start(struct ifnet *ifp) 857{ 858 hn_softc_t *sc; 859 860 sc = ifp->if_softc; 861 NV_LOCK(sc); 862 hn_start_locked(ifp); 863 NV_UNLOCK(sc); 864} 865 866/* 867 * 868 */ 869static void 870hn_ifinit_locked(hn_softc_t *sc) 871{ 872 struct ifnet *ifp; 873 struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); 874 int ret; 875 876 NV_LOCK_ASSERT(sc); 877 878 ifp = sc->hn_ifp; 879 880 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 881 return; 882 } 883 884 hv_promisc_mode = 1; 885 886 ret = hv_rf_on_open(device_ctx); 887 if (ret != 0) { 888 return; 889 } else { 890 sc->hn_initdone = 1; 891 } 892 ifp->if_drv_flags |= IFF_DRV_RUNNING; 893 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 894} 895 896/* 897 * 898 */ 899static void 900hn_ifinit(void *xsc) 901{ 902 hn_softc_t *sc = xsc; 903 904 NV_LOCK(sc); 905 hn_ifinit_locked(sc); 906 NV_UNLOCK(sc); 907} 908 909#ifdef LATER 910/* 911 * 912 */ 913static void 914hn_watchdog(struct ifnet *ifp) 915{ 916 hn_softc_t *sc; 917 sc = ifp->if_softc; 918 919 printf("hn%d: watchdog timeout -- resetting\n", sc->hn_unit); 920 hn_ifinit(sc); /*???*/ 921 ifp->if_oerrors++; 922} 923#endif 924 925static device_method_t netvsc_methods[] = { 926 /* Device interface */ 927 DEVMETHOD(device_probe, netvsc_probe), 928 DEVMETHOD(device_attach, netvsc_attach), 929 DEVMETHOD(device_detach, netvsc_detach), 930 DEVMETHOD(device_shutdown, netvsc_shutdown), 931 932 { 0, 0 } 933}; 934 935static driver_t netvsc_driver = { 936 NETVSC_DEVNAME, 937 netvsc_methods, 938 sizeof(hn_softc_t) 939}; 940 941static devclass_t netvsc_devclass; 942 943DRIVER_MODULE(hn, vmbus, netvsc_driver, netvsc_devclass, 0, 0); 944MODULE_VERSION(hn, 1); 945MODULE_DEPEND(hn, vmbus, 1, 1, 1); 946SYSINIT(netvsc_initx, SI_SUB_KTHREAD_IDLE, SI_ORDER_MIDDLE + 1, netvsc_init, 947 NULL); 948 949