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