1/*-
2 * Copyright (c) 2009-2012,2016-2017 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
29/*
30 * Network Virtualization Service.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD$");
35
36#include "opt_inet6.h"
37#include "opt_inet.h"
38
39#include <sys/param.h>
40#include <sys/kernel.h>
41#include <sys/limits.h>
42#include <sys/socket.h>
43#include <sys/systm.h>
44#include <sys/taskqueue.h>
45
46#include <net/ethernet.h>
47#include <net/if.h>
48#include <net/if_var.h>
49#include <net/if_media.h>
50
51#include <netinet/in.h>
52#include <netinet/tcp_lro.h>
53
54#include <dev/hyperv/include/hyperv.h>
55#include <dev/hyperv/include/hyperv_busdma.h>
56#include <dev/hyperv/include/vmbus.h>
57#include <dev/hyperv/include/vmbus_xact.h>
58
59#include <dev/hyperv/netvsc/ndis.h>
60#include <dev/hyperv/netvsc/if_hnreg.h>
61#include <dev/hyperv/netvsc/if_hnvar.h>
62#include <dev/hyperv/netvsc/hn_nvs.h>
63
64static int			hn_nvs_conn_chim(struct hn_softc *);
65static int			hn_nvs_conn_rxbuf(struct hn_softc *);
66static void			hn_nvs_disconn_chim(struct hn_softc *);
67static void			hn_nvs_disconn_rxbuf(struct hn_softc *);
68static int			hn_nvs_conf_ndis(struct hn_softc *, int);
69static int			hn_nvs_init_ndis(struct hn_softc *);
70static int			hn_nvs_doinit(struct hn_softc *, uint32_t);
71static int			hn_nvs_init(struct hn_softc *);
72static const void		*hn_nvs_xact_execute(struct hn_softc *,
73				    struct vmbus_xact *, void *, int,
74				    size_t *, uint32_t);
75static void			hn_nvs_sent_none(struct hn_nvs_sendctx *,
76				    struct hn_softc *, struct vmbus_channel *,
77				    const void *, int);
78
79struct hn_nvs_sendctx		hn_nvs_sendctx_none =
80    HN_NVS_SENDCTX_INITIALIZER(hn_nvs_sent_none, NULL);
81
82static const uint32_t		hn_nvs_version[] = {
83	HN_NVS_VERSION_61,
84	HN_NVS_VERSION_6,
85	HN_NVS_VERSION_5,
86	HN_NVS_VERSION_4,
87	HN_NVS_VERSION_2,
88	HN_NVS_VERSION_1
89};
90
91static const void *
92hn_nvs_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact,
93    void *req, int reqlen, size_t *resplen0, uint32_t type)
94{
95	struct hn_nvs_sendctx sndc;
96	size_t resplen, min_resplen = *resplen0;
97	const struct hn_nvs_hdr *hdr;
98	int error;
99
100	KASSERT(min_resplen >= sizeof(*hdr),
101	    ("invalid minimum response len %zu", min_resplen));
102
103	/*
104	 * Execute the xact setup by the caller.
105	 */
106	hn_nvs_sendctx_init(&sndc, hn_nvs_sent_xact, xact);
107
108	vmbus_xact_activate(xact);
109	error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC,
110	    req, reqlen, &sndc);
111	if (error) {
112		vmbus_xact_deactivate(xact);
113		return (NULL);
114	}
115	hdr = vmbus_chan_xact_wait(sc->hn_prichan, xact, &resplen,
116	    HN_CAN_SLEEP(sc));
117
118	/*
119	 * Check this NVS response message.
120	 */
121	if (resplen < min_resplen) {
122		if_printf(sc->hn_ifp, "invalid NVS resp len %zu\n", resplen);
123		return (NULL);
124	}
125	if (hdr->nvs_type != type) {
126		if_printf(sc->hn_ifp, "unexpected NVS resp 0x%08x, "
127		    "expect 0x%08x\n", hdr->nvs_type, type);
128		return (NULL);
129	}
130	/* All pass! */
131	*resplen0 = resplen;
132	return (hdr);
133}
134
135static __inline int
136hn_nvs_req_send(struct hn_softc *sc, void *req, int reqlen)
137{
138
139	return (hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE,
140	    req, reqlen, &hn_nvs_sendctx_none));
141}
142
143static int
144hn_nvs_conn_rxbuf(struct hn_softc *sc)
145{
146	struct vmbus_xact *xact = NULL;
147	struct hn_nvs_rxbuf_conn *conn;
148	const struct hn_nvs_rxbuf_connresp *resp;
149	size_t resp_len;
150	uint32_t status;
151	int error, rxbuf_size;
152
153	/*
154	 * Limit RXBUF size for old NVS.
155	 */
156	if (sc->hn_nvs_ver <= HN_NVS_VERSION_2)
157		rxbuf_size = HN_RXBUF_SIZE_COMPAT;
158	else
159		rxbuf_size = HN_RXBUF_SIZE;
160
161	/*
162	 * Connect the RXBUF GPADL to the primary channel.
163	 *
164	 * NOTE:
165	 * Only primary channel has RXBUF connected to it.  Sub-channels
166	 * just share this RXBUF.
167	 */
168	error = vmbus_chan_gpadl_connect(sc->hn_prichan,
169	    sc->hn_rxbuf_dma.hv_paddr, rxbuf_size, &sc->hn_rxbuf_gpadl);
170	if (error) {
171		if_printf(sc->hn_ifp, "rxbuf gpadl conn failed: %d\n",
172		    error);
173		goto cleanup;
174	}
175
176	/*
177	 * Connect RXBUF to NVS.
178	 */
179
180	xact = vmbus_xact_get(sc->hn_xact, sizeof(*conn));
181	if (xact == NULL) {
182		if_printf(sc->hn_ifp, "no xact for nvs rxbuf conn\n");
183		error = ENXIO;
184		goto cleanup;
185	}
186	conn = vmbus_xact_req_data(xact);
187	conn->nvs_type = HN_NVS_TYPE_RXBUF_CONN;
188	conn->nvs_gpadl = sc->hn_rxbuf_gpadl;
189	conn->nvs_sig = HN_NVS_RXBUF_SIG;
190
191	resp_len = sizeof(*resp);
192	resp = hn_nvs_xact_execute(sc, xact, conn, sizeof(*conn), &resp_len,
193	    HN_NVS_TYPE_RXBUF_CONNRESP);
194	if (resp == NULL) {
195		if_printf(sc->hn_ifp, "exec nvs rxbuf conn failed\n");
196		error = EIO;
197		goto cleanup;
198	}
199
200	status = resp->nvs_status;
201	vmbus_xact_put(xact);
202	xact = NULL;
203
204	if (status != HN_NVS_STATUS_OK) {
205		if_printf(sc->hn_ifp, "nvs rxbuf conn failed: %x\n", status);
206		error = EIO;
207		goto cleanup;
208	}
209	sc->hn_flags |= HN_FLAG_RXBUF_CONNECTED;
210
211	return (0);
212
213cleanup:
214	if (xact != NULL)
215		vmbus_xact_put(xact);
216	hn_nvs_disconn_rxbuf(sc);
217	return (error);
218}
219
220static int
221hn_nvs_conn_chim(struct hn_softc *sc)
222{
223	struct vmbus_xact *xact = NULL;
224	struct hn_nvs_chim_conn *chim;
225	const struct hn_nvs_chim_connresp *resp;
226	size_t resp_len;
227	uint32_t status, sectsz;
228	int error;
229
230	/*
231	 * Connect chimney sending buffer GPADL to the primary channel.
232	 *
233	 * NOTE:
234	 * Only primary channel has chimney sending buffer connected to it.
235	 * Sub-channels just share this chimney sending buffer.
236	 */
237	error = vmbus_chan_gpadl_connect(sc->hn_prichan,
238  	    sc->hn_chim_dma.hv_paddr, HN_CHIM_SIZE, &sc->hn_chim_gpadl);
239	if (error) {
240		if_printf(sc->hn_ifp, "chim gpadl conn failed: %d\n", error);
241		goto cleanup;
242	}
243
244	/*
245	 * Connect chimney sending buffer to NVS
246	 */
247
248	xact = vmbus_xact_get(sc->hn_xact, sizeof(*chim));
249	if (xact == NULL) {
250		if_printf(sc->hn_ifp, "no xact for nvs chim conn\n");
251		error = ENXIO;
252		goto cleanup;
253	}
254	chim = vmbus_xact_req_data(xact);
255	chim->nvs_type = HN_NVS_TYPE_CHIM_CONN;
256	chim->nvs_gpadl = sc->hn_chim_gpadl;
257	chim->nvs_sig = HN_NVS_CHIM_SIG;
258
259	resp_len = sizeof(*resp);
260	resp = hn_nvs_xact_execute(sc, xact, chim, sizeof(*chim), &resp_len,
261	    HN_NVS_TYPE_CHIM_CONNRESP);
262	if (resp == NULL) {
263		if_printf(sc->hn_ifp, "exec nvs chim conn failed\n");
264		error = EIO;
265		goto cleanup;
266	}
267
268	status = resp->nvs_status;
269	sectsz = resp->nvs_sectsz;
270	vmbus_xact_put(xact);
271	xact = NULL;
272
273	if (status != HN_NVS_STATUS_OK) {
274		if_printf(sc->hn_ifp, "nvs chim conn failed: %x\n", status);
275		error = EIO;
276		goto cleanup;
277	}
278	if (sectsz == 0 || sectsz % sizeof(uint32_t) != 0) {
279		/*
280		 * Can't use chimney sending buffer; done!
281		 */
282		if (sectsz == 0) {
283			if_printf(sc->hn_ifp, "zero chimney sending buffer "
284			    "section size\n");
285		} else {
286			if_printf(sc->hn_ifp, "misaligned chimney sending "
287			    "buffers, section size: %u\n", sectsz);
288		}
289		sc->hn_chim_szmax = 0;
290		sc->hn_chim_cnt = 0;
291		sc->hn_flags |= HN_FLAG_CHIM_CONNECTED;
292		return (0);
293	}
294
295	sc->hn_chim_szmax = sectsz;
296	sc->hn_chim_cnt = HN_CHIM_SIZE / sc->hn_chim_szmax;
297	if (HN_CHIM_SIZE % sc->hn_chim_szmax != 0) {
298		if_printf(sc->hn_ifp, "chimney sending sections are "
299		    "not properly aligned\n");
300	}
301	if (sc->hn_chim_cnt % LONG_BIT != 0) {
302		if_printf(sc->hn_ifp, "discard %d chimney sending sections\n",
303		    sc->hn_chim_cnt % LONG_BIT);
304	}
305
306	sc->hn_chim_bmap_cnt = sc->hn_chim_cnt / LONG_BIT;
307	sc->hn_chim_bmap = malloc(sc->hn_chim_bmap_cnt * sizeof(u_long),
308	    M_DEVBUF, M_WAITOK | M_ZERO);
309
310	/* Done! */
311	sc->hn_flags |= HN_FLAG_CHIM_CONNECTED;
312	if (bootverbose) {
313		if_printf(sc->hn_ifp, "chimney sending buffer %d/%d\n",
314		    sc->hn_chim_szmax, sc->hn_chim_cnt);
315	}
316	return (0);
317
318cleanup:
319	if (xact != NULL)
320		vmbus_xact_put(xact);
321	hn_nvs_disconn_chim(sc);
322	return (error);
323}
324
325static void
326hn_nvs_disconn_rxbuf(struct hn_softc *sc)
327{
328	int error;
329
330	if (sc->hn_flags & HN_FLAG_RXBUF_CONNECTED) {
331		struct hn_nvs_rxbuf_disconn disconn;
332
333		/*
334		 * Disconnect RXBUF from NVS.
335		 */
336		memset(&disconn, 0, sizeof(disconn));
337		disconn.nvs_type = HN_NVS_TYPE_RXBUF_DISCONN;
338		disconn.nvs_sig = HN_NVS_RXBUF_SIG;
339
340		/* NOTE: No response. */
341		error = hn_nvs_req_send(sc, &disconn, sizeof(disconn));
342		if (error) {
343			if_printf(sc->hn_ifp,
344			    "send nvs rxbuf disconn failed: %d\n", error);
345			/*
346			 * Fine for a revoked channel, since the hypervisor
347			 * does not drain TX bufring for a revoked channel.
348			 */
349			if (!vmbus_chan_is_revoked(sc->hn_prichan))
350				sc->hn_flags |= HN_FLAG_RXBUF_REF;
351		}
352		sc->hn_flags &= ~HN_FLAG_RXBUF_CONNECTED;
353
354		/*
355		 * Wait for the hypervisor to receive this NVS request.
356		 *
357		 * NOTE:
358		 * The TX bufring will not be drained by the hypervisor,
359		 * if the primary channel is revoked.
360		 */
361		while (!vmbus_chan_tx_empty(sc->hn_prichan) &&
362		    !vmbus_chan_is_revoked(sc->hn_prichan))
363			pause("waittx", 1);
364		/*
365		 * Linger long enough for NVS to disconnect RXBUF.
366		 */
367		pause("lingtx", (200 * hz) / 1000);
368	}
369
370	if (vmbus_current_version < VMBUS_VERSION_WIN10 && sc->hn_rxbuf_gpadl != 0) {
371		/*
372		 * Disconnect RXBUF from primary channel.
373		 */
374		error = vmbus_chan_gpadl_disconnect(sc->hn_prichan,
375		    sc->hn_rxbuf_gpadl);
376		if (error) {
377			if_printf(sc->hn_ifp,
378			    "rxbuf gpadl disconn failed: %d\n", error);
379			sc->hn_flags |= HN_FLAG_RXBUF_REF;
380		}
381		sc->hn_rxbuf_gpadl = 0;
382	}
383}
384
385static void
386hn_nvs_disconn_chim(struct hn_softc *sc)
387{
388	int error;
389
390	if (sc->hn_flags & HN_FLAG_CHIM_CONNECTED) {
391		struct hn_nvs_chim_disconn disconn;
392
393		/*
394		 * Disconnect chimney sending buffer from NVS.
395		 */
396		memset(&disconn, 0, sizeof(disconn));
397		disconn.nvs_type = HN_NVS_TYPE_CHIM_DISCONN;
398		disconn.nvs_sig = HN_NVS_CHIM_SIG;
399
400		/* NOTE: No response. */
401		error = hn_nvs_req_send(sc, &disconn, sizeof(disconn));
402		if (error) {
403			if_printf(sc->hn_ifp,
404			    "send nvs chim disconn failed: %d\n", error);
405			/*
406			 * Fine for a revoked channel, since the hypervisor
407			 * does not drain TX bufring for a revoked channel.
408			 */
409			if (!vmbus_chan_is_revoked(sc->hn_prichan))
410				sc->hn_flags |= HN_FLAG_CHIM_REF;
411		}
412		sc->hn_flags &= ~HN_FLAG_CHIM_CONNECTED;
413
414		/*
415		 * Wait for the hypervisor to receive this NVS request.
416		 *
417		 * NOTE:
418		 * The TX bufring will not be drained by the hypervisor,
419		 * if the primary channel is revoked.
420		 */
421		while (!vmbus_chan_tx_empty(sc->hn_prichan) &&
422		    !vmbus_chan_is_revoked(sc->hn_prichan))
423			pause("waittx", 1);
424		/*
425		 * Linger long enough for NVS to disconnect chimney
426		 * sending buffer.
427		 */
428		pause("lingtx", (200 * hz) / 1000);
429	}
430
431	if (vmbus_current_version < VMBUS_VERSION_WIN10 && sc->hn_chim_gpadl != 0) {
432		/*
433		 * Disconnect chimney sending buffer from primary channel.
434		 */
435		error = vmbus_chan_gpadl_disconnect(sc->hn_prichan,
436		    sc->hn_chim_gpadl);
437		if (error) {
438			if_printf(sc->hn_ifp,
439			    "chim gpadl disconn failed: %d\n", error);
440			sc->hn_flags |= HN_FLAG_CHIM_REF;
441		}
442		sc->hn_chim_gpadl = 0;
443	}
444
445	if (sc->hn_chim_bmap != NULL) {
446		free(sc->hn_chim_bmap, M_DEVBUF);
447		sc->hn_chim_bmap = NULL;
448		sc->hn_chim_bmap_cnt = 0;
449	}
450}
451
452static int
453hn_nvs_doinit(struct hn_softc *sc, uint32_t nvs_ver)
454{
455	struct vmbus_xact *xact;
456	struct hn_nvs_init *init;
457	const struct hn_nvs_init_resp *resp;
458	size_t resp_len;
459	uint32_t status;
460
461	xact = vmbus_xact_get(sc->hn_xact, sizeof(*init));
462	if (xact == NULL) {
463		if_printf(sc->hn_ifp, "no xact for nvs init\n");
464		return (ENXIO);
465	}
466	init = vmbus_xact_req_data(xact);
467	init->nvs_type = HN_NVS_TYPE_INIT;
468	init->nvs_ver_min = nvs_ver;
469	init->nvs_ver_max = nvs_ver;
470
471	resp_len = sizeof(*resp);
472	resp = hn_nvs_xact_execute(sc, xact, init, sizeof(*init), &resp_len,
473	    HN_NVS_TYPE_INIT_RESP);
474	if (resp == NULL) {
475		if_printf(sc->hn_ifp, "exec init failed\n");
476		vmbus_xact_put(xact);
477		return (EIO);
478	}
479
480	status = resp->nvs_status;
481	vmbus_xact_put(xact);
482
483	if (status != HN_NVS_STATUS_OK) {
484		if (bootverbose) {
485			/*
486			 * Caller may try another NVS version, and will log
487			 * error if there are no more NVS versions to try,
488			 * so don't bark out loud here.
489			 */
490			if_printf(sc->hn_ifp, "nvs init failed for ver 0x%x\n",
491			    nvs_ver);
492		}
493		return (EINVAL);
494	}
495	return (0);
496}
497
498/*
499 * Configure MTU and enable VLAN.
500 */
501static int
502hn_nvs_conf_ndis(struct hn_softc *sc, int mtu)
503{
504	struct hn_nvs_ndis_conf conf;
505	int error;
506
507	memset(&conf, 0, sizeof(conf));
508	conf.nvs_type = HN_NVS_TYPE_NDIS_CONF;
509	conf.nvs_mtu = mtu + ETHER_HDR_LEN;
510	conf.nvs_caps = HN_NVS_NDIS_CONF_VLAN;
511	if (sc->hn_nvs_ver >= HN_NVS_VERSION_5)
512		conf.nvs_caps |= HN_NVS_NDIS_CONF_SRIOV;
513	if (sc->hn_nvs_ver >= HN_NVS_VERSION_61)
514		conf.nvs_caps |= HN_NVS_NDIS_CONF_RSC;
515
516
517	/* NOTE: No response. */
518	error = hn_nvs_req_send(sc, &conf, sizeof(conf));
519	if (error) {
520		if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error);
521		return (error);
522	}
523
524	if (bootverbose)
525		if_printf(sc->hn_ifp, "nvs ndis conf done\n");
526	sc->hn_caps |= HN_CAP_MTU | HN_CAP_VLAN;
527	return (0);
528}
529
530static int
531hn_nvs_init_ndis(struct hn_softc *sc)
532{
533	struct hn_nvs_ndis_init ndis;
534	int error;
535
536	memset(&ndis, 0, sizeof(ndis));
537	ndis.nvs_type = HN_NVS_TYPE_NDIS_INIT;
538	ndis.nvs_ndis_major = HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver);
539	ndis.nvs_ndis_minor = HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver);
540
541	/* NOTE: No response. */
542	error = hn_nvs_req_send(sc, &ndis, sizeof(ndis));
543	if (error)
544		if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", error);
545	return (error);
546}
547
548static int
549hn_nvs_init(struct hn_softc *sc)
550{
551	int i, error;
552
553	if (device_is_attached(sc->hn_dev)) {
554		/*
555		 * NVS version and NDIS version MUST NOT be changed.
556		 */
557		if (bootverbose) {
558			if_printf(sc->hn_ifp, "reinit NVS version 0x%x, "
559			    "NDIS version %u.%u\n", sc->hn_nvs_ver,
560			    HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver),
561			    HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver));
562		}
563
564		error = hn_nvs_doinit(sc, sc->hn_nvs_ver);
565		if (error) {
566			if_printf(sc->hn_ifp, "reinit NVS version 0x%x "
567			    "failed: %d\n", sc->hn_nvs_ver, error);
568			return (error);
569		}
570		goto done;
571	}
572
573	/*
574	 * Find the supported NVS version and set NDIS version accordingly.
575	 */
576	for (i = 0; i < nitems(hn_nvs_version); ++i) {
577		error = hn_nvs_doinit(sc, hn_nvs_version[i]);
578		if (!error) {
579			sc->hn_nvs_ver = hn_nvs_version[i];
580
581			/* Set NDIS version according to NVS version. */
582			sc->hn_ndis_ver = HN_NDIS_VERSION_6_30;
583			if (sc->hn_nvs_ver <= HN_NVS_VERSION_4)
584				sc->hn_ndis_ver = HN_NDIS_VERSION_6_1;
585
586			if (bootverbose) {
587				if_printf(sc->hn_ifp, "NVS version 0x%x, "
588				    "NDIS version %u.%u\n", sc->hn_nvs_ver,
589				    HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver),
590				    HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver));
591			}
592			goto done;
593		}
594	}
595	if_printf(sc->hn_ifp, "no NVS available\n");
596	return (ENXIO);
597
598done:
599	if (sc->hn_nvs_ver >= HN_NVS_VERSION_5)
600		sc->hn_caps |= HN_CAP_HASHVAL;
601	return (0);
602}
603
604int
605hn_nvs_attach(struct hn_softc *sc, int mtu)
606{
607	int error;
608
609	if (hyperv_ver_major >= 10) {
610		/* UDP 4-tuple hash is enforced. */
611		sc->hn_caps |= HN_CAP_UDPHASH;
612	}
613
614	/*
615	 * Initialize NVS.
616	 */
617	error = hn_nvs_init(sc);
618	if (error)
619		return (error);
620
621	if (sc->hn_nvs_ver >= HN_NVS_VERSION_2) {
622		/*
623		 * Configure NDIS before initializing it.
624		 */
625		error = hn_nvs_conf_ndis(sc, mtu);
626		if (error)
627			return (error);
628	}
629
630	/*
631	 * Initialize NDIS.
632	 */
633	error = hn_nvs_init_ndis(sc);
634	if (error)
635		return (error);
636
637	/*
638	 * Connect RXBUF.
639	 */
640	error = hn_nvs_conn_rxbuf(sc);
641	if (error)
642		return (error);
643
644	/*
645	 * Connect chimney sending buffer.
646	 */
647	error = hn_nvs_conn_chim(sc);
648	if (error) {
649		hn_nvs_disconn_rxbuf(sc);
650		return (error);
651	}
652	return (0);
653}
654
655void
656hn_nvs_detach(struct hn_softc *sc)
657{
658
659	/* NOTE: there are no requests to stop the NVS. */
660	hn_nvs_disconn_rxbuf(sc);
661	hn_nvs_disconn_chim(sc);
662}
663
664void
665hn_nvs_sent_xact(struct hn_nvs_sendctx *sndc,
666    struct hn_softc *sc __unused, struct vmbus_channel *chan __unused,
667    const void *data, int dlen)
668{
669
670	vmbus_xact_wakeup(sndc->hn_cbarg, data, dlen);
671}
672
673static void
674hn_nvs_sent_none(struct hn_nvs_sendctx *sndc __unused,
675    struct hn_softc *sc __unused, struct vmbus_channel *chan __unused,
676    const void *data __unused, int dlen __unused)
677{
678	/* EMPTY */
679}
680
681int
682hn_nvs_alloc_subchans(struct hn_softc *sc, int *nsubch0)
683{
684	struct vmbus_xact *xact;
685	struct hn_nvs_subch_req *req;
686	const struct hn_nvs_subch_resp *resp;
687	int error, nsubch_req;
688	uint32_t nsubch;
689	size_t resp_len;
690
691	nsubch_req = *nsubch0;
692	KASSERT(nsubch_req > 0, ("invalid # of sub-channels %d", nsubch_req));
693
694	xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
695	if (xact == NULL) {
696		if_printf(sc->hn_ifp, "no xact for nvs subch alloc\n");
697		return (ENXIO);
698	}
699	req = vmbus_xact_req_data(xact);
700	req->nvs_type = HN_NVS_TYPE_SUBCH_REQ;
701	req->nvs_op = HN_NVS_SUBCH_OP_ALLOC;
702	req->nvs_nsubch = nsubch_req;
703
704	resp_len = sizeof(*resp);
705	resp = hn_nvs_xact_execute(sc, xact, req, sizeof(*req), &resp_len,
706	    HN_NVS_TYPE_SUBCH_RESP);
707	if (resp == NULL) {
708		if_printf(sc->hn_ifp, "exec nvs subch alloc failed\n");
709		error = EIO;
710		goto done;
711	}
712	if (resp->nvs_status != HN_NVS_STATUS_OK) {
713		if_printf(sc->hn_ifp, "nvs subch alloc failed: %x\n",
714		    resp->nvs_status);
715		error = EIO;
716		goto done;
717	}
718
719	nsubch = resp->nvs_nsubch;
720	if (nsubch > nsubch_req) {
721		if_printf(sc->hn_ifp, "%u subchans are allocated, "
722		    "requested %d\n", nsubch, nsubch_req);
723		nsubch = nsubch_req;
724	}
725	*nsubch0 = nsubch;
726	error = 0;
727done:
728	vmbus_xact_put(xact);
729	return (error);
730}
731
732int
733hn_nvs_send_rndis_ctrl(struct vmbus_channel *chan,
734    struct hn_nvs_sendctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt)
735{
736
737	return hn_nvs_send_rndis_sglist(chan, HN_NVS_RNDIS_MTYPE_CTRL,
738	    sndc, gpa, gpa_cnt);
739}
740
741void
742hn_nvs_set_datapath(struct hn_softc *sc, uint32_t path)
743{
744	struct hn_nvs_datapath dp;
745
746	memset(&dp, 0, sizeof(dp));
747	dp.nvs_type = HN_NVS_TYPE_SET_DATAPATH;
748	dp.nvs_active_path = path;
749
750	hn_nvs_req_send(sc, &dp, sizeof(dp));
751}
752