]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/hyperv/netvsc/hv_rndis_filter.c
MFC 304973,304975,304976,304979,305044-305048
[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 #include <dev/hyperv/netvsc/ndis.h>
56
57 #define HV_RF_RECVINFO_VLAN     0x1
58 #define HV_RF_RECVINFO_CSUM     0x2
59 #define HV_RF_RECVINFO_HASHINF  0x4
60 #define HV_RF_RECVINFO_HASHVAL  0x8
61 #define HV_RF_RECVINFO_ALL              \
62         (HV_RF_RECVINFO_VLAN |          \
63          HV_RF_RECVINFO_CSUM |          \
64          HV_RF_RECVINFO_HASHINF |       \
65          HV_RF_RECVINFO_HASHVAL)
66
67 #define HN_RNDIS_RID_COMPAT_MASK        0xffff
68 #define HN_RNDIS_RID_COMPAT_MAX         HN_RNDIS_RID_COMPAT_MASK
69
70 #define HN_RNDIS_XFER_SIZE              2048
71
72 /*
73  * Forward declarations
74  */
75 static int  hv_rf_send_request(rndis_device *device, rndis_request *request,
76                                uint32_t message_type);
77 static void hv_rf_receive_response(rndis_device *device,
78     const rndis_msg *response);
79 static void hv_rf_receive_indicate_status(rndis_device *device,
80     const rndis_msg *response);
81 static void hv_rf_receive_data(struct hn_rx_ring *rxr,
82     const void *data, int dlen);
83 static inline int hv_rf_query_device_mac(rndis_device *device);
84 static inline int hv_rf_query_device_link_status(rndis_device *device);
85 static int  hv_rf_init_device(rndis_device *device);
86
87 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
88     struct hn_softc *sc, struct vmbus_channel *chan,
89     const void *data, int dlen);
90 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
91     struct hn_softc *sc, struct vmbus_channel *chan,
92     const void *data, int dlen);
93 static int hn_rndis_query(struct hn_softc *sc, uint32_t oid,
94     const void *idata, size_t idlen, void *odata, size_t *odlen0);
95 static int hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data,
96     size_t dlen);
97 static int hn_rndis_conf_offload(struct hn_softc *sc);
98 static int hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt);
99 static int hn_rndis_conf_rss(struct hn_softc *sc, int nchan);
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 /*
354  * RNDIS filter receive indicate status
355  */
356 static void 
357 hv_rf_receive_indicate_status(rndis_device *device, const rndis_msg *response)
358 {
359         const rndis_indicate_status *indicate = &response->msg.indicate_status;
360                 
361         switch(indicate->status) {
362         case RNDIS_STATUS_MEDIA_CONNECT:
363                 netvsc_linkstatus_callback(device->sc, 1);
364                 break;
365         case RNDIS_STATUS_MEDIA_DISCONNECT:
366                 netvsc_linkstatus_callback(device->sc, 0);
367                 break;
368         default:
369                 /* TODO: */
370                 device_printf(device->sc->hn_dev,
371                     "unknown status %d received\n", indicate->status);
372                 break;
373         }
374 }
375
376 static int
377 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
378 {
379         const rndis_per_packet_info *ppi;
380         uint32_t mask, len;
381
382         info->vlan_info = NULL;
383         info->csum_info = NULL;
384         info->hash_info = NULL;
385         info->hash_value = NULL;
386
387         if (rpkt->per_pkt_info_offset == 0)
388                 return 0;
389
390         ppi = (const rndis_per_packet_info *)
391             ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
392         len = rpkt->per_pkt_info_length;
393         mask = 0;
394
395         while (len != 0) {
396                 const void *ppi_dptr;
397                 uint32_t ppi_dlen;
398
399                 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
400                         return EINVAL;
401                 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
402                 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
403
404                 switch (ppi->type) {
405                 case ieee_8021q_info:
406                         if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
407                                 return EINVAL;
408                         info->vlan_info = ppi_dptr;
409                         mask |= HV_RF_RECVINFO_VLAN;
410                         break;
411
412                 case tcpip_chksum_info:
413                         if (__predict_false(ppi_dlen <
414                             sizeof(rndis_tcp_ip_csum_info)))
415                                 return EINVAL;
416                         info->csum_info = ppi_dptr;
417                         mask |= HV_RF_RECVINFO_CSUM;
418                         break;
419
420                 case nbl_hash_value:
421                         if (__predict_false(ppi_dlen <
422                             sizeof(struct rndis_hash_value)))
423                                 return EINVAL;
424                         info->hash_value = ppi_dptr;
425                         mask |= HV_RF_RECVINFO_HASHVAL;
426                         break;
427
428                 case nbl_hash_info:
429                         if (__predict_false(ppi_dlen <
430                             sizeof(struct rndis_hash_info)))
431                                 return EINVAL;
432                         info->hash_info = ppi_dptr;
433                         mask |= HV_RF_RECVINFO_HASHINF;
434                         break;
435
436                 default:
437                         goto skip;
438                 }
439
440                 if (mask == HV_RF_RECVINFO_ALL) {
441                         /* All found; done */
442                         break;
443                 }
444 skip:
445                 if (__predict_false(len < ppi->size))
446                         return EINVAL;
447                 len -= ppi->size;
448                 ppi = (const rndis_per_packet_info *)
449                     ((const uint8_t *)ppi + ppi->size);
450         }
451         return 0;
452 }
453
454 /*
455  * RNDIS filter receive data
456  */
457 static void
458 hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen)
459 {
460         const rndis_msg *message = data;
461         const rndis_packet *rndis_pkt;
462         uint32_t data_offset;
463         struct hn_recvinfo info;
464
465         rndis_pkt = &message->msg.packet;
466
467         /*
468          * Fixme:  Handle multiple rndis pkt msgs that may be enclosed in this
469          * netvsc packet (ie tot_data_buf_len != message_length)
470          */
471
472         /* Remove rndis header, then pass data packet up the stack */
473         data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
474
475         dlen -= data_offset;
476         if (dlen < rndis_pkt->data_length) {
477                 if_printf(rxr->hn_ifp,
478                     "total length %u is less than data length %u\n",
479                     dlen, rndis_pkt->data_length);
480                 return;
481         }
482
483         dlen = rndis_pkt->data_length;
484         data = (const uint8_t *)data + data_offset;
485
486         if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
487                 if_printf(rxr->hn_ifp, "recvinfo parsing failed\n");
488                 return;
489         }
490         netvsc_recv(rxr, data, dlen, &info);
491 }
492
493 /*
494  * RNDIS filter on receive
495  */
496 int
497 hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
498     const void *data, int dlen)
499 {
500         rndis_device *rndis_dev;
501         const rndis_msg *rndis_hdr;
502         const struct rndis_comp_hdr *comp;
503
504         rndis_dev = sc->rndis_dev;
505         if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED)
506                 return (EINVAL);
507
508         rndis_hdr = data;
509         switch (rndis_hdr->ndis_msg_type) {
510         /* data message */
511         case REMOTE_NDIS_PACKET_MSG:
512                 hv_rf_receive_data(rxr, data, dlen);
513                 break;
514
515         /* completion messages */
516         case REMOTE_NDIS_INITIALIZE_CMPLT:
517         case REMOTE_NDIS_QUERY_CMPLT:
518         case REMOTE_NDIS_SET_CMPLT:
519         case REMOTE_NDIS_KEEPALIVE_CMPLT:
520                 comp = data;
521                 if (comp->rm_rid <= HN_RNDIS_RID_COMPAT_MAX) {
522                         /* Transition time compat code */
523                         hv_rf_receive_response(rndis_dev, rndis_hdr);
524                 } else {
525                         vmbus_xact_ctx_wakeup(sc->hn_xact, data, dlen);
526                 }
527                 break;
528
529         /* notification message */
530         case REMOTE_NDIS_INDICATE_STATUS_MSG:
531                 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
532                 break;
533
534         case REMOTE_NDIS_RESET_CMPLT:
535                 /*
536                  * Reset completed, no rid.
537                  *
538                  * NOTE:
539                  * RESET is not issued by hn(4), so this message should
540                  * _not_ be observed.
541                  */
542                 if_printf(sc->hn_ifp, "RESET CMPLT received\n");
543                 break;
544
545         default:
546                 if_printf(sc->hn_ifp, "unknown RNDIS message 0x%x\n",
547                         rndis_hdr->ndis_msg_type);
548                 break;
549         }
550         return (0);
551 }
552
553 /*
554  * RNDIS filter query device MAC address
555  */
556 static int
557 hv_rf_query_device_mac(rndis_device *device)
558 {
559         struct hn_softc *sc = device->sc;
560         size_t hwaddr_len;
561         int error;
562
563         hwaddr_len = ETHER_ADDR_LEN;
564         error = hn_rndis_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
565             device->hw_mac_addr, &hwaddr_len);
566         if (error)
567                 return (error);
568         if (hwaddr_len != ETHER_ADDR_LEN) {
569                 if_printf(sc->hn_ifp, "invalid hwaddr len %zu\n", hwaddr_len);
570                 return (EINVAL);
571         }
572         return (0);
573 }
574
575 /*
576  * RNDIS filter query device link status
577  */
578 static inline int
579 hv_rf_query_device_link_status(rndis_device *device)
580 {
581         struct hn_softc *sc = device->sc;
582         size_t size;
583         int error;
584
585         size = sizeof(uint32_t);
586         error = hn_rndis_query(sc, OID_GEN_MEDIA_CONNECT_STATUS, NULL, 0,
587             &device->link_status, &size);
588         if (error)
589                 return (error);
590         if (size != sizeof(uint32_t)) {
591                 if_printf(sc->hn_ifp, "invalid link status len %zu\n", size);
592                 return (EINVAL);
593         }
594         return (0);
595 }
596
597 static uint8_t netvsc_hash_key[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
598         0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
599         0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
600         0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
601         0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
602         0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
603 };
604
605 static const void *
606 hn_rndis_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, uint32_t rid,
607     size_t reqlen, size_t *comp_len0, uint32_t comp_type)
608 {
609         struct vmbus_gpa gpa[HN_XACT_REQ_PGCNT];
610         const struct rndis_comp_hdr *comp;
611         bus_addr_t paddr;
612         size_t comp_len, min_complen = *comp_len0;
613         int gpa_cnt, error;
614
615         KASSERT(rid > HN_RNDIS_RID_COMPAT_MAX, ("invalid rid %u\n", rid));
616         KASSERT(reqlen <= HN_XACT_REQ_SIZE && reqlen > 0,
617             ("invalid request length %zu", reqlen));
618         KASSERT(min_complen >= sizeof(*comp),
619             ("invalid minimum complete len %zu", min_complen));
620
621         /*
622          * Setup the SG list.
623          */
624         paddr = vmbus_xact_req_paddr(xact);
625         KASSERT((paddr & PAGE_MASK) == 0,
626             ("vmbus xact request is not page aligned 0x%jx", (uintmax_t)paddr));
627         for (gpa_cnt = 0; gpa_cnt < HN_XACT_REQ_PGCNT; ++gpa_cnt) {
628                 int len = PAGE_SIZE;
629
630                 if (reqlen == 0)
631                         break;
632                 if (reqlen < len)
633                         len = reqlen;
634
635                 gpa[gpa_cnt].gpa_page = atop(paddr) + gpa_cnt;
636                 gpa[gpa_cnt].gpa_len = len;
637                 gpa[gpa_cnt].gpa_ofs = 0;
638
639                 reqlen -= len;
640         }
641         KASSERT(reqlen == 0, ("still have %zu request data left", reqlen));
642
643         /*
644          * Send this RNDIS control message and wait for its completion
645          * message.
646          */
647         vmbus_xact_activate(xact);
648         error = hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
649             &hn_send_ctx_none, gpa, gpa_cnt);
650         if (error) {
651                 vmbus_xact_deactivate(xact);
652                 if_printf(sc->hn_ifp, "RNDIS ctrl send failed: %d\n", error);
653                 return (NULL);
654         }
655         comp = vmbus_xact_wait(xact, &comp_len);
656
657         /*
658          * Check this RNDIS complete message.
659          */
660         if (comp_len < min_complen) {
661                 if (comp_len >= sizeof(*comp)) {
662                         /* rm_status field is valid */
663                         if_printf(sc->hn_ifp, "invalid RNDIS comp len %zu, "
664                             "status 0x%08x\n", comp_len, comp->rm_status);
665                 } else {
666                         if_printf(sc->hn_ifp, "invalid RNDIS comp len %zu\n",
667                             comp_len);
668                 }
669                 return (NULL);
670         }
671         if (comp->rm_len < min_complen) {
672                 if_printf(sc->hn_ifp, "invalid RNDIS comp msglen %u\n",
673                     comp->rm_len);
674                 return (NULL);
675         }
676         if (comp->rm_type != comp_type) {
677                 if_printf(sc->hn_ifp, "unexpected RNDIS comp 0x%08x, "
678                     "expect 0x%08x\n", comp->rm_type, comp_type);
679                 return (NULL);
680         }
681         if (comp->rm_rid != rid) {
682                 if_printf(sc->hn_ifp, "RNDIS comp rid mismatch %u, "
683                     "expect %u\n", comp->rm_rid, rid);
684                 return (NULL);
685         }
686         /* All pass! */
687         *comp_len0 = comp_len;
688         return (comp);
689 }
690
691 static int
692 hn_rndis_query(struct hn_softc *sc, uint32_t oid,
693     const void *idata, size_t idlen, void *odata, size_t *odlen0)
694 {
695         struct rndis_query_req *req;
696         const struct rndis_query_comp *comp;
697         struct vmbus_xact *xact;
698         size_t reqlen, odlen = *odlen0, comp_len;
699         int error, ofs;
700         uint32_t rid;
701
702         reqlen = sizeof(*req) + idlen;
703         xact = vmbus_xact_get(sc->hn_xact, reqlen);
704         if (xact == NULL) {
705                 if_printf(sc->hn_ifp, "no xact for RNDIS query 0x%08x\n", oid);
706                 return (ENXIO);
707         }
708         rid = hn_rndis_rid(sc);
709         req = vmbus_xact_req_data(xact);
710         req->rm_type = REMOTE_NDIS_QUERY_MSG;
711         req->rm_len = reqlen;
712         req->rm_rid = rid;
713         req->rm_oid = oid;
714         /*
715          * XXX
716          * This is _not_ RNDIS Spec conforming:
717          * "This MUST be set to 0 when there is no input data
718          *  associated with the OID."
719          *
720          * If this field was set to 0 according to the RNDIS Spec,
721          * Hyper-V would set non-SUCCESS status in the query
722          * completion.
723          */
724         req->rm_infobufoffset = RNDIS_QUERY_REQ_INFOBUFOFFSET;
725
726         if (idlen > 0) {
727                 req->rm_infobuflen = idlen;
728                 /* Input data immediately follows RNDIS query. */
729                 memcpy(req + 1, idata, idlen);
730         }
731
732         comp_len = sizeof(*comp) + odlen;
733         comp = hn_rndis_xact_execute(sc, xact, rid, reqlen, &comp_len,
734             REMOTE_NDIS_QUERY_CMPLT);
735         if (comp == NULL) {
736                 if_printf(sc->hn_ifp, "exec RNDIS query 0x%08x failed\n", oid);
737                 error = EIO;
738                 goto done;
739         }
740
741         if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
742                 if_printf(sc->hn_ifp, "RNDIS query 0x%08x failed: "
743                     "status 0x%08x\n", oid, comp->rm_status);
744                 error = EIO;
745                 goto done;
746         }
747         if (comp->rm_infobuflen == 0 || comp->rm_infobufoffset == 0) {
748                 /* No output data! */
749                 if_printf(sc->hn_ifp, "RNDIS query 0x%08x, no data\n", oid);
750                 *odlen0 = 0;
751                 error = 0;
752                 goto done;
753         }
754
755         /*
756          * Check output data length and offset.
757          */
758         /* ofs is the offset from the beginning of comp. */
759         ofs = RNDIS_QUERY_COMP_INFOBUFABS(comp->rm_infobufoffset);
760         if (ofs < sizeof(*comp) || ofs + comp->rm_infobuflen > comp_len) {
761                 if_printf(sc->hn_ifp, "RNDIS query invalid comp ib off/len, "
762                     "%u/%u\n", comp->rm_infobufoffset, comp->rm_infobuflen);
763                 error = EINVAL;
764                 goto done;
765         }
766
767         /*
768          * Save output data.
769          */
770         if (comp->rm_infobuflen < odlen)
771                 odlen = comp->rm_infobuflen;
772         memcpy(odata, ((const uint8_t *)comp) + ofs, odlen);
773         *odlen0 = odlen;
774
775         error = 0;
776 done:
777         vmbus_xact_put(xact);
778         return (error);
779 }
780
781 static int
782 hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt)
783 {
784         struct ndis_rss_caps in, caps;
785         size_t caps_len;
786         int error;
787
788         /*
789          * Only NDIS 6.30+ is supported.
790          */
791         KASSERT(sc->hn_ndis_ver >= NDIS_VERSION_6_30,
792             ("NDIS 6.30+ is required, NDIS version 0x%08x", sc->hn_ndis_ver));
793         *rxr_cnt = 0;
794
795         memset(&in, 0, sizeof(in));
796         in.ndis_hdr.ndis_type = NDIS_OBJTYPE_RSS_CAPS;
797         in.ndis_hdr.ndis_rev = NDIS_RSS_CAPS_REV_2;
798         in.ndis_hdr.ndis_size = NDIS_RSS_CAPS_SIZE;
799
800         caps_len = NDIS_RSS_CAPS_SIZE;
801         error = hn_rndis_query(sc, OID_GEN_RECEIVE_SCALE_CAPABILITIES,
802             &in, NDIS_RSS_CAPS_SIZE, &caps, &caps_len);
803         if (error)
804                 return (error);
805         if (caps_len < NDIS_RSS_CAPS_SIZE_6_0) {
806                 if_printf(sc->hn_ifp, "invalid NDIS RSS caps len %zu",
807                     caps_len);
808                 return (EINVAL);
809         }
810
811         if (caps.ndis_nrxr == 0) {
812                 if_printf(sc->hn_ifp, "0 RX rings!?\n");
813                 return (EINVAL);
814         }
815         *rxr_cnt = caps.ndis_nrxr;
816
817         if (caps_len == NDIS_RSS_CAPS_SIZE) {
818                 if (bootverbose) {
819                         if_printf(sc->hn_ifp, "RSS indirect table size %u\n",
820                             caps.ndis_nind);
821                 }
822         }
823         return (0);
824 }
825
826 static int
827 hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data, size_t dlen)
828 {
829         struct rndis_set_req *req;
830         const struct rndis_set_comp *comp;
831         struct vmbus_xact *xact;
832         size_t reqlen, comp_len;
833         uint32_t rid;
834         int error;
835
836         KASSERT(dlen > 0, ("invalid dlen %zu", dlen));
837
838         reqlen = sizeof(*req) + dlen;
839         xact = vmbus_xact_get(sc->hn_xact, reqlen);
840         if (xact == NULL) {
841                 if_printf(sc->hn_ifp, "no xact for RNDIS set 0x%08x\n", oid);
842                 return (ENXIO);
843         }
844         rid = hn_rndis_rid(sc);
845         req = vmbus_xact_req_data(xact);
846         req->rm_type = REMOTE_NDIS_SET_MSG;
847         req->rm_len = reqlen;
848         req->rm_rid = rid;
849         req->rm_oid = oid;
850         req->rm_infobuflen = dlen;
851         req->rm_infobufoffset = RNDIS_SET_REQ_INFOBUFOFFSET;
852         /* Data immediately follows RNDIS set. */
853         memcpy(req + 1, data, dlen);
854
855         comp_len = sizeof(*comp);
856         comp = hn_rndis_xact_execute(sc, xact, rid, reqlen, &comp_len,
857             REMOTE_NDIS_SET_CMPLT);
858         if (comp == NULL) {
859                 if_printf(sc->hn_ifp, "exec RNDIS set 0x%08x failed\n", oid);
860                 error = EIO;
861                 goto done;
862         }
863
864         if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
865                 if_printf(sc->hn_ifp, "RNDIS set 0x%08x failed: "
866                     "status 0x%08x\n", oid, comp->rm_status);
867                 error = EIO;
868                 goto done;
869         }
870         error = 0;
871 done:
872         vmbus_xact_put(xact);
873         return (error);
874 }
875
876 static int
877 hn_rndis_conf_offload(struct hn_softc *sc)
878 {
879         struct ndis_offload_params params;
880         size_t paramsz;
881         int error;
882
883         /* NOTE: 0 means "no change" */
884         memset(&params, 0, sizeof(params));
885
886         params.ndis_hdr.ndis_type = NDIS_OBJTYPE_DEFAULT;
887         if (sc->hn_ndis_ver < NDIS_VERSION_6_30) {
888                 params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_2;
889                 paramsz = NDIS_OFFLOAD_PARAMS_SIZE_6_1;
890         } else {
891                 params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_3;
892                 paramsz = NDIS_OFFLOAD_PARAMS_SIZE;
893         }
894         params.ndis_hdr.ndis_size = paramsz;
895
896         params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX;
897         params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX;
898         params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX;
899         if (sc->hn_ndis_ver >= NDIS_VERSION_6_30) {
900                 params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX;
901                 params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX;
902         }
903         params.ndis_lsov2_ip4 = NDIS_OFFLOAD_LSOV2_ON;
904         /* XXX ndis_lsov2_ip6 = NDIS_OFFLOAD_LSOV2_ON */
905
906         error = hn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS, &params, paramsz);
907         if (error) {
908                 if_printf(sc->hn_ifp, "offload config failed: %d\n", error);
909         } else {
910                 if (bootverbose)
911                         if_printf(sc->hn_ifp, "offload config done\n");
912         }
913         return (error);
914 }
915
916 static int
917 hn_rndis_conf_rss(struct hn_softc *sc, int nchan)
918 {
919         struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
920         struct ndis_rss_params *prm = &rss->rss_params;
921         int i, error;
922
923         /*
924          * Only NDIS 6.30+ is supported.
925          */
926         KASSERT(sc->hn_ndis_ver >= NDIS_VERSION_6_30,
927             ("NDIS 6.30+ is required, NDIS version 0x%08x", sc->hn_ndis_ver));
928
929         memset(rss, 0, sizeof(*rss));
930         prm->ndis_hdr.ndis_type = NDIS_OBJTYPE_RSS_PARAMS;
931         prm->ndis_hdr.ndis_rev = NDIS_RSS_PARAMS_REV_2;
932         prm->ndis_hdr.ndis_size = sizeof(*rss);
933         prm->ndis_hash = NDIS_HASH_FUNCTION_TOEPLITZ |
934             NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4 |
935             NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6;
936         /* TODO: Take ndis_rss_caps.ndis_nind into account */
937         prm->ndis_indsize = sizeof(rss->rss_ind);
938         prm->ndis_indoffset =
939             __offsetof(struct ndis_rssprm_toeplitz, rss_ind[0]);
940         prm->ndis_keysize = sizeof(rss->rss_key);
941         prm->ndis_keyoffset =
942             __offsetof(struct ndis_rssprm_toeplitz, rss_key[0]);
943
944         /* Setup RSS key */
945         memcpy(rss->rss_key, netvsc_hash_key, sizeof(rss->rss_key));
946
947         /* Setup RSS indirect table */
948         /* TODO: Take ndis_rss_caps.ndis_nind into account */
949         for (i = 0; i < NDIS_HASH_INDCNT; ++i)
950                 rss->rss_ind[i] = i % nchan;
951
952         error = hn_rndis_set(sc, OID_GEN_RECEIVE_SCALE_PARAMETERS,
953             rss, sizeof(*rss));
954         if (error) {
955                 if_printf(sc->hn_ifp, "RSS config failed: %d\n", error);
956         } else {
957                 if (bootverbose)
958                         if_printf(sc->hn_ifp, "RSS config done\n");
959         }
960         return (error);
961 }
962
963 static int
964 hn_rndis_set_rxfilter(struct hn_softc *sc, uint32_t filter)
965 {
966         int error;
967
968         error = hn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
969             &filter, sizeof(filter));
970         if (error) {
971                 if_printf(sc->hn_ifp, "set RX filter 0x%08x failed: %d\n",
972                     filter, error);
973         } else {
974                 if (bootverbose) {
975                         if_printf(sc->hn_ifp, "set RX filter 0x%08x done\n",
976                             filter);
977                 }
978         }
979         return (error);
980 }
981
982 /*
983  * RNDIS filter init device
984  */
985 static int
986 hv_rf_init_device(rndis_device *device)
987 {
988         struct hn_softc *sc = device->sc;
989         struct rndis_init_req *req;
990         const struct rndis_init_comp *comp;
991         struct vmbus_xact *xact;
992         size_t comp_len;
993         uint32_t rid;
994         int error;
995
996         /* XXX */
997         device->state = RNDIS_DEV_INITIALIZED;
998
999         xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
1000         if (xact == NULL) {
1001                 if_printf(sc->hn_ifp, "no xact for RNDIS init\n");
1002                 return (ENXIO);
1003         }
1004         rid = hn_rndis_rid(sc);
1005         req = vmbus_xact_req_data(xact);
1006         req->rm_type = REMOTE_NDIS_INITIALIZE_MSG;
1007         req->rm_len = sizeof(*req);
1008         req->rm_rid = rid;
1009         req->rm_ver_major = RNDIS_VERSION_MAJOR;
1010         req->rm_ver_minor = RNDIS_VERSION_MINOR;
1011         req->rm_max_xfersz = HN_RNDIS_XFER_SIZE;
1012
1013         comp_len = RNDIS_INIT_COMP_SIZE_MIN;
1014         comp = hn_rndis_xact_execute(sc, xact, rid, sizeof(*req), &comp_len,
1015             REMOTE_NDIS_INITIALIZE_CMPLT);
1016         if (comp == NULL) {
1017                 if_printf(sc->hn_ifp, "exec RNDIS init failed\n");
1018                 error = EIO;
1019                 goto done;
1020         }
1021
1022         if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
1023                 if_printf(sc->hn_ifp, "RNDIS init failed: status 0x%08x\n",
1024                     comp->rm_status);
1025                 error = EIO;
1026                 goto done;
1027         }
1028         if (bootverbose) {
1029                 if_printf(sc->hn_ifp, "RNDIS ver %u.%u, pktsz %u, pktcnt %u\n",
1030                     comp->rm_ver_major, comp->rm_ver_minor,
1031                     comp->rm_pktmaxsz, comp->rm_pktmaxcnt);
1032         }
1033         error = 0;
1034
1035 done:
1036         if (xact != NULL)
1037                 vmbus_xact_put(xact);
1038         return (error);
1039 }
1040
1041 #define HALT_COMPLETION_WAIT_COUNT      25
1042
1043 /*
1044  * RNDIS filter halt device
1045  */
1046 static int
1047 hv_rf_halt_device(rndis_device *device)
1048 {
1049         rndis_request *request;
1050         int i, ret;
1051
1052         /* Attempt to do a rndis device halt */
1053         request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
1054             RNDIS_MESSAGE_SIZE(rndis_halt_request));
1055         if (request == NULL) {
1056                 return (-1);
1057         }
1058
1059         /* initialize "poor man's semaphore" */
1060         request->halt_complete_flag = 0;
1061
1062         ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
1063         if (ret != 0) {
1064                 return (-1);
1065         }
1066
1067         /*
1068          * Wait for halt response from halt callback.  We must wait for
1069          * the transaction response before freeing the request and other
1070          * resources.
1071          */
1072         for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
1073                 if (request->halt_complete_flag != 0) {
1074                         break;
1075                 }
1076                 DELAY(400);
1077         }
1078         if (i == 0) {
1079                 return (-1);
1080         }
1081
1082         device->state = RNDIS_DEV_UNINITIALIZED;
1083
1084         hv_put_rndis_request(device, request);
1085
1086         return (0);
1087 }
1088
1089 /*
1090  * RNDIS filter on device add
1091  */
1092 int
1093 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1094     int *nchan0, struct hn_rx_ring *rxr)
1095 {
1096         int ret;
1097         rndis_device *rndis_dev;
1098         netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1099         device_t dev = sc->hn_dev;
1100         struct hn_nvs_subch_req *req;
1101         const struct hn_nvs_subch_resp *resp;
1102         size_t resp_len;
1103         struct vmbus_xact *xact = NULL;
1104         uint32_t status, nsubch;
1105         int nchan = *nchan0;
1106         int rxr_cnt;
1107
1108         rndis_dev = hv_get_rndis_device();
1109         if (rndis_dev == NULL) {
1110                 return (ENOMEM);
1111         }
1112         sc->rndis_dev = rndis_dev;
1113         rndis_dev->sc = sc;
1114
1115         /*
1116          * Let the inner driver handle this first to create the netvsc channel
1117          * NOTE! Once the channel is created, we may get a receive callback 
1118          * (hv_rf_on_receive()) before this call is completed.
1119          * Note:  Earlier code used a function pointer here.
1120          */
1121         ret = hv_nv_on_device_add(sc, rxr);
1122         if (ret != 0) {
1123                 hv_put_rndis_device(rndis_dev);
1124                 return (ret);
1125         }
1126
1127         /*
1128          * Initialize the rndis device
1129          */
1130
1131         /* Send the rndis initialization message */
1132         ret = hv_rf_init_device(rndis_dev);
1133         if (ret != 0) {
1134                 /*
1135                  * TODO: If rndis init failed, we will need to shut down
1136                  * the channel
1137                  */
1138         }
1139
1140         /* Get the mac address */
1141         ret = hv_rf_query_device_mac(rndis_dev);
1142         if (ret != 0) {
1143                 /* TODO: shut down rndis device and the channel */
1144         }
1145
1146         /* Configure NDIS offload settings */
1147         hn_rndis_conf_offload(sc);
1148         
1149         memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN);
1150
1151         hv_rf_query_device_link_status(rndis_dev);
1152         
1153         dev_info->link_state = rndis_dev->link_status;
1154
1155         if (sc->hn_ndis_ver < NDIS_VERSION_6_30 || nchan == 1) {
1156                 /*
1157                  * Either RSS is not supported, or multiple RX/TX rings
1158                  * are not requested.
1159                  */
1160                 *nchan0 = 1;
1161                 return (0);
1162         }
1163
1164         /*
1165          * Get RSS capabilities, e.g. # of RX rings, and # of indirect
1166          * table entries.
1167          */
1168         ret = hn_rndis_get_rsscaps(sc, &rxr_cnt);
1169         if (ret) {
1170                 /* No RSS; this is benign. */
1171                 *nchan0 = 1;
1172                 return (0);
1173         }
1174         if (nchan > rxr_cnt)
1175                 nchan = rxr_cnt;
1176         if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n",
1177             rxr_cnt, nchan);
1178
1179         if (nchan == 1) {
1180                 device_printf(dev, "only 1 channel is supported, no vRSS\n");
1181                 goto out;
1182         }
1183         
1184         /*
1185          * Ask NVS to allocate sub-channels.
1186          */
1187         xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
1188         if (xact == NULL) {
1189                 if_printf(sc->hn_ifp, "no xact for nvs subch req\n");
1190                 ret = ENXIO;
1191                 goto out;
1192         }
1193         req = vmbus_xact_req_data(xact);
1194         req->nvs_type = HN_NVS_TYPE_SUBCH_REQ;
1195         req->nvs_op = HN_NVS_SUBCH_OP_ALLOC;
1196         req->nvs_nsubch = nchan - 1;
1197
1198         resp = hn_nvs_xact_execute(sc, xact, req, sizeof(*req), &resp_len);
1199         if (resp == NULL) {
1200                 if_printf(sc->hn_ifp, "exec subch failed\n");
1201                 ret = EIO;
1202                 goto out;
1203         }
1204         if (resp_len < sizeof(*resp)) {
1205                 if_printf(sc->hn_ifp, "invalid subch resp length %zu\n",
1206                     resp_len);
1207                 ret = EINVAL;
1208                 goto out;
1209         }
1210         if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) {
1211                 if_printf(sc->hn_ifp, "not subch resp, type %u\n",
1212                     resp->nvs_type);
1213                 ret = EINVAL;
1214                 goto out;
1215         }
1216
1217         status = resp->nvs_status;
1218         nsubch = resp->nvs_nsubch;
1219         vmbus_xact_put(xact);
1220         xact = NULL;
1221
1222         if (status != HN_NVS_STATUS_OK) {
1223                 if_printf(sc->hn_ifp, "subch req failed: %x\n", status);
1224                 ret = EIO;
1225                 goto out;
1226         }
1227         if (nsubch > nchan - 1) {
1228                 if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n",
1229                     nsubch, nchan - 1);
1230                 nsubch = nchan - 1;
1231         }
1232         nchan = nsubch + 1;
1233
1234         ret = hn_rndis_conf_rss(sc, nchan);
1235         if (ret != 0)
1236                 *nchan0 = 1;
1237         else
1238                 *nchan0 = nchan;
1239 out:
1240         if (xact != NULL)
1241                 vmbus_xact_put(xact);
1242         return (ret);
1243 }
1244
1245 /*
1246  * RNDIS filter on device remove
1247  */
1248 int
1249 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1250 {
1251         rndis_device *rndis_dev = sc->rndis_dev;
1252         int ret;
1253
1254         /* Halt and release the rndis device */
1255         ret = hv_rf_halt_device(rndis_dev);
1256
1257         sc->rndis_dev = NULL;
1258         hv_put_rndis_device(rndis_dev);
1259
1260         /* Pass control to inner driver to remove the device */
1261         ret |= hv_nv_on_device_remove(sc, destroy_channel);
1262
1263         return (ret);
1264 }
1265
1266 /*
1267  * RNDIS filter on open
1268  */
1269 int
1270 hv_rf_on_open(struct hn_softc *sc)
1271 {
1272         uint32_t filter;
1273
1274         /* XXX */
1275         if (hv_promisc_mode != 1) {
1276                 filter = NDIS_PACKET_TYPE_BROADCAST |
1277                     NDIS_PACKET_TYPE_ALL_MULTICAST |
1278                     NDIS_PACKET_TYPE_DIRECTED;
1279         } else {
1280                 filter = NDIS_PACKET_TYPE_PROMISCUOUS;
1281         }
1282         return (hn_rndis_set_rxfilter(sc, filter));
1283 }
1284
1285 /*
1286  * RNDIS filter on close
1287  */
1288 int 
1289 hv_rf_on_close(struct hn_softc *sc)
1290 {
1291
1292         return (hn_rndis_set_rxfilter(sc, 0));
1293 }
1294
1295 static void
1296 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct hn_softc *sc,
1297     struct vmbus_channel *chan __unused, const void *data __unused,
1298     int dlen __unused)
1299 {
1300         if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1301                 hn_chim_free(sc, sndc->hn_chim_idx);
1302 }
1303
1304 static void
1305 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct hn_softc *sc,
1306     struct vmbus_channel *chan __unused, const void *data __unused,
1307     int dlen __unused)
1308 {
1309         rndis_request *request = sndc->hn_cbarg;
1310
1311         if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1312                 hn_chim_free(sc, sndc->hn_chim_idx);
1313
1314         /*
1315          * Notify hv_rf_halt_device() about halt completion.
1316          * The halt code must wait for completion before freeing
1317          * the transaction resources.
1318          */
1319         request->halt_complete_flag = 1;
1320 }
1321
1322 void
1323 hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr)
1324 {
1325
1326         netvsc_channel_rollup(rxr, txr);
1327 }