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