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 <dev/hyperv/vmbus/hv_vmbus_priv.h>
49 #include "hv_net_vsc.h"
51 #include "hv_rndis_filter.h"
55 * Forward declarations
57 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
58 uint32_t message_type);
59 static void hv_rf_receive_response(rndis_device *device, rndis_msg *response);
60 static void hv_rf_receive_indicate_status(rndis_device *device,
62 static void hv_rf_receive_data(rndis_device *device, rndis_msg *message,
63 struct hv_vmbus_channel *chan,
65 static int hv_rf_query_device(rndis_device *device, uint32_t oid,
66 void *result, uint32_t *result_size);
67 static inline int hv_rf_query_device_mac(rndis_device *device);
68 static inline int hv_rf_query_device_link_status(rndis_device *device);
69 static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
70 static int hv_rf_init_device(rndis_device *device);
71 static int hv_rf_open_device(rndis_device *device);
72 static int hv_rf_close_device(rndis_device *device);
73 static void hv_rf_on_send_request_completion(struct hv_vmbus_channel *, void *context);
74 static void hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *, void *context);
76 hv_rf_send_offload_request(struct hv_device *device,
77 rndis_offload_params *offloads);
79 * Set the Per-Packet-Info with the specified type
82 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
85 rndis_packet *rndis_pkt;
86 rndis_per_packet_info *rppi;
88 rndis_pkt = &rndis_mesg->msg.packet;
89 rndis_pkt->data_offset += rppi_size;
91 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
92 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
94 rppi->size = rppi_size;
95 rppi->type = pkt_type;
96 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
98 rndis_pkt->per_pkt_info_length += rppi_size;
104 * Get the Per-Packet-Info with the specified type
105 * return NULL if not found.
108 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
110 rndis_per_packet_info *ppi;
113 if (rpkt->per_pkt_info_offset == 0)
116 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
117 rpkt->per_pkt_info_offset);
118 len = rpkt->per_pkt_info_length;
121 if (ppi->type == type)
122 return (void *)((unsigned long)ppi +
123 ppi->per_packet_info_offset);
126 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
134 * Allow module_param to work and override to switch to promiscuous mode.
136 static inline rndis_device *
137 hv_get_rndis_device(void)
139 rndis_device *device;
141 device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
143 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
145 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
146 STAILQ_INIT(&device->myrequest_list);
148 device->state = RNDIS_DEV_UNINITIALIZED;
157 hv_put_rndis_device(rndis_device *device)
159 mtx_destroy(&device->req_lock);
160 free(device, M_NETVSC);
166 static inline rndis_request *
167 hv_rndis_request(rndis_device *device, uint32_t message_type,
168 uint32_t message_length)
170 rndis_request *request;
171 rndis_msg *rndis_mesg;
172 rndis_set_request *set;
174 request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
176 sema_init(&request->wait_sema, 0, "rndis sema");
178 rndis_mesg = &request->request_msg;
179 rndis_mesg->ndis_msg_type = message_type;
180 rndis_mesg->msg_len = message_length;
183 * Set the request id. This field is always after the rndis header
184 * for request/response packet types so we just use the set_request
187 set = &rndis_mesg->msg.set_request;
188 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
189 /* Increment to get the new value (call above returns old value) */
190 set->request_id += 1;
192 /* Add to the request list */
193 mtx_lock(&device->req_lock);
194 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
195 mtx_unlock(&device->req_lock);
204 hv_put_rndis_request(rndis_device *device, rndis_request *request)
206 mtx_lock(&device->req_lock);
207 /* Fixme: Has O(n) performance */
209 * XXXKYS: Use Doubly linked lists.
211 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
213 mtx_unlock(&device->req_lock);
215 sema_destroy(&request->wait_sema);
216 free(request, M_NETVSC);
223 hv_rf_send_request(rndis_device *device, rndis_request *request,
224 uint32_t message_type)
227 netvsc_packet *packet;
228 netvsc_dev *net_dev = device->net_dev;
229 int send_buf_section_idx;
231 /* Set up the packet to send it */
232 packet = &request->pkt;
234 packet->is_data_pkt = FALSE;
235 packet->tot_data_buf_len = request->request_msg.msg_len;
236 packet->page_buf_count = 1;
238 packet->page_buffers[0].pfn =
239 hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
240 packet->page_buffers[0].length = request->request_msg.msg_len;
241 packet->page_buffers[0].offset =
242 (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
244 if (packet->page_buffers[0].offset +
245 packet->page_buffers[0].length > PAGE_SIZE) {
246 packet->page_buf_count = 2;
247 packet->page_buffers[0].length =
248 PAGE_SIZE - packet->page_buffers[0].offset;
249 packet->page_buffers[1].pfn =
250 hv_get_phys_addr((char*)&request->request_msg +
251 packet->page_buffers[0].length) >> PAGE_SHIFT;
252 packet->page_buffers[1].offset = 0;
253 packet->page_buffers[1].length =
254 request->request_msg.msg_len -
255 packet->page_buffers[0].length;
258 packet->compl.send.send_completion_context = request; /* packet */
259 if (message_type != REMOTE_NDIS_HALT_MSG) {
260 packet->compl.send.on_send_completion =
261 hv_rf_on_send_request_completion;
263 packet->compl.send.on_send_completion =
264 hv_rf_on_send_request_halt_completion;
266 packet->compl.send.send_completion_tid = (unsigned long)device;
267 if (packet->tot_data_buf_len < net_dev->send_section_size) {
268 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
269 if (send_buf_section_idx !=
270 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
271 char *dest = ((char *)net_dev->send_buf +
272 send_buf_section_idx * net_dev->send_section_size);
274 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
275 packet->send_buf_section_idx = send_buf_section_idx;
276 packet->send_buf_section_size = packet->tot_data_buf_len;
277 packet->page_buf_count = 0;
280 /* Failed to allocate chimney send buffer; move on */
282 packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
283 packet->send_buf_section_size = 0;
286 ret = hv_nv_on_send(device->net_dev->dev->channel, packet);
292 * RNDIS filter receive response
295 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
297 rndis_request *request = NULL;
298 rndis_request *next_request;
299 boolean_t found = FALSE;
301 mtx_lock(&device->req_lock);
302 request = STAILQ_FIRST(&device->myrequest_list);
303 while (request != NULL) {
305 * All request/response message contains request_id as the
308 if (request->request_msg.msg.init_request.request_id ==
309 response->msg.init_complete.request_id) {
313 next_request = STAILQ_NEXT(request, mylist_entry);
314 request = next_request;
316 mtx_unlock(&device->req_lock);
319 if (response->msg_len <= sizeof(rndis_msg)) {
320 memcpy(&request->response_msg, response,
323 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
324 /* Does not have a request id field */
325 request->response_msg.msg.reset_complete.status =
326 STATUS_BUFFER_OVERFLOW;
328 request->response_msg.msg.init_complete.status =
329 STATUS_BUFFER_OVERFLOW;
333 sema_post(&request->wait_sema);
338 hv_rf_send_offload_request(struct hv_device *device,
339 rndis_offload_params *offloads)
341 rndis_request *request;
342 rndis_set_request *set;
343 rndis_offload_params *offload_req;
344 rndis_set_complete *set_complete;
345 rndis_device *rndis_dev;
346 hn_softc_t *sc = device_get_softc(device->device);
347 device_t dev = device->device;
348 netvsc_dev *net_dev = sc->net_dev;
349 uint32_t vsp_version = net_dev->nvsp_version;
350 uint32_t extlen = sizeof(rndis_offload_params);
353 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
354 extlen = VERSION_4_OFFLOAD_SIZE;
355 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
356 * UDP checksum offload.
358 offloads->udp_ipv4_csum = 0;
359 offloads->udp_ipv6_csum = 0;
362 rndis_dev = net_dev->extension;
364 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
365 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
369 set = &request->request_msg.msg.set_request;
370 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
371 set->info_buffer_length = extlen;
372 set->info_buffer_offset = sizeof(rndis_set_request);
373 set->device_vc_handle = 0;
375 offload_req = (rndis_offload_params *)((unsigned long)set +
376 set->info_buffer_offset);
377 *offload_req = *offloads;
378 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
379 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
380 offload_req->header.size = extlen;
382 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
384 device_printf(dev, "hv send offload request failed, ret=%d!\n",
389 ret = sema_timedwait(&request->wait_sema, 5 * hz);
391 device_printf(dev, "hv send offload request timeout\n");
395 set_complete = &request->response_msg.msg.set_complete;
396 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
397 device_printf(dev, "hv send offload request succeeded\n");
400 if (set_complete->status == STATUS_NOT_SUPPORTED) {
401 device_printf(dev, "HV Not support offload\n");
404 ret = set_complete->status;
410 hv_put_rndis_request(rndis_dev, request);
416 * RNDIS filter receive indicate status
419 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
421 rndis_indicate_status *indicate = &response->msg.indicate_status;
423 switch(indicate->status) {
424 case RNDIS_STATUS_MEDIA_CONNECT:
425 netvsc_linkstatus_callback(device->net_dev->dev, 1);
427 case RNDIS_STATUS_MEDIA_DISCONNECT:
428 netvsc_linkstatus_callback(device->net_dev->dev, 0);
432 device_printf(device->net_dev->dev->device,
433 "unknown status %d received\n", indicate->status);
439 * RNDIS filter receive data
442 hv_rf_receive_data(rndis_device *device, rndis_msg *message,
443 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
445 rndis_packet *rndis_pkt;
446 ndis_8021q_info *rppi_vlan_info;
447 uint32_t data_offset;
448 rndis_tcp_ip_csum_info *csum_info = NULL;
449 device_t dev = device->net_dev->dev->device;
451 rndis_pkt = &message->msg.packet;
454 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
455 * netvsc packet (ie tot_data_buf_len != message_length)
458 /* Remove rndis header, then pass data packet up the stack */
459 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
461 pkt->tot_data_buf_len -= data_offset;
462 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
463 pkt->status = nvsp_status_failure;
465 "total length %u is less than data length %u\n",
466 pkt->tot_data_buf_len, rndis_pkt->data_length);
470 pkt->tot_data_buf_len = rndis_pkt->data_length;
471 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
473 rppi_vlan_info = hv_get_ppi_data(rndis_pkt, ieee_8021q_info);
474 if (rppi_vlan_info) {
475 pkt->vlan_tci = rppi_vlan_info->u1.s1.vlan_id;
480 csum_info = hv_get_ppi_data(rndis_pkt, tcpip_chksum_info);
481 netvsc_recv(chan, pkt, csum_info);
485 * RNDIS filter on receive
488 hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device,
489 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
491 rndis_device *rndis_dev;
492 rndis_msg *rndis_hdr;
494 /* Make sure the rndis device state is initialized */
495 if (net_dev->extension == NULL) {
496 pkt->status = nvsp_status_failure;
500 rndis_dev = (rndis_device *)net_dev->extension;
501 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
502 pkt->status = nvsp_status_failure;
506 rndis_hdr = pkt->data;
508 switch (rndis_hdr->ndis_msg_type) {
511 case REMOTE_NDIS_PACKET_MSG:
512 hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt);
514 /* completion messages */
515 case REMOTE_NDIS_INITIALIZE_CMPLT:
516 case REMOTE_NDIS_QUERY_CMPLT:
517 case REMOTE_NDIS_SET_CMPLT:
518 case REMOTE_NDIS_RESET_CMPLT:
519 case REMOTE_NDIS_KEEPALIVE_CMPLT:
520 hv_rf_receive_response(rndis_dev, rndis_hdr);
522 /* notification message */
523 case REMOTE_NDIS_INDICATE_STATUS_MSG:
524 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
527 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
528 rndis_hdr->ndis_msg_type);
536 * RNDIS filter query device
539 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
540 uint32_t *result_size)
542 rndis_request *request;
543 uint32_t in_result_size = *result_size;
544 rndis_query_request *query;
545 rndis_query_complete *query_complete;
549 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
550 RNDIS_MESSAGE_SIZE(rndis_query_request));
551 if (request == NULL) {
556 /* Set up the rndis query */
557 query = &request->request_msg.msg.query_request;
559 query->info_buffer_offset = sizeof(rndis_query_request);
560 query->info_buffer_length = 0;
561 query->device_vc_handle = 0;
563 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
564 struct rndis_recv_scale_cap *cap;
566 request->request_msg.msg_len +=
567 sizeof(struct rndis_recv_scale_cap);
568 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
569 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
570 query->info_buffer_offset);
571 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
572 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
573 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
576 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
578 /* Fixme: printf added */
579 printf("RNDISFILTER request failed to Send!\n");
583 sema_wait(&request->wait_sema);
585 /* Copy the response back */
586 query_complete = &request->response_msg.msg.query_complete;
588 if (query_complete->info_buffer_length > in_result_size) {
593 memcpy(result, (void *)((unsigned long)query_complete +
594 query_complete->info_buffer_offset),
595 query_complete->info_buffer_length);
597 *result_size = query_complete->info_buffer_length;
601 hv_put_rndis_request(device, request);
607 * RNDIS filter query device MAC address
610 hv_rf_query_device_mac(rndis_device *device)
612 uint32_t size = HW_MACADDR_LEN;
614 return (hv_rf_query_device(device,
615 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
619 * RNDIS filter query device link status
622 hv_rf_query_device_link_status(rndis_device *device)
624 uint32_t size = sizeof(uint32_t);
626 return (hv_rf_query_device(device,
627 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
630 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
631 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
632 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
633 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
634 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
635 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
639 * RNDIS set vRSS parameters
642 hv_rf_set_rss_param(rndis_device *device, int num_queue)
644 rndis_request *request;
645 rndis_set_request *set;
646 rndis_set_complete *set_complete;
647 rndis_recv_scale_param *rssp;
648 uint32_t extlen = sizeof(rndis_recv_scale_param) +
649 (4 * ITAB_NUM) + HASH_KEYLEN;
650 uint32_t *itab, status;
655 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
656 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
657 if (request == NULL) {
659 printf("Netvsc: No memory to set vRSS parameters.\n");
664 set = &request->request_msg.msg.set_request;
665 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
666 set->info_buffer_length = extlen;
667 set->info_buffer_offset = sizeof(rndis_set_request);
668 set->device_vc_handle = 0;
670 /* Fill out the rssp parameter structure */
671 rssp = (rndis_recv_scale_param *)(set + 1);
672 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
673 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
674 rssp->hdr.size = sizeof(rndis_recv_scale_param);
676 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
677 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
678 rssp->indirect_tabsize = 4 * ITAB_NUM;
679 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
680 rssp->hashkey_size = HASH_KEYLEN;
681 rssp->hashkey_offset = rssp->indirect_taboffset +
682 rssp->indirect_tabsize;
684 /* Set indirection table entries */
685 itab = (uint32_t *)(rssp + 1);
686 for (i = 0; i < ITAB_NUM; i++)
687 itab[i] = i % num_queue;
689 /* Set hash key values */
690 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
691 for (i = 0; i < HASH_KEYLEN; i++)
692 keyp[i] = netvsc_hash_key[i];
694 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
700 * Wait for the response from the host. Another thread will signal
701 * us when the response has arrived. In the failure case,
702 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
704 ret = sema_timedwait(&request->wait_sema, 5 * hz);
706 /* Response received, check status */
707 set_complete = &request->response_msg.msg.set_complete;
708 status = set_complete->status;
709 if (status != RNDIS_STATUS_SUCCESS) {
710 /* Bad response status, return error */
712 printf("Netvsc: Failed to set vRSS "
717 printf("Netvsc: Successfully set vRSS "
722 * We cannot deallocate the request since we may still
723 * receive a send completion for it.
725 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
726 request->request_msg.msg.init_request.request_id, ret);
731 if (request != NULL) {
732 hv_put_rndis_request(device, request);
739 * RNDIS filter set packet filter
740 * Sends an rndis request with the new filter, then waits for a response
742 * Returns zero on success, non-zero on failure.
745 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
747 rndis_request *request;
748 rndis_set_request *set;
749 rndis_set_complete *set_complete;
753 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
754 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
755 if (request == NULL) {
760 /* Set up the rndis set */
761 set = &request->request_msg.msg.set_request;
762 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
763 set->info_buffer_length = sizeof(uint32_t);
764 set->info_buffer_offset = sizeof(rndis_set_request);
766 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
767 &new_filter, sizeof(uint32_t));
769 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
775 * Wait for the response from the host. Another thread will signal
776 * us when the response has arrived. In the failure case,
777 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
779 ret = sema_timedwait(&request->wait_sema, 5 * hz);
781 /* Response received, check status */
782 set_complete = &request->response_msg.msg.set_complete;
783 status = set_complete->status;
784 if (status != RNDIS_STATUS_SUCCESS) {
785 /* Bad response status, return error */
790 * We cannot deallocate the request since we may still
791 * receive a send completion for it.
797 if (request != NULL) {
798 hv_put_rndis_request(device, request);
805 * RNDIS filter init device
808 hv_rf_init_device(rndis_device *device)
810 rndis_request *request;
811 rndis_initialize_request *init;
812 rndis_initialize_complete *init_complete;
816 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
817 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
823 /* Set up the rndis set */
824 init = &request->request_msg.msg.init_request;
825 init->major_version = RNDIS_MAJOR_VERSION;
826 init->minor_version = RNDIS_MINOR_VERSION;
828 * Per the RNDIS document, this should be set to the max MTU
829 * plus the header size. However, 2048 works fine, so leaving
832 init->max_xfer_size = 2048;
834 device->state = RNDIS_DEV_INITIALIZING;
836 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
838 device->state = RNDIS_DEV_UNINITIALIZED;
842 sema_wait(&request->wait_sema);
844 init_complete = &request->response_msg.msg.init_complete;
845 status = init_complete->status;
846 if (status == RNDIS_STATUS_SUCCESS) {
847 device->state = RNDIS_DEV_INITIALIZED;
850 device->state = RNDIS_DEV_UNINITIALIZED;
856 hv_put_rndis_request(device, request);
862 #define HALT_COMPLETION_WAIT_COUNT 25
865 * RNDIS filter halt device
868 hv_rf_halt_device(rndis_device *device)
870 rndis_request *request;
871 rndis_halt_request *halt;
874 /* Attempt to do a rndis device halt */
875 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
876 RNDIS_MESSAGE_SIZE(rndis_halt_request));
877 if (request == NULL) {
881 /* initialize "poor man's semaphore" */
882 request->halt_complete_flag = 0;
884 /* Set up the rndis set */
885 halt = &request->request_msg.msg.halt_request;
886 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
887 /* Increment to get the new value (call above returns old value) */
888 halt->request_id += 1;
890 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
896 * Wait for halt response from halt callback. We must wait for
897 * the transaction response before freeing the request and other
900 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
901 if (request->halt_complete_flag != 0) {
910 device->state = RNDIS_DEV_UNINITIALIZED;
912 if (request != NULL) {
913 hv_put_rndis_request(device, request);
920 * RNDIS filter open device
923 hv_rf_open_device(rndis_device *device)
927 if (device->state != RNDIS_DEV_INITIALIZED) {
931 if (hv_promisc_mode != 1) {
932 ret = hv_rf_set_packet_filter(device,
933 NDIS_PACKET_TYPE_BROADCAST |
934 NDIS_PACKET_TYPE_ALL_MULTICAST |
935 NDIS_PACKET_TYPE_DIRECTED);
937 ret = hv_rf_set_packet_filter(device,
938 NDIS_PACKET_TYPE_PROMISCUOUS);
942 device->state = RNDIS_DEV_DATAINITIALIZED;
949 * RNDIS filter close device
952 hv_rf_close_device(rndis_device *device)
956 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
960 ret = hv_rf_set_packet_filter(device, 0);
962 device->state = RNDIS_DEV_INITIALIZED;
969 * RNDIS filter on device add
972 hv_rf_on_device_add(struct hv_device *device, void *additl_info,
977 rndis_device *rndis_dev;
979 rndis_offload_params offloads;
980 struct rndis_recv_scale_cap rsscaps;
981 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
982 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
983 device_t dev = device->device;
985 rndis_dev = hv_get_rndis_device();
986 if (rndis_dev == NULL) {
991 * Let the inner driver handle this first to create the netvsc channel
992 * NOTE! Once the channel is created, we may get a receive callback
993 * (hv_rf_on_receive()) before this call is completed.
994 * Note: Earlier code used a function pointer here.
996 net_dev = hv_nv_on_device_add(device, additl_info);
998 hv_put_rndis_device(rndis_dev);
1004 * Initialize the rndis device
1007 net_dev->extension = rndis_dev;
1008 rndis_dev->net_dev = net_dev;
1010 /* Send the rndis initialization message */
1011 ret = hv_rf_init_device(rndis_dev);
1014 * TODO: If rndis init failed, we will need to shut down
1019 /* Get the mac address */
1020 ret = hv_rf_query_device_mac(rndis_dev);
1022 /* TODO: shut down rndis device and the channel */
1025 /* config csum offload and send request to host */
1026 memset(&offloads, 0, sizeof(offloads));
1027 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1028 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1029 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1030 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1031 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1032 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1034 ret = hv_rf_send_offload_request(device, &offloads);
1036 /* TODO: shut down rndis device and the channel */
1038 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1041 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
1043 hv_rf_query_device_link_status(rndis_dev);
1045 dev_info->link_state = rndis_dev->link_status;
1047 net_dev->num_channel = 1;
1048 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1051 memset(&rsscaps, 0, rsscaps_size);
1052 ret = hv_rf_query_device(rndis_dev,
1053 RNDIS_OID_GEN_RSS_CAPABILITIES,
1054 &rsscaps, &rsscaps_size);
1055 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1056 device_printf(dev, "hv_rf_query_device failed or "
1057 "rsscaps.num_recv_que < 2 \n");
1060 device_printf(dev, "channel, offered %u, requested %d\n",
1061 rsscaps.num_recv_que, nchan);
1062 if (nchan > rsscaps.num_recv_que)
1063 nchan = rsscaps.num_recv_que;
1064 net_dev->num_channel = nchan;
1066 if (net_dev->num_channel == 1) {
1067 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1071 /* request host to create sub channels */
1072 init_pkt = &net_dev->channel_init_packet;
1073 memset(init_pkt, 0, sizeof(nvsp_msg));
1075 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1076 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1077 NVSP_SUBCHANNE_ALLOCATE;
1078 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1079 net_dev->num_channel - 1;
1081 ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
1082 sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
1083 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
1084 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1086 device_printf(dev, "Fail to allocate subchannel\n");
1090 sema_wait(&net_dev->channel_init_sema);
1092 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1093 nvsp_status_success) {
1095 device_printf(dev, "sub channel complete error\n");
1099 net_dev->num_channel = 1 +
1100 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1102 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1106 net_dev->num_channel = 1;
1112 * RNDIS filter on device remove
1115 hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel)
1117 hn_softc_t *sc = device_get_softc(device->device);
1118 netvsc_dev *net_dev = sc->net_dev;
1119 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1122 /* Halt and release the rndis device */
1123 ret = hv_rf_halt_device(rndis_dev);
1125 hv_put_rndis_device(rndis_dev);
1126 net_dev->extension = NULL;
1128 /* Pass control to inner driver to remove the device */
1129 ret |= hv_nv_on_device_remove(device, destroy_channel);
1135 * RNDIS filter on open
1138 hv_rf_on_open(struct hv_device *device)
1140 hn_softc_t *sc = device_get_softc(device->device);
1141 netvsc_dev *net_dev = sc->net_dev;
1143 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1147 * RNDIS filter on close
1150 hv_rf_on_close(struct hv_device *device)
1152 hn_softc_t *sc = device_get_softc(device->device);
1153 netvsc_dev *net_dev = sc->net_dev;
1155 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1159 * RNDIS filter on send request completion callback
1162 hv_rf_on_send_request_completion(struct hv_vmbus_channel *chan __unused,
1163 void *context __unused)
1168 * RNDIS filter on send request (halt only) completion callback
1171 hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused,
1174 rndis_request *request = context;
1177 * Notify hv_rf_halt_device() about halt completion.
1178 * The halt code must wait for completion before freeing
1179 * the transaction resources.
1181 request->halt_complete_flag = 1;
1185 hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
1188 netvsc_channel_rollup(chan);