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