]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hyperv/netvsc/hv_net_vsc.c
MFV r294491: ntp 4.2.8p6.
[FreeBSD/FreeBSD.git] / sys / dev / hyperv / netvsc / hv_net_vsc.c
1 /*-
2  * Copyright (c) 2009-2012 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  * $FreeBSD$
29  */
30
31 /**
32  * HyperV vmbus network VSC (virtual services client) module
33  *
34  */
35
36
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/socket.h>
40 #include <sys/lock.h>
41 #include <net/if.h>
42 #include <net/if_var.h>
43 #include <net/if_arp.h>
44 #include <machine/bus.h>
45 #include <machine/atomic.h>
46
47 #include <dev/hyperv/include/hyperv.h>
48 #include "hv_net_vsc.h"
49 #include "hv_rndis.h"
50 #include "hv_rndis_filter.h"
51
52 MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver");
53
54 /*
55  * Forward declarations
56  */
57 static void hv_nv_on_channel_callback(void *context);
58 static int  hv_nv_init_send_buffer_with_net_vsp(struct hv_device *device);
59 static int  hv_nv_init_rx_buffer_with_net_vsp(struct hv_device *device);
60 static int  hv_nv_destroy_send_buffer(netvsc_dev *net_dev);
61 static int  hv_nv_destroy_rx_buffer(netvsc_dev *net_dev);
62 static int  hv_nv_connect_to_vsp(struct hv_device *device);
63 static void hv_nv_on_send_completion(netvsc_dev *net_dev,
64     struct hv_device *device, hv_vm_packet_descriptor *pkt);
65 static void hv_nv_on_receive(netvsc_dev *net_dev,
66     struct hv_device *device, hv_vm_packet_descriptor *pkt);
67
68 /*
69  *
70  */
71 static inline netvsc_dev *
72 hv_nv_alloc_net_device(struct hv_device *device)
73 {
74         netvsc_dev *net_dev;
75         hn_softc_t *sc = device_get_softc(device->device);
76
77         net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_NOWAIT | M_ZERO);
78         if (net_dev == NULL) {
79                 return (NULL);
80         }
81
82         net_dev->dev = device;
83         net_dev->destroy = FALSE;
84         sc->net_dev = net_dev;
85
86         return (net_dev);
87 }
88
89 /*
90  *
91  */
92 static inline netvsc_dev *
93 hv_nv_get_outbound_net_device(struct hv_device *device)
94 {
95         hn_softc_t *sc = device_get_softc(device->device);
96         netvsc_dev *net_dev = sc->net_dev;;
97
98         if ((net_dev != NULL) && net_dev->destroy) {
99                 return (NULL);
100         }
101
102         return (net_dev);
103 }
104
105 /*
106  *
107  */
108 static inline netvsc_dev *
109 hv_nv_get_inbound_net_device(struct hv_device *device)
110 {
111         hn_softc_t *sc = device_get_softc(device->device);
112         netvsc_dev *net_dev = sc->net_dev;;
113
114         if (net_dev == NULL) {
115                 return (net_dev);
116         }
117         /*
118          * When the device is being destroyed; we only
119          * permit incoming packets if and only if there
120          * are outstanding sends.
121          */
122         if (net_dev->destroy && net_dev->num_outstanding_sends == 0) {
123                 return (NULL);
124         }
125
126         return (net_dev);
127 }
128
129 int
130 hv_nv_get_next_send_section(netvsc_dev *net_dev)
131 {
132         unsigned long bitsmap_words = net_dev->bitsmap_words;
133         unsigned long *bitsmap = net_dev->send_section_bitsmap;
134         unsigned long idx;
135         int ret = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
136         int i;
137
138         for (i = 0; i < bitsmap_words; i++) {
139                 idx = ffs(~bitsmap[i]);
140                 if (0 == idx)
141                         continue;
142
143                 idx--;
144                 if (i * BITS_PER_LONG + idx >= net_dev->send_section_count)
145                         return (ret);
146
147                 if (synch_test_and_set_bit(idx, &bitsmap[i]))
148                         continue;
149
150                 ret = i * BITS_PER_LONG + idx;
151                 break;
152         }
153
154         return (ret);
155 }
156
157 /*
158  * Net VSC initialize receive buffer with net VSP
159  * 
160  * Net VSP:  Network virtual services client, also known as the
161  *     Hyper-V extensible switch and the synthetic data path.
162  */
163 static int 
164 hv_nv_init_rx_buffer_with_net_vsp(struct hv_device *device)
165 {
166         netvsc_dev *net_dev;
167         nvsp_msg *init_pkt;
168         int ret = 0;
169
170         net_dev = hv_nv_get_outbound_net_device(device);
171         if (!net_dev) {
172                 return (ENODEV);
173         }
174
175         net_dev->rx_buf = contigmalloc(net_dev->rx_buf_size, M_NETVSC,
176             M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
177
178         /*
179          * Establish the GPADL handle for this buffer on this channel.
180          * Note:  This call uses the vmbus connection rather than the
181          * channel to establish the gpadl handle. 
182          * GPADL:  Guest physical address descriptor list.
183          */
184         ret = hv_vmbus_channel_establish_gpadl(
185                 device->channel, net_dev->rx_buf,
186                 net_dev->rx_buf_size, &net_dev->rx_buf_gpadl_handle);
187         if (ret != 0) {
188                 goto cleanup;
189         }
190         
191         /* sema_wait(&ext->channel_init_sema); KYS CHECK */
192
193         /* Notify the NetVsp of the gpadl handle */
194         init_pkt = &net_dev->channel_init_packet;
195
196         memset(init_pkt, 0, sizeof(nvsp_msg));
197
198         init_pkt->hdr.msg_type = nvsp_msg_1_type_send_rx_buf;
199         init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle =
200             net_dev->rx_buf_gpadl_handle;
201         init_pkt->msgs.vers_1_msgs.send_rx_buf.id =
202             NETVSC_RECEIVE_BUFFER_ID;
203
204         /* Send the gpadl notification request */
205
206         ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
207             sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
208             HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
209             HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
210         if (ret != 0) {
211                 goto cleanup;
212         }
213
214         sema_wait(&net_dev->channel_init_sema);
215
216         /* Check the response */
217         if (init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.status
218             != nvsp_status_success) {
219                 ret = EINVAL;
220                 goto cleanup;
221         }
222
223         net_dev->rx_section_count =
224             init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections;
225
226         net_dev->rx_sections = malloc(net_dev->rx_section_count *
227             sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_NOWAIT);
228         if (net_dev->rx_sections == NULL) {
229                 ret = EINVAL;
230                 goto cleanup;
231         }
232         memcpy(net_dev->rx_sections, 
233             init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections,
234             net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section));
235
236
237         /*
238          * For first release, there should only be 1 section that represents
239          * the entire receive buffer
240          */
241         if (net_dev->rx_section_count != 1
242             || net_dev->rx_sections->offset != 0) {
243                 ret = EINVAL;
244                 goto cleanup;
245         }
246
247         goto exit;
248
249 cleanup:
250         hv_nv_destroy_rx_buffer(net_dev);
251         
252 exit:
253         return (ret);
254 }
255
256 /*
257  * Net VSC initialize send buffer with net VSP
258  */
259 static int 
260 hv_nv_init_send_buffer_with_net_vsp(struct hv_device *device)
261 {
262         netvsc_dev *net_dev;
263         nvsp_msg *init_pkt;
264         int ret = 0;
265
266         net_dev = hv_nv_get_outbound_net_device(device);
267         if (!net_dev) {
268                 return (ENODEV);
269         }
270
271         net_dev->send_buf  = contigmalloc(net_dev->send_buf_size, M_NETVSC,
272             M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
273         if (net_dev->send_buf == NULL) {
274                 ret = ENOMEM;
275                 goto cleanup;
276         }
277
278         /*
279          * Establish the gpadl handle for this buffer on this channel.
280          * Note:  This call uses the vmbus connection rather than the
281          * channel to establish the gpadl handle. 
282          */
283         ret = hv_vmbus_channel_establish_gpadl(device->channel,
284             net_dev->send_buf, net_dev->send_buf_size,
285             &net_dev->send_buf_gpadl_handle);
286         if (ret != 0) {
287                 goto cleanup;
288         }
289
290         /* Notify the NetVsp of the gpadl handle */
291
292         init_pkt = &net_dev->channel_init_packet;
293
294         memset(init_pkt, 0, sizeof(nvsp_msg));
295
296         init_pkt->hdr.msg_type = nvsp_msg_1_type_send_send_buf;
297         init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle =
298             net_dev->send_buf_gpadl_handle;
299         init_pkt->msgs.vers_1_msgs.send_rx_buf.id =
300             NETVSC_SEND_BUFFER_ID;
301
302         /* Send the gpadl notification request */
303
304         ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
305             sizeof(nvsp_msg), (uint64_t)init_pkt,
306             HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
307             HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
308         if (ret != 0) {
309                 goto cleanup;
310         }
311
312         sema_wait(&net_dev->channel_init_sema);
313
314         /* Check the response */
315         if (init_pkt->msgs.vers_1_msgs.send_send_buf_complete.status
316             != nvsp_status_success) {
317                 ret = EINVAL;
318                 goto cleanup;
319         }
320
321         net_dev->send_section_size =
322             init_pkt->msgs.vers_1_msgs.send_send_buf_complete.section_size;
323         net_dev->send_section_count =
324             net_dev->send_buf_size / net_dev->send_section_size;
325         net_dev->bitsmap_words = howmany(net_dev->send_section_count,
326             BITS_PER_LONG);
327         net_dev->send_section_bitsmap =
328             malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC,
329             M_NOWAIT | M_ZERO);
330         if (NULL == net_dev->send_section_bitsmap) {
331                 ret = ENOMEM;
332                 goto cleanup;
333         }
334
335         goto exit;
336
337 cleanup:
338         hv_nv_destroy_send_buffer(net_dev);
339         
340 exit:
341         return (ret);
342 }
343
344 /*
345  * Net VSC destroy receive buffer
346  */
347 static int
348 hv_nv_destroy_rx_buffer(netvsc_dev *net_dev)
349 {
350         nvsp_msg *revoke_pkt;
351         int ret = 0;
352
353         /*
354          * If we got a section count, it means we received a
355          * send_rx_buf_complete msg 
356          * (ie sent nvsp_msg_1_type_send_rx_buf msg) therefore,
357          * we need to send a revoke msg here
358          */
359         if (net_dev->rx_section_count) {
360                 /* Send the revoke receive buffer */
361                 revoke_pkt = &net_dev->revoke_packet;
362                 memset(revoke_pkt, 0, sizeof(nvsp_msg));
363
364                 revoke_pkt->hdr.msg_type = nvsp_msg_1_type_revoke_rx_buf;
365                 revoke_pkt->msgs.vers_1_msgs.revoke_rx_buf.id =
366                     NETVSC_RECEIVE_BUFFER_ID;
367
368                 ret = hv_vmbus_channel_send_packet(net_dev->dev->channel,
369                     revoke_pkt, sizeof(nvsp_msg),
370                     (uint64_t)(uintptr_t)revoke_pkt,
371                     HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
372
373                 /*
374                  * If we failed here, we might as well return and have a leak 
375                  * rather than continue and a bugchk
376                  */
377                 if (ret != 0) {
378                         return (ret);
379                 }
380         }
381                 
382         /* Tear down the gpadl on the vsp end */
383         if (net_dev->rx_buf_gpadl_handle) {
384                 ret = hv_vmbus_channel_teardown_gpdal(net_dev->dev->channel,
385                     net_dev->rx_buf_gpadl_handle);
386                 /*
387                  * If we failed here, we might as well return and have a leak 
388                  * rather than continue and a bugchk
389                  */
390                 if (ret != 0) {
391                         return (ret);
392                 }
393                 net_dev->rx_buf_gpadl_handle = 0;
394         }
395
396         if (net_dev->rx_buf) {
397                 /* Free up the receive buffer */
398                 contigfree(net_dev->rx_buf, net_dev->rx_buf_size, M_NETVSC);
399                 net_dev->rx_buf = NULL;
400         }
401
402         if (net_dev->rx_sections) {
403                 free(net_dev->rx_sections, M_NETVSC);
404                 net_dev->rx_sections = NULL;
405                 net_dev->rx_section_count = 0;
406         }
407
408         return (ret);
409 }
410
411 /*
412  * Net VSC destroy send buffer
413  */
414 static int
415 hv_nv_destroy_send_buffer(netvsc_dev *net_dev)
416 {
417         nvsp_msg *revoke_pkt;
418         int ret = 0;
419
420         /*
421          * If we got a section count, it means we received a
422          * send_rx_buf_complete msg 
423          * (ie sent nvsp_msg_1_type_send_rx_buf msg) therefore,
424          * we need to send a revoke msg here
425          */
426         if (net_dev->send_section_size) {
427                 /* Send the revoke send buffer */
428                 revoke_pkt = &net_dev->revoke_packet;
429                 memset(revoke_pkt, 0, sizeof(nvsp_msg));
430
431                 revoke_pkt->hdr.msg_type =
432                     nvsp_msg_1_type_revoke_send_buf;
433                 revoke_pkt->msgs.vers_1_msgs.revoke_send_buf.id =
434                     NETVSC_SEND_BUFFER_ID;
435
436                 ret = hv_vmbus_channel_send_packet(net_dev->dev->channel,
437                     revoke_pkt, sizeof(nvsp_msg),
438                     (uint64_t)(uintptr_t)revoke_pkt,
439                     HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
440                 /*
441                  * If we failed here, we might as well return and have a leak 
442                  * rather than continue and a bugchk
443                  */
444                 if (ret != 0) {
445                         return (ret);
446                 }
447         }
448                 
449         /* Tear down the gpadl on the vsp end */
450         if (net_dev->send_buf_gpadl_handle) {
451                 ret = hv_vmbus_channel_teardown_gpdal(net_dev->dev->channel,
452                     net_dev->send_buf_gpadl_handle);
453
454                 /*
455                  * If we failed here, we might as well return and have a leak 
456                  * rather than continue and a bugchk
457                  */
458                 if (ret != 0) {
459                         return (ret);
460                 }
461                 net_dev->send_buf_gpadl_handle = 0;
462         }
463
464         if (net_dev->send_buf) {
465                 /* Free up the receive buffer */
466                 contigfree(net_dev->send_buf, net_dev->send_buf_size, M_NETVSC);
467                 net_dev->send_buf = NULL;
468         }
469
470         if (net_dev->send_section_bitsmap) {
471                 free(net_dev->send_section_bitsmap, M_NETVSC);
472         }
473
474         return (ret);
475 }
476
477
478 /*
479  * Attempt to negotiate the caller-specified NVSP version
480  *
481  * For NVSP v2, Server 2008 R2 does not set
482  * init_pkt->msgs.init_msgs.init_compl.negotiated_prot_vers
483  * to the negotiated version, so we cannot rely on that.
484  */
485 static int
486 hv_nv_negotiate_nvsp_protocol(struct hv_device *device, netvsc_dev *net_dev,
487     uint32_t nvsp_ver)
488 {
489         nvsp_msg *init_pkt;
490         int ret;
491
492         init_pkt = &net_dev->channel_init_packet;
493         memset(init_pkt, 0, sizeof(nvsp_msg));
494         init_pkt->hdr.msg_type = nvsp_msg_type_init;
495
496         /*
497          * Specify parameter as the only acceptable protocol version
498          */
499         init_pkt->msgs.init_msgs.init.p1.protocol_version = nvsp_ver;
500         init_pkt->msgs.init_msgs.init.protocol_version_2 = nvsp_ver;
501
502         /* Send the init request */
503         ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
504             sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
505             HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
506             HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
507         if (ret != 0)
508                 return (-1);
509
510         sema_wait(&net_dev->channel_init_sema);
511
512         if (init_pkt->msgs.init_msgs.init_compl.status != nvsp_status_success)
513                 return (EINVAL);
514
515         return (0);
516 }
517
518 /*
519  * Send NDIS version 2 config packet containing MTU.
520  *
521  * Not valid for NDIS version 1.
522  */
523 static int
524 hv_nv_send_ndis_config(struct hv_device *device, uint32_t mtu)
525 {
526         netvsc_dev *net_dev;
527         nvsp_msg *init_pkt;
528         int ret;
529
530         net_dev = hv_nv_get_outbound_net_device(device);
531         if (!net_dev)
532                 return (-ENODEV);
533
534         /*
535          * Set up configuration packet, write MTU
536          * Indicate we are capable of handling VLAN tags
537          */
538         init_pkt = &net_dev->channel_init_packet;
539         memset(init_pkt, 0, sizeof(nvsp_msg));
540         init_pkt->hdr.msg_type = nvsp_msg_2_type_send_ndis_config;
541         init_pkt->msgs.vers_2_msgs.send_ndis_config.mtu = mtu;
542         init_pkt->
543                 msgs.vers_2_msgs.send_ndis_config.capabilities.u1.u2.ieee8021q
544                 = 1;
545
546         /* Send the configuration packet */
547         ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
548             sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
549             HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
550         if (ret != 0)
551                 return (-EINVAL);
552
553         return (0);
554 }
555
556 /*
557  * Net VSC connect to VSP
558  */
559 static int
560 hv_nv_connect_to_vsp(struct hv_device *device)
561 {
562         netvsc_dev *net_dev;
563         nvsp_msg *init_pkt;
564         uint32_t ndis_version;
565         uint32_t protocol_list[] = { NVSP_PROTOCOL_VERSION_1,
566             NVSP_PROTOCOL_VERSION_2,
567             NVSP_PROTOCOL_VERSION_4,
568             NVSP_PROTOCOL_VERSION_5 };
569         int i;
570         int protocol_number = nitems(protocol_list);
571         int ret = 0;
572         device_t dev = device->device;
573         hn_softc_t *sc = device_get_softc(dev);
574         struct ifnet *ifp = sc->hn_ifp;
575
576         net_dev = hv_nv_get_outbound_net_device(device);
577         if (!net_dev) {
578                 return (ENODEV);
579         }
580
581         /*
582          * Negotiate the NVSP version.  Try the latest NVSP first.
583          */
584         for (i = protocol_number - 1; i >= 0; i--) {
585                 if (hv_nv_negotiate_nvsp_protocol(device, net_dev,
586                     protocol_list[i]) == 0) {
587                         net_dev->nvsp_version = protocol_list[i];
588                         if (bootverbose)
589                                 device_printf(dev, "Netvsc: got version 0x%x\n",
590                                     net_dev->nvsp_version);
591                         break;
592                 }
593         }
594
595         if (i < 0) {
596                 if (bootverbose)
597                         device_printf(dev, "failed to negotiate a valid "
598                             "protocol.\n");
599                 return (EPROTO);
600         }
601
602         /*
603          * Set the MTU if supported by this NVSP protocol version
604          * This needs to be right after the NVSP init message per Haiyang
605          */
606         if (net_dev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
607                 ret = hv_nv_send_ndis_config(device, ifp->if_mtu);
608
609         /*
610          * Send the NDIS version
611          */
612         init_pkt = &net_dev->channel_init_packet;
613
614         memset(init_pkt, 0, sizeof(nvsp_msg));
615
616         if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_4) {
617                 ndis_version = NDIS_VERSION_6_1;
618         } else {
619                 ndis_version = NDIS_VERSION_6_30;
620         }
621
622         init_pkt->hdr.msg_type = nvsp_msg_1_type_send_ndis_vers;
623         init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_major_vers =
624             (ndis_version & 0xFFFF0000) >> 16;
625         init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_minor_vers =
626             ndis_version & 0xFFFF;
627
628         /* Send the init request */
629
630         ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
631             sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
632             HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
633         if (ret != 0) {
634                 goto cleanup;
635         }
636         /*
637          * TODO:  BUGBUG - We have to wait for the above msg since the netvsp
638          * uses KMCL which acknowledges packet (completion packet) 
639          * since our Vmbus always set the
640          * HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
641          */
642         /* sema_wait(&NetVscChannel->channel_init_sema); */
643
644         /* Post the big receive buffer to NetVSP */
645         if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_2)
646                 net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY;
647         else
648                 net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
649         net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
650
651         ret = hv_nv_init_rx_buffer_with_net_vsp(device);
652         if (ret == 0)
653                 ret = hv_nv_init_send_buffer_with_net_vsp(device);
654
655 cleanup:
656         return (ret);
657 }
658
659 /*
660  * Net VSC disconnect from VSP
661  */
662 static void
663 hv_nv_disconnect_from_vsp(netvsc_dev *net_dev)
664 {
665         hv_nv_destroy_rx_buffer(net_dev);
666         hv_nv_destroy_send_buffer(net_dev);
667 }
668
669 /*
670  * Net VSC on device add
671  * 
672  * Callback when the device belonging to this driver is added
673  */
674 netvsc_dev *
675 hv_nv_on_device_add(struct hv_device *device, void *additional_info)
676 {
677         netvsc_dev *net_dev;
678         int ret = 0;
679
680         net_dev = hv_nv_alloc_net_device(device);
681         if (!net_dev)
682                 goto cleanup;
683
684         /* Initialize the NetVSC channel extension */
685
686         sema_init(&net_dev->channel_init_sema, 0, "netdev_sema");
687
688         /*
689          * Open the channel
690          */
691         ret = hv_vmbus_channel_open(device->channel,
692             NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE,
693             NULL, 0, hv_nv_on_channel_callback, device);
694         if (ret != 0)
695                 goto cleanup;
696
697         /*
698          * Connect with the NetVsp
699          */
700         ret = hv_nv_connect_to_vsp(device);
701         if (ret != 0)
702                 goto close;
703
704         return (net_dev);
705
706 close:
707         /* Now, we can close the channel safely */
708
709         hv_vmbus_channel_close(device->channel);
710
711 cleanup:
712         /*
713          * Free the packet buffers on the netvsc device packet queue.
714          * Release other resources.
715          */
716         if (net_dev) {
717                 sema_destroy(&net_dev->channel_init_sema);
718                 free(net_dev, M_NETVSC);
719         }
720
721         return (NULL);
722 }
723
724 /*
725  * Net VSC on device remove
726  */
727 int
728 hv_nv_on_device_remove(struct hv_device *device, boolean_t destroy_channel)
729 {
730         hn_softc_t *sc = device_get_softc(device->device);
731         netvsc_dev *net_dev = sc->net_dev;;
732         
733         /* Stop outbound traffic ie sends and receives completions */
734         mtx_lock(&device->channel->inbound_lock);
735         net_dev->destroy = TRUE;
736         mtx_unlock(&device->channel->inbound_lock);
737
738         /* Wait for all send completions */
739         while (net_dev->num_outstanding_sends) {
740                 DELAY(100);
741         }
742
743         hv_nv_disconnect_from_vsp(net_dev);
744
745         /* At this point, no one should be accessing net_dev except in here */
746
747         /* Now, we can close the channel safely */
748
749         if (!destroy_channel) {
750                 device->channel->state =
751                     HV_CHANNEL_CLOSING_NONDESTRUCTIVE_STATE;
752         }
753
754         hv_vmbus_channel_close(device->channel);
755
756         sema_destroy(&net_dev->channel_init_sema);
757         free(net_dev, M_NETVSC);
758
759         return (0);
760 }
761
762 /*
763  * Net VSC on send completion
764  */
765 static void
766 hv_nv_on_send_completion(netvsc_dev *net_dev,
767     struct hv_device *device, hv_vm_packet_descriptor *pkt)
768 {
769         nvsp_msg *nvsp_msg_pkt;
770         netvsc_packet *net_vsc_pkt;
771
772         nvsp_msg_pkt =
773             (nvsp_msg *)((unsigned long)pkt + (pkt->data_offset8 << 3));
774
775         if (nvsp_msg_pkt->hdr.msg_type == nvsp_msg_type_init_complete
776                 || nvsp_msg_pkt->hdr.msg_type
777                         == nvsp_msg_1_type_send_rx_buf_complete
778                 || nvsp_msg_pkt->hdr.msg_type
779                         == nvsp_msg_1_type_send_send_buf_complete) {
780                 /* Copy the response back */
781                 memcpy(&net_dev->channel_init_packet, nvsp_msg_pkt,
782                     sizeof(nvsp_msg));
783                 sema_post(&net_dev->channel_init_sema);
784         } else if (nvsp_msg_pkt->hdr.msg_type ==
785                     nvsp_msg_1_type_send_rndis_pkt_complete) {
786                 /* Get the send context */
787                 net_vsc_pkt =
788                     (netvsc_packet *)(unsigned long)pkt->transaction_id;
789                 if (NULL != net_vsc_pkt) {
790                         if (net_vsc_pkt->send_buf_section_idx !=
791                             NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
792                                 synch_change_bit(net_vsc_pkt->send_buf_section_idx,
793                                     net_dev->send_section_bitsmap);
794                         }
795                         
796                         /* Notify the layer above us */
797                         net_vsc_pkt->compl.send.on_send_completion(
798                             net_vsc_pkt->compl.send.send_completion_context);
799
800                 }
801
802                 atomic_subtract_int(&net_dev->num_outstanding_sends, 1);
803         }
804 }
805
806 /*
807  * Net VSC on send
808  * Sends a packet on the specified Hyper-V device.
809  * Returns 0 on success, non-zero on failure.
810  */
811 int
812 hv_nv_on_send(struct hv_device *device, netvsc_packet *pkt)
813 {
814         netvsc_dev *net_dev;
815         nvsp_msg send_msg;
816         int ret;
817
818         net_dev = hv_nv_get_outbound_net_device(device);
819         if (!net_dev)
820                 return (ENODEV);
821
822         send_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt;
823         if (pkt->is_data_pkt) {
824                 /* 0 is RMC_DATA */
825                 send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 0;
826         } else {
827                 /* 1 is RMC_CONTROL */
828                 send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 1;
829         }
830
831         send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_idx =
832             pkt->send_buf_section_idx;
833         send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size =
834             pkt->send_buf_section_size;
835
836         if (pkt->page_buf_count) {
837                 ret = hv_vmbus_channel_send_packet_pagebuffer(device->channel,
838                     pkt->page_buffers, pkt->page_buf_count,
839                     &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt);
840         } else {
841                 ret = hv_vmbus_channel_send_packet(device->channel,
842                     &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt,
843                     HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
844                     HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
845         }
846
847         /* Record outstanding send only if send_packet() succeeded */
848         if (ret == 0)
849                 atomic_add_int(&net_dev->num_outstanding_sends, 1);
850
851         return (ret);
852 }
853
854 /*
855  * Net VSC on receive
856  *
857  * In the FreeBSD Hyper-V virtual world, this function deals exclusively
858  * with virtual addresses.
859  */
860 static void
861 hv_nv_on_receive(netvsc_dev *net_dev, struct hv_device *device,
862     hv_vm_packet_descriptor *pkt)
863 {
864         hv_vm_transfer_page_packet_header *vm_xfer_page_pkt;
865         nvsp_msg *nvsp_msg_pkt;
866         netvsc_packet vsc_pkt;
867         netvsc_packet *net_vsc_pkt = &vsc_pkt;
868         device_t dev = device->device;
869         int count = 0;
870         int i = 0;
871         int status = nvsp_status_success;
872
873         /*
874          * All inbound packets other than send completion should be
875          * xfer page packet.
876          */
877         if (pkt->type != HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES) {
878                 device_printf(dev, "packet type %d is invalid!\n", pkt->type);
879                 return;
880         }
881
882         nvsp_msg_pkt = (nvsp_msg *)((unsigned long)pkt
883                 + (pkt->data_offset8 << 3));
884
885         /* Make sure this is a valid nvsp packet */
886         if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) {
887                 device_printf(dev, "packet hdr type %d is invalid!\n",
888                     pkt->type);
889                 return;
890         }
891         
892         vm_xfer_page_pkt = (hv_vm_transfer_page_packet_header *)pkt;
893
894         if (vm_xfer_page_pkt->transfer_page_set_id !=
895             NETVSC_RECEIVE_BUFFER_ID) {
896                 device_printf(dev, "transfer_page_set_id %d is invalid!\n",
897                     vm_xfer_page_pkt->transfer_page_set_id);
898                 return;
899         }
900
901         count = vm_xfer_page_pkt->range_count;
902         net_vsc_pkt->device = device;
903
904         /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */
905         for (i = 0; i < count; i++) {
906                 net_vsc_pkt->status = nvsp_status_success;
907                 net_vsc_pkt->data = (void *)((unsigned long)net_dev->rx_buf +
908                     vm_xfer_page_pkt->ranges[i].byte_offset);
909                 net_vsc_pkt->tot_data_buf_len = 
910                     vm_xfer_page_pkt->ranges[i].byte_count;
911
912                 hv_rf_on_receive(net_dev, device, net_vsc_pkt);
913                 if (net_vsc_pkt->status != nvsp_status_success) {
914                         status = nvsp_status_failure;
915                 }
916         }
917         
918         /*
919          * Moved completion call back here so that all received 
920          * messages (not just data messages) will trigger a response
921          * message back to the host.
922          */
923         hv_nv_on_receive_completion(device, vm_xfer_page_pkt->d.transaction_id,
924             status);
925         hv_rf_receive_rollup(net_dev);
926 }
927
928 /*
929  * Net VSC on receive completion
930  *
931  * Send a receive completion packet to RNDIS device (ie NetVsp)
932  */
933 void
934 hv_nv_on_receive_completion(struct hv_device *device, uint64_t tid,
935     uint32_t status)
936 {
937         nvsp_msg rx_comp_msg;
938         int retries = 0;
939         int ret = 0;
940         
941         rx_comp_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt_complete;
942
943         /* Pass in the status */
944         rx_comp_msg.msgs.vers_1_msgs.send_rndis_pkt_complete.status =
945             status;
946
947 retry_send_cmplt:
948         /* Send the completion */
949         ret = hv_vmbus_channel_send_packet(device->channel, &rx_comp_msg,
950             sizeof(nvsp_msg), tid, HV_VMBUS_PACKET_TYPE_COMPLETION, 0);
951         if (ret == 0) {
952                 /* success */
953                 /* no-op */
954         } else if (ret == EAGAIN) {
955                 /* no more room... wait a bit and attempt to retry 3 times */
956                 retries++;
957
958                 if (retries < 4) {
959                         DELAY(100);
960                         goto retry_send_cmplt;
961                 }
962         }
963 }
964
965 /*
966  * Net VSC on channel callback
967  */
968 static void
969 hv_nv_on_channel_callback(void *context)
970 {
971         struct hv_device *device = (struct hv_device *)context;
972         netvsc_dev *net_dev;
973         device_t dev = device->device;
974         uint32_t bytes_rxed;
975         uint64_t request_id;
976         hv_vm_packet_descriptor *desc;
977         uint8_t *buffer;
978         int bufferlen = NETVSC_PACKET_SIZE;
979         int ret = 0;
980
981         net_dev = hv_nv_get_inbound_net_device(device);
982         if (net_dev == NULL)
983                 return;
984
985         buffer = net_dev->callback_buf;
986
987         do {
988                 ret = hv_vmbus_channel_recv_packet_raw(device->channel,
989                     buffer, bufferlen, &bytes_rxed, &request_id);
990                 if (ret == 0) {
991                         if (bytes_rxed > 0) {
992                                 desc = (hv_vm_packet_descriptor *)buffer;
993                                 switch (desc->type) {
994                                 case HV_VMBUS_PACKET_TYPE_COMPLETION:
995                                         hv_nv_on_send_completion(net_dev, device, desc);
996                                         break;
997                                 case HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES:
998                                         hv_nv_on_receive(net_dev, device, desc);
999                                         break;
1000                                 default:
1001                                         device_printf(dev,
1002                                             "hv_cb recv unknow type %d "
1003                                             " packet\n", desc->type);
1004                                         break;
1005                                 }
1006                         } else {
1007                                 break;
1008                         }
1009                 } else if (ret == ENOBUFS) {
1010                         /* Handle large packet */
1011                         if (bufferlen > NETVSC_PACKET_SIZE) {
1012                                 free(buffer, M_NETVSC);
1013                                 buffer = NULL;
1014                         }
1015
1016                         /* alloc new buffer */
1017                         buffer = malloc(bytes_rxed, M_NETVSC, M_NOWAIT);
1018                         if (buffer == NULL) {
1019                                 device_printf(dev,
1020                                     "hv_cb malloc buffer failed, len=%u\n",
1021                                     bytes_rxed);
1022                                 bufferlen = 0;
1023                                 break;
1024                         }
1025                         bufferlen = bytes_rxed;
1026                 }
1027         } while (1);
1028
1029         if (bufferlen > NETVSC_PACKET_SIZE)
1030                 free(buffer, M_NETVSC);
1031 }