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