hv_net_vsc.c revision 285236
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: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c 285236 2015-07-07 04:15:22Z whu $
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
51MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver");
52
53/*
54 * Forward declarations
55 */
56static void hv_nv_on_channel_callback(void *context);
57static int  hv_nv_init_send_buffer_with_net_vsp(struct hv_device *device);
58static int  hv_nv_init_rx_buffer_with_net_vsp(struct hv_device *device);
59static int  hv_nv_destroy_send_buffer(netvsc_dev *net_dev);
60static int  hv_nv_destroy_rx_buffer(netvsc_dev *net_dev);
61static int  hv_nv_connect_to_vsp(struct hv_device *device);
62static void hv_nv_on_send_completion(netvsc_dev *net_dev,
63    struct hv_device *device, hv_vm_packet_descriptor *pkt);
64static void hv_nv_on_receive(netvsc_dev *net_dev,
65    struct hv_device *device, hv_vm_packet_descriptor *pkt);
66
67/*
68 *
69 */
70static inline netvsc_dev *
71hv_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 */
91static inline netvsc_dev *
92hv_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 */
107static inline netvsc_dev *
108hv_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
128int
129hv_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 */
162static int
163hv_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
248cleanup:
249	hv_nv_destroy_rx_buffer(net_dev);
250
251exit:
252	return (ret);
253}
254
255/*
256 * Net VSC initialize send buffer with net VSP
257 */
258static int
259hv_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
336cleanup:
337	hv_nv_destroy_send_buffer(net_dev);
338
339exit:
340	return (ret);
341}
342
343/*
344 * Net VSC destroy receive buffer
345 */
346static int
347hv_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 */
413static int
414hv_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 */
484static int
485hv_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 */
522static int
523hv_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 */
558static int
559hv_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
648cleanup:
649	return (ret);
650}
651
652/*
653 * Net VSC disconnect from VSP
654 */
655static void
656hv_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 */
667netvsc_dev *
668hv_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
702close:
703	/* Now, we can close the channel safely */
704
705	hv_vmbus_channel_close(device->channel);
706
707cleanup:
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 */
723int
724hv_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 */
761static void
762hv_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 */
807int
808hv_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 */
856static void
857hv_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 */
928void
929hv_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
942retry_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 */
963static void
964hv_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}
1027