]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/hyperv/netvsc/hv_rndis_filter.c
MFC 304783-304785
[FreeBSD/stable/10.git] / sys / dev / hyperv / netvsc / hv_rndis_filter.c
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
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/mbuf.h>
35 #include <sys/socket.h>
36 #include <sys/lock.h>
37 #include <sys/mutex.h>
38 #include <net/if.h>
39 #include <net/if_arp.h>
40 #include <net/if_var.h>
41 #include <net/ethernet.h>
42 #include <sys/types.h>
43 #include <machine/atomic.h>
44 #include <sys/sema.h>
45 #include <vm/vm.h>
46 #include <vm/vm_param.h>
47 #include <vm/pmap.h>
48
49 #include <dev/hyperv/include/hyperv.h>
50 #include <dev/hyperv/include/vmbus_xact.h>
51 #include <dev/hyperv/netvsc/hv_net_vsc.h>
52 #include <dev/hyperv/netvsc/hv_rndis.h>
53 #include <dev/hyperv/netvsc/hv_rndis_filter.h>
54 #include <dev/hyperv/netvsc/if_hnreg.h>
55
56 #define HV_RF_RECVINFO_VLAN     0x1
57 #define HV_RF_RECVINFO_CSUM     0x2
58 #define HV_RF_RECVINFO_HASHINF  0x4
59 #define HV_RF_RECVINFO_HASHVAL  0x8
60 #define HV_RF_RECVINFO_ALL              \
61         (HV_RF_RECVINFO_VLAN |          \
62          HV_RF_RECVINFO_CSUM |          \
63          HV_RF_RECVINFO_HASHINF |       \
64          HV_RF_RECVINFO_HASHVAL)
65
66 #define HN_RNDIS_RID_COMPAT_MASK        0xffff
67 #define HN_RNDIS_RID_COMPAT_MAX         HN_RNDIS_RID_COMPAT_MASK
68
69 #define HN_RNDIS_XFER_SIZE              2048
70
71 /*
72  * Forward declarations
73  */
74 static int  hv_rf_send_request(rndis_device *device, rndis_request *request,
75                                uint32_t message_type);
76 static void hv_rf_receive_response(rndis_device *device,
77     const rndis_msg *response);
78 static void hv_rf_receive_indicate_status(rndis_device *device,
79     const rndis_msg *response);
80 static void hv_rf_receive_data(struct hn_rx_ring *rxr,
81     const void *data, int dlen);
82 static int  hv_rf_query_device(rndis_device *device, uint32_t oid,
83                                void *result, uint32_t *result_size);
84 static inline int hv_rf_query_device_mac(rndis_device *device);
85 static inline int hv_rf_query_device_link_status(rndis_device *device);
86 static int  hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
87 static int  hv_rf_init_device(rndis_device *device);
88 static int  hv_rf_open_device(rndis_device *device);
89 static int  hv_rf_close_device(rndis_device *device);
90 int
91 hv_rf_send_offload_request(struct hn_softc *sc,
92     rndis_offload_params *offloads);
93
94 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
95     struct hn_softc *sc, struct vmbus_channel *chan,
96     const void *data, int dlen);
97 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
98     struct hn_softc *sc, struct vmbus_channel *chan,
99     const void *data, int dlen);
100
101 static __inline uint32_t
102 hn_rndis_rid(struct hn_softc *sc)
103 {
104         uint32_t rid;
105
106 again:
107         rid = atomic_fetchadd_int(&sc->hn_rndis_rid, 1);
108         if (rid == 0)
109                 goto again;
110
111         /* Use upper 16 bits for non-compat RNDIS messages. */
112         return ((rid & 0xffff) << 16);
113 }
114
115 /*
116  * Set the Per-Packet-Info with the specified type
117  */
118 void *
119 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
120         int pkt_type)
121 {
122         rndis_packet *rndis_pkt;
123         rndis_per_packet_info *rppi;
124
125         rndis_pkt = &rndis_mesg->msg.packet;
126         rndis_pkt->data_offset += rppi_size;
127
128         rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
129             rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
130
131         rppi->size = rppi_size;
132         rppi->type = pkt_type;
133         rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
134
135         rndis_pkt->per_pkt_info_length += rppi_size;
136
137         return (rppi);
138 }
139
140 /*
141  * Get the Per-Packet-Info with the specified type
142  * return NULL if not found.
143  */
144 void *
145 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
146 {
147         rndis_per_packet_info *ppi;
148         int len;
149
150         if (rpkt->per_pkt_info_offset == 0)
151                 return (NULL);
152
153         ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
154             rpkt->per_pkt_info_offset);
155         len = rpkt->per_pkt_info_length;
156
157         while (len > 0) {
158                 if (ppi->type == type)
159                         return (void *)((unsigned long)ppi +
160                             ppi->per_packet_info_offset);
161
162                 len -= ppi->size;
163                 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
164         }
165
166         return (NULL);
167 }
168
169
170 /*
171  * Allow module_param to work and override to switch to promiscuous mode.
172  */
173 static inline rndis_device *
174 hv_get_rndis_device(void)
175 {
176         rndis_device *device;
177
178         device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
179
180         mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
181
182         /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
183         STAILQ_INIT(&device->myrequest_list);
184
185         device->state = RNDIS_DEV_UNINITIALIZED;
186
187         return (device);
188 }
189
190 /*
191  *
192  */
193 static inline void
194 hv_put_rndis_device(rndis_device *device)
195 {
196         mtx_destroy(&device->req_lock);
197         free(device, M_NETVSC);
198 }
199
200 /*
201  *
202  */
203 static inline rndis_request *
204 hv_rndis_request(rndis_device *device, uint32_t message_type,
205                  uint32_t message_length)
206 {
207         rndis_request *request;
208         rndis_msg *rndis_mesg;
209         rndis_set_request *set;
210
211         request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
212
213         sema_init(&request->wait_sema, 0, "rndis sema");
214         
215         rndis_mesg = &request->request_msg;
216         rndis_mesg->ndis_msg_type = message_type;
217         rndis_mesg->msg_len = message_length;
218
219         /*
220          * Set the request id. This field is always after the rndis header
221          * for request/response packet types so we just use the set_request
222          * as a template.
223          */
224         set = &rndis_mesg->msg.set_request;
225         set->request_id = atomic_fetchadd_int(&device->new_request_id, 1) &
226             HN_RNDIS_RID_COMPAT_MASK;
227
228         /* Add to the request list */
229         mtx_lock(&device->req_lock);
230         STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
231         mtx_unlock(&device->req_lock);
232
233         return (request);
234 }
235
236 /*
237  *
238  */
239 static inline void
240 hv_put_rndis_request(rndis_device *device, rndis_request *request)
241 {
242         mtx_lock(&device->req_lock);
243         /* Fixme:  Has O(n) performance */
244         /*
245          * XXXKYS: Use Doubly linked lists.
246          */
247         STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
248             mylist_entry);
249         mtx_unlock(&device->req_lock);
250
251         sema_destroy(&request->wait_sema);
252         free(request, M_NETVSC);
253 }
254
255 /*
256  *
257  */
258 static int
259 hv_rf_send_request(rndis_device *device, rndis_request *request,
260     uint32_t message_type)
261 {
262         struct hn_softc *sc = device->sc;
263         uint32_t send_buf_section_idx, tot_data_buf_len;
264         struct vmbus_gpa gpa[2];
265         int gpa_cnt, send_buf_section_size;
266         hn_sent_callback_t cb;
267
268         /* Set up the packet to send it */
269         tot_data_buf_len = request->request_msg.msg_len;
270
271         gpa_cnt = 1;
272         gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
273         gpa[0].gpa_len = request->request_msg.msg_len;
274         gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
275
276         if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) {
277                 gpa_cnt = 2;
278                 gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs;
279                 gpa[1].gpa_page =
280                     hv_get_phys_addr((char*)&request->request_msg +
281                     gpa[0].gpa_len) >> PAGE_SHIFT;
282                 gpa[1].gpa_ofs = 0;
283                 gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
284         }
285
286         if (message_type != REMOTE_NDIS_HALT_MSG)
287                 cb = hn_rndis_sent_cb;
288         else
289                 cb = hn_rndis_sent_halt;
290
291         if (tot_data_buf_len < sc->hn_chim_szmax) {
292                 send_buf_section_idx = hn_chim_alloc(sc);
293                 if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) {
294                         uint8_t *dest = sc->hn_chim +
295                                 (send_buf_section_idx * sc->hn_chim_szmax);
296
297                         memcpy(dest, &request->request_msg, request->request_msg.msg_len);
298                         send_buf_section_size = tot_data_buf_len;
299                         gpa_cnt = 0;
300                         goto sendit;
301                 }
302                 /* Failed to allocate chimney send buffer; move on */
303         }
304         send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID;
305         send_buf_section_size = 0;
306
307 sendit:
308         hn_send_ctx_init(&request->send_ctx, cb, request,
309             send_buf_section_idx, send_buf_section_size);
310         return hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
311             &request->send_ctx, gpa, gpa_cnt);
312 }
313
314 /*
315  * RNDIS filter receive response
316  */
317 static void 
318 hv_rf_receive_response(rndis_device *device, const rndis_msg *response)
319 {
320         rndis_request *request = NULL;
321         rndis_request *next_request;
322         boolean_t found = FALSE;
323
324         mtx_lock(&device->req_lock);
325         request = STAILQ_FIRST(&device->myrequest_list);
326         while (request != NULL) {
327                 /*
328                  * All request/response message contains request_id as the
329                  * first field
330                  */
331                 if (request->request_msg.msg.init_request.request_id ==
332                                       response->msg.init_complete.request_id) {
333                         found = TRUE;
334                         break;
335                 }
336                 next_request = STAILQ_NEXT(request, mylist_entry);
337                 request = next_request;
338         }
339         mtx_unlock(&device->req_lock);
340
341         if (found) {
342                 if (response->msg_len <= sizeof(rndis_msg)) {
343                         memcpy(&request->response_msg, response,
344                             response->msg_len);
345                 } else {
346                         request->response_msg.msg.init_complete.status =
347                             RNDIS_STATUS_BUFFER_OVERFLOW;
348                 }
349                 sema_post(&request->wait_sema);
350         }
351 }
352
353 int
354 hv_rf_send_offload_request(struct hn_softc *sc,
355     rndis_offload_params *offloads)
356 {
357         rndis_request *request;
358         rndis_set_request *set;
359         rndis_offload_params *offload_req;
360         rndis_set_complete *set_complete;       
361         rndis_device *rndis_dev = sc->rndis_dev;
362         device_t dev = sc->hn_dev;
363         uint32_t extlen = sizeof(rndis_offload_params);
364         int ret;
365
366         if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) {
367                 extlen = VERSION_4_OFFLOAD_SIZE;
368                 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
369                  * UDP checksum offload.
370                  */
371                 offloads->udp_ipv4_csum = 0;
372                 offloads->udp_ipv6_csum = 0;
373         }
374
375         request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
376             RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
377         if (!request)
378                 return (ENOMEM);
379
380         set = &request->request_msg.msg.set_request;
381         set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
382         set->info_buffer_length = extlen;
383         set->info_buffer_offset = sizeof(rndis_set_request);
384         set->device_vc_handle = 0;
385
386         offload_req = (rndis_offload_params *)((unsigned long)set +
387             set->info_buffer_offset);
388         *offload_req = *offloads;
389         offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
390         offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
391         offload_req->header.size = extlen;
392
393         ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
394         if (ret != 0) {
395                 device_printf(dev, "hv send offload request failed, ret=%d!\n",
396                     ret);
397                 goto cleanup;
398         }
399
400         ret = sema_timedwait(&request->wait_sema, 5 * hz);
401         if (ret != 0) {
402                 device_printf(dev, "hv send offload request timeout\n");
403                 goto cleanup;
404         }
405
406         set_complete = &request->response_msg.msg.set_complete;
407         if (set_complete->status == RNDIS_STATUS_SUCCESS) {
408                 device_printf(dev, "hv send offload request succeeded\n");
409                 ret = 0;
410         } else {
411                 if (set_complete->status == RNDIS_STATUS_NOT_SUPPORTED) {
412                         device_printf(dev, "HV Not support offload\n");
413                         ret = 0;
414                 } else {
415                         ret = set_complete->status;
416                 }
417         }
418
419 cleanup:
420         hv_put_rndis_request(rndis_dev, request);
421
422         return (ret);
423 }
424
425 /*
426  * RNDIS filter receive indicate status
427  */
428 static void 
429 hv_rf_receive_indicate_status(rndis_device *device, const rndis_msg *response)
430 {
431         const rndis_indicate_status *indicate = &response->msg.indicate_status;
432                 
433         switch(indicate->status) {
434         case RNDIS_STATUS_MEDIA_CONNECT:
435                 netvsc_linkstatus_callback(device->sc, 1);
436                 break;
437         case RNDIS_STATUS_MEDIA_DISCONNECT:
438                 netvsc_linkstatus_callback(device->sc, 0);
439                 break;
440         default:
441                 /* TODO: */
442                 device_printf(device->sc->hn_dev,
443                     "unknown status %d received\n", indicate->status);
444                 break;
445         }
446 }
447
448 static int
449 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
450 {
451         const rndis_per_packet_info *ppi;
452         uint32_t mask, len;
453
454         info->vlan_info = NULL;
455         info->csum_info = NULL;
456         info->hash_info = NULL;
457         info->hash_value = NULL;
458
459         if (rpkt->per_pkt_info_offset == 0)
460                 return 0;
461
462         ppi = (const rndis_per_packet_info *)
463             ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
464         len = rpkt->per_pkt_info_length;
465         mask = 0;
466
467         while (len != 0) {
468                 const void *ppi_dptr;
469                 uint32_t ppi_dlen;
470
471                 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
472                         return EINVAL;
473                 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
474                 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
475
476                 switch (ppi->type) {
477                 case ieee_8021q_info:
478                         if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
479                                 return EINVAL;
480                         info->vlan_info = ppi_dptr;
481                         mask |= HV_RF_RECVINFO_VLAN;
482                         break;
483
484                 case tcpip_chksum_info:
485                         if (__predict_false(ppi_dlen <
486                             sizeof(rndis_tcp_ip_csum_info)))
487                                 return EINVAL;
488                         info->csum_info = ppi_dptr;
489                         mask |= HV_RF_RECVINFO_CSUM;
490                         break;
491
492                 case nbl_hash_value:
493                         if (__predict_false(ppi_dlen <
494                             sizeof(struct rndis_hash_value)))
495                                 return EINVAL;
496                         info->hash_value = ppi_dptr;
497                         mask |= HV_RF_RECVINFO_HASHVAL;
498                         break;
499
500                 case nbl_hash_info:
501                         if (__predict_false(ppi_dlen <
502                             sizeof(struct rndis_hash_info)))
503                                 return EINVAL;
504                         info->hash_info = ppi_dptr;
505                         mask |= HV_RF_RECVINFO_HASHINF;
506                         break;
507
508                 default:
509                         goto skip;
510                 }
511
512                 if (mask == HV_RF_RECVINFO_ALL) {
513                         /* All found; done */
514                         break;
515                 }
516 skip:
517                 if (__predict_false(len < ppi->size))
518                         return EINVAL;
519                 len -= ppi->size;
520                 ppi = (const rndis_per_packet_info *)
521                     ((const uint8_t *)ppi + ppi->size);
522         }
523         return 0;
524 }
525
526 /*
527  * RNDIS filter receive data
528  */
529 static void
530 hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen)
531 {
532         const rndis_msg *message = data;
533         const rndis_packet *rndis_pkt;
534         uint32_t data_offset;
535         struct hn_recvinfo info;
536
537         rndis_pkt = &message->msg.packet;
538
539         /*
540          * Fixme:  Handle multiple rndis pkt msgs that may be enclosed in this
541          * netvsc packet (ie tot_data_buf_len != message_length)
542          */
543
544         /* Remove rndis header, then pass data packet up the stack */
545         data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
546
547         dlen -= data_offset;
548         if (dlen < rndis_pkt->data_length) {
549                 if_printf(rxr->hn_ifp,
550                     "total length %u is less than data length %u\n",
551                     dlen, rndis_pkt->data_length);
552                 return;
553         }
554
555         dlen = rndis_pkt->data_length;
556         data = (const uint8_t *)data + data_offset;
557
558         if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
559                 if_printf(rxr->hn_ifp, "recvinfo parsing failed\n");
560                 return;
561         }
562         netvsc_recv(rxr, data, dlen, &info);
563 }
564
565 /*
566  * RNDIS filter on receive
567  */
568 int
569 hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
570     const void *data, int dlen)
571 {
572         rndis_device *rndis_dev;
573         const rndis_msg *rndis_hdr;
574         const struct rndis_comp_hdr *comp;
575
576         rndis_dev = sc->rndis_dev;
577         if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED)
578                 return (EINVAL);
579
580         rndis_hdr = data;
581         switch (rndis_hdr->ndis_msg_type) {
582         /* data message */
583         case REMOTE_NDIS_PACKET_MSG:
584                 hv_rf_receive_data(rxr, data, dlen);
585                 break;
586
587         /* completion messages */
588         case REMOTE_NDIS_INITIALIZE_CMPLT:
589         case REMOTE_NDIS_QUERY_CMPLT:
590         case REMOTE_NDIS_SET_CMPLT:
591         case REMOTE_NDIS_KEEPALIVE_CMPLT:
592                 comp = data;
593                 if (comp->rm_rid <= HN_RNDIS_RID_COMPAT_MAX) {
594                         /* Transition time compat code */
595                         hv_rf_receive_response(rndis_dev, rndis_hdr);
596                 } else {
597                         vmbus_xact_ctx_wakeup(sc->hn_xact, data, dlen);
598                 }
599                 break;
600
601         /* notification message */
602         case REMOTE_NDIS_INDICATE_STATUS_MSG:
603                 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
604                 break;
605
606         case REMOTE_NDIS_RESET_CMPLT:
607                 /*
608                  * Reset completed, no rid.
609                  *
610                  * NOTE:
611                  * RESET is not issued by hn(4), so this message should
612                  * _not_ be observed.
613                  */
614                 if_printf(sc->hn_ifp, "RESET CMPLT received\n");
615                 break;
616
617         default:
618                 if_printf(sc->hn_ifp, "unknown RNDIS message 0x%x\n",
619                         rndis_hdr->ndis_msg_type);
620                 break;
621         }
622         return (0);
623 }
624
625 /*
626  * RNDIS filter query device
627  */
628 static int
629 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
630                    uint32_t *result_size)
631 {
632         rndis_request *request;
633         uint32_t in_result_size = *result_size;
634         rndis_query_request *query;
635         rndis_query_complete *query_complete;
636         int ret = 0;
637
638         *result_size = 0;
639         request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
640             RNDIS_MESSAGE_SIZE(rndis_query_request));
641         if (request == NULL) {
642                 ret = -1;
643                 goto cleanup;
644         }
645
646         /* Set up the rndis query */
647         query = &request->request_msg.msg.query_request;
648         query->oid = oid;
649         query->info_buffer_offset = sizeof(rndis_query_request); 
650         query->info_buffer_length = 0;
651         query->device_vc_handle = 0;
652
653         if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
654                 struct rndis_recv_scale_cap *cap;
655
656                 request->request_msg.msg_len += 
657                         sizeof(struct rndis_recv_scale_cap);
658                 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
659                 cap = (struct rndis_recv_scale_cap *)((unsigned long)query + 
660                                                 query->info_buffer_offset);
661                 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
662                 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
663                 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
664         }
665
666         ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
667         if (ret != 0) {
668                 /* Fixme:  printf added */
669                 printf("RNDISFILTER request failed to Send!\n");
670                 goto cleanup;
671         }
672
673         sema_wait(&request->wait_sema);
674
675         /* Copy the response back */
676         query_complete = &request->response_msg.msg.query_complete;
677         
678         if (query_complete->info_buffer_length > in_result_size) {
679                 ret = EINVAL;
680                 goto cleanup;
681         }
682
683         memcpy(result, (void *)((unsigned long)query_complete +
684             query_complete->info_buffer_offset),
685             query_complete->info_buffer_length);
686
687         *result_size = query_complete->info_buffer_length;
688
689 cleanup:
690         if (request != NULL)
691                 hv_put_rndis_request(device, request);
692
693         return (ret);
694 }
695
696 /*
697  * RNDIS filter query device MAC address
698  */
699 static inline int
700 hv_rf_query_device_mac(rndis_device *device)
701 {
702         uint32_t size = ETHER_ADDR_LEN;
703
704         return (hv_rf_query_device(device,
705             RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
706 }
707
708 /*
709  * RNDIS filter query device link status
710  */
711 static inline int
712 hv_rf_query_device_link_status(rndis_device *device)
713 {
714         uint32_t size = sizeof(uint32_t);
715
716         return (hv_rf_query_device(device,
717             RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
718 }
719
720 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
721         0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
722         0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
723         0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
724         0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
725         0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
726 };
727
728 /*
729  * RNDIS set vRSS parameters
730  */
731 static int
732 hv_rf_set_rss_param(rndis_device *device, int num_queue)
733 {
734         rndis_request *request;
735         rndis_set_request *set;
736         rndis_set_complete *set_complete;
737         rndis_recv_scale_param *rssp;
738         uint32_t extlen = sizeof(rndis_recv_scale_param) +
739             (4 * ITAB_NUM) + HASH_KEYLEN;
740         uint32_t *itab, status;
741         uint8_t *keyp;
742         int i, ret;
743
744
745         request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
746             RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
747         if (request == NULL) {
748                 if (bootverbose)
749                         printf("Netvsc: No memory to set vRSS parameters.\n");
750                 ret = -1;
751                 goto cleanup;
752         }
753
754         set = &request->request_msg.msg.set_request;
755         set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
756         set->info_buffer_length = extlen;
757         set->info_buffer_offset = sizeof(rndis_set_request);
758         set->device_vc_handle = 0;
759
760         /* Fill out the rssp parameter structure */
761         rssp = (rndis_recv_scale_param *)(set + 1);
762         rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
763         rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
764         rssp->hdr.size = sizeof(rndis_recv_scale_param);
765         rssp->flag = 0;
766         rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
767             RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
768         rssp->indirect_tabsize = 4 * ITAB_NUM;
769         rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
770         rssp->hashkey_size = HASH_KEYLEN;
771         rssp->hashkey_offset = rssp->indirect_taboffset +
772             rssp->indirect_tabsize;
773
774         /* Set indirection table entries */
775         itab = (uint32_t *)(rssp + 1);
776         for (i = 0; i < ITAB_NUM; i++)
777                 itab[i] = i % num_queue;
778
779         /* Set hash key values */
780         keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
781         for (i = 0; i < HASH_KEYLEN; i++)
782                 keyp[i] = netvsc_hash_key[i];
783
784         ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
785         if (ret != 0) {
786                 goto cleanup;
787         }
788
789         /*
790          * Wait for the response from the host.  Another thread will signal
791          * us when the response has arrived.  In the failure case,
792          * sema_timedwait() returns a non-zero status after waiting 5 seconds.
793          */
794         ret = sema_timedwait(&request->wait_sema, 5 * hz);
795         if (ret == 0) {
796                 /* Response received, check status */
797                 set_complete = &request->response_msg.msg.set_complete;
798                 status = set_complete->status;
799                 if (status != RNDIS_STATUS_SUCCESS) {
800                         /* Bad response status, return error */
801                         if (bootverbose)
802                                 printf("Netvsc: Failed to set vRSS "
803                                     "parameters.\n");
804                         ret = -2;
805                 } else {
806                         if (bootverbose)
807                                 printf("Netvsc: Successfully set vRSS "
808                                     "parameters.\n");
809                 }
810         } else {
811                 /*
812                  * We cannot deallocate the request since we may still
813                  * receive a send completion for it.
814                  */
815                 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
816                     request->request_msg.msg.init_request.request_id, ret);
817                 goto exit;
818         }
819
820 cleanup:
821         if (request != NULL) {
822                 hv_put_rndis_request(device, request);
823         }
824 exit:
825         return (ret);
826 }
827
828 /*
829  * RNDIS filter set packet filter
830  * Sends an rndis request with the new filter, then waits for a response
831  * from the host.
832  * Returns zero on success, non-zero on failure.
833  */
834 static int
835 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
836 {
837         rndis_request *request;
838         rndis_set_request *set;
839         rndis_set_complete *set_complete;
840         uint32_t status;
841         int ret;
842
843         request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
844             RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
845         if (request == NULL) {
846                 ret = -1;
847                 goto cleanup;
848         }
849
850         /* Set up the rndis set */
851         set = &request->request_msg.msg.set_request;
852         set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
853         set->info_buffer_length = sizeof(uint32_t);
854         set->info_buffer_offset = sizeof(rndis_set_request); 
855
856         memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
857             &new_filter, sizeof(uint32_t));
858
859         ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
860         if (ret != 0) {
861                 goto cleanup;
862         }
863
864         /*
865          * Wait for the response from the host.  Another thread will signal
866          * us when the response has arrived.  In the failure case,
867          * sema_timedwait() returns a non-zero status after waiting 5 seconds.
868          */
869         ret = sema_timedwait(&request->wait_sema, 5 * hz);
870         if (ret == 0) {
871                 /* Response received, check status */
872                 set_complete = &request->response_msg.msg.set_complete;
873                 status = set_complete->status;
874                 if (status != RNDIS_STATUS_SUCCESS) {
875                         /* Bad response status, return error */
876                         ret = -2;
877                 }
878         } else {
879                 /*
880                  * We cannot deallocate the request since we may still
881                  * receive a send completion for it.
882                  */
883                 goto exit;
884         }
885
886 cleanup:
887         if (request != NULL) {
888                 hv_put_rndis_request(device, request);
889         }
890 exit:
891         return (ret);
892 }
893
894 static const void *
895 hn_rndis_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, uint32_t rid,
896     size_t reqlen, size_t min_complen, uint32_t comp_type)
897 {
898         struct vmbus_gpa gpa[HN_XACT_REQ_PGCNT];
899         const struct rndis_comp_hdr *comp;
900         bus_addr_t paddr;
901         size_t comp_len;
902         int gpa_cnt, error;
903
904         KASSERT(rid > HN_RNDIS_RID_COMPAT_MAX, ("invalid rid %u\n", rid));
905         KASSERT(reqlen <= HN_XACT_REQ_SIZE && reqlen > 0,
906             ("invalid request length %zu", reqlen));
907         KASSERT(min_complen >= sizeof(*comp),
908             ("invalid minimum complete len %zu", min_complen));
909
910         /*
911          * Setup the SG list.
912          */
913         paddr = vmbus_xact_req_paddr(xact);
914         KASSERT((paddr & PAGE_MASK) == 0,
915             ("vmbus xact request is not page aligned 0x%jx", (uintmax_t)paddr));
916         for (gpa_cnt = 0; gpa_cnt < HN_XACT_REQ_PGCNT; ++gpa_cnt) {
917                 int len = PAGE_SIZE;
918
919                 if (reqlen == 0)
920                         break;
921                 if (reqlen < len)
922                         len = reqlen;
923
924                 gpa[gpa_cnt].gpa_page = atop(paddr) + gpa_cnt;
925                 gpa[gpa_cnt].gpa_len = len;
926                 gpa[gpa_cnt].gpa_ofs = 0;
927
928                 reqlen -= len;
929         }
930         KASSERT(reqlen == 0, ("still have %zu request data left", reqlen));
931
932         /*
933          * Send this RNDIS control message and wait for its completion
934          * message.
935          */
936         vmbus_xact_activate(xact);
937         error = hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
938             &hn_send_ctx_none, gpa, gpa_cnt);
939         if (error) {
940                 vmbus_xact_deactivate(xact);
941                 if_printf(sc->hn_ifp, "RNDIS ctrl send failed: %d\n", error);
942                 return (NULL);
943         }
944         comp = vmbus_xact_wait(xact, &comp_len);
945
946         /*
947          * Check this RNDIS complete message.
948          */
949         if (comp_len < min_complen) {
950                 if_printf(sc->hn_ifp, "invalid RNDIS comp len %zu\n", comp_len);
951                 return (NULL);
952         }
953         if (comp->rm_len < min_complen) {
954                 if_printf(sc->hn_ifp, "invalid RNDIS comp msglen %u\n",
955                     comp->rm_len);
956                 return (NULL);
957         }
958         if (comp->rm_type != comp_type) {
959                 if_printf(sc->hn_ifp, "unexpected RNDIS comp 0x%08x, "
960                     "expect 0x%08x\n", comp->rm_type, comp_type);
961                 return (NULL);
962         }
963         if (comp->rm_rid != rid) {
964                 if_printf(sc->hn_ifp, "RNDIS comp rid mismatch %u, "
965                     "expect %u\n", comp->rm_rid, rid);
966                 return (NULL);
967         }
968         /* All pass! */
969         return (comp);
970 }
971
972 /*
973  * RNDIS filter init device
974  */
975 static int
976 hv_rf_init_device(rndis_device *device)
977 {
978         struct hn_softc *sc = device->sc;
979         struct rndis_init_req *req;
980         const struct rndis_init_comp *comp;
981         struct vmbus_xact *xact;
982         uint32_t rid;
983         int error;
984
985         /* XXX */
986         device->state = RNDIS_DEV_INITIALIZED;
987
988         xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
989         if (xact == NULL) {
990                 if_printf(sc->hn_ifp, "no xact for RNDIS init\n");
991                 return (ENXIO);
992         }
993         rid = hn_rndis_rid(sc);
994         req = vmbus_xact_req_data(xact);
995         req->rm_type = REMOTE_NDIS_INITIALIZE_MSG;
996         req->rm_len = sizeof(*req);
997         req->rm_rid = rid;
998         req->rm_ver_major = RNDIS_VERSION_MAJOR;
999         req->rm_ver_minor = RNDIS_VERSION_MINOR;
1000         req->rm_max_xfersz = HN_RNDIS_XFER_SIZE;
1001
1002         comp = hn_rndis_xact_execute(sc, xact, rid, sizeof(*req),
1003             RNDIS_INIT_COMP_SIZE_MIN, REMOTE_NDIS_INITIALIZE_CMPLT);
1004         if (comp == NULL) {
1005                 if_printf(sc->hn_ifp, "exec RNDIS init failed\n");
1006                 error = EIO;
1007                 goto done;
1008         }
1009
1010         if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
1011                 if_printf(sc->hn_ifp, "RNDIS init failed: status 0x%08x\n",
1012                     comp->rm_status);
1013                 error = EIO;
1014                 goto done;
1015         }
1016         if (bootverbose) {
1017                 if_printf(sc->hn_ifp, "RNDIS ver %u.%u, pktsz %u, pktcnt %u\n",
1018                     comp->rm_ver_major, comp->rm_ver_minor,
1019                     comp->rm_pktmaxsz, comp->rm_pktmaxcnt);
1020         }
1021         error = 0;
1022
1023 done:
1024         if (xact != NULL)
1025                 vmbus_xact_put(xact);
1026         return (error);
1027 }
1028
1029 #define HALT_COMPLETION_WAIT_COUNT      25
1030
1031 /*
1032  * RNDIS filter halt device
1033  */
1034 static int
1035 hv_rf_halt_device(rndis_device *device)
1036 {
1037         rndis_request *request;
1038         int i, ret;
1039
1040         /* Attempt to do a rndis device halt */
1041         request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
1042             RNDIS_MESSAGE_SIZE(rndis_halt_request));
1043         if (request == NULL) {
1044                 return (-1);
1045         }
1046
1047         /* initialize "poor man's semaphore" */
1048         request->halt_complete_flag = 0;
1049
1050         ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
1051         if (ret != 0) {
1052                 return (-1);
1053         }
1054
1055         /*
1056          * Wait for halt response from halt callback.  We must wait for
1057          * the transaction response before freeing the request and other
1058          * resources.
1059          */
1060         for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
1061                 if (request->halt_complete_flag != 0) {
1062                         break;
1063                 }
1064                 DELAY(400);
1065         }
1066         if (i == 0) {
1067                 return (-1);
1068         }
1069
1070         device->state = RNDIS_DEV_UNINITIALIZED;
1071
1072         hv_put_rndis_request(device, request);
1073
1074         return (0);
1075 }
1076
1077 /*
1078  * RNDIS filter open device
1079  */
1080 static int
1081 hv_rf_open_device(rndis_device *device)
1082 {
1083         int ret;
1084
1085         if (device->state != RNDIS_DEV_INITIALIZED) {
1086                 return (0);
1087         }
1088
1089         if (hv_promisc_mode != 1) {
1090                 ret = hv_rf_set_packet_filter(device, 
1091                     NDIS_PACKET_TYPE_BROADCAST     |
1092                     NDIS_PACKET_TYPE_ALL_MULTICAST |
1093                     NDIS_PACKET_TYPE_DIRECTED);
1094         } else {
1095                 ret = hv_rf_set_packet_filter(device, 
1096                     NDIS_PACKET_TYPE_PROMISCUOUS);
1097         }
1098
1099         if (ret == 0) {
1100                 device->state = RNDIS_DEV_DATAINITIALIZED;
1101         }
1102
1103         return (ret);
1104 }
1105
1106 /*
1107  * RNDIS filter close device
1108  */
1109 static int
1110 hv_rf_close_device(rndis_device *device)
1111 {
1112         int ret;
1113
1114         if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1115                 return (0);
1116         }
1117
1118         ret = hv_rf_set_packet_filter(device, 0);
1119         if (ret == 0) {
1120                 device->state = RNDIS_DEV_INITIALIZED;
1121         }
1122
1123         return (ret);
1124 }
1125
1126 /*
1127  * RNDIS filter on device add
1128  */
1129 int
1130 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1131     int *nchan0, struct hn_rx_ring *rxr)
1132 {
1133         int ret;
1134         rndis_device *rndis_dev;
1135         rndis_offload_params offloads;
1136         struct rndis_recv_scale_cap rsscaps;
1137         uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1138         netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1139         device_t dev = sc->hn_dev;
1140         struct hn_nvs_subch_req *req;
1141         const struct hn_nvs_subch_resp *resp;
1142         size_t resp_len;
1143         struct vmbus_xact *xact = NULL;
1144         uint32_t status, nsubch;
1145         int nchan = *nchan0;
1146
1147         rndis_dev = hv_get_rndis_device();
1148         if (rndis_dev == NULL) {
1149                 return (ENOMEM);
1150         }
1151         sc->rndis_dev = rndis_dev;
1152         rndis_dev->sc = sc;
1153
1154         /*
1155          * Let the inner driver handle this first to create the netvsc channel
1156          * NOTE! Once the channel is created, we may get a receive callback 
1157          * (hv_rf_on_receive()) before this call is completed.
1158          * Note:  Earlier code used a function pointer here.
1159          */
1160         ret = hv_nv_on_device_add(sc, rxr);
1161         if (ret != 0) {
1162                 hv_put_rndis_device(rndis_dev);
1163                 return (ret);
1164         }
1165
1166         /*
1167          * Initialize the rndis device
1168          */
1169
1170         /* Send the rndis initialization message */
1171         ret = hv_rf_init_device(rndis_dev);
1172         if (ret != 0) {
1173                 /*
1174                  * TODO: If rndis init failed, we will need to shut down
1175                  * the channel
1176                  */
1177         }
1178
1179         /* Get the mac address */
1180         ret = hv_rf_query_device_mac(rndis_dev);
1181         if (ret != 0) {
1182                 /* TODO: shut down rndis device and the channel */
1183         }
1184
1185         /* config csum offload and send request to host */
1186         memset(&offloads, 0, sizeof(offloads));
1187         offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1188         offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1189         offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1190         offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1191         offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1192         offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1193
1194         ret = hv_rf_send_offload_request(sc, &offloads);
1195         if (ret != 0) {
1196                 /* TODO: shut down rndis device and the channel */
1197                 device_printf(dev,
1198                     "hv_rf_send_offload_request failed, ret=%d\n", ret);
1199         }
1200         
1201         memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN);
1202
1203         hv_rf_query_device_link_status(rndis_dev);
1204         
1205         dev_info->link_state = rndis_dev->link_status;
1206
1207         if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1208                 return (0);
1209
1210         memset(&rsscaps, 0, rsscaps_size);
1211         ret = hv_rf_query_device(rndis_dev,
1212                         RNDIS_OID_GEN_RSS_CAPABILITIES,
1213                         &rsscaps, &rsscaps_size);
1214         if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1215                 device_printf(dev, "hv_rf_query_device failed or "
1216                         "rsscaps.num_recv_que < 2 \n");
1217                 goto out;
1218         }
1219         device_printf(dev, "channel, offered %u, requested %d\n",
1220             rsscaps.num_recv_que, nchan);
1221         if (nchan > rsscaps.num_recv_que)
1222                 nchan = rsscaps.num_recv_que;
1223
1224         if (nchan == 1) {
1225                 device_printf(dev, "only 1 channel is supported, no vRSS\n");
1226                 goto out;
1227         }
1228         
1229         /*
1230          * Ask NVS to allocate sub-channels.
1231          */
1232         xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
1233         if (xact == NULL) {
1234                 if_printf(sc->hn_ifp, "no xact for nvs subch req\n");
1235                 ret = ENXIO;
1236                 goto out;
1237         }
1238         req = vmbus_xact_req_data(xact);
1239         req->nvs_type = HN_NVS_TYPE_SUBCH_REQ;
1240         req->nvs_op = HN_NVS_SUBCH_OP_ALLOC;
1241         req->nvs_nsubch = nchan - 1;
1242
1243         resp = hn_nvs_xact_execute(sc, xact, req, sizeof(*req), &resp_len);
1244         if (resp == NULL) {
1245                 if_printf(sc->hn_ifp, "exec subch failed\n");
1246                 ret = EIO;
1247                 goto out;
1248         }
1249         if (resp_len < sizeof(*resp)) {
1250                 if_printf(sc->hn_ifp, "invalid subch resp length %zu\n",
1251                     resp_len);
1252                 ret = EINVAL;
1253                 goto out;
1254         }
1255         if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) {
1256                 if_printf(sc->hn_ifp, "not subch resp, type %u\n",
1257                     resp->nvs_type);
1258                 ret = EINVAL;
1259                 goto out;
1260         }
1261
1262         status = resp->nvs_status;
1263         nsubch = resp->nvs_nsubch;
1264         vmbus_xact_put(xact);
1265         xact = NULL;
1266
1267         if (status != HN_NVS_STATUS_OK) {
1268                 if_printf(sc->hn_ifp, "subch req failed: %x\n", status);
1269                 ret = EIO;
1270                 goto out;
1271         }
1272         if (nsubch > nchan - 1) {
1273                 if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n",
1274                     nsubch, nchan - 1);
1275                 nsubch = nchan - 1;
1276         }
1277         nchan = nsubch + 1;
1278
1279         ret = hv_rf_set_rss_param(rndis_dev, nchan);
1280         *nchan0 = nchan;
1281 out:
1282         if (xact != NULL)
1283                 vmbus_xact_put(xact);
1284         return (ret);
1285 }
1286
1287 /*
1288  * RNDIS filter on device remove
1289  */
1290 int
1291 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1292 {
1293         rndis_device *rndis_dev = sc->rndis_dev;
1294         int ret;
1295
1296         /* Halt and release the rndis device */
1297         ret = hv_rf_halt_device(rndis_dev);
1298
1299         sc->rndis_dev = NULL;
1300         hv_put_rndis_device(rndis_dev);
1301
1302         /* Pass control to inner driver to remove the device */
1303         ret |= hv_nv_on_device_remove(sc, destroy_channel);
1304
1305         return (ret);
1306 }
1307
1308 /*
1309  * RNDIS filter on open
1310  */
1311 int
1312 hv_rf_on_open(struct hn_softc *sc)
1313 {
1314
1315         return (hv_rf_open_device(sc->rndis_dev));
1316 }
1317
1318 /*
1319  * RNDIS filter on close
1320  */
1321 int 
1322 hv_rf_on_close(struct hn_softc *sc)
1323 {
1324
1325         return (hv_rf_close_device(sc->rndis_dev));
1326 }
1327
1328 static void
1329 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct hn_softc *sc,
1330     struct vmbus_channel *chan __unused, const void *data __unused,
1331     int dlen __unused)
1332 {
1333         if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1334                 hn_chim_free(sc, sndc->hn_chim_idx);
1335 }
1336
1337 static void
1338 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct hn_softc *sc,
1339     struct vmbus_channel *chan __unused, const void *data __unused,
1340     int dlen __unused)
1341 {
1342         rndis_request *request = sndc->hn_cbarg;
1343
1344         if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1345                 hn_chim_free(sc, sndc->hn_chim_idx);
1346
1347         /*
1348          * Notify hv_rf_halt_device() about halt completion.
1349          * The halt code must wait for completion before freeing
1350          * the transaction resources.
1351          */
1352         request->halt_complete_flag = 1;
1353 }
1354
1355 void
1356 hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr)
1357 {
1358
1359         netvsc_channel_rollup(rxr, txr);
1360 }