2 * Copyright (c) 2009-2012 Microsoft Corp.
3 * Copyright (c) 2010-2012 Citrix Inc.
4 * Copyright (c) 2012 NetApp Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice unmodified, this list of conditions, and the following
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.
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.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/kernel.h>
35 #include <sys/socket.h>
37 #include <sys/mutex.h>
38 #include <net/if_arp.h>
39 #include <net/ethernet.h>
40 #include <sys/types.h>
41 #include <machine/atomic.h>
44 #include <vm/vm_param.h>
47 #include <dev/hyperv/include/hyperv.h>
48 #include "hv_net_vsc.h"
50 #include "hv_rndis_filter.h"
54 * Forward declarations
56 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
57 uint32_t message_type);
58 static void hv_rf_receive_response(rndis_device *device, rndis_msg *response);
59 static void hv_rf_receive_indicate_status(rndis_device *device,
61 static void hv_rf_receive_data(rndis_device *device, rndis_msg *message,
63 static int hv_rf_query_device(rndis_device *device, uint32_t oid,
64 void *result, uint32_t *result_size);
65 static inline int hv_rf_query_device_mac(rndis_device *device);
66 static inline int hv_rf_query_device_link_status(rndis_device *device);
67 static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
68 static int hv_rf_init_device(rndis_device *device);
69 static int hv_rf_open_device(rndis_device *device);
70 static int hv_rf_close_device(rndis_device *device);
71 static void hv_rf_on_send_request_completion(void *context);
72 static void hv_rf_on_send_request_halt_completion(void *context);
74 hv_rf_send_offload_request(struct hv_device *device,
75 rndis_offload_params *offloads);
77 * Set the Per-Packet-Info with the specified type
80 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
83 rndis_packet *rndis_pkt;
84 rndis_per_packet_info *rppi;
86 rndis_pkt = &rndis_mesg->msg.packet;
87 rndis_pkt->data_offset += rppi_size;
89 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
90 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
92 rppi->size = rppi_size;
93 rppi->type = pkt_type;
94 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
96 rndis_pkt->per_pkt_info_length += rppi_size;
102 * Get the Per-Packet-Info with the specified type
103 * return NULL if not found.
106 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
108 rndis_per_packet_info *ppi;
111 if (rpkt->per_pkt_info_offset == 0)
114 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
115 rpkt->per_pkt_info_offset);
116 len = rpkt->per_pkt_info_length;
119 if (ppi->type == type)
120 return (void *)((unsigned long)ppi +
121 ppi->per_packet_info_offset);
124 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
132 * Allow module_param to work and override to switch to promiscuous mode.
134 static inline rndis_device *
135 hv_get_rndis_device(void)
137 rndis_device *device;
139 device = malloc(sizeof(rndis_device), M_NETVSC, M_NOWAIT | M_ZERO);
140 if (device == NULL) {
144 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_SPIN | MTX_RECURSE);
146 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
147 STAILQ_INIT(&device->myrequest_list);
149 device->state = RNDIS_DEV_UNINITIALIZED;
158 hv_put_rndis_device(rndis_device *device)
160 mtx_destroy(&device->req_lock);
161 free(device, M_NETVSC);
167 static inline rndis_request *
168 hv_rndis_request(rndis_device *device, uint32_t message_type,
169 uint32_t message_length)
171 rndis_request *request;
172 rndis_msg *rndis_mesg;
173 rndis_set_request *set;
175 request = malloc(sizeof(rndis_request), M_NETVSC, M_NOWAIT | M_ZERO);
176 if (request == NULL) {
180 sema_init(&request->wait_sema, 0, "rndis sema");
182 rndis_mesg = &request->request_msg;
183 rndis_mesg->ndis_msg_type = message_type;
184 rndis_mesg->msg_len = message_length;
187 * Set the request id. This field is always after the rndis header
188 * for request/response packet types so we just use the set_request
191 set = &rndis_mesg->msg.set_request;
192 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
193 /* Increment to get the new value (call above returns old value) */
194 set->request_id += 1;
196 /* Add to the request list */
197 mtx_lock_spin(&device->req_lock);
198 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
199 mtx_unlock_spin(&device->req_lock);
208 hv_put_rndis_request(rndis_device *device, rndis_request *request)
210 mtx_lock_spin(&device->req_lock);
211 /* Fixme: Has O(n) performance */
213 * XXXKYS: Use Doubly linked lists.
215 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
217 mtx_unlock_spin(&device->req_lock);
219 sema_destroy(&request->wait_sema);
220 free(request, M_NETVSC);
227 hv_rf_send_request(rndis_device *device, rndis_request *request,
228 uint32_t message_type)
231 netvsc_packet *packet;
233 /* Set up the packet to send it */
234 packet = &request->pkt;
236 packet->is_data_pkt = FALSE;
237 packet->tot_data_buf_len = request->request_msg.msg_len;
238 packet->page_buf_count = 1;
240 packet->page_buffers[0].pfn =
241 hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
242 packet->page_buffers[0].length = request->request_msg.msg_len;
243 packet->page_buffers[0].offset =
244 (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
246 packet->compl.send.send_completion_context = request; /* packet */
247 if (message_type != REMOTE_NDIS_HALT_MSG) {
248 packet->compl.send.on_send_completion =
249 hv_rf_on_send_request_completion;
251 packet->compl.send.on_send_completion =
252 hv_rf_on_send_request_halt_completion;
254 packet->compl.send.send_completion_tid = (unsigned long)device;
255 packet->send_buf_section_idx =
256 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
257 packet->send_buf_section_size = 0;
259 ret = hv_nv_on_send(device->net_dev->dev, packet);
265 * RNDIS filter receive response
268 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
270 rndis_request *request = NULL;
271 rndis_request *next_request;
272 boolean_t found = FALSE;
274 mtx_lock_spin(&device->req_lock);
275 request = STAILQ_FIRST(&device->myrequest_list);
276 while (request != NULL) {
278 * All request/response message contains request_id as the
281 if (request->request_msg.msg.init_request.request_id ==
282 response->msg.init_complete.request_id) {
286 next_request = STAILQ_NEXT(request, mylist_entry);
287 request = next_request;
289 mtx_unlock_spin(&device->req_lock);
292 if (response->msg_len <= sizeof(rndis_msg)) {
293 memcpy(&request->response_msg, response,
296 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
297 /* Does not have a request id field */
298 request->response_msg.msg.reset_complete.status =
299 STATUS_BUFFER_OVERFLOW;
301 request->response_msg.msg.init_complete.status =
302 STATUS_BUFFER_OVERFLOW;
306 sema_post(&request->wait_sema);
311 hv_rf_send_offload_request(struct hv_device *device,
312 rndis_offload_params *offloads)
314 rndis_request *request;
315 rndis_set_request *set;
316 rndis_offload_params *offload_req;
317 rndis_set_complete *set_complete;
318 rndis_device *rndis_dev;
319 hn_softc_t *sc = device_get_softc(device->device);
320 device_t dev = device->device;
321 netvsc_dev *net_dev = sc->net_dev;
322 uint32_t vsp_version = net_dev->nvsp_version;
323 uint32_t extlen = sizeof(rndis_offload_params);
326 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
327 extlen = VERSION_4_OFFLOAD_SIZE;
328 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
329 * UDP checksum offload.
331 offloads->udp_ipv4_csum = 0;
332 offloads->udp_ipv6_csum = 0;
335 rndis_dev = net_dev->extension;
337 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
338 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
342 set = &request->request_msg.msg.set_request;
343 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
344 set->info_buffer_length = extlen;
345 set->info_buffer_offset = sizeof(rndis_set_request);
346 set->device_vc_handle = 0;
348 offload_req = (rndis_offload_params *)((unsigned long)set +
349 set->info_buffer_offset);
350 *offload_req = *offloads;
351 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
352 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
353 offload_req->header.size = extlen;
355 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
357 device_printf(dev, "hv send offload request failed, ret=%d!\n",
362 ret = sema_timedwait(&request->wait_sema, 5 * hz);
364 device_printf(dev, "hv send offload request timeout\n");
368 set_complete = &request->response_msg.msg.set_complete;
369 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
370 device_printf(dev, "hv send offload request succeeded\n");
373 if (set_complete->status == STATUS_NOT_SUPPORTED) {
374 device_printf(dev, "HV Not support offload\n");
377 ret = set_complete->status;
383 hv_put_rndis_request(rndis_dev, request);
389 * RNDIS filter receive indicate status
392 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
394 rndis_indicate_status *indicate = &response->msg.indicate_status;
396 switch(indicate->status) {
397 case RNDIS_STATUS_MEDIA_CONNECT:
398 netvsc_linkstatus_callback(device->net_dev->dev, 1);
400 case RNDIS_STATUS_MEDIA_DISCONNECT:
401 netvsc_linkstatus_callback(device->net_dev->dev, 0);
405 device_printf(device->net_dev->dev->device,
406 "unknown status %d received\n", indicate->status);
412 * RNDIS filter receive data
415 hv_rf_receive_data(rndis_device *device, rndis_msg *message, netvsc_packet *pkt)
417 rndis_packet *rndis_pkt;
418 ndis_8021q_info *rppi_vlan_info;
419 uint32_t data_offset;
420 rndis_tcp_ip_csum_info *csum_info = NULL;
421 device_t dev = device->net_dev->dev->device;
423 rndis_pkt = &message->msg.packet;
426 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
427 * netvsc packet (ie tot_data_buf_len != message_length)
430 /* Remove rndis header, then pass data packet up the stack */
431 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
433 pkt->tot_data_buf_len -= data_offset;
434 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
435 pkt->status = nvsp_status_failure;
437 "total length %u is less than data length %u\n",
438 pkt->tot_data_buf_len, rndis_pkt->data_length);
442 pkt->tot_data_buf_len = rndis_pkt->data_length;
443 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
445 rppi_vlan_info = hv_get_ppi_data(rndis_pkt, ieee_8021q_info);
446 if (rppi_vlan_info) {
447 pkt->vlan_tci = rppi_vlan_info->u1.s1.vlan_id;
452 csum_info = hv_get_ppi_data(rndis_pkt, tcpip_chksum_info);
453 netvsc_recv(device->net_dev->dev, pkt, csum_info);
457 * RNDIS filter on receive
460 hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device, netvsc_packet *pkt)
462 rndis_device *rndis_dev;
463 rndis_msg *rndis_hdr;
465 /* Make sure the rndis device state is initialized */
466 if (net_dev->extension == NULL) {
467 pkt->status = nvsp_status_failure;
471 rndis_dev = (rndis_device *)net_dev->extension;
472 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
473 pkt->status = nvsp_status_failure;
477 rndis_hdr = pkt->data;
479 switch (rndis_hdr->ndis_msg_type) {
482 case REMOTE_NDIS_PACKET_MSG:
483 hv_rf_receive_data(rndis_dev, rndis_hdr, pkt);
485 /* completion messages */
486 case REMOTE_NDIS_INITIALIZE_CMPLT:
487 case REMOTE_NDIS_QUERY_CMPLT:
488 case REMOTE_NDIS_SET_CMPLT:
489 case REMOTE_NDIS_RESET_CMPLT:
490 case REMOTE_NDIS_KEEPALIVE_CMPLT:
491 hv_rf_receive_response(rndis_dev, rndis_hdr);
493 /* notification message */
494 case REMOTE_NDIS_INDICATE_STATUS_MSG:
495 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
498 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
499 rndis_hdr->ndis_msg_type);
507 * RNDIS filter query device
510 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
511 uint32_t *result_size)
513 rndis_request *request;
514 uint32_t in_result_size = *result_size;
515 rndis_query_request *query;
516 rndis_query_complete *query_complete;
520 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
521 RNDIS_MESSAGE_SIZE(rndis_query_request));
522 if (request == NULL) {
527 /* Set up the rndis query */
528 query = &request->request_msg.msg.query_request;
530 query->info_buffer_offset = sizeof(rndis_query_request);
531 query->info_buffer_length = 0;
532 query->device_vc_handle = 0;
534 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
536 /* Fixme: printf added */
537 printf("RNDISFILTER request failed to Send!\n");
541 sema_wait(&request->wait_sema);
543 /* Copy the response back */
544 query_complete = &request->response_msg.msg.query_complete;
546 if (query_complete->info_buffer_length > in_result_size) {
551 memcpy(result, (void *)((unsigned long)query_complete +
552 query_complete->info_buffer_offset),
553 query_complete->info_buffer_length);
555 *result_size = query_complete->info_buffer_length;
559 hv_put_rndis_request(device, request);
565 * RNDIS filter query device MAC address
568 hv_rf_query_device_mac(rndis_device *device)
570 uint32_t size = HW_MACADDR_LEN;
572 return (hv_rf_query_device(device,
573 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
577 * RNDIS filter query device link status
580 hv_rf_query_device_link_status(rndis_device *device)
582 uint32_t size = sizeof(uint32_t);
584 return (hv_rf_query_device(device,
585 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
589 * RNDIS filter set packet filter
590 * Sends an rndis request with the new filter, then waits for a response
592 * Returns zero on success, non-zero on failure.
595 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
597 rndis_request *request;
598 rndis_set_request *set;
599 rndis_set_complete *set_complete;
603 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
604 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
605 if (request == NULL) {
610 /* Set up the rndis set */
611 set = &request->request_msg.msg.set_request;
612 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
613 set->info_buffer_length = sizeof(uint32_t);
614 set->info_buffer_offset = sizeof(rndis_set_request);
616 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
617 &new_filter, sizeof(uint32_t));
619 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
625 * Wait for the response from the host. Another thread will signal
626 * us when the response has arrived. In the failure case,
627 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
629 ret = sema_timedwait(&request->wait_sema, 5 * hz);
631 /* Response received, check status */
632 set_complete = &request->response_msg.msg.set_complete;
633 status = set_complete->status;
634 if (status != RNDIS_STATUS_SUCCESS) {
635 /* Bad response status, return error */
640 * We cannot deallocate the request since we may still
641 * receive a send completion for it.
647 if (request != NULL) {
648 hv_put_rndis_request(device, request);
655 * RNDIS filter init device
658 hv_rf_init_device(rndis_device *device)
660 rndis_request *request;
661 rndis_initialize_request *init;
662 rndis_initialize_complete *init_complete;
666 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
667 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
673 /* Set up the rndis set */
674 init = &request->request_msg.msg.init_request;
675 init->major_version = RNDIS_MAJOR_VERSION;
676 init->minor_version = RNDIS_MINOR_VERSION;
678 * Per the RNDIS document, this should be set to the max MTU
679 * plus the header size. However, 2048 works fine, so leaving
682 init->max_xfer_size = 2048;
684 device->state = RNDIS_DEV_INITIALIZING;
686 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
688 device->state = RNDIS_DEV_UNINITIALIZED;
692 sema_wait(&request->wait_sema);
694 init_complete = &request->response_msg.msg.init_complete;
695 status = init_complete->status;
696 if (status == RNDIS_STATUS_SUCCESS) {
697 device->state = RNDIS_DEV_INITIALIZED;
700 device->state = RNDIS_DEV_UNINITIALIZED;
706 hv_put_rndis_request(device, request);
712 #define HALT_COMPLETION_WAIT_COUNT 25
715 * RNDIS filter halt device
718 hv_rf_halt_device(rndis_device *device)
720 rndis_request *request;
721 rndis_halt_request *halt;
724 /* Attempt to do a rndis device halt */
725 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
726 RNDIS_MESSAGE_SIZE(rndis_halt_request));
727 if (request == NULL) {
731 /* initialize "poor man's semaphore" */
732 request->halt_complete_flag = 0;
734 /* Set up the rndis set */
735 halt = &request->request_msg.msg.halt_request;
736 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
737 /* Increment to get the new value (call above returns old value) */
738 halt->request_id += 1;
740 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
746 * Wait for halt response from halt callback. We must wait for
747 * the transaction response before freeing the request and other
750 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
751 if (request->halt_complete_flag != 0) {
760 device->state = RNDIS_DEV_UNINITIALIZED;
762 if (request != NULL) {
763 hv_put_rndis_request(device, request);
770 * RNDIS filter open device
773 hv_rf_open_device(rndis_device *device)
777 if (device->state != RNDIS_DEV_INITIALIZED) {
781 if (hv_promisc_mode != 1) {
782 ret = hv_rf_set_packet_filter(device,
783 NDIS_PACKET_TYPE_BROADCAST |
784 NDIS_PACKET_TYPE_ALL_MULTICAST |
785 NDIS_PACKET_TYPE_DIRECTED);
787 ret = hv_rf_set_packet_filter(device,
788 NDIS_PACKET_TYPE_PROMISCUOUS);
792 device->state = RNDIS_DEV_DATAINITIALIZED;
799 * RNDIS filter close device
802 hv_rf_close_device(rndis_device *device)
806 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
810 ret = hv_rf_set_packet_filter(device, 0);
812 device->state = RNDIS_DEV_INITIALIZED;
819 * RNDIS filter on device add
822 hv_rf_on_device_add(struct hv_device *device, void *additl_info)
826 rndis_device *rndis_dev;
827 rndis_offload_params offloads;
828 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
829 device_t dev = device->device;
831 rndis_dev = hv_get_rndis_device();
832 if (rndis_dev == NULL) {
837 * Let the inner driver handle this first to create the netvsc channel
838 * NOTE! Once the channel is created, we may get a receive callback
839 * (hv_rf_on_receive()) before this call is completed.
840 * Note: Earlier code used a function pointer here.
842 net_dev = hv_nv_on_device_add(device, additl_info);
844 hv_put_rndis_device(rndis_dev);
850 * Initialize the rndis device
853 net_dev->extension = rndis_dev;
854 rndis_dev->net_dev = net_dev;
856 /* Send the rndis initialization message */
857 ret = hv_rf_init_device(rndis_dev);
860 * TODO: If rndis init failed, we will need to shut down
865 /* Get the mac address */
866 ret = hv_rf_query_device_mac(rndis_dev);
868 /* TODO: shut down rndis device and the channel */
871 /* config csum offload and send request to host */
872 memset(&offloads, 0, sizeof(offloads));
873 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
874 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
875 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
876 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
877 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
878 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
880 ret = hv_rf_send_offload_request(device, &offloads);
882 /* TODO: shut down rndis device and the channel */
884 "hv_rf_send_offload_request failed, ret=%d\n", ret);
887 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
889 hv_rf_query_device_link_status(rndis_dev);
891 dev_info->link_state = rndis_dev->link_status;
897 * RNDIS filter on device remove
900 hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel)
902 hn_softc_t *sc = device_get_softc(device->device);
903 netvsc_dev *net_dev = sc->net_dev;
904 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
907 /* Halt and release the rndis device */
908 ret = hv_rf_halt_device(rndis_dev);
910 hv_put_rndis_device(rndis_dev);
911 net_dev->extension = NULL;
913 /* Pass control to inner driver to remove the device */
914 ret |= hv_nv_on_device_remove(device, destroy_channel);
920 * RNDIS filter on open
923 hv_rf_on_open(struct hv_device *device)
925 hn_softc_t *sc = device_get_softc(device->device);
926 netvsc_dev *net_dev = sc->net_dev;
928 return (hv_rf_open_device((rndis_device *)net_dev->extension));
932 * RNDIS filter on close
935 hv_rf_on_close(struct hv_device *device)
937 hn_softc_t *sc = device_get_softc(device->device);
938 netvsc_dev *net_dev = sc->net_dev;
940 return (hv_rf_close_device((rndis_device *)net_dev->extension));
944 * RNDIS filter on send request completion callback
947 hv_rf_on_send_request_completion(void *context)
952 * RNDIS filter on send request (halt only) completion callback
955 hv_rf_on_send_request_halt_completion(void *context)
957 rndis_request *request = context;
960 * Notify hv_rf_halt_device() about halt completion.
961 * The halt code must wait for completion before freeing
962 * the transaction resources.
964 request->halt_complete_flag = 1;
968 * RNDIS filter when "all" reception is done
971 hv_rf_receive_rollup(netvsc_dev *net_dev)
973 rndis_device *rndis_dev;
975 rndis_dev = (rndis_device *)net_dev->extension;
976 netvsc_recv_rollup(rndis_dev->net_dev->dev);
980 hv_rf_channel_rollup(netvsc_dev *net_dev)
982 rndis_device *rndis_dev;
984 rndis_dev = (rndis_device *)net_dev->extension;
987 * This could be called pretty early, so we need
988 * to make sure everything has been setup.
990 if (rndis_dev == NULL ||
991 rndis_dev->net_dev == NULL ||
992 rndis_dev->net_dev->dev == NULL)
994 netvsc_channel_rollup(rndis_dev->net_dev->dev);