hn_nvs.c revision 307199
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 307199 2016-10-13 07:52:39Z 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/limits.h>
41#include <sys/lock.h>
42#include <net/if.h>
43#include <net/if_arp.h>
44#include <machine/bus.h>
45#include <machine/atomic.h>
46
47#include <dev/hyperv/include/hyperv.h>
48#include <dev/hyperv/include/vmbus_xact.h>
49#include <dev/hyperv/netvsc/hv_net_vsc.h>
50#include <dev/hyperv/netvsc/hv_rndis_filter.h>
51#include <dev/hyperv/netvsc/if_hnreg.h>
52#include <dev/hyperv/netvsc/if_hnvar.h>
53
54MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver");
55
56/*
57 * Forward declarations
58 */
59static void hv_nv_on_channel_callback(struct vmbus_channel *chan,
60    void *xrxr);
61static int  hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc);
62static int  hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *, int);
63static int  hv_nv_destroy_send_buffer(struct hn_softc *sc);
64static int  hv_nv_destroy_rx_buffer(struct hn_softc *sc);
65static int  hv_nv_connect_to_vsp(struct hn_softc *sc);
66static void hv_nv_on_send_completion(struct hn_softc *sc,
67    struct vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt);
68static void hv_nv_on_receive_completion(struct vmbus_channel *chan,
69    uint64_t tid);
70static void hv_nv_on_receive(struct hn_softc *sc,
71    struct hn_rx_ring *rxr, struct vmbus_channel *chan,
72    const struct vmbus_chanpkt_hdr *pkt);
73static void hn_nvs_sent_none(struct hn_send_ctx *sndc,
74    struct hn_softc *, struct vmbus_channel *chan,
75    const void *, int);
76
77struct hn_send_ctx	hn_send_ctx_none =
78    HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL);
79
80uint32_t
81hn_chim_alloc(struct hn_softc *sc)
82{
83	int i, bmap_cnt = sc->hn_chim_bmap_cnt;
84	u_long *bmap = sc->hn_chim_bmap;
85	uint32_t ret = HN_NVS_CHIM_IDX_INVALID;
86
87	for (i = 0; i < bmap_cnt; ++i) {
88		int idx;
89
90		idx = ffsl(~bmap[i]);
91		if (idx == 0)
92			continue;
93
94		--idx; /* ffsl is 1-based */
95		KASSERT(i * LONG_BIT + idx < sc->hn_chim_cnt,
96		    ("invalid i %d and idx %d", i, idx));
97
98		if (atomic_testandset_long(&bmap[i], idx))
99			continue;
100
101		ret = i * LONG_BIT + idx;
102		break;
103	}
104	return (ret);
105}
106
107const void *
108hn_nvs_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact,
109    void *req, int reqlen, size_t *resplen0, uint32_t type)
110{
111	struct hn_send_ctx sndc;
112	size_t resplen, min_resplen = *resplen0;
113	const struct hn_nvs_hdr *hdr;
114	int error;
115
116	KASSERT(min_resplen >= sizeof(*hdr),
117	    ("invalid minimum response len %zu", min_resplen));
118
119	/*
120	 * Execute the xact setup by the caller.
121	 */
122	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
123
124	vmbus_xact_activate(xact);
125	error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC,
126	    req, reqlen, &sndc);
127	if (error) {
128		vmbus_xact_deactivate(xact);
129		return (NULL);
130	}
131	hdr = vmbus_xact_wait(xact, &resplen);
132
133	/*
134	 * Check this NVS response message.
135	 */
136	if (resplen < min_resplen) {
137		if_printf(sc->hn_ifp, "invalid NVS resp len %zu\n", resplen);
138		return (NULL);
139	}
140	if (hdr->nvs_type != type) {
141		if_printf(sc->hn_ifp, "unexpected NVS resp 0x%08x, "
142		    "expect 0x%08x\n", hdr->nvs_type, type);
143		return (NULL);
144	}
145	/* All pass! */
146	*resplen0 = resplen;
147	return (hdr);
148}
149
150static __inline int
151hn_nvs_req_send(struct hn_softc *sc, void *req, int reqlen)
152{
153
154	return (hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE,
155	    req, reqlen, &hn_send_ctx_none));
156}
157
158/*
159 * Net VSC initialize receive buffer with net VSP
160 *
161 * Net VSP:  Network virtual services client, also known as the
162 *     Hyper-V extensible switch and the synthetic data path.
163 */
164static int
165hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc, int rxbuf_size)
166{
167	struct vmbus_xact *xact = NULL;
168	struct hn_nvs_rxbuf_conn *conn;
169	const struct hn_nvs_rxbuf_connresp *resp;
170	size_t resp_len;
171	uint32_t status;
172	int error;
173
174	KASSERT(rxbuf_size <= NETVSC_RECEIVE_BUFFER_SIZE,
175	    ("invalid rxbuf size %d", rxbuf_size));
176
177	/*
178	 * Connect the RXBUF GPADL to the primary channel.
179	 *
180	 * NOTE:
181	 * Only primary channel has RXBUF connected to it.  Sub-channels
182	 * just share this RXBUF.
183	 */
184	error = vmbus_chan_gpadl_connect(sc->hn_prichan,
185	    sc->hn_rxbuf_dma.hv_paddr, rxbuf_size, &sc->hn_rxbuf_gpadl);
186	if (error) {
187		if_printf(sc->hn_ifp, "rxbuf gpadl connect failed: %d\n",
188		    error);
189		goto cleanup;
190	}
191
192	/*
193	 * Connect RXBUF to NVS.
194	 */
195
196	xact = vmbus_xact_get(sc->hn_xact, sizeof(*conn));
197	if (xact == NULL) {
198		if_printf(sc->hn_ifp, "no xact for nvs rxbuf conn\n");
199		error = ENXIO;
200		goto cleanup;
201	}
202	conn = vmbus_xact_req_data(xact);
203	conn->nvs_type = HN_NVS_TYPE_RXBUF_CONN;
204	conn->nvs_gpadl = sc->hn_rxbuf_gpadl;
205	conn->nvs_sig = HN_NVS_RXBUF_SIG;
206
207	resp_len = sizeof(*resp);
208	resp = hn_nvs_xact_execute(sc, xact, conn, sizeof(*conn), &resp_len,
209	    HN_NVS_TYPE_RXBUF_CONNRESP);
210	if (resp == NULL) {
211		if_printf(sc->hn_ifp, "exec rxbuf conn failed\n");
212		error = EIO;
213		goto cleanup;
214	}
215
216	status = resp->nvs_status;
217	vmbus_xact_put(xact);
218	xact = NULL;
219
220	if (status != HN_NVS_STATUS_OK) {
221		if_printf(sc->hn_ifp, "rxbuf conn failed: %x\n", status);
222		error = EIO;
223		goto cleanup;
224	}
225	sc->hn_flags |= HN_FLAG_RXBUF_CONNECTED;
226
227	return (0);
228
229cleanup:
230	if (xact != NULL)
231		vmbus_xact_put(xact);
232	hv_nv_destroy_rx_buffer(sc);
233	return (error);
234}
235
236/*
237 * Net VSC initialize send buffer with net VSP
238 */
239static int
240hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc)
241{
242	struct vmbus_xact *xact = NULL;
243	struct hn_nvs_chim_conn *chim;
244	const struct hn_nvs_chim_connresp *resp;
245	size_t resp_len;
246	uint32_t status, sectsz;
247	int error;
248
249	/*
250	 * Connect chimney sending buffer GPADL to the primary channel.
251	 *
252	 * NOTE:
253	 * Only primary channel has chimney sending buffer connected to it.
254	 * Sub-channels just share this chimney sending buffer.
255	 */
256	error = vmbus_chan_gpadl_connect(sc->hn_prichan,
257  	    sc->hn_chim_dma.hv_paddr, NETVSC_SEND_BUFFER_SIZE,
258	    &sc->hn_chim_gpadl);
259	if (error) {
260		if_printf(sc->hn_ifp, "chimney sending buffer gpadl "
261		    "connect failed: %d\n", error);
262		goto cleanup;
263	}
264
265	/*
266	 * Connect chimney sending buffer to NVS
267	 */
268
269	xact = vmbus_xact_get(sc->hn_xact, sizeof(*chim));
270	if (xact == NULL) {
271		if_printf(sc->hn_ifp, "no xact for nvs chim conn\n");
272		error = ENXIO;
273		goto cleanup;
274	}
275	chim = vmbus_xact_req_data(xact);
276	chim->nvs_type = HN_NVS_TYPE_CHIM_CONN;
277	chim->nvs_gpadl = sc->hn_chim_gpadl;
278	chim->nvs_sig = HN_NVS_CHIM_SIG;
279
280	resp_len = sizeof(*resp);
281	resp = hn_nvs_xact_execute(sc, xact, chim, sizeof(*chim), &resp_len,
282	    HN_NVS_TYPE_CHIM_CONNRESP);
283	if (resp == NULL) {
284		if_printf(sc->hn_ifp, "exec chim conn failed\n");
285		error = EIO;
286		goto cleanup;
287	}
288
289	status = resp->nvs_status;
290	sectsz = resp->nvs_sectsz;
291	vmbus_xact_put(xact);
292	xact = NULL;
293
294	if (status != HN_NVS_STATUS_OK) {
295		if_printf(sc->hn_ifp, "chim conn failed: %x\n", status);
296		error = EIO;
297		goto cleanup;
298	}
299	if (sectsz == 0) {
300		if_printf(sc->hn_ifp, "zero chimney sending buffer "
301		    "section size\n");
302		return 0;
303	}
304
305	sc->hn_chim_szmax = sectsz;
306	sc->hn_chim_cnt = NETVSC_SEND_BUFFER_SIZE / sc->hn_chim_szmax;
307	if (NETVSC_SEND_BUFFER_SIZE % sc->hn_chim_szmax != 0) {
308		if_printf(sc->hn_ifp, "chimney sending sections are "
309		    "not properly aligned\n");
310	}
311	if (sc->hn_chim_cnt % LONG_BIT != 0) {
312		if_printf(sc->hn_ifp, "discard %d chimney sending sections\n",
313		    sc->hn_chim_cnt % LONG_BIT);
314	}
315
316	sc->hn_chim_bmap_cnt = sc->hn_chim_cnt / LONG_BIT;
317	sc->hn_chim_bmap = malloc(sc->hn_chim_bmap_cnt * sizeof(u_long),
318	    M_NETVSC, M_WAITOK | M_ZERO);
319
320	/* Done! */
321	sc->hn_flags |= HN_FLAG_CHIM_CONNECTED;
322	if (bootverbose) {
323		if_printf(sc->hn_ifp, "chimney sending buffer %d/%d\n",
324		    sc->hn_chim_szmax, sc->hn_chim_cnt);
325	}
326	return 0;
327
328cleanup:
329	if (xact != NULL)
330		vmbus_xact_put(xact);
331	hv_nv_destroy_send_buffer(sc);
332	return (error);
333}
334
335/*
336 * Net VSC destroy receive buffer
337 */
338static int
339hv_nv_destroy_rx_buffer(struct hn_softc *sc)
340{
341	int ret = 0;
342
343	if (sc->hn_flags & HN_FLAG_RXBUF_CONNECTED) {
344		struct hn_nvs_rxbuf_disconn disconn;
345
346		/*
347		 * Disconnect RXBUF from NVS.
348		 */
349		memset(&disconn, 0, sizeof(disconn));
350		disconn.nvs_type = HN_NVS_TYPE_RXBUF_DISCONN;
351		disconn.nvs_sig = HN_NVS_RXBUF_SIG;
352
353		/* NOTE: No response. */
354		ret = hn_nvs_req_send(sc, &disconn, sizeof(disconn));
355		if (ret != 0) {
356			if_printf(sc->hn_ifp,
357			    "send rxbuf disconn failed: %d\n", ret);
358			return (ret);
359		}
360		sc->hn_flags &= ~HN_FLAG_RXBUF_CONNECTED;
361	}
362
363	if (sc->hn_rxbuf_gpadl != 0) {
364		/*
365		 * Disconnect RXBUF from primary channel.
366		 */
367		ret = vmbus_chan_gpadl_disconnect(sc->hn_prichan,
368		    sc->hn_rxbuf_gpadl);
369		if (ret != 0) {
370			if_printf(sc->hn_ifp,
371			    "rxbuf disconn failed: %d\n", ret);
372			return (ret);
373		}
374		sc->hn_rxbuf_gpadl = 0;
375	}
376	return (ret);
377}
378
379/*
380 * Net VSC destroy send buffer
381 */
382static int
383hv_nv_destroy_send_buffer(struct hn_softc *sc)
384{
385	int ret = 0;
386
387	if (sc->hn_flags & HN_FLAG_CHIM_CONNECTED) {
388		struct hn_nvs_chim_disconn disconn;
389
390		/*
391		 * Disconnect chimney sending buffer from NVS.
392		 */
393		memset(&disconn, 0, sizeof(disconn));
394		disconn.nvs_type = HN_NVS_TYPE_CHIM_DISCONN;
395		disconn.nvs_sig = HN_NVS_CHIM_SIG;
396
397		/* NOTE: No response. */
398		ret = hn_nvs_req_send(sc, &disconn, sizeof(disconn));
399		if (ret != 0) {
400			if_printf(sc->hn_ifp,
401			    "send chim disconn failed: %d\n", ret);
402			return (ret);
403		}
404		sc->hn_flags &= ~HN_FLAG_CHIM_CONNECTED;
405	}
406
407	if (sc->hn_chim_gpadl != 0) {
408		/*
409		 * Disconnect chimney sending buffer from primary channel.
410		 */
411		ret = vmbus_chan_gpadl_disconnect(sc->hn_prichan,
412		    sc->hn_chim_gpadl);
413		if (ret != 0) {
414			if_printf(sc->hn_ifp,
415			    "chim disconn failed: %d\n", ret);
416			return (ret);
417		}
418		sc->hn_chim_gpadl = 0;
419	}
420
421	if (sc->hn_chim_bmap != NULL) {
422		free(sc->hn_chim_bmap, M_NETVSC);
423		sc->hn_chim_bmap = NULL;
424	}
425
426	return (ret);
427}
428
429static int
430hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, uint32_t nvs_ver)
431{
432	struct vmbus_xact *xact;
433	struct hn_nvs_init *init;
434	const struct hn_nvs_init_resp *resp;
435	size_t resp_len;
436	uint32_t status;
437
438	xact = vmbus_xact_get(sc->hn_xact, sizeof(*init));
439	if (xact == NULL) {
440		if_printf(sc->hn_ifp, "no xact for nvs init\n");
441		return (ENXIO);
442	}
443	init = vmbus_xact_req_data(xact);
444	init->nvs_type = HN_NVS_TYPE_INIT;
445	init->nvs_ver_min = nvs_ver;
446	init->nvs_ver_max = nvs_ver;
447
448	resp_len = sizeof(*resp);
449	resp = hn_nvs_xact_execute(sc, xact, init, sizeof(*init), &resp_len,
450	    HN_NVS_TYPE_INIT_RESP);
451	if (resp == NULL) {
452		if_printf(sc->hn_ifp, "exec init failed\n");
453		vmbus_xact_put(xact);
454		return (EIO);
455	}
456
457	status = resp->nvs_status;
458	vmbus_xact_put(xact);
459
460	if (status != HN_NVS_STATUS_OK) {
461		if_printf(sc->hn_ifp, "nvs init failed for ver 0x%x\n",
462		    nvs_ver);
463		return (EINVAL);
464	}
465	return (0);
466}
467
468/*
469 * Send NDIS version 2 config packet containing MTU.
470 *
471 * Not valid for NDIS version 1.
472 */
473static int
474hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu)
475{
476	struct hn_nvs_ndis_conf conf;
477	int error;
478
479	memset(&conf, 0, sizeof(conf));
480	conf.nvs_type = HN_NVS_TYPE_NDIS_CONF;
481	conf.nvs_mtu = mtu;
482	conf.nvs_caps = HN_NVS_NDIS_CONF_VLAN;
483
484	/* NOTE: No response. */
485	error = hn_nvs_req_send(sc, &conf, sizeof(conf));
486	if (error)
487		if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error);
488	return (error);
489}
490
491/*
492 * Net VSC connect to VSP
493 */
494static int
495hv_nv_connect_to_vsp(struct hn_softc *sc)
496{
497	uint32_t protocol_list[] = { NVSP_PROTOCOL_VERSION_1,
498	    NVSP_PROTOCOL_VERSION_2,
499	    NVSP_PROTOCOL_VERSION_4,
500	    NVSP_PROTOCOL_VERSION_5 };
501	int i;
502	int protocol_number = nitems(protocol_list);
503	int ret = 0;
504	device_t dev = sc->hn_dev;
505	struct ifnet *ifp = sc->arpcom.ac_ifp;
506	struct hn_nvs_ndis_init ndis;
507	int rxbuf_size;
508
509	/*
510	 * Negotiate the NVSP version.  Try the latest NVSP first.
511	 */
512	for (i = protocol_number - 1; i >= 0; i--) {
513		if (hv_nv_negotiate_nvsp_protocol(sc, protocol_list[i]) == 0) {
514			sc->hn_nvs_ver = protocol_list[i];
515			sc->hn_ndis_ver = HN_NDIS_VERSION_6_30;
516			if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4)
517				sc->hn_ndis_ver = HN_NDIS_VERSION_6_1;
518			if (bootverbose) {
519				if_printf(sc->hn_ifp, "NVS version 0x%x, "
520				    "NDIS version %u.%u\n",
521				    sc->hn_nvs_ver,
522				    HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver),
523				    HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver));
524			}
525			break;
526		}
527	}
528
529	if (i < 0) {
530		if (bootverbose)
531			device_printf(dev, "failed to negotiate a valid "
532			    "protocol.\n");
533		return (EPROTO);
534	}
535
536	/*
537	 * Set the MTU if supported by this NVSP protocol version
538	 * This needs to be right after the NVSP init message per Haiyang
539	 */
540	if (sc->hn_nvs_ver >= NVSP_PROTOCOL_VERSION_2)
541		ret = hv_nv_send_ndis_config(sc, ifp->if_mtu);
542
543	/*
544	 * Initialize NDIS.
545	 */
546
547	memset(&ndis, 0, sizeof(ndis));
548	ndis.nvs_type = HN_NVS_TYPE_NDIS_INIT;
549	ndis.nvs_ndis_major = HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver);
550	ndis.nvs_ndis_minor = HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver);
551
552	/* NOTE: No response. */
553	ret = hn_nvs_req_send(sc, &ndis, sizeof(ndis));
554	if (ret != 0) {
555		if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", ret);
556		goto cleanup;
557	}
558
559	/* Post the big receive buffer to NetVSP */
560	if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_2)
561		rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY;
562	else
563		rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE;
564
565	ret = hv_nv_init_rx_buffer_with_net_vsp(sc, rxbuf_size);
566	if (ret == 0)
567		ret = hv_nv_init_send_buffer_with_net_vsp(sc);
568
569cleanup:
570	return (ret);
571}
572
573/*
574 * Net VSC disconnect from VSP
575 */
576static void
577hv_nv_disconnect_from_vsp(struct hn_softc *sc)
578{
579	hv_nv_destroy_rx_buffer(sc);
580	hv_nv_destroy_send_buffer(sc);
581}
582
583void
584hv_nv_subchan_attach(struct vmbus_channel *chan, struct hn_rx_ring *rxr)
585{
586	KASSERT(rxr->hn_rx_idx == vmbus_chan_subidx(chan),
587	    ("chan%u subidx %u, rxr%d mismatch",
588	     vmbus_chan_id(chan), vmbus_chan_subidx(chan), rxr->hn_rx_idx));
589	vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
590	    NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0,
591	    hv_nv_on_channel_callback, rxr);
592}
593
594/*
595 * Net VSC on device add
596 *
597 * Callback when the device belonging to this driver is added
598 */
599int
600hv_nv_on_device_add(struct hn_softc *sc, struct hn_rx_ring *rxr)
601{
602	struct vmbus_channel *chan = sc->hn_prichan;
603	int ret = 0;
604
605	/*
606	 * Open the channel
607	 */
608	KASSERT(rxr->hn_rx_idx == vmbus_chan_subidx(chan),
609	    ("chan%u subidx %u, rxr%d mismatch",
610	     vmbus_chan_id(chan), vmbus_chan_subidx(chan), rxr->hn_rx_idx));
611	ret = vmbus_chan_open(chan,
612	    NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE,
613	    NULL, 0, hv_nv_on_channel_callback, rxr);
614	if (ret != 0)
615		goto cleanup;
616
617	/*
618	 * Connect with the NetVsp
619	 */
620	ret = hv_nv_connect_to_vsp(sc);
621	if (ret != 0)
622		goto close;
623
624	return (0);
625
626close:
627	/* Now, we can close the channel safely */
628	vmbus_chan_close(chan);
629cleanup:
630	return (ret);
631}
632
633/*
634 * Net VSC on device remove
635 */
636int
637hv_nv_on_device_remove(struct hn_softc *sc)
638{
639
640	hv_nv_disconnect_from_vsp(sc);
641
642	/* Now, we can close the channel safely */
643
644	vmbus_chan_close(sc->hn_prichan);
645
646	return (0);
647}
648
649void
650hn_nvs_sent_xact(struct hn_send_ctx *sndc,
651    struct hn_softc *sc __unused, struct vmbus_channel *chan __unused,
652    const void *data, int dlen)
653{
654
655	vmbus_xact_wakeup(sndc->hn_cbarg, data, dlen);
656}
657
658static void
659hn_nvs_sent_none(struct hn_send_ctx *sndc __unused,
660    struct hn_softc *sc __unused, struct vmbus_channel *chan __unused,
661    const void *data __unused, int dlen __unused)
662{
663	/* EMPTY */
664}
665
666void
667hn_chim_free(struct hn_softc *sc, uint32_t chim_idx)
668{
669	u_long mask;
670	uint32_t idx;
671
672	idx = chim_idx / LONG_BIT;
673	KASSERT(idx < sc->hn_chim_bmap_cnt,
674	    ("invalid chimney index 0x%x", chim_idx));
675
676	mask = 1UL << (chim_idx % LONG_BIT);
677	KASSERT(sc->hn_chim_bmap[idx] & mask,
678	    ("index bitmap 0x%lx, chimney index %u, "
679	     "bitmap idx %d, bitmask 0x%lx",
680	     sc->hn_chim_bmap[idx], chim_idx, idx, mask));
681
682	atomic_clear_long(&sc->hn_chim_bmap[idx], mask);
683}
684
685/*
686 * Net VSC on send completion
687 */
688static void
689hv_nv_on_send_completion(struct hn_softc *sc, struct vmbus_channel *chan,
690    const struct vmbus_chanpkt_hdr *pkt)
691{
692	struct hn_send_ctx *sndc;
693
694	sndc = (struct hn_send_ctx *)(uintptr_t)pkt->cph_xactid;
695	sndc->hn_cb(sndc, sc, chan, VMBUS_CHANPKT_CONST_DATA(pkt),
696	    VMBUS_CHANPKT_DATALEN(pkt));
697	/*
698	 * NOTE:
699	 * 'sndc' CAN NOT be accessed anymore, since it can be freed by
700	 * its callback.
701	 */
702}
703
704/*
705 * Net VSC on send
706 * Sends a packet on the specified Hyper-V device.
707 * Returns 0 on success, non-zero on failure.
708 */
709int
710hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype,
711    struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt)
712{
713	struct hn_nvs_rndis rndis;
714	int ret;
715
716	rndis.nvs_type = HN_NVS_TYPE_RNDIS;
717	rndis.nvs_rndis_mtype = rndis_mtype;
718	rndis.nvs_chim_idx = sndc->hn_chim_idx;
719	rndis.nvs_chim_sz = sndc->hn_chim_sz;
720
721	if (gpa_cnt) {
722		ret = hn_nvs_send_sglist(chan, gpa, gpa_cnt,
723		    &rndis, sizeof(rndis), sndc);
724	} else {
725		ret = hn_nvs_send(chan, VMBUS_CHANPKT_FLAG_RC,
726		    &rndis, sizeof(rndis), sndc);
727	}
728
729	return (ret);
730}
731
732/*
733 * Net VSC on receive
734 *
735 * In the FreeBSD Hyper-V virtual world, this function deals exclusively
736 * with virtual addresses.
737 */
738static void
739hv_nv_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
740    struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr)
741{
742	const struct vmbus_chanpkt_rxbuf *pkt;
743	const struct hn_nvs_hdr *nvs_hdr;
744	int count, i, hlen;
745
746	if (__predict_false(VMBUS_CHANPKT_DATALEN(pkthdr) < sizeof(*nvs_hdr))) {
747		if_printf(rxr->hn_ifp, "invalid nvs RNDIS\n");
748		return;
749	}
750	nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr);
751
752	/* Make sure that this is a RNDIS message. */
753	if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) {
754		if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n",
755		    nvs_hdr->nvs_type);
756		return;
757	}
758
759	hlen = VMBUS_CHANPKT_GETLEN(pkthdr->cph_hlen);
760	if (__predict_false(hlen < sizeof(*pkt))) {
761		if_printf(rxr->hn_ifp, "invalid rxbuf chanpkt\n");
762		return;
763	}
764	pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr;
765
766	if (__predict_false(pkt->cp_rxbuf_id != HN_NVS_RXBUF_SIG)) {
767		if_printf(rxr->hn_ifp, "invalid rxbuf_id 0x%08x\n",
768		    pkt->cp_rxbuf_id);
769		return;
770	}
771
772	count = pkt->cp_rxbuf_cnt;
773	if (__predict_false(hlen <
774	    __offsetof(struct vmbus_chanpkt_rxbuf, cp_rxbuf[count]))) {
775		if_printf(rxr->hn_ifp, "invalid rxbuf_cnt %d\n", count);
776		return;
777	}
778
779	/* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */
780	for (i = 0; i < count; ++i) {
781		int ofs, len;
782
783		ofs = pkt->cp_rxbuf[i].rb_ofs;
784		len = pkt->cp_rxbuf[i].rb_len;
785		if (__predict_false(ofs + len > NETVSC_RECEIVE_BUFFER_SIZE)) {
786			if_printf(rxr->hn_ifp, "%dth RNDIS msg overflow rxbuf, "
787			    "ofs %d, len %d\n", i, ofs, len);
788			continue;
789		}
790		hv_rf_on_receive(sc, rxr, rxr->hn_rxbuf + ofs, len);
791	}
792
793	/*
794	 * Moved completion call back here so that all received
795	 * messages (not just data messages) will trigger a response
796	 * message back to the host.
797	 */
798	hv_nv_on_receive_completion(chan, pkt->cp_hdr.cph_xactid);
799}
800
801/*
802 * Net VSC on receive completion
803 *
804 * Send a receive completion packet to RNDIS device (ie NetVsp)
805 */
806static void
807hv_nv_on_receive_completion(struct vmbus_channel *chan, uint64_t tid)
808{
809	struct hn_nvs_rndis_ack ack;
810	int retries = 0;
811	int ret = 0;
812
813	ack.nvs_type = HN_NVS_TYPE_RNDIS_ACK;
814	ack.nvs_status = HN_NVS_STATUS_OK;
815
816retry_send_cmplt:
817	/* Send the completion */
818	ret = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_COMP,
819	    VMBUS_CHANPKT_FLAG_NONE, &ack, sizeof(ack), tid);
820	if (ret == 0) {
821		/* success */
822		/* no-op */
823	} else if (ret == EAGAIN) {
824		/* no more room... wait a bit and attempt to retry 3 times */
825		retries++;
826
827		if (retries < 4) {
828			DELAY(100);
829			goto retry_send_cmplt;
830		}
831	}
832}
833
834static void
835hn_proc_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt)
836{
837	const struct hn_nvs_hdr *hdr;
838
839	if (VMBUS_CHANPKT_DATALEN(pkt) < sizeof(*hdr)) {
840		if_printf(sc->hn_ifp, "invalid nvs notify\n");
841		return;
842	}
843	hdr = VMBUS_CHANPKT_CONST_DATA(pkt);
844
845	if (hdr->nvs_type == HN_NVS_TYPE_TXTBL_NOTE) {
846		/* Useless; ignore */
847		return;
848	}
849	if_printf(sc->hn_ifp, "got notify, nvs type %u\n", hdr->nvs_type);
850}
851
852/*
853 * Net VSC on channel callback
854 */
855static void
856hv_nv_on_channel_callback(struct vmbus_channel *chan, void *xrxr)
857{
858	struct hn_rx_ring *rxr = xrxr;
859	struct hn_softc *sc = rxr->hn_ifp->if_softc;
860	void *buffer;
861	int bufferlen = NETVSC_PACKET_SIZE;
862
863	buffer = rxr->hn_rdbuf;
864	do {
865		struct vmbus_chanpkt_hdr *pkt = buffer;
866		uint32_t bytes_rxed;
867		int ret;
868
869		bytes_rxed = bufferlen;
870		ret = vmbus_chan_recv_pkt(chan, pkt, &bytes_rxed);
871		if (ret == 0) {
872			if (bytes_rxed > 0) {
873				switch (pkt->cph_type) {
874				case VMBUS_CHANPKT_TYPE_COMP:
875					hv_nv_on_send_completion(sc, chan, pkt);
876					break;
877				case VMBUS_CHANPKT_TYPE_RXBUF:
878					hv_nv_on_receive(sc, rxr, chan, pkt);
879					break;
880				case VMBUS_CHANPKT_TYPE_INBAND:
881					hn_proc_notify(sc, pkt);
882					break;
883				default:
884					if_printf(rxr->hn_ifp,
885					    "unknown chan pkt %u\n",
886					    pkt->cph_type);
887					break;
888				}
889			}
890		} else if (ret == ENOBUFS) {
891			/* Handle large packet */
892			if (bufferlen > NETVSC_PACKET_SIZE) {
893				free(buffer, M_NETVSC);
894				buffer = NULL;
895			}
896
897			/* alloc new buffer */
898			buffer = malloc(bytes_rxed, M_NETVSC, M_NOWAIT);
899			if (buffer == NULL) {
900				if_printf(rxr->hn_ifp,
901				    "hv_cb malloc buffer failed, len=%u\n",
902				    bytes_rxed);
903				bufferlen = 0;
904				break;
905			}
906			bufferlen = bytes_rxed;
907		} else {
908			/* No more packets */
909			break;
910		}
911	} while (1);
912
913	if (bufferlen > NETVSC_PACKET_SIZE)
914		free(buffer, M_NETVSC);
915
916	hv_rf_channel_rollup(rxr, rxr->hn_txr);
917}
918