xref: /openbsd/sys/dev/pv/if_hvn.c (revision 905646f0)
1 /*-
2  * Copyright (c) 2009-2012,2016 Microsoft Corp.
3  * Copyright (c) 2010-2012 Citrix Inc.
4  * Copyright (c) 2012 NetApp Inc.
5  * Copyright (c) 2016 Mike Belopuhov <mike@esdenera.com>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice unmodified, this list of conditions, and the following
13  *    disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * The OpenBSD port was done under funding by Esdenera Networks GmbH.
32  */
33 
34 #include "bpfilter.h"
35 #include "vlan.h"
36 #include "hyperv.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/atomic.h>
41 #include <sys/device.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/mbuf.h>
45 #include <sys/pool.h>
46 #include <sys/queue.h>
47 #include <sys/socket.h>
48 #include <sys/sockio.h>
49 #include <sys/task.h>
50 #include <sys/timeout.h>
51 
52 #include <machine/bus.h>
53 
54 #include <uvm/uvm_extern.h>
55 
56 #include <dev/pv/hypervreg.h>
57 #include <dev/pv/hypervvar.h>
58 
59 #include <dev/rndis.h>
60 #include <dev/pv/ndis.h>
61 #include <dev/pv/if_hvnreg.h>
62 
63 #include <net/if.h>
64 #include <net/if_media.h>
65 
66 #include <netinet/in.h>
67 #include <netinet/if_ether.h>
68 
69 #ifdef INET6
70 #include <netinet/ip6.h>
71 #endif
72 
73 #if NBPFILTER > 0
74 #include <net/bpf.h>
75 #endif
76 
77 #define HVN_NVS_MSGSIZE			32
78 #define HVN_NVS_BUFSIZE			PAGE_SIZE
79 
80 /*
81  * RNDIS control interface
82  */
83 #define HVN_RNDIS_CTLREQS		4
84 #define HVN_RNDIS_BUFSIZE		512
85 
86 struct rndis_cmd {
87 	uint32_t			 rc_id;
88 	struct hvn_nvs_rndis		 rc_msg;
89 	void				*rc_req;
90 	bus_dmamap_t			 rc_dmap;
91 	bus_dma_segment_t		 rc_segs;
92 	int				 rc_nsegs;
93 	uint64_t			 rc_gpa;
94 	struct rndis_packet_msg		 rc_cmp;
95 	uint32_t			 rc_cmplen;
96 	uint8_t				 rc_cmpbuf[HVN_RNDIS_BUFSIZE];
97 	int				 rc_done;
98 	TAILQ_ENTRY(rndis_cmd)		 rc_entry;
99 };
100 TAILQ_HEAD(rndis_queue, rndis_cmd);
101 
102 #define HVN_MAXMTU			(9 * 1024)
103 
104 #define HVN_RNDIS_XFER_SIZE		2048
105 
106 /*
107  * Tx ring
108  */
109 #define HVN_TX_DESC			256
110 #define HVN_TX_FRAGS			15		/* 31 is the max */
111 #define HVN_TX_FRAG_SIZE		PAGE_SIZE
112 #define HVN_TX_PKT_SIZE			16384
113 
114 #define HVN_RNDIS_PKT_LEN					\
115 	(sizeof(struct rndis_packet_msg) +			\
116 	 sizeof(struct rndis_pktinfo) + NDIS_VLAN_INFO_SIZE +	\
117 	 sizeof(struct rndis_pktinfo) + NDIS_TXCSUM_INFO_SIZE)
118 
119 struct hvn_tx_desc {
120 	uint32_t			 txd_id;
121 	int				 txd_ready;
122 	struct vmbus_gpa		 txd_sgl[HVN_TX_FRAGS + 1];
123 	int				 txd_nsge;
124 	struct mbuf			*txd_buf;
125 	bus_dmamap_t			 txd_dmap;
126 	struct vmbus_gpa		 txd_gpa;
127 	struct rndis_packet_msg		*txd_req;
128 };
129 
130 struct hvn_softc {
131 	struct device			 sc_dev;
132 	struct hv_softc			*sc_hvsc;
133 	struct hv_channel		*sc_chan;
134 	bus_dma_tag_t			 sc_dmat;
135 
136 	struct arpcom			 sc_ac;
137 	struct ifmedia			 sc_media;
138 	int				 sc_link_state;
139 
140 	/* NVS protocol */
141 	int				 sc_proto;
142 	uint32_t			 sc_nvstid;
143 	uint8_t				 sc_nvsrsp[HVN_NVS_MSGSIZE];
144 	uint8_t				*sc_nvsbuf;
145 	int				 sc_nvsdone;
146 
147 	/* RNDIS protocol */
148 	int				 sc_ndisver;
149 	uint32_t			 sc_rndisrid;
150 	struct rndis_queue		 sc_cntl_sq; /* submission queue */
151 	struct mutex			 sc_cntl_sqlck;
152 	struct rndis_queue		 sc_cntl_cq; /* completion queue */
153 	struct mutex			 sc_cntl_cqlck;
154 	struct rndis_queue		 sc_cntl_fq; /* free queue */
155 	struct mutex			 sc_cntl_fqlck;
156 	struct rndis_cmd		 sc_cntl_msgs[HVN_RNDIS_CTLREQS];
157 	struct hvn_nvs_rndis		 sc_data_msg;
158 
159 	/* Rx ring */
160 	void				*sc_rx_ring;
161 	int				 sc_rx_size;
162 	uint32_t			 sc_rx_hndl;
163 
164 	/* Tx ring */
165 	uint32_t			 sc_tx_next;
166 	uint32_t			 sc_tx_avail;
167 	struct hvn_tx_desc		 sc_tx_desc[HVN_TX_DESC];
168 	bus_dmamap_t			 sc_tx_rmap;
169 	void				*sc_tx_msgs;
170 	bus_dma_segment_t		 sc_tx_mseg;
171 };
172 
173 int	hvn_match(struct device *, void *, void *);
174 void	hvn_attach(struct device *, struct device *, void *);
175 int	hvn_ioctl(struct ifnet *, u_long, caddr_t);
176 int	hvn_media_change(struct ifnet *);
177 void	hvn_media_status(struct ifnet *, struct ifmediareq *);
178 int	hvn_iff(struct hvn_softc *);
179 void	hvn_init(struct hvn_softc *);
180 void	hvn_stop(struct hvn_softc *);
181 void	hvn_start(struct ifqueue *);
182 int	hvn_encap(struct hvn_softc *, struct mbuf *, struct hvn_tx_desc **);
183 void	hvn_decap(struct hvn_softc *, struct hvn_tx_desc *);
184 void	hvn_txeof(struct hvn_softc *, uint64_t);
185 int	hvn_rx_ring_create(struct hvn_softc *);
186 int	hvn_rx_ring_destroy(struct hvn_softc *);
187 int	hvn_tx_ring_create(struct hvn_softc *);
188 void	hvn_tx_ring_destroy(struct hvn_softc *);
189 int	hvn_set_capabilities(struct hvn_softc *);
190 int	hvn_get_lladdr(struct hvn_softc *);
191 int	hvn_set_lladdr(struct hvn_softc *);
192 void	hvn_get_link_status(struct hvn_softc *);
193 void	hvn_link_status(struct hvn_softc *);
194 
195 /* NSVP */
196 int	hvn_nvs_attach(struct hvn_softc *);
197 void	hvn_nvs_intr(void *);
198 int	hvn_nvs_cmd(struct hvn_softc *, void *, size_t, uint64_t, int);
199 int	hvn_nvs_ack(struct hvn_softc *, uint64_t);
200 void	hvn_nvs_detach(struct hvn_softc *);
201 
202 /* RNDIS */
203 int	hvn_rndis_attach(struct hvn_softc *);
204 int	hvn_rndis_cmd(struct hvn_softc *, struct rndis_cmd *, int);
205 void	hvn_rndis_input(struct hvn_softc *, uint64_t, void *);
206 void	hvn_rxeof(struct hvn_softc *, caddr_t, uint32_t, struct mbuf_list *);
207 void	hvn_rndis_complete(struct hvn_softc *, caddr_t, uint32_t);
208 int	hvn_rndis_output(struct hvn_softc *, struct hvn_tx_desc *);
209 void	hvn_rndis_status(struct hvn_softc *, caddr_t, uint32_t);
210 int	hvn_rndis_query(struct hvn_softc *, uint32_t, void *, size_t *);
211 int	hvn_rndis_set(struct hvn_softc *, uint32_t, void *, size_t);
212 int	hvn_rndis_close(struct hvn_softc *);
213 void	hvn_rndis_detach(struct hvn_softc *);
214 
215 struct cfdriver hvn_cd = {
216 	NULL, "hvn", DV_IFNET
217 };
218 
219 const struct cfattach hvn_ca = {
220 	sizeof(struct hvn_softc), hvn_match, hvn_attach
221 };
222 
223 int
224 hvn_match(struct device *parent, void *match, void *aux)
225 {
226 	struct hv_attach_args *aa = aux;
227 
228 	if (strcmp("network", aa->aa_ident))
229 		return (0);
230 
231 	return (1);
232 }
233 
234 void
235 hvn_attach(struct device *parent, struct device *self, void *aux)
236 {
237 	struct hv_attach_args *aa = aux;
238 	struct hvn_softc *sc = (struct hvn_softc *)self;
239 	struct ifnet *ifp = &sc->sc_ac.ac_if;
240 
241 	sc->sc_hvsc = (struct hv_softc *)parent;
242 	sc->sc_chan = aa->aa_chan;
243 	sc->sc_dmat = aa->aa_dmat;
244 
245 	strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
246 
247 	printf(" channel %u", sc->sc_chan->ch_id);
248 
249 	if (hvn_nvs_attach(sc)) {
250 		printf(": failed to init NVSP\n");
251 		return;
252 	}
253 
254 	if (hvn_rx_ring_create(sc)) {
255 		printf(": failed to create Rx ring\n");
256 		goto detach;
257 	}
258 
259 	if (hvn_tx_ring_create(sc)) {
260 		printf(": failed to create Tx ring\n");
261 		goto detach;
262 	}
263 
264 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
265 	ifp->if_xflags = IFXF_MPSAFE;
266 	ifp->if_ioctl = hvn_ioctl;
267 	ifp->if_qstart = hvn_start;
268 	ifp->if_softc = sc;
269 
270 	ifp->if_capabilities = IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
271 	    IFCAP_CSUM_TCPv6;
272 	if (sc->sc_ndisver > NDIS_VERSION_6_30)
273 		ifp->if_capabilities |= IFCAP_CSUM_UDPv4 | IFCAP_CSUM_UDPv6;
274 
275 	if (sc->sc_proto >= HVN_NVS_PROTO_VERSION_2) {
276 		ifp->if_hardmtu = HVN_MAXMTU;
277 #if NVLAN > 0
278 		ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
279 #endif
280 	}
281 
282 	ifq_set_maxlen(&ifp->if_snd, HVN_TX_DESC - 1);
283 
284 	ifmedia_init(&sc->sc_media, IFM_IMASK, hvn_media_change,
285 	    hvn_media_status);
286 	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL);
287 	ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL);
288 
289 	if_attach(ifp);
290 
291 	if (hvn_rndis_attach(sc)) {
292 		printf(": failed to init RNDIS\n");
293 		goto detach;
294 	}
295 
296 	printf(": NVS %d.%d NDIS %d.%d", sc->sc_proto >> 16,
297 	    sc->sc_proto & 0xffff, sc->sc_ndisver >> 16 ,
298 	    sc->sc_ndisver & 0xffff);
299 
300 	if (hvn_set_capabilities(sc)) {
301 		printf(": failed to setup offloading\n");
302 		hvn_rndis_detach(sc);
303 		goto detach;
304 	}
305 
306 	if (hvn_get_lladdr(sc)) {
307 		printf(": failed to obtain an ethernet address\n");
308 		hvn_rndis_detach(sc);
309 		goto detach;
310 	}
311 
312 	printf(", address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr));
313 
314 	ether_ifattach(ifp);
315 	return;
316 
317  detach:
318 	hvn_rx_ring_destroy(sc);
319 	hvn_tx_ring_destroy(sc);
320 	hvn_nvs_detach(sc);
321 	if (ifp->if_qstart)
322 		if_detach(ifp);
323 }
324 
325 int
326 hvn_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
327 {
328 	struct hvn_softc *sc = ifp->if_softc;
329 	struct ifreq *ifr = (struct ifreq *)data;
330 	int s, error = 0;
331 
332 	s = splnet();
333 
334 	switch (command) {
335 	case SIOCSIFADDR:
336 		ifp->if_flags |= IFF_UP;
337 		if (!(ifp->if_flags & IFF_RUNNING))
338 			hvn_init(sc);
339 		break;
340 	case SIOCSIFFLAGS:
341 		if (ifp->if_flags & IFF_UP) {
342 			if (ifp->if_flags & IFF_RUNNING)
343 				error = ENETRESET;
344 			else
345 				hvn_init(sc);
346 		} else {
347 			if (ifp->if_flags & IFF_RUNNING)
348 				hvn_stop(sc);
349 		}
350 		break;
351 	case SIOCGIFMEDIA:
352 	case SIOCSIFMEDIA:
353 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
354 		break;
355 	default:
356 		error = ether_ioctl(ifp, &sc->sc_ac, command, data);
357 	}
358 
359 	if (error == ENETRESET) {
360 		if (ifp->if_flags & IFF_RUNNING)
361 			hvn_iff(sc);
362 		error = 0;
363 	}
364 
365 	splx(s);
366 
367 	return (error);
368 }
369 
370 int
371 hvn_media_change(struct ifnet *ifp)
372 {
373 	return (0);
374 }
375 
376 void
377 hvn_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
378 {
379 	struct hvn_softc *sc = ifp->if_softc;
380 
381 	hvn_get_link_status(sc);
382 	hvn_link_status(sc);
383 
384 	ifmr->ifm_status = IFM_AVALID;
385 	ifmr->ifm_active = IFM_ETHER | IFM_MANUAL;
386 	if (sc->sc_link_state == LINK_STATE_UP)
387 		ifmr->ifm_status |= IFM_ACTIVE;
388 }
389 
390 void
391 hvn_link_status(struct hvn_softc *sc)
392 {
393 	struct ifnet *ifp = &sc->sc_ac.ac_if;
394 
395 	if (sc->sc_link_state != ifp->if_link_state) {
396 		ifp->if_link_state = sc->sc_link_state;
397 		if_link_state_change(ifp);
398 	}
399 }
400 
401 int
402 hvn_iff(struct hvn_softc *sc)
403 {
404 	struct ifnet *ifp = &sc->sc_ac.ac_if;
405 	uint32_t filter = 0;
406 	int rv;
407 
408 	ifp->if_flags &= ~IFF_ALLMULTI;
409 
410 	if ((ifp->if_flags & IFF_PROMISC) || sc->sc_ac.ac_multirangecnt > 0) {
411 		ifp->if_flags |= IFF_ALLMULTI;
412 		filter = NDIS_PACKET_TYPE_PROMISCUOUS;
413 	} else {
414 		filter = NDIS_PACKET_TYPE_BROADCAST |
415 		    NDIS_PACKET_TYPE_DIRECTED;
416 		if (sc->sc_ac.ac_multicnt > 0) {
417 			ifp->if_flags |= IFF_ALLMULTI;
418 			filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
419 		}
420 	}
421 
422 	rv = hvn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
423 	    &filter, sizeof(filter));
424 	if (rv)
425 		DPRINTF("%s: failed to set RNDIS filter to %#x\n",
426 		    sc->sc_dev.dv_xname, filter);
427 	return (rv);
428 }
429 
430 void
431 hvn_init(struct hvn_softc *sc)
432 {
433 	struct ifnet *ifp = &sc->sc_ac.ac_if;
434 
435 	hvn_stop(sc);
436 
437 	if (hvn_iff(sc) == 0) {
438 		ifp->if_flags |= IFF_RUNNING;
439 		ifq_clr_oactive(&ifp->if_snd);
440 	}
441 }
442 
443 void
444 hvn_stop(struct hvn_softc *sc)
445 {
446 	struct ifnet *ifp = &sc->sc_ac.ac_if;
447 
448 	if (ifp->if_flags & IFF_RUNNING) {
449 		ifp->if_flags &= ~IFF_RUNNING;
450 		hvn_rndis_close(sc);
451 	}
452 
453 	ifq_barrier(&ifp->if_snd);
454 	sched_barrier(NULL);
455 
456 	ifq_clr_oactive(&ifp->if_snd);
457 }
458 
459 void
460 hvn_start(struct ifqueue *ifq)
461 {
462 	struct ifnet *ifp = ifq->ifq_if;
463 	struct hvn_softc *sc = ifp->if_softc;
464 	struct hvn_tx_desc *txd;
465 	struct mbuf *m;
466 
467 	for (;;) {
468 		if (!sc->sc_tx_avail) {
469 			/* transient */
470 			ifq_set_oactive(ifq);
471 			break;
472 		}
473 
474 		m = ifq_dequeue(ifq);
475 		if (m == NULL)
476 			break;
477 
478 		if (hvn_encap(sc, m, &txd)) {
479 			/* the chain is too large */
480 			ifp->if_oerrors++;
481 			m_freem(m);
482 			continue;
483 		}
484 
485 #if NBPFILTER > 0
486 		if (ifp->if_bpf)
487 			bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT);
488 #endif
489 
490 		if (hvn_rndis_output(sc, txd)) {
491 			hvn_decap(sc, txd);
492 			ifp->if_oerrors++;
493 			m_freem(m);
494 			continue;
495 		}
496 
497 		sc->sc_tx_next++;
498 	}
499 }
500 
501 static inline char *
502 hvn_rndis_pktinfo_append(struct rndis_packet_msg *pkt, size_t pktsize,
503     size_t datalen, uint32_t type)
504 {
505 	struct rndis_pktinfo *pi;
506 	size_t pi_size = sizeof(*pi) + datalen;
507 	char *cp;
508 
509 	KASSERT(pkt->rm_pktinfooffset + pkt->rm_pktinfolen + pi_size <=
510 	    pktsize);
511 
512 	cp = (char *)pkt + pkt->rm_pktinfooffset + pkt->rm_pktinfolen;
513 	pi = (struct rndis_pktinfo *)cp;
514 	pi->rm_size = pi_size;
515 	pi->rm_type = type;
516 	pi->rm_pktinfooffset = sizeof(*pi);
517 	pkt->rm_pktinfolen += pi_size;
518 	pkt->rm_dataoffset += pi_size;
519 	pkt->rm_len += pi_size;
520 	return ((char *)pi->rm_data);
521 }
522 
523 int
524 hvn_encap(struct hvn_softc *sc, struct mbuf *m, struct hvn_tx_desc **txd0)
525 {
526 	struct hvn_tx_desc *txd;
527 	struct rndis_packet_msg *pkt;
528 	bus_dma_segment_t *seg;
529 	size_t pktlen;
530 	int i, rv;
531 
532 	do {
533 		txd = &sc->sc_tx_desc[sc->sc_tx_next % HVN_TX_DESC];
534 		sc->sc_tx_next++;
535 	} while (!txd->txd_ready);
536 	txd->txd_ready = 0;
537 
538 	pkt = txd->txd_req;
539 	memset(pkt, 0, HVN_RNDIS_PKT_LEN);
540 	pkt->rm_type = REMOTE_NDIS_PACKET_MSG;
541 	pkt->rm_len = sizeof(*pkt) + m->m_pkthdr.len;
542 	pkt->rm_dataoffset = RNDIS_DATA_OFFSET;
543 	pkt->rm_datalen = m->m_pkthdr.len;
544 	pkt->rm_pktinfooffset = sizeof(*pkt); /* adjusted below */
545 	pkt->rm_pktinfolen = 0;
546 
547 	rv = bus_dmamap_load_mbuf(sc->sc_dmat, txd->txd_dmap, m, BUS_DMA_READ |
548 	    BUS_DMA_NOWAIT);
549 	switch (rv) {
550 	case 0:
551 		break;
552 	case EFBIG:
553 		if (m_defrag(m, M_NOWAIT) == 0 &&
554 		    bus_dmamap_load_mbuf(sc->sc_dmat, txd->txd_dmap, m,
555 		    BUS_DMA_READ | BUS_DMA_NOWAIT) == 0)
556 			break;
557 		/* FALLTHROUGH */
558 	default:
559 		DPRINTF("%s: failed to load mbuf\n", sc->sc_dev.dv_xname);
560 		return (-1);
561 	}
562 	txd->txd_buf = m;
563 
564 #if NVLAN > 0
565 	if (m->m_flags & M_VLANTAG) {
566 		uint32_t vlan;
567 		char *cp;
568 
569 		vlan = NDIS_VLAN_INFO(EVL_VLANOFTAG(m->m_pkthdr.ether_vtag),
570 		    EVL_PRIOFTAG(m->m_pkthdr.ether_vtag));
571 		cp = hvn_rndis_pktinfo_append(pkt, HVN_RNDIS_PKT_LEN,
572 		    NDIS_VLAN_INFO_SIZE, NDIS_PKTINFO_TYPE_VLAN);
573 		memcpy(cp, &vlan, NDIS_VLAN_INFO_SIZE);
574 	}
575 #endif
576 
577 	if (m->m_pkthdr.csum_flags & (M_IPV4_CSUM_OUT | M_UDP_CSUM_OUT |
578 	    M_TCP_CSUM_OUT)) {
579 		uint32_t csum = NDIS_TXCSUM_INFO_IPV4;
580 		char *cp;
581 
582 		if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
583 			csum |= NDIS_TXCSUM_INFO_IPCS;
584 		if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT)
585 			csum |= NDIS_TXCSUM_INFO_TCPCS;
586 		if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT)
587 			csum |= NDIS_TXCSUM_INFO_UDPCS;
588 		cp = hvn_rndis_pktinfo_append(pkt, HVN_RNDIS_PKT_LEN,
589 		    NDIS_TXCSUM_INFO_SIZE, NDIS_PKTINFO_TYPE_CSUM);
590 		memcpy(cp, &csum, NDIS_TXCSUM_INFO_SIZE);
591 	}
592 
593 	pktlen = pkt->rm_pktinfooffset + pkt->rm_pktinfolen;
594 	pkt->rm_pktinfooffset -= RNDIS_HEADER_OFFSET;
595 
596 	/* Attach an RNDIS message to the first slot */
597 	txd->txd_sgl[0].gpa_page = txd->txd_gpa.gpa_page;
598 	txd->txd_sgl[0].gpa_ofs = txd->txd_gpa.gpa_ofs;
599 	txd->txd_sgl[0].gpa_len = pktlen;
600 	txd->txd_nsge = txd->txd_dmap->dm_nsegs + 1;
601 
602 	for (i = 0; i < txd->txd_dmap->dm_nsegs; i++) {
603 		seg = &txd->txd_dmap->dm_segs[i];
604 		txd->txd_sgl[1 + i].gpa_page = atop(seg->ds_addr);
605 		txd->txd_sgl[1 + i].gpa_ofs = seg->ds_addr & PAGE_MASK;
606 		txd->txd_sgl[1 + i].gpa_len = seg->ds_len;
607 	}
608 
609 	*txd0 = txd;
610 
611 	atomic_dec_int(&sc->sc_tx_avail);
612 
613 	return (0);
614 }
615 
616 void
617 hvn_decap(struct hvn_softc *sc, struct hvn_tx_desc *txd)
618 {
619 	bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 0, 0,
620 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
621 	bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap);
622 	txd->txd_buf = NULL;
623 	txd->txd_nsge = 0;
624 	txd->txd_ready = 1;
625 	atomic_inc_int(&sc->sc_tx_avail);
626 }
627 
628 void
629 hvn_txeof(struct hvn_softc *sc, uint64_t tid)
630 {
631 	struct hvn_tx_desc *txd;
632 	struct mbuf *m;
633 	uint32_t id = tid >> 32;
634 
635 	if ((tid & 0xffffffffU) != 0)
636 		return;
637 	id -= HVN_NVS_CHIM_SIG;
638 	if (id >= HVN_TX_DESC)
639 		panic("tx packet index too large: %u", id);
640 
641 	txd = &sc->sc_tx_desc[id];
642 
643 	if ((m = txd->txd_buf) == NULL)
644 		panic("%s: no mbuf @%u\n", sc->sc_dev.dv_xname, id);
645 	txd->txd_buf = NULL;
646 
647 	bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 0, 0,
648 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
649 	bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap);
650 	m_freem(m);
651 
652 	txd->txd_ready = 1;
653 
654 	atomic_inc_int(&sc->sc_tx_avail);
655 
656 }
657 
658 int
659 hvn_rx_ring_create(struct hvn_softc *sc)
660 {
661 	struct hvn_nvs_rxbuf_conn cmd;
662 	struct hvn_nvs_rxbuf_conn_resp *rsp;
663 	uint64_t tid;
664 
665 	if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_2)
666 		sc->sc_rx_size = 15 * 1024 * 1024;	/* 15MB */
667 	else
668 		sc->sc_rx_size = 16 * 1024 * 1024; 	/* 16MB */
669 	sc->sc_rx_ring = km_alloc(sc->sc_rx_size, &kv_any, &kp_zero,
670 	    cold ? &kd_nowait : &kd_waitok);
671 	if (sc->sc_rx_ring == NULL) {
672 		DPRINTF("%s: failed to allocate Rx ring buffer\n",
673 		    sc->sc_dev.dv_xname);
674 		return (-1);
675 	}
676 	if (hv_handle_alloc(sc->sc_chan, sc->sc_rx_ring, sc->sc_rx_size,
677 	    &sc->sc_rx_hndl)) {
678 		DPRINTF("%s: failed to obtain a PA handle\n",
679 		    sc->sc_dev.dv_xname);
680 		goto errout;
681 	}
682 
683 	memset(&cmd, 0, sizeof(cmd));
684 	cmd.nvs_type = HVN_NVS_TYPE_RXBUF_CONN;
685 	cmd.nvs_gpadl = sc->sc_rx_hndl;
686 	cmd.nvs_sig = HVN_NVS_RXBUF_SIG;
687 
688 	tid = atomic_inc_int_nv(&sc->sc_nvstid);
689 	if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100))
690 		goto errout;
691 
692 	rsp = (struct hvn_nvs_rxbuf_conn_resp *)&sc->sc_nvsrsp;
693 	if (rsp->nvs_status != HVN_NVS_STATUS_OK) {
694 		DPRINTF("%s: failed to set up the Rx ring\n",
695 		    sc->sc_dev.dv_xname);
696 		goto errout;
697 	}
698 	if (rsp->nvs_nsect > 1) {
699 		DPRINTF("%s: invalid number of Rx ring sections: %u\n",
700 		    sc->sc_dev.dv_xname, rsp->nvs_nsect);
701 		hvn_rx_ring_destroy(sc);
702 		return (-1);
703 	}
704 	return (0);
705 
706  errout:
707 	if (sc->sc_rx_hndl) {
708 		hv_handle_free(sc->sc_chan, sc->sc_rx_hndl);
709 		sc->sc_rx_hndl = 0;
710 	}
711 	if (sc->sc_rx_ring) {
712 		km_free(sc->sc_rx_ring, sc->sc_rx_size, &kv_any, &kp_zero);
713 		sc->sc_rx_ring = NULL;
714 	}
715 	return (-1);
716 }
717 
718 int
719 hvn_rx_ring_destroy(struct hvn_softc *sc)
720 {
721 	struct hvn_nvs_rxbuf_disconn cmd;
722 	uint64_t tid;
723 
724 	if (sc->sc_rx_ring == NULL)
725 		return (0);
726 
727 	memset(&cmd, 0, sizeof(cmd));
728 	cmd.nvs_type = HVN_NVS_TYPE_RXBUF_DISCONN;
729 	cmd.nvs_sig = HVN_NVS_RXBUF_SIG;
730 
731 	tid = atomic_inc_int_nv(&sc->sc_nvstid);
732 	if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 0))
733 		return (-1);
734 
735 	delay(100);
736 
737 	hv_handle_free(sc->sc_chan, sc->sc_rx_hndl);
738 
739 	sc->sc_rx_hndl = 0;
740 
741 	km_free(sc->sc_rx_ring, sc->sc_rx_size, &kv_any, &kp_zero);
742 	sc->sc_rx_ring = NULL;
743 
744 	return (0);
745 }
746 
747 int
748 hvn_tx_ring_create(struct hvn_softc *sc)
749 {
750 	struct hvn_tx_desc *txd;
751 	bus_dma_segment_t *seg;
752 	size_t msgsize;
753 	int i, rsegs;
754 	paddr_t pa;
755 
756 	msgsize = roundup(HVN_RNDIS_PKT_LEN, 128);
757 
758 	/* Allocate memory to store RNDIS messages */
759 	if (bus_dmamem_alloc(sc->sc_dmat, msgsize * HVN_TX_DESC, PAGE_SIZE, 0,
760 	    &sc->sc_tx_mseg, 1, &rsegs, BUS_DMA_ZERO | BUS_DMA_WAITOK)) {
761 		DPRINTF("%s: failed to allocate memory for RDNIS messages\n",
762 		    sc->sc_dev.dv_xname);
763 		goto errout;
764 	}
765 	if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tx_mseg, 1, msgsize *
766 	    HVN_TX_DESC, (caddr_t *)&sc->sc_tx_msgs, BUS_DMA_WAITOK)) {
767 		DPRINTF("%s: failed to establish mapping for RDNIS messages\n",
768 		    sc->sc_dev.dv_xname);
769 		goto errout;
770 	}
771 	if (bus_dmamap_create(sc->sc_dmat, msgsize * HVN_TX_DESC, 1,
772 	    msgsize * HVN_TX_DESC, 0, BUS_DMA_WAITOK, &sc->sc_tx_rmap)) {
773 		DPRINTF("%s: failed to create map for RDNIS messages\n",
774 		    sc->sc_dev.dv_xname);
775 		goto errout;
776 	}
777 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_tx_rmap, sc->sc_tx_msgs,
778 	    msgsize * HVN_TX_DESC, NULL, BUS_DMA_WAITOK)) {
779 		DPRINTF("%s: failed to create map for RDNIS messages\n",
780 		    sc->sc_dev.dv_xname);
781 		goto errout;
782 	}
783 
784 	for (i = 0; i < HVN_TX_DESC; i++) {
785 		txd = &sc->sc_tx_desc[i];
786 		if (bus_dmamap_create(sc->sc_dmat, HVN_TX_PKT_SIZE,
787 		    HVN_TX_FRAGS, HVN_TX_FRAG_SIZE, PAGE_SIZE,
788 		    BUS_DMA_WAITOK, &txd->txd_dmap)) {
789 			DPRINTF("%s: failed to create map for TX descriptors\n",
790 			    sc->sc_dev.dv_xname);
791 			goto errout;
792 		}
793 		seg = &sc->sc_tx_rmap->dm_segs[0];
794 		pa = seg->ds_addr + (msgsize * i);
795 		txd->txd_gpa.gpa_page = atop(pa);
796 		txd->txd_gpa.gpa_ofs = pa & PAGE_MASK;
797 		txd->txd_gpa.gpa_len = msgsize;
798 		txd->txd_req = (void *)((caddr_t)sc->sc_tx_msgs +
799 		    (msgsize * i));
800 		txd->txd_id = i + HVN_NVS_CHIM_SIG;
801 		txd->txd_ready = 1;
802 	}
803 	sc->sc_tx_avail = HVN_TX_DESC;
804 
805 	return (0);
806 
807  errout:
808 	hvn_tx_ring_destroy(sc);
809 	return (-1);
810 }
811 
812 void
813 hvn_tx_ring_destroy(struct hvn_softc *sc)
814 {
815 	struct hvn_tx_desc *txd;
816 	int i;
817 
818 	for (i = 0; i < HVN_TX_DESC; i++) {
819 		txd = &sc->sc_tx_desc[i];
820 		if (txd->txd_dmap == NULL)
821 			continue;
822 		bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 0, 0,
823 		    BUS_DMASYNC_POSTWRITE);
824 		bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap);
825 		bus_dmamap_destroy(sc->sc_dmat, txd->txd_dmap);
826 		txd->txd_dmap = NULL;
827 		if (txd->txd_buf == NULL)
828 			continue;
829 		m_free(txd->txd_buf);
830 		txd->txd_buf = NULL;
831 	}
832 	if (sc->sc_tx_rmap) {
833 		bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_rmap, 0, 0,
834 		    BUS_DMASYNC_POSTWRITE);
835 		bus_dmamap_unload(sc->sc_dmat, sc->sc_tx_rmap);
836 		bus_dmamap_destroy(sc->sc_dmat, sc->sc_tx_rmap);
837 	}
838 	if (sc->sc_tx_msgs) {
839 		size_t msgsize = roundup(HVN_RNDIS_PKT_LEN, 128);
840 
841 		bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_tx_msgs,
842 		    msgsize * HVN_TX_DESC);
843 		bus_dmamem_free(sc->sc_dmat, &sc->sc_tx_mseg, 1);
844 	}
845 	sc->sc_tx_rmap = NULL;
846 	sc->sc_tx_msgs = NULL;
847 }
848 
849 int
850 hvn_get_lladdr(struct hvn_softc *sc)
851 {
852 	char enaddr[ETHER_ADDR_LEN];
853 	size_t addrlen = ETHER_ADDR_LEN;
854 	int rv;
855 
856 	rv = hvn_rndis_query(sc, OID_802_3_PERMANENT_ADDRESS,
857 	    enaddr, &addrlen);
858 	if (rv == 0 && addrlen == ETHER_ADDR_LEN)
859 		memcpy(sc->sc_ac.ac_enaddr, enaddr, ETHER_ADDR_LEN);
860 	return (rv);
861 }
862 
863 int
864 hvn_set_lladdr(struct hvn_softc *sc)
865 {
866 	return (hvn_rndis_set(sc, OID_802_3_CURRENT_ADDRESS,
867 	    sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN));
868 }
869 
870 void
871 hvn_get_link_status(struct hvn_softc *sc)
872 {
873 	uint32_t state;
874 	size_t len = sizeof(state);
875 
876 	if (hvn_rndis_query(sc, OID_GEN_MEDIA_CONNECT_STATUS,
877 	    &state, &len) == 0)
878 		sc->sc_link_state = (state == NDIS_MEDIA_STATE_CONNECTED) ?
879 		    LINK_STATE_UP : LINK_STATE_DOWN;
880 }
881 
882 int
883 hvn_nvs_attach(struct hvn_softc *sc)
884 {
885 	const uint32_t protos[] = {
886 		HVN_NVS_PROTO_VERSION_5, HVN_NVS_PROTO_VERSION_4,
887 		HVN_NVS_PROTO_VERSION_2, HVN_NVS_PROTO_VERSION_1
888 	};
889 	struct hvn_nvs_init cmd;
890 	struct hvn_nvs_init_resp *rsp;
891 	struct hvn_nvs_ndis_init ncmd;
892 	struct hvn_nvs_ndis_conf ccmd;
893 	uint32_t ndisver, ringsize;
894 	uint64_t tid;
895 	int i;
896 
897 	sc->sc_nvsbuf = malloc(HVN_NVS_BUFSIZE, M_DEVBUF, M_ZERO |
898 	    (cold ? M_NOWAIT : M_WAITOK));
899 	if (sc->sc_nvsbuf == NULL) {
900 		DPRINTF("%s: failed to allocate channel data buffer\n",
901 		    sc->sc_dev.dv_xname);
902 		return (-1);
903 	}
904 
905 	/* We need to be able to fit all RNDIS control and data messages */
906 	ringsize = HVN_RNDIS_CTLREQS *
907 	    (sizeof(struct hvn_nvs_rndis) + sizeof(struct vmbus_gpa)) +
908 	    HVN_TX_DESC * (sizeof(struct hvn_nvs_rndis) +
909 	    (HVN_TX_FRAGS + 1) * sizeof(struct vmbus_gpa));
910 
911 	sc->sc_chan->ch_flags &= ~CHF_BATCHED;
912 
913 	/* Associate our interrupt handler with the channel */
914 	if (hv_channel_open(sc->sc_chan, ringsize, NULL, 0,
915 	    hvn_nvs_intr, sc)) {
916 		DPRINTF("%s: failed to open channel\n", sc->sc_dev.dv_xname);
917 		free(sc->sc_nvsbuf, M_DEVBUF, HVN_NVS_BUFSIZE);
918 		return (-1);
919 	}
920 
921 	hv_evcount_attach(sc->sc_chan, sc->sc_dev.dv_xname);
922 
923 	memset(&cmd, 0, sizeof(cmd));
924 	cmd.nvs_type = HVN_NVS_TYPE_INIT;
925 	for (i = 0; i < nitems(protos); i++) {
926 		cmd.nvs_ver_min = cmd.nvs_ver_max = protos[i];
927 		tid = atomic_inc_int_nv(&sc->sc_nvstid);
928 		if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100))
929 			return (-1);
930 		rsp = (struct hvn_nvs_init_resp *)&sc->sc_nvsrsp;
931 		if (rsp->nvs_status == HVN_NVS_STATUS_OK) {
932 			sc->sc_proto = protos[i];
933 			break;
934 		}
935 	}
936 	if (!sc->sc_proto) {
937 		DPRINTF("%s: failed to negotiate NVSP version\n",
938 		    sc->sc_dev.dv_xname);
939 		return (-1);
940 	}
941 
942 	if (sc->sc_proto >= HVN_NVS_PROTO_VERSION_2) {
943 		memset(&ccmd, 0, sizeof(ccmd));
944 		ccmd.nvs_type = HVN_NVS_TYPE_NDIS_CONF;
945 		ccmd.nvs_mtu = HVN_MAXMTU;
946 		ccmd.nvs_caps = HVN_NVS_NDIS_CONF_VLAN;
947 
948 		tid = atomic_inc_int_nv(&sc->sc_nvstid);
949 		if (hvn_nvs_cmd(sc, &ccmd, sizeof(ccmd), tid, 100))
950 			return (-1);
951 	}
952 
953 	memset(&ncmd, 0, sizeof(ncmd));
954 	ncmd.nvs_type = HVN_NVS_TYPE_NDIS_INIT;
955 	if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_4)
956 		ndisver = NDIS_VERSION_6_1;
957 	else
958 		ndisver = NDIS_VERSION_6_30;
959 	ncmd.nvs_ndis_major = (ndisver & 0xffff0000) >> 16;
960 	ncmd.nvs_ndis_minor = (ndisver & 0x0000ffff);
961 
962 	tid = atomic_inc_int_nv(&sc->sc_nvstid);
963 	if (hvn_nvs_cmd(sc, &ncmd, sizeof(ncmd), tid, 100))
964 		return (-1);
965 
966 	sc->sc_ndisver = ndisver;
967 
968 	return (0);
969 }
970 
971 void
972 hvn_nvs_intr(void *arg)
973 {
974 	struct hvn_softc *sc = arg;
975 	struct ifnet *ifp = &sc->sc_ac.ac_if;
976 	struct vmbus_chanpkt_hdr *cph;
977 	struct hvn_nvs_hdr *nvs;
978 	uint64_t rid;
979 	uint32_t rlen;
980 	int rv;
981 
982 	for (;;) {
983 		rv = hv_channel_recv(sc->sc_chan, sc->sc_nvsbuf,
984 		    HVN_NVS_BUFSIZE, &rlen, &rid, 1);
985 		if (rv != 0 || rlen == 0) {
986 			if (rv != EAGAIN)
987 				printf("%s: failed to receive an NVSP "
988 				    "packet\n", sc->sc_dev.dv_xname);
989 			break;
990 		}
991 		cph = (struct vmbus_chanpkt_hdr *)sc->sc_nvsbuf;
992 		nvs = (struct hvn_nvs_hdr *)VMBUS_CHANPKT_CONST_DATA(cph);
993 
994 		if (cph->cph_type == VMBUS_CHANPKT_TYPE_COMP) {
995 			switch (nvs->nvs_type) {
996 			case HVN_NVS_TYPE_INIT_RESP:
997 			case HVN_NVS_TYPE_RXBUF_CONNRESP:
998 			case HVN_NVS_TYPE_CHIM_CONNRESP:
999 			case HVN_NVS_TYPE_SUBCH_RESP:
1000 				/* copy the response back */
1001 				memcpy(&sc->sc_nvsrsp, nvs, HVN_NVS_MSGSIZE);
1002 				sc->sc_nvsdone = 1;
1003 				wakeup_one(&sc->sc_nvsrsp);
1004 				break;
1005 			case HVN_NVS_TYPE_RNDIS_ACK:
1006 				hvn_txeof(sc, cph->cph_tid);
1007 				break;
1008 			default:
1009 				printf("%s: unhandled NVSP packet type %u "
1010 				    "on completion\n", sc->sc_dev.dv_xname,
1011 				    nvs->nvs_type);
1012 			}
1013 		} else if (cph->cph_type == VMBUS_CHANPKT_TYPE_RXBUF) {
1014 			switch (nvs->nvs_type) {
1015 			case HVN_NVS_TYPE_RNDIS:
1016 				hvn_rndis_input(sc, cph->cph_tid, cph);
1017 				break;
1018 			default:
1019 				printf("%s: unhandled NVSP packet type %u "
1020 				    "on receive\n", sc->sc_dev.dv_xname,
1021 				    nvs->nvs_type);
1022 			}
1023 		} else
1024 			printf("%s: unknown NVSP packet type %u\n",
1025 			    sc->sc_dev.dv_xname, cph->cph_type);
1026 	}
1027 
1028 	if (ifq_is_oactive(&ifp->if_snd))
1029 		ifq_restart(&ifp->if_snd);
1030 }
1031 
1032 int
1033 hvn_nvs_cmd(struct hvn_softc *sc, void *cmd, size_t cmdsize, uint64_t tid,
1034     int timo)
1035 {
1036 	struct hvn_nvs_hdr *hdr = cmd;
1037 	int tries = 10;
1038 	int rv, s;
1039 
1040 	KERNEL_ASSERT_LOCKED();
1041 
1042 	sc->sc_nvsdone = 0;
1043 
1044 	do {
1045 		rv = hv_channel_send(sc->sc_chan, cmd, cmdsize,
1046 		    tid, VMBUS_CHANPKT_TYPE_INBAND,
1047 		    timo ? VMBUS_CHANPKT_FLAG_RC : 0);
1048 		if (rv == EAGAIN) {
1049 			if (cold)
1050 				delay(1000);
1051 			else
1052 				tsleep(cmd, PRIBIO, "nvsout", 1);
1053 		} else if (rv) {
1054 			DPRINTF("%s: NVSP operation %u send error %d\n",
1055 			    sc->sc_dev.dv_xname, hdr->nvs_type, rv);
1056 			return (rv);
1057 		}
1058 	} while (rv != 0 && --tries > 0);
1059 
1060 	if (tries == 0 && rv != 0) {
1061 		printf("%s: NVSP operation %u send error %d\n",
1062 		    sc->sc_dev.dv_xname, hdr->nvs_type, rv);
1063 		return (rv);
1064 	}
1065 
1066 	if (timo == 0)
1067 		return (0);
1068 
1069 	do {
1070 		if (cold)
1071 			delay(1000);
1072 		else
1073 			tsleep(sc, PRIBIO | PCATCH, "nvscmd", 1);
1074 		s = splnet();
1075 		hvn_nvs_intr(sc);
1076 		splx(s);
1077 	} while (--timo > 0 && sc->sc_nvsdone != 1);
1078 
1079 	if (timo == 0 && sc->sc_nvsdone != 1) {
1080 		printf("%s: NVSP operation %u timed out\n",
1081 		    sc->sc_dev.dv_xname, hdr->nvs_type);
1082 		return (ETIMEDOUT);
1083 	}
1084 	return (0);
1085 }
1086 
1087 int
1088 hvn_nvs_ack(struct hvn_softc *sc, uint64_t tid)
1089 {
1090 	struct hvn_nvs_rndis_ack cmd;
1091 	int tries = 5;
1092 	int rv;
1093 
1094 	cmd.nvs_type = HVN_NVS_TYPE_RNDIS_ACK;
1095 	cmd.nvs_status = HVN_NVS_STATUS_OK;
1096 	do {
1097 		rv = hv_channel_send(sc->sc_chan, &cmd, sizeof(cmd),
1098 		    tid, VMBUS_CHANPKT_TYPE_COMP, 0);
1099 		if (rv == EAGAIN)
1100 			delay(10);
1101 		else if (rv) {
1102 			DPRINTF("%s: NVSP acknowledgement error %d\n",
1103 			    sc->sc_dev.dv_xname, rv);
1104 			return (rv);
1105 		}
1106 	} while (rv != 0 && --tries > 0);
1107 	return (rv);
1108 }
1109 
1110 void
1111 hvn_nvs_detach(struct hvn_softc *sc)
1112 {
1113 	if (hv_channel_close(sc->sc_chan) == 0) {
1114 		free(sc->sc_nvsbuf, M_DEVBUF, HVN_NVS_BUFSIZE);
1115 		sc->sc_nvsbuf = NULL;
1116 	}
1117 }
1118 
1119 static inline struct rndis_cmd *
1120 hvn_alloc_cmd(struct hvn_softc *sc)
1121 {
1122 	struct rndis_cmd *rc;
1123 
1124 	mtx_enter(&sc->sc_cntl_fqlck);
1125 	while ((rc = TAILQ_FIRST(&sc->sc_cntl_fq)) == NULL)
1126 		msleep(&sc->sc_cntl_fq, &sc->sc_cntl_fqlck,
1127 		    PRIBIO, "nvsalloc", 1);
1128 	TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry);
1129 	mtx_leave(&sc->sc_cntl_fqlck);
1130 	return (rc);
1131 }
1132 
1133 static inline void
1134 hvn_submit_cmd(struct hvn_softc *sc, struct rndis_cmd *rc)
1135 {
1136 	mtx_enter(&sc->sc_cntl_sqlck);
1137 	TAILQ_INSERT_TAIL(&sc->sc_cntl_sq, rc, rc_entry);
1138 	mtx_leave(&sc->sc_cntl_sqlck);
1139 }
1140 
1141 static inline struct rndis_cmd *
1142 hvn_complete_cmd(struct hvn_softc *sc, uint32_t id)
1143 {
1144 	struct rndis_cmd *rc;
1145 
1146 	mtx_enter(&sc->sc_cntl_sqlck);
1147 	TAILQ_FOREACH(rc, &sc->sc_cntl_sq, rc_entry) {
1148 		if (rc->rc_id == id) {
1149 			TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry);
1150 			break;
1151 		}
1152 	}
1153 	mtx_leave(&sc->sc_cntl_sqlck);
1154 	if (rc != NULL) {
1155 		mtx_enter(&sc->sc_cntl_cqlck);
1156 		TAILQ_INSERT_TAIL(&sc->sc_cntl_cq, rc, rc_entry);
1157 		mtx_leave(&sc->sc_cntl_cqlck);
1158 	}
1159 	return (rc);
1160 }
1161 
1162 static inline void
1163 hvn_release_cmd(struct hvn_softc *sc, struct rndis_cmd *rc)
1164 {
1165 	mtx_enter(&sc->sc_cntl_cqlck);
1166 	TAILQ_REMOVE(&sc->sc_cntl_cq, rc, rc_entry);
1167 	mtx_leave(&sc->sc_cntl_cqlck);
1168 }
1169 
1170 static inline int
1171 hvn_rollback_cmd(struct hvn_softc *sc, struct rndis_cmd *rc)
1172 {
1173 	struct rndis_cmd *rn;
1174 
1175 	mtx_enter(&sc->sc_cntl_sqlck);
1176 	TAILQ_FOREACH(rn, &sc->sc_cntl_sq, rc_entry) {
1177 		if (rn == rc) {
1178 			TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry);
1179 			mtx_leave(&sc->sc_cntl_sqlck);
1180 			return (0);
1181 		}
1182 	}
1183 	mtx_leave(&sc->sc_cntl_sqlck);
1184 	return (-1);
1185 }
1186 
1187 static inline void
1188 hvn_free_cmd(struct hvn_softc *sc, struct rndis_cmd *rc)
1189 {
1190 	memset(rc->rc_req, 0, sizeof(struct rndis_packet_msg));
1191 	memset(&rc->rc_cmp, 0, sizeof(rc->rc_cmp));
1192 	memset(&rc->rc_msg, 0, sizeof(rc->rc_msg));
1193 	mtx_enter(&sc->sc_cntl_fqlck);
1194 	TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry);
1195 	mtx_leave(&sc->sc_cntl_fqlck);
1196 	wakeup(&sc->sc_cntl_fq);
1197 }
1198 
1199 int
1200 hvn_rndis_attach(struct hvn_softc *sc)
1201 {
1202 	struct rndis_init_req *req;
1203 	struct rndis_init_comp *cmp;
1204 	struct rndis_cmd *rc;
1205 	int i, rv;
1206 
1207 	/* RNDIS control message queues */
1208 	TAILQ_INIT(&sc->sc_cntl_sq);
1209 	TAILQ_INIT(&sc->sc_cntl_cq);
1210 	TAILQ_INIT(&sc->sc_cntl_fq);
1211 	mtx_init(&sc->sc_cntl_sqlck, IPL_NET);
1212 	mtx_init(&sc->sc_cntl_cqlck, IPL_NET);
1213 	mtx_init(&sc->sc_cntl_fqlck, IPL_NET);
1214 
1215 	for (i = 0; i < HVN_RNDIS_CTLREQS; i++) {
1216 		rc = &sc->sc_cntl_msgs[i];
1217 		if (bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1,
1218 		    PAGE_SIZE, 0, BUS_DMA_WAITOK, &rc->rc_dmap)) {
1219 			DPRINTF("%s: failed to create RNDIS command map\n",
1220 			    sc->sc_dev.dv_xname);
1221 			goto errout;
1222 		}
1223 		if (bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
1224 		    0, &rc->rc_segs, 1, &rc->rc_nsegs, BUS_DMA_NOWAIT |
1225 		    BUS_DMA_ZERO)) {
1226 			DPRINTF("%s: failed to allocate RNDIS command\n",
1227 			    sc->sc_dev.dv_xname);
1228 			bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap);
1229 			goto errout;
1230 		}
1231 		if (bus_dmamem_map(sc->sc_dmat, &rc->rc_segs, rc->rc_nsegs,
1232 		    PAGE_SIZE, (caddr_t *)&rc->rc_req, BUS_DMA_NOWAIT)) {
1233 			DPRINTF("%s: failed to allocate RNDIS command\n",
1234 			    sc->sc_dev.dv_xname);
1235 			bus_dmamem_free(sc->sc_dmat, &rc->rc_segs,
1236 			    rc->rc_nsegs);
1237 			bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap);
1238 			goto errout;
1239 		}
1240 		if (bus_dmamap_load(sc->sc_dmat, rc->rc_dmap, rc->rc_req,
1241 		    PAGE_SIZE, NULL, BUS_DMA_WAITOK)) {
1242 			DPRINTF("%s: failed to load RNDIS command map\n",
1243 			    sc->sc_dev.dv_xname);
1244 			bus_dmamem_free(sc->sc_dmat, &rc->rc_segs,
1245 			    rc->rc_nsegs);
1246 			bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap);
1247 			goto errout;
1248 		}
1249 		rc->rc_gpa = atop(rc->rc_dmap->dm_segs[0].ds_addr);
1250 		TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry);
1251 	}
1252 
1253 	rc = hvn_alloc_cmd(sc);
1254 
1255 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1256 	    BUS_DMASYNC_PREREAD);
1257 
1258 	rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid);
1259 
1260 	req = rc->rc_req;
1261 	req->rm_type = REMOTE_NDIS_INITIALIZE_MSG;
1262 	req->rm_len = sizeof(*req);
1263 	req->rm_rid = rc->rc_id;
1264 	req->rm_ver_major = RNDIS_VERSION_MAJOR;
1265 	req->rm_ver_minor = RNDIS_VERSION_MINOR;
1266 	req->rm_max_xfersz = HVN_RNDIS_XFER_SIZE;
1267 
1268 	rc->rc_cmplen = sizeof(*cmp);
1269 
1270 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1271 	    BUS_DMASYNC_PREWRITE);
1272 
1273 	if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) {
1274 		DPRINTF("%s: INITIALIZE_MSG failed, error %d\n",
1275 		    sc->sc_dev.dv_xname, rv);
1276 		hvn_free_cmd(sc, rc);
1277 		goto errout;
1278 	}
1279 	cmp = (struct rndis_init_comp *)&rc->rc_cmp;
1280 	if (cmp->rm_status != RNDIS_STATUS_SUCCESS) {
1281 		DPRINTF("%s: failed to init RNDIS, error %#x\n",
1282 		    sc->sc_dev.dv_xname, cmp->rm_status);
1283 		hvn_free_cmd(sc, rc);
1284 		goto errout;
1285 	}
1286 
1287 	hvn_free_cmd(sc, rc);
1288 
1289 	/* Initialize RNDIS Data command */
1290 	memset(&sc->sc_data_msg, 0, sizeof(sc->sc_data_msg));
1291 	sc->sc_data_msg.nvs_type = HVN_NVS_TYPE_RNDIS;
1292 	sc->sc_data_msg.nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_DATA;
1293 	sc->sc_data_msg.nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID;
1294 
1295 	return (0);
1296 
1297 errout:
1298 	for (i = 0; i < HVN_RNDIS_CTLREQS; i++) {
1299 		rc = &sc->sc_cntl_msgs[i];
1300 		if (rc->rc_req == NULL)
1301 			continue;
1302 		TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry);
1303 		bus_dmamem_free(sc->sc_dmat, &rc->rc_segs, rc->rc_nsegs);
1304 		rc->rc_req = NULL;
1305 		bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap);
1306 	}
1307 	return (-1);
1308 }
1309 
1310 int
1311 hvn_set_capabilities(struct hvn_softc *sc)
1312 {
1313 	struct ndis_offload_params params;
1314 	size_t len = sizeof(params);
1315 
1316 	memset(&params, 0, sizeof(params));
1317 
1318 	params.ndis_hdr.ndis_type = NDIS_OBJTYPE_DEFAULT;
1319 	if (sc->sc_ndisver < NDIS_VERSION_6_30) {
1320 		params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_2;
1321 		len = params.ndis_hdr.ndis_size = NDIS_OFFLOAD_PARAMS_SIZE_6_1;
1322 	} else {
1323 		params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_3;
1324 		len = params.ndis_hdr.ndis_size = NDIS_OFFLOAD_PARAMS_SIZE;
1325 	}
1326 
1327 	params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX;
1328 	params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX;
1329 	params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX;
1330 	if (sc->sc_ndisver >= NDIS_VERSION_6_30) {
1331 		params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX;
1332 		params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX;
1333 	}
1334 
1335 	return (hvn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS, &params, len));
1336 }
1337 
1338 int
1339 hvn_rndis_cmd(struct hvn_softc *sc, struct rndis_cmd *rc, int timo)
1340 {
1341 	struct hvn_nvs_rndis *msg = &rc->rc_msg;
1342 	struct rndis_msghdr *hdr = rc->rc_req;
1343 	struct vmbus_gpa sgl[1];
1344 	int tries = 10;
1345 	int rv, s;
1346 
1347 	KERNEL_ASSERT_LOCKED();
1348 
1349 	KASSERT(timo > 0);
1350 
1351 	msg->nvs_type = HVN_NVS_TYPE_RNDIS;
1352 	msg->nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_CTRL;
1353 	msg->nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID;
1354 
1355 	sgl[0].gpa_page = rc->rc_gpa;
1356 	sgl[0].gpa_len = hdr->rm_len;
1357 	sgl[0].gpa_ofs = 0;
1358 
1359 	rc->rc_done = 0;
1360 
1361 	hvn_submit_cmd(sc, rc);
1362 
1363 	do {
1364 		rv = hv_channel_send_sgl(sc->sc_chan, sgl, 1, &rc->rc_msg,
1365 		    sizeof(*msg), rc->rc_id);
1366 		if (rv == EAGAIN) {
1367 			if (cold)
1368 				delay(100);
1369 			else
1370 				tsleep(rc, PRIBIO, "rndisout", 1);
1371 		} else if (rv) {
1372 			DPRINTF("%s: RNDIS operation %u send error %d\n",
1373 			    sc->sc_dev.dv_xname, hdr->rm_type, rv);
1374 			hvn_rollback_cmd(sc, rc);
1375 			return (rv);
1376 		}
1377 	} while (rv != 0 && --tries > 0);
1378 
1379 	if (tries == 0 && rv != 0) {
1380 		printf("%s: RNDIS operation %u send error %d\n",
1381 		    sc->sc_dev.dv_xname, hdr->rm_type, rv);
1382 		return (rv);
1383 	}
1384 
1385 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1386 	    BUS_DMASYNC_POSTWRITE);
1387 
1388 	do {
1389 		if (cold)
1390 			delay(1000);
1391 		else
1392 			tsleep(rc, PRIBIO | PCATCH, "rndiscmd", 1);
1393 		s = splnet();
1394 		hvn_nvs_intr(sc);
1395 		splx(s);
1396 	} while (--timo > 0 && rc->rc_done != 1);
1397 
1398 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1399 	    BUS_DMASYNC_POSTREAD);
1400 
1401 	if (rc->rc_done != 1) {
1402 		rv = timo == 0 ? ETIMEDOUT : EINTR;
1403 		if (hvn_rollback_cmd(sc, rc)) {
1404 			hvn_release_cmd(sc, rc);
1405 			rv = 0;
1406 		} else if (rv == ETIMEDOUT) {
1407 			printf("%s: RNDIS operation %u timed out\n",
1408 			    sc->sc_dev.dv_xname, hdr->rm_type);
1409 		}
1410 		return (rv);
1411 	}
1412 
1413 	hvn_release_cmd(sc, rc);
1414 	return (0);
1415 }
1416 
1417 void
1418 hvn_rndis_input(struct hvn_softc *sc, uint64_t tid, void *arg)
1419 {
1420 	struct ifnet *ifp = &sc->sc_ac.ac_if;
1421 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
1422 	struct vmbus_chanpkt_prplist *cp = arg;
1423 	uint32_t off, len, type;
1424 	int i;
1425 
1426 	if (sc->sc_rx_ring == NULL) {
1427 		DPRINTF("%s: invalid rx ring\n", sc->sc_dev.dv_xname);
1428 		return;
1429 	}
1430 	for (i = 0; i < cp->cp_range_cnt; i++) {
1431 		off = cp->cp_range[i].gpa_ofs;
1432 		len = cp->cp_range[i].gpa_len;
1433 
1434 		KASSERT(off + len <= sc->sc_rx_size);
1435 		KASSERT(len >= RNDIS_HEADER_OFFSET + 4);
1436 
1437 		memcpy(&type, (caddr_t)sc->sc_rx_ring + off, sizeof(type));
1438 		switch (type) {
1439 		/* data message */
1440 		case REMOTE_NDIS_PACKET_MSG:
1441 			hvn_rxeof(sc, (caddr_t)sc->sc_rx_ring +
1442 			    off, len, &ml);
1443 			break;
1444 		/* completion messages */
1445 		case REMOTE_NDIS_INITIALIZE_CMPLT:
1446 		case REMOTE_NDIS_QUERY_CMPLT:
1447 		case REMOTE_NDIS_SET_CMPLT:
1448 		case REMOTE_NDIS_RESET_CMPLT:
1449 		case REMOTE_NDIS_KEEPALIVE_CMPLT:
1450 			hvn_rndis_complete(sc, (caddr_t)sc->sc_rx_ring +
1451 			    off, len);
1452 			break;
1453 		/* notification message */
1454 		case REMOTE_NDIS_INDICATE_STATUS_MSG:
1455 			hvn_rndis_status(sc, (caddr_t)sc->sc_rx_ring +
1456 			    off, len);
1457 			break;
1458 		default:
1459 			printf("%s: unhandled RNDIS message type %u\n",
1460 			    sc->sc_dev.dv_xname, type);
1461 		}
1462 	}
1463 	hvn_nvs_ack(sc, tid);
1464 
1465 	if_input(ifp, &ml);
1466 }
1467 
1468 static inline struct mbuf *
1469 hvn_devget(struct hvn_softc *sc, caddr_t buf, uint32_t len)
1470 {
1471 	struct mbuf *m;
1472 
1473 	if (len + ETHER_ALIGN <= MHLEN)
1474 		MGETHDR(m, M_NOWAIT, MT_DATA);
1475 	else
1476 		m = MCLGETI(NULL, M_NOWAIT, NULL, len + ETHER_ALIGN);
1477 	if (m == NULL)
1478 		return (NULL);
1479 	m->m_len = m->m_pkthdr.len = len;
1480 	m_adj(m, ETHER_ALIGN);
1481 
1482 	if (m_copyback(m, 0, len, buf, M_NOWAIT)) {
1483 		m_freem(m);
1484 		return (NULL);
1485 	}
1486 
1487 	return (m);
1488 }
1489 
1490 void
1491 hvn_rxeof(struct hvn_softc *sc, caddr_t buf, uint32_t len, struct mbuf_list *ml)
1492 {
1493 	struct ifnet *ifp = &sc->sc_ac.ac_if;
1494 	struct rndis_packet_msg *pkt;
1495 	struct rndis_pktinfo *pi;
1496 	uint32_t csum, vlan;
1497 	struct mbuf *m;
1498 
1499 	if (!(ifp->if_flags & IFF_RUNNING))
1500 		return;
1501 
1502 	if (len < sizeof(*pkt)) {
1503 		printf("%s: data packet too short: %u\n",
1504 		    sc->sc_dev.dv_xname, len);
1505 		return;
1506 	}
1507 
1508 	pkt = (struct rndis_packet_msg *)buf;
1509 
1510 	if (pkt->rm_dataoffset + pkt->rm_datalen > len) {
1511 		printf("%s: data packet out of bounds: %u@%u\n",
1512 		    sc->sc_dev.dv_xname, pkt->rm_dataoffset, pkt->rm_datalen);
1513 		return;
1514 	}
1515 
1516 	if ((m = hvn_devget(sc, buf + RNDIS_HEADER_OFFSET + pkt->rm_dataoffset,
1517 	    pkt->rm_datalen)) == NULL) {
1518 		ifp->if_ierrors++;
1519 		return;
1520 	}
1521 
1522 	if (pkt->rm_pktinfooffset + pkt->rm_pktinfolen > len) {
1523 		printf("%s: pktinfo is out of bounds: %u@%u vs %u\n",
1524 		    sc->sc_dev.dv_xname, pkt->rm_pktinfolen,
1525 		    pkt->rm_pktinfooffset, len);
1526 		goto done;
1527 	}
1528 	pi = (struct rndis_pktinfo *)((caddr_t)pkt + RNDIS_HEADER_OFFSET +
1529 	    pkt->rm_pktinfooffset);
1530 	while (pkt->rm_pktinfolen > 0) {
1531 		if (pi->rm_size > pkt->rm_pktinfolen) {
1532 			printf("%s: invalid pktinfo size: %u/%u\n",
1533 			    sc->sc_dev.dv_xname, pi->rm_size,
1534 			    pkt->rm_pktinfolen);
1535 			break;
1536 		}
1537 		switch (pi->rm_type) {
1538 		case NDIS_PKTINFO_TYPE_CSUM:
1539 			memcpy(&csum, pi->rm_data, sizeof(csum));
1540 			if (csum & NDIS_RXCSUM_INFO_IPCS_OK)
1541 				m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
1542 			if (csum & NDIS_RXCSUM_INFO_TCPCS_OK)
1543 				m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK;
1544 			if (csum & NDIS_RXCSUM_INFO_UDPCS_OK)
1545 				m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK;
1546 			break;
1547 		case NDIS_PKTINFO_TYPE_VLAN:
1548 			memcpy(&vlan, pi->rm_data, sizeof(vlan));
1549 #if NVLAN > 0
1550 			if (vlan != 0xffffffff) {
1551 				m->m_pkthdr.ether_vtag =
1552 				    NDIS_VLAN_INFO_ID(vlan) |
1553 				    (NDIS_VLAN_INFO_PRI(vlan) << EVL_PRIO_BITS);
1554 				m->m_flags |= M_VLANTAG;
1555 			}
1556 #endif
1557 			break;
1558 		default:
1559 			DPRINTF("%s: unhandled pktinfo type %u\n",
1560 			    sc->sc_dev.dv_xname, pi->rm_type);
1561 		}
1562 		pkt->rm_pktinfolen -= pi->rm_size;
1563 		pi = (struct rndis_pktinfo *)((caddr_t)pi + pi->rm_size);
1564 	}
1565 
1566  done:
1567 	ml_enqueue(ml, m);
1568 }
1569 
1570 void
1571 hvn_rndis_complete(struct hvn_softc *sc, caddr_t buf, uint32_t len)
1572 {
1573 	struct rndis_cmd *rc;
1574 	uint32_t id;
1575 
1576 	memcpy(&id, buf + RNDIS_HEADER_OFFSET, sizeof(id));
1577 	if ((rc = hvn_complete_cmd(sc, id)) != NULL) {
1578 		if (len < rc->rc_cmplen)
1579 			printf("%s: RNDIS response %u too short: %u\n",
1580 			    sc->sc_dev.dv_xname, id, len);
1581 		else
1582 			memcpy(&rc->rc_cmp, buf, rc->rc_cmplen);
1583 		if (len > rc->rc_cmplen &&
1584 		    len - rc->rc_cmplen > HVN_RNDIS_BUFSIZE)
1585 			printf("%s: RNDIS response %u too large: %u\n",
1586 			    sc->sc_dev.dv_xname, id, len);
1587 		else if (len > rc->rc_cmplen)
1588 			memcpy(&rc->rc_cmpbuf, buf + rc->rc_cmplen,
1589 			    len - rc->rc_cmplen);
1590 		rc->rc_done = 1;
1591 		wakeup_one(rc);
1592 	} else
1593 		DPRINTF("%s: failed to complete RNDIS request id %u\n",
1594 		    sc->sc_dev.dv_xname, id);
1595 }
1596 
1597 int
1598 hvn_rndis_output(struct hvn_softc *sc, struct hvn_tx_desc *txd)
1599 {
1600 	uint64_t rid = (uint64_t)txd->txd_id << 32;
1601 	int rv;
1602 
1603 	rv = hv_channel_send_sgl(sc->sc_chan, txd->txd_sgl, txd->txd_nsge,
1604 	    &sc->sc_data_msg, sizeof(sc->sc_data_msg), rid);
1605 	if (rv) {
1606 		DPRINTF("%s: RNDIS data send error %d\n",
1607 		    sc->sc_dev.dv_xname, rv);
1608 		return (rv);
1609 	}
1610 
1611 	return (0);
1612 }
1613 
1614 void
1615 hvn_rndis_status(struct hvn_softc *sc, caddr_t buf, uint32_t len)
1616 {
1617 	uint32_t status;
1618 
1619 	memcpy(&status, buf + RNDIS_HEADER_OFFSET, sizeof(status));
1620 	switch (status) {
1621 	case RNDIS_STATUS_MEDIA_CONNECT:
1622 		sc->sc_link_state = LINK_STATE_UP;
1623 		break;
1624 	case RNDIS_STATUS_MEDIA_DISCONNECT:
1625 		sc->sc_link_state = LINK_STATE_DOWN;
1626 		break;
1627 	/* Ignore these */
1628 	case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG:
1629 		return;
1630 	default:
1631 		DPRINTF("%s: unhandled status %#x\n", sc->sc_dev.dv_xname,
1632 		    status);
1633 		return;
1634 	}
1635 	KERNEL_LOCK();
1636 	hvn_link_status(sc);
1637 	KERNEL_UNLOCK();
1638 }
1639 
1640 int
1641 hvn_rndis_query(struct hvn_softc *sc, uint32_t oid, void *res, size_t *length)
1642 {
1643 	struct rndis_cmd *rc;
1644 	struct rndis_query_req *req;
1645 	struct rndis_query_comp *cmp;
1646 	size_t olength = *length;
1647 	int rv;
1648 
1649 	rc = hvn_alloc_cmd(sc);
1650 
1651 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1652 	    BUS_DMASYNC_PREREAD);
1653 
1654 	rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid);
1655 
1656 	req = rc->rc_req;
1657 	req->rm_type = REMOTE_NDIS_QUERY_MSG;
1658 	req->rm_len = sizeof(*req);
1659 	req->rm_rid = rc->rc_id;
1660 	req->rm_oid = oid;
1661 	req->rm_infobufoffset = sizeof(*req) - RNDIS_HEADER_OFFSET;
1662 
1663 	rc->rc_cmplen = sizeof(*cmp);
1664 
1665 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1666 	    BUS_DMASYNC_PREWRITE);
1667 
1668 	if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) {
1669 		DPRINTF("%s: QUERY_MSG failed, error %d\n",
1670 		    sc->sc_dev.dv_xname, rv);
1671 		hvn_free_cmd(sc, rc);
1672 		return (rv);
1673 	}
1674 
1675 	cmp = (struct rndis_query_comp *)&rc->rc_cmp;
1676 	switch (cmp->rm_status) {
1677 	case RNDIS_STATUS_SUCCESS:
1678 		if (cmp->rm_infobuflen > olength) {
1679 			rv = EINVAL;
1680 			break;
1681 		}
1682 		memcpy(res, rc->rc_cmpbuf, cmp->rm_infobuflen);
1683 		*length = cmp->rm_infobuflen;
1684 		break;
1685 	default:
1686 		*length = 0;
1687 		rv = EIO;
1688 	}
1689 
1690 	hvn_free_cmd(sc, rc);
1691 
1692 	return (rv);
1693 }
1694 
1695 int
1696 hvn_rndis_set(struct hvn_softc *sc, uint32_t oid, void *data, size_t length)
1697 {
1698 	struct rndis_cmd *rc;
1699 	struct rndis_set_req *req;
1700 	struct rndis_set_comp *cmp;
1701 	int rv;
1702 
1703 	rc = hvn_alloc_cmd(sc);
1704 
1705 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1706 	    BUS_DMASYNC_PREREAD);
1707 
1708 	rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid);
1709 
1710 	req = rc->rc_req;
1711 	req->rm_type = REMOTE_NDIS_SET_MSG;
1712 	req->rm_len = sizeof(*req) + length;
1713 	req->rm_rid = rc->rc_id;
1714 	req->rm_oid = oid;
1715 	req->rm_infobufoffset = sizeof(*req) - RNDIS_HEADER_OFFSET;
1716 
1717 	rc->rc_cmplen = sizeof(*cmp);
1718 
1719 	if (length > 0) {
1720 		KASSERT(sizeof(*req) + length < PAGE_SIZE);
1721 		req->rm_infobuflen = length;
1722 		memcpy((caddr_t)(req + 1), data, length);
1723 	}
1724 
1725 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1726 	    BUS_DMASYNC_PREWRITE);
1727 
1728 	if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) {
1729 		DPRINTF("%s: SET_MSG failed, error %d\n",
1730 		    sc->sc_dev.dv_xname, rv);
1731 		hvn_free_cmd(sc, rc);
1732 		return (rv);
1733 	}
1734 
1735 	cmp = (struct rndis_set_comp *)&rc->rc_cmp;
1736 	if (cmp->rm_status != RNDIS_STATUS_SUCCESS)
1737 		rv = EIO;
1738 
1739 	hvn_free_cmd(sc, rc);
1740 
1741 	return (rv);
1742 }
1743 
1744 int
1745 hvn_rndis_close(struct hvn_softc *sc)
1746 {
1747 	uint32_t filter = 0;
1748 	int rv;
1749 
1750 	rv = hvn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
1751 	    &filter, sizeof(filter));
1752 	if (rv)
1753 		DPRINTF("%s: failed to clear RNDIS filter\n",
1754 		    sc->sc_dev.dv_xname);
1755 	return (rv);
1756 }
1757 
1758 void
1759 hvn_rndis_detach(struct hvn_softc *sc)
1760 {
1761 	struct rndis_cmd *rc;
1762 	struct rndis_halt_req *req;
1763 	int rv;
1764 
1765 	rc = hvn_alloc_cmd(sc);
1766 
1767 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1768 	    BUS_DMASYNC_PREREAD);
1769 
1770 	rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid);
1771 
1772 	req = rc->rc_req;
1773 	req->rm_type = REMOTE_NDIS_HALT_MSG;
1774 	req->rm_len = sizeof(*req);
1775 	req->rm_rid = rc->rc_id;
1776 
1777 	bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,
1778 	    BUS_DMASYNC_PREWRITE);
1779 
1780 	if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0)
1781 		DPRINTF("%s: HALT_MSG failed, error %d\n",
1782 		    sc->sc_dev.dv_xname, rv);
1783 
1784 	hvn_free_cmd(sc, rc);
1785 }
1786