Bug Summary

File:dev/pv/if_hvn.c
Warning:line 1791, column 7
Although the value stored to 'rv' is used in the enclosing expression, the value is never actually read from 'rv'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_hvn.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pv/if_hvn.c
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 INET61
70#include <netinet/ip6.h>
71#endif
72
73#if NBPFILTER1 > 0
74#include <net/bpf.h>
75#endif
76
77#define HVN_NVS_MSGSIZE32 32
78#define HVN_NVS_BUFSIZE(1 << 12) PAGE_SIZE(1 << 12)
79
80/*
81 * RNDIS control interface
82 */
83#define HVN_RNDIS_CTLREQS4 4
84#define HVN_RNDIS_BUFSIZE512 512
85
86struct 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_BUFSIZE512];
97 int rc_done;
98 TAILQ_ENTRY(rndis_cmd)struct { struct rndis_cmd *tqe_next; struct rndis_cmd **tqe_prev
; }
rc_entry;
99};
100TAILQ_HEAD(rndis_queue, rndis_cmd)struct rndis_queue { struct rndis_cmd *tqh_first; struct rndis_cmd
**tqh_last; }
;
101
102#define HVN_MAXMTU(9 * 1024) (9 * 1024)
103
104#define HVN_RNDIS_XFER_SIZE2048 2048
105
106/*
107 * Tx ring
108 */
109#define HVN_TX_DESC256 256
110#define HVN_TX_FRAGS15 15 /* 31 is the max */
111#define HVN_TX_FRAG_SIZE(1 << 12) PAGE_SIZE(1 << 12)
112#define HVN_TX_PKT_SIZE16384 16384
113
114#define HVN_RNDIS_PKT_LEN(sizeof(struct rndis_packet_msg) + sizeof(struct rndis_pktinfo
) + sizeof(uint32_t) + sizeof(struct rndis_pktinfo) + sizeof(
uint32_t))
\
115 (sizeof(struct rndis_packet_msg) + \
116 sizeof(struct rndis_pktinfo) + NDIS_VLAN_INFO_SIZEsizeof(uint32_t) + \
117 sizeof(struct rndis_pktinfo) + NDIS_TXCSUM_INFO_SIZEsizeof(uint32_t))
118
119struct hvn_tx_desc {
120 uint32_t txd_id;
121 int txd_ready;
122 struct vmbus_gpa txd_sgl[HVN_TX_FRAGS15 + 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
130struct 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_MSGSIZE32];
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_CTLREQS4];
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_DESC256];
168 bus_dmamap_t sc_tx_rmap;
169 void *sc_tx_msgs;
170 bus_dma_segment_t sc_tx_mseg;
171};
172
173int hvn_match(struct device *, void *, void *);
174void hvn_attach(struct device *, struct device *, void *);
175int hvn_ioctl(struct ifnet *, u_long, caddr_t);
176int hvn_media_change(struct ifnet *);
177void hvn_media_status(struct ifnet *, struct ifmediareq *);
178int hvn_iff(struct hvn_softc *);
179void hvn_init(struct hvn_softc *);
180void hvn_stop(struct hvn_softc *);
181void hvn_start(struct ifqueue *);
182int hvn_encap(struct hvn_softc *, struct mbuf *, struct hvn_tx_desc **);
183void hvn_decap(struct hvn_softc *, struct hvn_tx_desc *);
184void hvn_txeof(struct hvn_softc *, uint64_t);
185int hvn_rx_ring_create(struct hvn_softc *);
186int hvn_rx_ring_destroy(struct hvn_softc *);
187int hvn_tx_ring_create(struct hvn_softc *);
188void hvn_tx_ring_destroy(struct hvn_softc *);
189int hvn_set_capabilities(struct hvn_softc *);
190int hvn_get_lladdr(struct hvn_softc *);
191int hvn_set_lladdr(struct hvn_softc *);
192void hvn_get_link_status(struct hvn_softc *);
193void hvn_link_status(struct hvn_softc *);
194
195/* NSVP */
196int hvn_nvs_attach(struct hvn_softc *);
197void hvn_nvs_intr(void *);
198int hvn_nvs_cmd(struct hvn_softc *, void *, size_t, uint64_t, int);
199int hvn_nvs_ack(struct hvn_softc *, uint64_t);
200void hvn_nvs_detach(struct hvn_softc *);
201
202/* RNDIS */
203int hvn_rndis_attach(struct hvn_softc *);
204int hvn_rndis_cmd(struct hvn_softc *, struct rndis_cmd *, int);
205void hvn_rndis_input(struct hvn_softc *, uint64_t, void *);
206void hvn_rxeof(struct hvn_softc *, caddr_t, uint32_t, struct mbuf_list *);
207void hvn_rndis_complete(struct hvn_softc *, caddr_t, uint32_t);
208int hvn_rndis_output(struct hvn_softc *, struct hvn_tx_desc *);
209void hvn_rndis_status(struct hvn_softc *, caddr_t, uint32_t);
210int hvn_rndis_query(struct hvn_softc *, uint32_t, void *, size_t *);
211int hvn_rndis_set(struct hvn_softc *, uint32_t, void *, size_t);
212int hvn_rndis_close(struct hvn_softc *);
213void hvn_rndis_detach(struct hvn_softc *);
214
215struct cfdriver hvn_cd = {
216 NULL((void *)0), "hvn", DV_IFNET
217};
218
219const struct cfattach hvn_ca = {
220 sizeof(struct hvn_softc), hvn_match, hvn_attach
221};
222
223int
224hvn_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
234void
235hvn_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, IFNAMSIZ16);
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_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
265 ifp->if_xflags = IFXF_MPSAFE0x1;
266 ifp->if_ioctl = hvn_ioctl;
267 ifp->if_qstart = hvn_start;
268 ifp->if_softc = sc;
269
270 ifp->if_capabilitiesif_data.ifi_capabilities = IFCAP_CSUM_IPv40x00000001 | IFCAP_CSUM_TCPv40x00000002 |
271 IFCAP_CSUM_TCPv60x00000080;
272 if (sc->sc_ndisver > NDIS_VERSION_6_300x0006001e)
273 ifp->if_capabilitiesif_data.ifi_capabilities |= IFCAP_CSUM_UDPv40x00000004 | IFCAP_CSUM_UDPv60x00000100;
274
275 if (sc->sc_proto >= HVN_NVS_PROTO_VERSION_20x30002) {
276 ifp->if_hardmtu = HVN_MAXMTU(9 * 1024);
277#if NVLAN1 > 0
278 ifp->if_capabilitiesif_data.ifi_capabilities |= IFCAP_VLAN_HWTAGGING0x00000020 | IFCAP_VLAN_MTU0x00000010;
279#endif
280 }
281
282 ifq_set_maxlen(&ifp->if_snd, HVN_TX_DESC - 1)((&ifp->if_snd)->ifq_maxlen = (256 - 1));
283
284 ifmedia_init(&sc->sc_media, IFM_IMASK0xff00000000000000ULL, hvn_media_change,
285 hvn_media_status);
286 ifmedia_add(&sc->sc_media, IFM_ETHER0x0000000000000100ULL | IFM_MANUAL1ULL, 0, NULL((void *)0));
287 ifmedia_set(&sc->sc_media, IFM_ETHER0x0000000000000100ULL | IFM_MANUAL1ULL);
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
325int
326hvn_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()splraise(0x7);
333
334 switch (command) {
335 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
336 ifp->if_flags |= IFF_UP0x1;
337 if (!(ifp->if_flags & IFF_RUNNING0x40))
338 hvn_init(sc);
339 break;
340 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
341 if (ifp->if_flags & IFF_UP0x1) {
342 if (ifp->if_flags & IFF_RUNNING0x40)
343 error = ENETRESET52;
344 else
345 hvn_init(sc);
346 } else {
347 if (ifp->if_flags & IFF_RUNNING0x40)
348 hvn_stop(sc);
349 }
350 break;
351 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
352 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
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 == ENETRESET52) {
360 if (ifp->if_flags & IFF_RUNNING0x40)
361 hvn_iff(sc);
362 error = 0;
363 }
364
365 splx(s)spllower(s);
366
367 return (error);
368}
369
370int
371hvn_media_change(struct ifnet *ifp)
372{
373 return (0);
374}
375
376void
377hvn_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_AVALID0x0000000000000001ULL;
385 ifmr->ifm_active = IFM_ETHER0x0000000000000100ULL | IFM_MANUAL1ULL;
386 if (sc->sc_link_state == LINK_STATE_UP4)
387 ifmr->ifm_status |= IFM_ACTIVE0x0000000000000002ULL;
388}
389
390void
391hvn_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_stateif_data.ifi_link_state) {
396 ifp->if_link_stateif_data.ifi_link_state = sc->sc_link_state;
397 if_link_state_change(ifp);
398 }
399}
400
401int
402hvn_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_ALLMULTI0x200;
409
410 if ((ifp->if_flags & IFF_PROMISC0x100) || sc->sc_ac.ac_multirangecnt > 0) {
411 ifp->if_flags |= IFF_ALLMULTI0x200;
412 filter = NDIS_PACKET_TYPE_PROMISCUOUS0x00000020;
413 } else {
414 filter = NDIS_PACKET_TYPE_BROADCAST0x00000008 |
415 NDIS_PACKET_TYPE_DIRECTED0x00000001;
416 if (sc->sc_ac.ac_multicnt > 0) {
417 ifp->if_flags |= IFF_ALLMULTI0x200;
418 filter |= NDIS_PACKET_TYPE_ALL_MULTICAST0x00000004;
419 }
420 }
421
422 rv = hvn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER0x0001010E,
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
430void
431hvn_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_RUNNING0x40;
439 ifq_clr_oactive(&ifp->if_snd);
440 }
441}
442
443void
444hvn_stop(struct hvn_softc *sc)
445{
446 struct ifnet *ifp = &sc->sc_ac.ac_if;
447
448 if (ifp->if_flags & IFF_RUNNING0x40) {
449 ifp->if_flags &= ~IFF_RUNNING0x40;
450 hvn_rndis_close(sc);
451 }
452
453 ifq_barrier(&ifp->if_snd);
454 sched_barrier(NULL((void *)0));
455
456 ifq_clr_oactive(&ifp->if_snd);
457}
458
459void
460hvn_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((void *)0))
476 break;
477
478 if (hvn_encap(sc, m, &txd)) {
479 /* the chain is too large */
480 ifp->if_oerrorsif_data.ifi_oerrors++;
481 m_freem(m);
482 continue;
483 }
484
485#if NBPFILTER1 > 0
486 if (ifp->if_bpf)
487 bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
488#endif
489
490 if (hvn_rndis_output(sc, txd)) {
491 hvn_decap(sc, txd);
492 ifp->if_oerrorsif_data.ifi_oerrors++;
493 m_freem(m);
494 continue;
495 }
496
497 sc->sc_tx_next++;
498 }
499}
500
501static inline char *
502hvn_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 <=((pkt->rm_pktinfooffset + pkt->rm_pktinfolen + pi_size <=
pktsize) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/pv/if_hvn.c"
, 510, "pkt->rm_pktinfooffset + pkt->rm_pktinfolen + pi_size <= pktsize"
))
510 pktsize)((pkt->rm_pktinfooffset + pkt->rm_pktinfolen + pi_size <=
pktsize) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/pv/if_hvn.c"
, 510, "pkt->rm_pktinfooffset + pkt->rm_pktinfolen + pi_size <= 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
523int
524hvn_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_DESC256];
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)__builtin_memset((pkt), (0), ((sizeof(struct rndis_packet_msg
) + sizeof(struct rndis_pktinfo) + sizeof(uint32_t) + sizeof(
struct rndis_pktinfo) + sizeof(uint32_t))))
;
540 pkt->rm_type = REMOTE_NDIS_PACKET_MSG0x00000001;
541 pkt->rm_len = sizeof(*pkt) + m->m_pkthdrM_dat.MH.MH_pkthdr.len;
542 pkt->rm_dataoffset = RNDIS_DATA_OFFSET(sizeof(struct rndis_packet_msg) - (sizeof(struct rndis_msghdr
)))
;
543 pkt->rm_datalen = m->m_pkthdrM_dat.MH.MH_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 |(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
txd->txd_dmap), (m), (0x0200 | 0x0001))
548 BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
txd->txd_dmap), (m), (0x0200 | 0x0001))
;
549 switch (rv) {
550 case 0:
551 break;
552 case EFBIG27:
553 if (m_defrag(m, M_NOWAIT0x0002) == 0 &&
554 bus_dmamap_load_mbuf(sc->sc_dmat, txd->txd_dmap, m,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
txd->txd_dmap), (m), (0x0200 | 0x0001))
555 BUS_DMA_READ | BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
txd->txd_dmap), (m), (0x0200 | 0x0001))
== 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 NVLAN1 > 0
565 if (m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020) {
566 uint32_t vlan;
567 char *cp;
568
569 vlan = NDIS_VLAN_INFO(EVL_VLANOFTAG(m->m_pkthdr.ether_vtag),((((((m->M_dat.MH.MH_pkthdr.ether_vtag) >> 13) &
7)) & 0x0007) | (((((m->M_dat.MH.MH_pkthdr.ether_vtag
) & 0xFFF)) & 0xfff) << 4))
570 EVL_PRIOFTAG(m->m_pkthdr.ether_vtag))((((((m->M_dat.MH.MH_pkthdr.ether_vtag) >> 13) &
7)) & 0x0007) | (((((m->M_dat.MH.MH_pkthdr.ether_vtag
) & 0xFFF)) & 0xfff) << 4))
;
571 cp = hvn_rndis_pktinfo_append(pkt, HVN_RNDIS_PKT_LEN(sizeof(struct rndis_packet_msg) + sizeof(struct rndis_pktinfo
) + sizeof(uint32_t) + sizeof(struct rndis_pktinfo) + sizeof(
uint32_t))
,
572 NDIS_VLAN_INFO_SIZEsizeof(uint32_t), NDIS_PKTINFO_TYPE_VLAN6);
573 memcpy(cp, &vlan, NDIS_VLAN_INFO_SIZE)__builtin_memcpy((cp), (&vlan), (sizeof(uint32_t)));
574 }
575#endif
576
577 if (m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags & (M_IPV4_CSUM_OUT0x0001 | M_UDP_CSUM_OUT0x0004 |
578 M_TCP_CSUM_OUT0x0002)) {
579 uint32_t csum = NDIS_TXCSUM_INFO_IPV40x00000001;
580 char *cp;
581
582 if (m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags & M_IPV4_CSUM_OUT0x0001)
583 csum |= NDIS_TXCSUM_INFO_IPCS0x00000010;
584 if (m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags & M_TCP_CSUM_OUT0x0002)
585 csum |= NDIS_TXCSUM_INFO_TCPCS0x00000004;
586 if (m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags & M_UDP_CSUM_OUT0x0004)
587 csum |= NDIS_TXCSUM_INFO_UDPCS0x00000008;
588 cp = hvn_rndis_pktinfo_append(pkt, HVN_RNDIS_PKT_LEN(sizeof(struct rndis_packet_msg) + sizeof(struct rndis_pktinfo
) + sizeof(uint32_t) + sizeof(struct rndis_pktinfo) + sizeof(
uint32_t))
,
589 NDIS_TXCSUM_INFO_SIZEsizeof(uint32_t), NDIS_PKTINFO_TYPE_CSUM0);
590 memcpy(cp, &csum, NDIS_TXCSUM_INFO_SIZE)__builtin_memcpy((cp), (&csum), (sizeof(uint32_t)));
591 }
592
593 pktlen = pkt->rm_pktinfooffset + pkt->rm_pktinfolen;
594 pkt->rm_pktinfooffset -= RNDIS_HEADER_OFFSET(sizeof(struct rndis_msghdr));
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)((seg->ds_addr) >> 12);
605 txd->txd_sgl[1 + i].gpa_ofs = seg->ds_addr & PAGE_MASK((1 << 12) - 1);
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)_atomic_dec_int(&sc->sc_tx_avail);
612
613 return (0);
614}
615
616void
617hvn_decap(struct hvn_softc *sc, struct hvn_tx_desc *txd)
618{
619 bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 0, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (txd->
txd_dmap), (0), (0), (0x02 | 0x08))
620 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (txd->
txd_dmap), (0), (0), (0x02 | 0x08))
;
621 bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (txd
->txd_dmap))
;
622 txd->txd_buf = NULL((void *)0);
623 txd->txd_nsge = 0;
624 txd->txd_ready = 1;
625 atomic_inc_int(&sc->sc_tx_avail)_atomic_inc_int(&sc->sc_tx_avail);
626}
627
628void
629hvn_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_SIG0x1984;
638 if (id >= HVN_TX_DESC256)
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((void *)0))
644 panic("%s: no mbuf @%u", sc->sc_dev.dv_xname, id);
645 txd->txd_buf = NULL((void *)0);
646
647 bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 0, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (txd->
txd_dmap), (0), (0), (0x02 | 0x08))
648 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (txd->
txd_dmap), (0), (0), (0x02 | 0x08))
;
649 bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap)(*(sc->sc_dmat)->_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)_atomic_inc_int(&sc->sc_tx_avail);
655
656}
657
658int
659hvn_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_20x30002)
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((void *)0)) {
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))__builtin_memset((&cmd), (0), (sizeof(cmd)));
684 cmd.nvs_type = HVN_NVS_TYPE_RXBUF_CONN101;
685 cmd.nvs_gpadl = sc->sc_rx_hndl;
686 cmd.nvs_sig = HVN_NVS_RXBUF_SIG0x2409;
687
688 tid = atomic_inc_int_nv(&sc->sc_nvstid)_atomic_add_int_nv((&sc->sc_nvstid), 1);
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_OK1) {
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((void *)0);
714 }
715 return (-1);
716}
717
718int
719hvn_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((void *)0))
725 return (0);
726
727 memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd)));
728 cmd.nvs_type = HVN_NVS_TYPE_RXBUF_DISCONN103;
729 cmd.nvs_sig = HVN_NVS_RXBUF_SIG0x2409;
730
731 tid = atomic_inc_int_nv(&sc->sc_nvstid)_atomic_add_int_nv((&sc->sc_nvstid), 1);
732 if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 0))
733 return (-1);
734
735 delay(100)(*delay_func)(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((void *)0);
743
744 return (0);
745}
746
747int
748hvn_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)(((((sizeof(struct rndis_packet_msg) + sizeof(struct rndis_pktinfo
) + sizeof(uint32_t) + sizeof(struct rndis_pktinfo) + sizeof(
uint32_t)))+((128)-1))/(128))*(128))
;
757
758 /* Allocate memory to store RNDIS messages */
759 if (bus_dmamem_alloc(sc->sc_dmat, msgsize * HVN_TX_DESC, PAGE_SIZE, 0,(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (msgsize
* 256), ((1 << 12)), (0), (&sc->sc_tx_mseg), (1
), (&rsegs), (0x1000 | 0x0000))
760 &sc->sc_tx_mseg, 1, &rsegs, BUS_DMA_ZERO | BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (msgsize
* 256), ((1 << 12)), (0), (&sc->sc_tx_mseg), (1
), (&rsegs), (0x1000 | 0x0000))
) {
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 *(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&sc
->sc_tx_mseg), (1), (msgsize * 256), ((caddr_t *)&sc->
sc_tx_msgs), (0x0000))
766 HVN_TX_DESC, (caddr_t *)&sc->sc_tx_msgs, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&sc
->sc_tx_mseg), (1), (msgsize * 256), ((caddr_t *)&sc->
sc_tx_msgs), (0x0000))
) {
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,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (msgsize
* 256), (1), (msgsize * 256), (0), (0x0000), (&sc->sc_tx_rmap
))
772 msgsize * HVN_TX_DESC, 0, BUS_DMA_WAITOK, &sc->sc_tx_rmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (msgsize
* 256), (1), (msgsize * 256), (0), (0x0000), (&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,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (sc->
sc_tx_rmap), (sc->sc_tx_msgs), (msgsize * 256), (((void *)
0)), (0x0000))
778 msgsize * HVN_TX_DESC, NULL, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (sc->
sc_tx_rmap), (sc->sc_tx_msgs), (msgsize * 256), (((void *)
0)), (0x0000))
) {
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_DESC256; i++) {
785 txd = &sc->sc_tx_desc[i];
786 if (bus_dmamap_create(sc->sc_dmat, HVN_TX_PKT_SIZE,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (16384
), (15), ((1 << 12)), ((1 << 12)), (0x0000), (&
txd->txd_dmap))
787 HVN_TX_FRAGS, HVN_TX_FRAG_SIZE, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (16384
), (15), ((1 << 12)), ((1 << 12)), (0x0000), (&
txd->txd_dmap))
788 BUS_DMA_WAITOK, &txd->txd_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (16384
), (15), ((1 << 12)), ((1 << 12)), (0x0000), (&
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)((pa) >> 12);
796 txd->txd_gpa.gpa_ofs = pa & PAGE_MASK((1 << 12) - 1);
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_SIG0x1984;
801 txd->txd_ready = 1;
802 }
803 sc->sc_tx_avail = HVN_TX_DESC256;
804
805 return (0);
806
807 errout:
808 hvn_tx_ring_destroy(sc);
809 return (-1);
810}
811
812void
813hvn_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_DESC256; i++) {
819 txd = &sc->sc_tx_desc[i];
820 if (txd->txd_dmap == NULL((void *)0))
821 continue;
822 bus_dmamap_sync(sc->sc_dmat, txd->txd_dmap, 0, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (txd->
txd_dmap), (0), (0), (0x08))
823 BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (txd->
txd_dmap), (0), (0), (0x08))
;
824 bus_dmamap_unload(sc->sc_dmat, txd->txd_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (txd
->txd_dmap))
;
825 bus_dmamap_destroy(sc->sc_dmat, txd->txd_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (txd
->txd_dmap))
;
826 txd->txd_dmap = NULL((void *)0);
827 if (txd->txd_buf == NULL((void *)0))
828 continue;
829 m_free(txd->txd_buf);
830 txd->txd_buf = NULL((void *)0);
831 }
832 if (sc->sc_tx_rmap) {
833 bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_rmap, 0, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sc_tx_rmap), (0), (0), (0x08))
834 BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sc_tx_rmap), (0), (0), (0x08))
;
835 bus_dmamap_unload(sc->sc_dmat, sc->sc_tx_rmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (sc->
sc_tx_rmap))
;
836 bus_dmamap_destroy(sc->sc_dmat, sc->sc_tx_rmap)(*(sc->sc_dmat)->_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)(((((sizeof(struct rndis_packet_msg) + sizeof(struct rndis_pktinfo
) + sizeof(uint32_t) + sizeof(struct rndis_pktinfo) + sizeof(
uint32_t)))+((128)-1))/(128))*(128))
;
840
841 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_tx_msgs,(*(sc->sc_dmat)->_dmamem_unmap)((sc->sc_dmat), ((caddr_t
)sc->sc_tx_msgs), (msgsize * 256))
842 msgsize * HVN_TX_DESC)(*(sc->sc_dmat)->_dmamem_unmap)((sc->sc_dmat), ((caddr_t
)sc->sc_tx_msgs), (msgsize * 256))
;
843 bus_dmamem_free(sc->sc_dmat, &sc->sc_tx_mseg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
sc->sc_tx_mseg), (1))
;
844 }
845 sc->sc_tx_rmap = NULL((void *)0);
846 sc->sc_tx_msgs = NULL((void *)0);
847}
848
849int
850hvn_get_lladdr(struct hvn_softc *sc)
851{
852 char enaddr[ETHER_ADDR_LEN6];
853 size_t addrlen = ETHER_ADDR_LEN6;
854 int rv;
855
856 rv = hvn_rndis_query(sc, OID_802_3_PERMANENT_ADDRESS0x01010101,
857 enaddr, &addrlen);
858 if (rv == 0 && addrlen == ETHER_ADDR_LEN6)
859 memcpy(sc->sc_ac.ac_enaddr, enaddr, ETHER_ADDR_LEN)__builtin_memcpy((sc->sc_ac.ac_enaddr), (enaddr), (6));
860 return (rv);
861}
862
863int
864hvn_set_lladdr(struct hvn_softc *sc)
865{
866 return (hvn_rndis_set(sc, OID_802_3_CURRENT_ADDRESS0x01010102,
867 sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN6));
868}
869
870void
871hvn_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_STATUS0x00010114,
877 &state, &len) == 0)
878 sc->sc_link_state = (state == NDIS_MEDIA_STATE_CONNECTED0) ?
879 LINK_STATE_UP4 : LINK_STATE_DOWN2;
880}
881
882int
883hvn_nvs_attach(struct hvn_softc *sc)
884{
885 const uint32_t protos[] = {
886 HVN_NVS_PROTO_VERSION_50x50000, HVN_NVS_PROTO_VERSION_40x40000,
887 HVN_NVS_PROTO_VERSION_20x30002, HVN_NVS_PROTO_VERSION_10x00002
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(1 << 12), M_DEVBUF2, M_ZERO0x0008 |
898 (cold ? M_NOWAIT0x0002 : M_WAITOK0x0001));
899 if (sc->sc_nvsbuf == NULL((void *)0)) {
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_CTLREQS4 *
907 (sizeof(struct hvn_nvs_rndis) + sizeof(struct vmbus_gpa)) +
908 HVN_TX_DESC256 * (sizeof(struct hvn_nvs_rndis) +
909 (HVN_TX_FRAGS15 + 1) * sizeof(struct vmbus_gpa));
910
911 sc->sc_chan->ch_flags &= ~CHF_BATCHED0x0001;
912
913 /* Associate our interrupt handler with the channel */
914 if (hv_channel_open(sc->sc_chan, ringsize, NULL((void *)0), 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_DEVBUF2, HVN_NVS_BUFSIZE(1 << 12));
918 return (-1);
919 }
920
921 hv_evcount_attach(sc->sc_chan, sc->sc_dev.dv_xname);
922
923 memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd)));
924 cmd.nvs_type = HVN_NVS_TYPE_INIT1;
925 for (i = 0; i < nitems(protos)(sizeof((protos)) / sizeof((protos)[0])); i++) {
926 cmd.nvs_ver_min = cmd.nvs_ver_max = protos[i];
927 tid = atomic_inc_int_nv(&sc->sc_nvstid)_atomic_add_int_nv((&sc->sc_nvstid), 1);
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_OK1) {
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_20x30002) {
943 memset(&ccmd, 0, sizeof(ccmd))__builtin_memset((&ccmd), (0), (sizeof(ccmd)));
944 ccmd.nvs_type = HVN_NVS_TYPE_NDIS_CONF125;
945 ccmd.nvs_mtu = HVN_MAXMTU(9 * 1024);
946 ccmd.nvs_caps = HVN_NVS_NDIS_CONF_VLAN0x0008;
947
948 tid = atomic_inc_int_nv(&sc->sc_nvstid)_atomic_add_int_nv((&sc->sc_nvstid), 1);
949 if (hvn_nvs_cmd(sc, &ccmd, sizeof(ccmd), tid, 100))
950 return (-1);
951 }
952
953 memset(&ncmd, 0, sizeof(ncmd))__builtin_memset((&ncmd), (0), (sizeof(ncmd)));
954 ncmd.nvs_type = HVN_NVS_TYPE_NDIS_INIT100;
955 if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_40x40000)
956 ndisver = NDIS_VERSION_6_10x00060001;
957 else
958 ndisver = NDIS_VERSION_6_300x0006001e;
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)_atomic_add_int_nv((&sc->sc_nvstid), 1);
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
971void
972hvn_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(1 << 12), &rlen, &rid, 1);
985 if (rv != 0 || rlen == 0) {
986 if (rv != EAGAIN35)
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)((const void *)((const uint8_t *)(cph) + (((int)((cph)->cph_hlen
)) << 3)))
;
993
994 if (cph->cph_type == VMBUS_CHANPKT_TYPE_COMP0x000b) {
995 switch (nvs->nvs_type) {
996 case HVN_NVS_TYPE_INIT_RESP2:
997 case HVN_NVS_TYPE_RXBUF_CONNRESP102:
998 case HVN_NVS_TYPE_CHIM_CONNRESP105:
999 case HVN_NVS_TYPE_SUBCH_RESP133:
1000 /* copy the response back */
1001 memcpy(&sc->sc_nvsrsp, nvs, HVN_NVS_MSGSIZE)__builtin_memcpy((&sc->sc_nvsrsp), (nvs), (32));
1002 sc->sc_nvsdone = 1;
1003 wakeup_one(&sc->sc_nvsrsp)wakeup_n((&sc->sc_nvsrsp), 1);
1004 break;
1005 case HVN_NVS_TYPE_RNDIS_ACK108:
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_RXBUF0x0007) {
1014 switch (nvs->nvs_type) {
1015 case HVN_NVS_TYPE_RNDIS107:
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
1032int
1033hvn_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()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/pv/if_hvn.c"
, 1040, "_kernel_lock_held()"))
;
1041
1042 sc->sc_nvsdone = 0;
1043
1044 do {
1045 rv = hv_channel_send(sc->sc_chan, cmd, cmdsize,
1046 tid, VMBUS_CHANPKT_TYPE_INBAND0x0006,
1047 timo ? VMBUS_CHANPKT_FLAG_RC0x0001 : 0);
1048 if (rv == EAGAIN35) {
1049 if (cold)
1050 delay(1000)(*delay_func)(1000);
1051 else {
1052 tsleep_nsec(cmd, PRIBIO16, "nvsout",
1053 USEC_TO_NSEC(1000));
1054 }
1055 } else if (rv) {
1056 DPRINTF("%s: NVSP operation %u send error %d\n",
1057 sc->sc_dev.dv_xname, hdr->nvs_type, rv);
1058 return (rv);
1059 }
1060 } while (rv != 0 && --tries > 0);
1061
1062 if (tries == 0 && rv != 0) {
1063 printf("%s: NVSP operation %u send error %d\n",
1064 sc->sc_dev.dv_xname, hdr->nvs_type, rv);
1065 return (rv);
1066 }
1067
1068 if (timo == 0)
1069 return (0);
1070
1071 do {
1072 if (cold)
1073 delay(1000)(*delay_func)(1000);
1074 else {
1075 tsleep_nsec(sc, PRIBIO16 | PCATCH0x100, "nvscmd",
1076 USEC_TO_NSEC(1000));
1077 }
1078 s = splnet()splraise(0x7);
1079 hvn_nvs_intr(sc);
1080 splx(s)spllower(s);
1081 } while (--timo > 0 && sc->sc_nvsdone != 1);
1082
1083 if (timo == 0 && sc->sc_nvsdone != 1) {
1084 printf("%s: NVSP operation %u timed out\n",
1085 sc->sc_dev.dv_xname, hdr->nvs_type);
1086 return (ETIMEDOUT60);
1087 }
1088 return (0);
1089}
1090
1091int
1092hvn_nvs_ack(struct hvn_softc *sc, uint64_t tid)
1093{
1094 struct hvn_nvs_rndis_ack cmd;
1095 int tries = 5;
1096 int rv;
1097
1098 cmd.nvs_type = HVN_NVS_TYPE_RNDIS_ACK108;
1099 cmd.nvs_status = HVN_NVS_STATUS_OK1;
1100 do {
1101 rv = hv_channel_send(sc->sc_chan, &cmd, sizeof(cmd),
1102 tid, VMBUS_CHANPKT_TYPE_COMP0x000b, 0);
1103 if (rv == EAGAIN35)
1104 delay(10)(*delay_func)(10);
1105 else if (rv) {
1106 DPRINTF("%s: NVSP acknowledgement error %d\n",
1107 sc->sc_dev.dv_xname, rv);
1108 return (rv);
1109 }
1110 } while (rv != 0 && --tries > 0);
1111 return (rv);
1112}
1113
1114void
1115hvn_nvs_detach(struct hvn_softc *sc)
1116{
1117 if (hv_channel_close(sc->sc_chan) == 0) {
1118 free(sc->sc_nvsbuf, M_DEVBUF2, HVN_NVS_BUFSIZE(1 << 12));
1119 sc->sc_nvsbuf = NULL((void *)0);
1120 }
1121}
1122
1123static inline struct rndis_cmd *
1124hvn_alloc_cmd(struct hvn_softc *sc)
1125{
1126 struct rndis_cmd *rc;
1127
1128 mtx_enter(&sc->sc_cntl_fqlck);
1129 while ((rc = TAILQ_FIRST(&sc->sc_cntl_fq)((&sc->sc_cntl_fq)->tqh_first)) == NULL((void *)0))
1130 msleep_nsec(&sc->sc_cntl_fq, &sc->sc_cntl_fqlck,
1131 PRIBIO16, "nvsalloc", INFSLP0xffffffffffffffffULL);
1132 TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry)do { if (((rc)->rc_entry.tqe_next) != ((void *)0)) (rc)->
rc_entry.tqe_next->rc_entry.tqe_prev = (rc)->rc_entry.tqe_prev
; else (&sc->sc_cntl_fq)->tqh_last = (rc)->rc_entry
.tqe_prev; *(rc)->rc_entry.tqe_prev = (rc)->rc_entry.tqe_next
; ((rc)->rc_entry.tqe_prev) = ((void *)-1); ((rc)->rc_entry
.tqe_next) = ((void *)-1); } while (0)
;
1133 mtx_leave(&sc->sc_cntl_fqlck);
1134 return (rc);
1135}
1136
1137static inline void
1138hvn_submit_cmd(struct hvn_softc *sc, struct rndis_cmd *rc)
1139{
1140 mtx_enter(&sc->sc_cntl_sqlck);
1141 TAILQ_INSERT_TAIL(&sc->sc_cntl_sq, rc, rc_entry)do { (rc)->rc_entry.tqe_next = ((void *)0); (rc)->rc_entry
.tqe_prev = (&sc->sc_cntl_sq)->tqh_last; *(&sc->
sc_cntl_sq)->tqh_last = (rc); (&sc->sc_cntl_sq)->
tqh_last = &(rc)->rc_entry.tqe_next; } while (0)
;
1142 mtx_leave(&sc->sc_cntl_sqlck);
1143}
1144
1145static inline struct rndis_cmd *
1146hvn_complete_cmd(struct hvn_softc *sc, uint32_t id)
1147{
1148 struct rndis_cmd *rc;
1149
1150 mtx_enter(&sc->sc_cntl_sqlck);
1151 TAILQ_FOREACH(rc, &sc->sc_cntl_sq, rc_entry)for((rc) = ((&sc->sc_cntl_sq)->tqh_first); (rc) != (
(void *)0); (rc) = ((rc)->rc_entry.tqe_next))
{
1152 if (rc->rc_id == id) {
1153 TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry)do { if (((rc)->rc_entry.tqe_next) != ((void *)0)) (rc)->
rc_entry.tqe_next->rc_entry.tqe_prev = (rc)->rc_entry.tqe_prev
; else (&sc->sc_cntl_sq)->tqh_last = (rc)->rc_entry
.tqe_prev; *(rc)->rc_entry.tqe_prev = (rc)->rc_entry.tqe_next
; ((rc)->rc_entry.tqe_prev) = ((void *)-1); ((rc)->rc_entry
.tqe_next) = ((void *)-1); } while (0)
;
1154 break;
1155 }
1156 }
1157 mtx_leave(&sc->sc_cntl_sqlck);
1158 if (rc != NULL((void *)0)) {
1159 mtx_enter(&sc->sc_cntl_cqlck);
1160 TAILQ_INSERT_TAIL(&sc->sc_cntl_cq, rc, rc_entry)do { (rc)->rc_entry.tqe_next = ((void *)0); (rc)->rc_entry
.tqe_prev = (&sc->sc_cntl_cq)->tqh_last; *(&sc->
sc_cntl_cq)->tqh_last = (rc); (&sc->sc_cntl_cq)->
tqh_last = &(rc)->rc_entry.tqe_next; } while (0)
;
1161 mtx_leave(&sc->sc_cntl_cqlck);
1162 }
1163 return (rc);
1164}
1165
1166static inline void
1167hvn_release_cmd(struct hvn_softc *sc, struct rndis_cmd *rc)
1168{
1169 mtx_enter(&sc->sc_cntl_cqlck);
1170 TAILQ_REMOVE(&sc->sc_cntl_cq, rc, rc_entry)do { if (((rc)->rc_entry.tqe_next) != ((void *)0)) (rc)->
rc_entry.tqe_next->rc_entry.tqe_prev = (rc)->rc_entry.tqe_prev
; else (&sc->sc_cntl_cq)->tqh_last = (rc)->rc_entry
.tqe_prev; *(rc)->rc_entry.tqe_prev = (rc)->rc_entry.tqe_next
; ((rc)->rc_entry.tqe_prev) = ((void *)-1); ((rc)->rc_entry
.tqe_next) = ((void *)-1); } while (0)
;
1171 mtx_leave(&sc->sc_cntl_cqlck);
1172}
1173
1174static inline int
1175hvn_rollback_cmd(struct hvn_softc *sc, struct rndis_cmd *rc)
1176{
1177 struct rndis_cmd *rn;
1178
1179 mtx_enter(&sc->sc_cntl_sqlck);
1180 TAILQ_FOREACH(rn, &sc->sc_cntl_sq, rc_entry)for((rn) = ((&sc->sc_cntl_sq)->tqh_first); (rn) != (
(void *)0); (rn) = ((rn)->rc_entry.tqe_next))
{
1181 if (rn == rc) {
1182 TAILQ_REMOVE(&sc->sc_cntl_sq, rc, rc_entry)do { if (((rc)->rc_entry.tqe_next) != ((void *)0)) (rc)->
rc_entry.tqe_next->rc_entry.tqe_prev = (rc)->rc_entry.tqe_prev
; else (&sc->sc_cntl_sq)->tqh_last = (rc)->rc_entry
.tqe_prev; *(rc)->rc_entry.tqe_prev = (rc)->rc_entry.tqe_next
; ((rc)->rc_entry.tqe_prev) = ((void *)-1); ((rc)->rc_entry
.tqe_next) = ((void *)-1); } while (0)
;
1183 mtx_leave(&sc->sc_cntl_sqlck);
1184 return (0);
1185 }
1186 }
1187 mtx_leave(&sc->sc_cntl_sqlck);
1188 return (-1);
1189}
1190
1191static inline void
1192hvn_free_cmd(struct hvn_softc *sc, struct rndis_cmd *rc)
1193{
1194 memset(rc->rc_req, 0, sizeof(struct rndis_packet_msg))__builtin_memset((rc->rc_req), (0), (sizeof(struct rndis_packet_msg
)))
;
1195 memset(&rc->rc_cmp, 0, sizeof(rc->rc_cmp))__builtin_memset((&rc->rc_cmp), (0), (sizeof(rc->rc_cmp
)))
;
1196 memset(&rc->rc_msg, 0, sizeof(rc->rc_msg))__builtin_memset((&rc->rc_msg), (0), (sizeof(rc->rc_msg
)))
;
1197 mtx_enter(&sc->sc_cntl_fqlck);
1198 TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry)do { (rc)->rc_entry.tqe_next = ((void *)0); (rc)->rc_entry
.tqe_prev = (&sc->sc_cntl_fq)->tqh_last; *(&sc->
sc_cntl_fq)->tqh_last = (rc); (&sc->sc_cntl_fq)->
tqh_last = &(rc)->rc_entry.tqe_next; } while (0)
;
1199 mtx_leave(&sc->sc_cntl_fqlck);
1200 wakeup(&sc->sc_cntl_fq);
1201}
1202
1203int
1204hvn_rndis_attach(struct hvn_softc *sc)
1205{
1206 struct rndis_init_req *req;
1207 struct rndis_init_comp *cmp;
1208 struct rndis_cmd *rc;
1209 int i, rv;
1210
1211 /* RNDIS control message queues */
1212 TAILQ_INIT(&sc->sc_cntl_sq)do { (&sc->sc_cntl_sq)->tqh_first = ((void *)0); (&
sc->sc_cntl_sq)->tqh_last = &(&sc->sc_cntl_sq
)->tqh_first; } while (0)
;
1213 TAILQ_INIT(&sc->sc_cntl_cq)do { (&sc->sc_cntl_cq)->tqh_first = ((void *)0); (&
sc->sc_cntl_cq)->tqh_last = &(&sc->sc_cntl_cq
)->tqh_first; } while (0)
;
1214 TAILQ_INIT(&sc->sc_cntl_fq)do { (&sc->sc_cntl_fq)->tqh_first = ((void *)0); (&
sc->sc_cntl_fq)->tqh_last = &(&sc->sc_cntl_fq
)->tqh_first; } while (0)
;
1215 mtx_init(&sc->sc_cntl_sqlck, IPL_NET)do { (void)(((void *)0)); (void)(0); __mtx_init((&sc->
sc_cntl_sqlck), ((((0x7)) > 0x0 && ((0x7)) < 0x9
) ? 0x9 : ((0x7)))); } while (0)
;
1216 mtx_init(&sc->sc_cntl_cqlck, IPL_NET)do { (void)(((void *)0)); (void)(0); __mtx_init((&sc->
sc_cntl_cqlck), ((((0x7)) > 0x0 && ((0x7)) < 0x9
) ? 0x9 : ((0x7)))); } while (0)
;
1217 mtx_init(&sc->sc_cntl_fqlck, IPL_NET)do { (void)(((void *)0)); (void)(0); __mtx_init((&sc->
sc_cntl_fqlck), ((((0x7)) > 0x0 && ((0x7)) < 0x9
) ? 0x9 : ((0x7)))); } while (0)
;
1218
1219 for (i = 0; i < HVN_RNDIS_CTLREQS4; i++) {
1220 rc = &sc->sc_cntl_msgs[i];
1221 if (bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
12)), (1), ((1 << 12)), (0), (0x0000), (&rc->rc_dmap
))
1222 PAGE_SIZE, 0, BUS_DMA_WAITOK, &rc->rc_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
12)), (1), ((1 << 12)), (0), (0x0000), (&rc->rc_dmap
))
) {
1223 DPRINTF("%s: failed to create RNDIS command map\n",
1224 sc->sc_dev.dv_xname);
1225 goto errout;
1226 }
1227 if (bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), ((1 <<
12)), ((1 << 12)), (0), (&rc->rc_segs), (1), (&
rc->rc_nsegs), (0x0001 | 0x1000))
1228 0, &rc->rc_segs, 1, &rc->rc_nsegs, BUS_DMA_NOWAIT |(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), ((1 <<
12)), ((1 << 12)), (0), (&rc->rc_segs), (1), (&
rc->rc_nsegs), (0x0001 | 0x1000))
1229 BUS_DMA_ZERO)(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), ((1 <<
12)), ((1 << 12)), (0), (&rc->rc_segs), (1), (&
rc->rc_nsegs), (0x0001 | 0x1000))
) {
1230 DPRINTF("%s: failed to allocate RNDIS command\n",
1231 sc->sc_dev.dv_xname);
1232 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rc
->rc_dmap))
;
1233 goto errout;
1234 }
1235 if (bus_dmamem_map(sc->sc_dmat, &rc->rc_segs, rc->rc_nsegs,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&rc
->rc_segs), (rc->rc_nsegs), ((1 << 12)), ((caddr_t
*)&rc->rc_req), (0x0001))
1236 PAGE_SIZE, (caddr_t *)&rc->rc_req, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&rc
->rc_segs), (rc->rc_nsegs), ((1 << 12)), ((caddr_t
*)&rc->rc_req), (0x0001))
) {
1237 DPRINTF("%s: failed to allocate RNDIS command\n",
1238 sc->sc_dev.dv_xname);
1239 bus_dmamem_free(sc->sc_dmat, &rc->rc_segs,(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
rc->rc_segs), (rc->rc_nsegs))
1240 rc->rc_nsegs)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
rc->rc_segs), (rc->rc_nsegs))
;
1241 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rc
->rc_dmap))
;
1242 goto errout;
1243 }
1244 if (bus_dmamap_load(sc->sc_dmat, rc->rc_dmap, rc->rc_req,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rc->
rc_dmap), (rc->rc_req), ((1 << 12)), (((void *)0)), (
0x0000))
1245 PAGE_SIZE, NULL, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rc->
rc_dmap), (rc->rc_req), ((1 << 12)), (((void *)0)), (
0x0000))
) {
1246 DPRINTF("%s: failed to load RNDIS command map\n",
1247 sc->sc_dev.dv_xname);
1248 bus_dmamem_free(sc->sc_dmat, &rc->rc_segs,(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
rc->rc_segs), (rc->rc_nsegs))
1249 rc->rc_nsegs)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
rc->rc_segs), (rc->rc_nsegs))
;
1250 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rc
->rc_dmap))
;
1251 goto errout;
1252 }
1253 rc->rc_gpa = atop(rc->rc_dmap->dm_segs[0].ds_addr)((rc->rc_dmap->dm_segs[0].ds_addr) >> 12);
1254 TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry)do { (rc)->rc_entry.tqe_next = ((void *)0); (rc)->rc_entry
.tqe_prev = (&sc->sc_cntl_fq)->tqh_last; *(&sc->
sc_cntl_fq)->tqh_last = (rc); (&sc->sc_cntl_fq)->
tqh_last = &(rc)->rc_entry.tqe_next; } while (0)
;
1255 }
1256
1257 rc = hvn_alloc_cmd(sc);
1258
1259 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x01))
1260 BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x01))
;
1261
1262 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid)_atomic_add_int_nv((&sc->sc_rndisrid), 1);
1263
1264 req = rc->rc_req;
1265 req->rm_type = REMOTE_NDIS_INITIALIZE_MSG0x00000002;
1266 req->rm_len = sizeof(*req);
1267 req->rm_rid = rc->rc_id;
1268 req->rm_ver_major = RNDIS_VERSION_MAJOR0x00000001;
1269 req->rm_ver_minor = RNDIS_VERSION_MINOR0x00000000;
1270 req->rm_max_xfersz = HVN_RNDIS_XFER_SIZE2048;
1271
1272 rc->rc_cmplen = sizeof(*cmp);
1273
1274 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x04))
1275 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x04))
;
1276
1277 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) {
1278 DPRINTF("%s: INITIALIZE_MSG failed, error %d\n",
1279 sc->sc_dev.dv_xname, rv);
1280 hvn_free_cmd(sc, rc);
1281 goto errout;
1282 }
1283 cmp = (struct rndis_init_comp *)&rc->rc_cmp;
1284 if (cmp->rm_status != RNDIS_STATUS_SUCCESS0x00000000L) {
1285 DPRINTF("%s: failed to init RNDIS, error %#x\n",
1286 sc->sc_dev.dv_xname, cmp->rm_status);
1287 hvn_free_cmd(sc, rc);
1288 goto errout;
1289 }
1290
1291 hvn_free_cmd(sc, rc);
1292
1293 /* Initialize RNDIS Data command */
1294 memset(&sc->sc_data_msg, 0, sizeof(sc->sc_data_msg))__builtin_memset((&sc->sc_data_msg), (0), (sizeof(sc->
sc_data_msg)))
;
1295 sc->sc_data_msg.nvs_type = HVN_NVS_TYPE_RNDIS107;
1296 sc->sc_data_msg.nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_DATA0;
1297 sc->sc_data_msg.nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID0xffffffff;
1298
1299 return (0);
1300
1301errout:
1302 for (i = 0; i < HVN_RNDIS_CTLREQS4; i++) {
1303 rc = &sc->sc_cntl_msgs[i];
1304 if (rc->rc_req == NULL((void *)0))
1305 continue;
1306 TAILQ_REMOVE(&sc->sc_cntl_fq, rc, rc_entry)do { if (((rc)->rc_entry.tqe_next) != ((void *)0)) (rc)->
rc_entry.tqe_next->rc_entry.tqe_prev = (rc)->rc_entry.tqe_prev
; else (&sc->sc_cntl_fq)->tqh_last = (rc)->rc_entry
.tqe_prev; *(rc)->rc_entry.tqe_prev = (rc)->rc_entry.tqe_next
; ((rc)->rc_entry.tqe_prev) = ((void *)-1); ((rc)->rc_entry
.tqe_next) = ((void *)-1); } while (0)
;
1307 bus_dmamem_free(sc->sc_dmat, &rc->rc_segs, rc->rc_nsegs)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
rc->rc_segs), (rc->rc_nsegs))
;
1308 rc->rc_req = NULL((void *)0);
1309 bus_dmamap_destroy(sc->sc_dmat, rc->rc_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rc
->rc_dmap))
;
1310 }
1311 return (-1);
1312}
1313
1314int
1315hvn_set_capabilities(struct hvn_softc *sc)
1316{
1317 struct ndis_offload_params params;
1318 size_t len = sizeof(params);
1319
1320 memset(&params, 0, sizeof(params))__builtin_memset((&params), (0), (sizeof(params)));
1321
1322 params.ndis_hdr.ndis_type = NDIS_OBJTYPE_DEFAULT0x80;
1323 if (sc->sc_ndisver < NDIS_VERSION_6_300x0006001e) {
1324 params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_22;
1325 len = params.ndis_hdr.ndis_size = NDIS_OFFLOAD_PARAMS_SIZE_6_1__builtin_offsetof(struct ndis_offload_params, ndis_rsc_ip4);
1326 } else {
1327 params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_33;
1328 len = params.ndis_hdr.ndis_size = NDIS_OFFLOAD_PARAMS_SIZEsizeof(struct ndis_offload_params);
1329 }
1330
1331 params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX4;
1332 params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX4;
1333 params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX4;
1334 if (sc->sc_ndisver >= NDIS_VERSION_6_300x0006001e) {
1335 params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX4;
1336 params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX4;
1337 }
1338
1339 return (hvn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS0xFC01020C, &params, len));
1340}
1341
1342int
1343hvn_rndis_cmd(struct hvn_softc *sc, struct rndis_cmd *rc, int timo)
1344{
1345 struct hvn_nvs_rndis *msg = &rc->rc_msg;
1346 struct rndis_msghdr *hdr = rc->rc_req;
1347 struct vmbus_gpa sgl[1];
1348 int tries = 10;
1349 int rv, s;
1350
1351 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/pv/if_hvn.c"
, 1351, "_kernel_lock_held()"))
;
1352
1353 KASSERT(timo > 0)((timo > 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/pv/if_hvn.c"
, 1353, "timo > 0"))
;
1354
1355 msg->nvs_type = HVN_NVS_TYPE_RNDIS107;
1356 msg->nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_CTRL1;
1357 msg->nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID0xffffffff;
1358
1359 sgl[0].gpa_page = rc->rc_gpa;
1360 sgl[0].gpa_len = hdr->rm_len;
1361 sgl[0].gpa_ofs = 0;
1362
1363 rc->rc_done = 0;
1364
1365 hvn_submit_cmd(sc, rc);
1366
1367 do {
1368 rv = hv_channel_send_sgl(sc->sc_chan, sgl, 1, &rc->rc_msg,
1369 sizeof(*msg), rc->rc_id);
1370 if (rv == EAGAIN35) {
1371 if (cold)
1372 delay(100)(*delay_func)(100);
1373 else {
1374 tsleep_nsec(rc, PRIBIO16, "rndisout",
1375 USEC_TO_NSEC(100));
1376 }
1377 } else if (rv) {
1378 DPRINTF("%s: RNDIS operation %u send error %d\n",
1379 sc->sc_dev.dv_xname, hdr->rm_type, rv);
1380 hvn_rollback_cmd(sc, rc);
1381 return (rv);
1382 }
1383 } while (rv != 0 && --tries > 0);
1384
1385 if (tries == 0 && rv != 0) {
1386 printf("%s: RNDIS operation %u send error %d\n",
1387 sc->sc_dev.dv_xname, hdr->rm_type, rv);
1388 return (rv);
1389 }
1390
1391 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x08))
1392 BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x08))
;
1393
1394 do {
1395 if (cold)
1396 delay(1000)(*delay_func)(1000);
1397 else {
1398 tsleep_nsec(rc, PRIBIO16 | PCATCH0x100, "rndiscmd",
1399 USEC_TO_NSEC(1000));
1400 }
1401 s = splnet()splraise(0x7);
1402 hvn_nvs_intr(sc);
1403 splx(s)spllower(s);
1404 } while (--timo > 0 && rc->rc_done != 1);
1405
1406 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x02))
1407 BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x02))
;
1408
1409 if (rc->rc_done != 1) {
1410 rv = timo == 0 ? ETIMEDOUT60 : EINTR4;
1411 if (hvn_rollback_cmd(sc, rc)) {
1412 hvn_release_cmd(sc, rc);
1413 rv = 0;
1414 } else if (rv == ETIMEDOUT60) {
1415 printf("%s: RNDIS operation %u timed out\n",
1416 sc->sc_dev.dv_xname, hdr->rm_type);
1417 }
1418 return (rv);
1419 }
1420
1421 hvn_release_cmd(sc, rc);
1422 return (0);
1423}
1424
1425void
1426hvn_rndis_input(struct hvn_softc *sc, uint64_t tid, void *arg)
1427{
1428 struct ifnet *ifp = &sc->sc_ac.ac_if;
1429 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1430 struct vmbus_chanpkt_prplist *cp = arg;
1431 uint32_t off, len, type;
1432 int i;
1433
1434 if (sc->sc_rx_ring == NULL((void *)0)) {
1435 DPRINTF("%s: invalid rx ring\n", sc->sc_dev.dv_xname);
1436 return;
1437 }
1438 for (i = 0; i < cp->cp_range_cnt; i++) {
1439 off = cp->cp_range[i].gpa_ofs;
1440 len = cp->cp_range[i].gpa_len;
1441
1442 KASSERT(off + len <= sc->sc_rx_size)((off + len <= sc->sc_rx_size) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/pv/if_hvn.c", 1442, "off + len <= sc->sc_rx_size"
))
;
1443 KASSERT(len >= RNDIS_HEADER_OFFSET + 4)((len >= (sizeof(struct rndis_msghdr)) + 4) ? (void)0 : __assert
("diagnostic ", "/usr/src/sys/dev/pv/if_hvn.c", 1443, "len >= RNDIS_HEADER_OFFSET + 4"
))
;
1444
1445 memcpy(&type, (caddr_t)sc->sc_rx_ring + off, sizeof(type))__builtin_memcpy((&type), ((caddr_t)sc->sc_rx_ring + off
), (sizeof(type)))
;
1446 switch (type) {
1447 /* data message */
1448 case REMOTE_NDIS_PACKET_MSG0x00000001:
1449 hvn_rxeof(sc, (caddr_t)sc->sc_rx_ring +
1450 off, len, &ml);
1451 break;
1452 /* completion messages */
1453 case REMOTE_NDIS_INITIALIZE_CMPLT0x80000002:
1454 case REMOTE_NDIS_QUERY_CMPLT0x80000004:
1455 case REMOTE_NDIS_SET_CMPLT0x80000005:
1456 case REMOTE_NDIS_RESET_CMPLT0x80000006:
1457 case REMOTE_NDIS_KEEPALIVE_CMPLT0x80000008:
1458 hvn_rndis_complete(sc, (caddr_t)sc->sc_rx_ring +
1459 off, len);
1460 break;
1461 /* notification message */
1462 case REMOTE_NDIS_INDICATE_STATUS_MSG0x00000007:
1463 hvn_rndis_status(sc, (caddr_t)sc->sc_rx_ring +
1464 off, len);
1465 break;
1466 default:
1467 printf("%s: unhandled RNDIS message type %u\n",
1468 sc->sc_dev.dv_xname, type);
1469 }
1470 }
1471 hvn_nvs_ack(sc, tid);
1472
1473 if (ifp->if_flags & IFF_RUNNING0x40)
1474 if_input(ifp, &ml);
1475 else
1476 ml_purge(&ml);
1477}
1478
1479static inline struct mbuf *
1480hvn_devget(struct hvn_softc *sc, caddr_t buf, uint32_t len)
1481{
1482 struct mbuf *m;
1483
1484 if (len + ETHER_ALIGN2 <= MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr)))
1485 MGETHDR(m, M_NOWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
1486 else
1487 m = MCLGETL(NULL, M_NOWAIT, len + ETHER_ALIGN)m_clget((((void *)0)), (0x0002), (len + 2));
1488 if (m == NULL((void *)0))
1489 return (NULL((void *)0));
1490 m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = len;
1491 m_adj(m, ETHER_ALIGN2);
1492
1493 if (m_copyback(m, 0, len, buf, M_NOWAIT0x0002)) {
1494 m_freem(m);
1495 return (NULL((void *)0));
1496 }
1497
1498 return (m);
1499}
1500
1501void
1502hvn_rxeof(struct hvn_softc *sc, caddr_t buf, uint32_t len, struct mbuf_list *ml)
1503{
1504 struct ifnet *ifp = &sc->sc_ac.ac_if;
1505 struct rndis_packet_msg *pkt;
1506 struct rndis_pktinfo *pi;
1507 uint32_t csum, vlan;
1508 struct mbuf *m;
1509
1510 if (!(ifp->if_flags & IFF_RUNNING0x40))
1511 return;
1512
1513 if (len < sizeof(*pkt)) {
1514 printf("%s: data packet too short: %u\n",
1515 sc->sc_dev.dv_xname, len);
1516 return;
1517 }
1518
1519 pkt = (struct rndis_packet_msg *)buf;
1520
1521 if (pkt->rm_dataoffset + pkt->rm_datalen > len) {
1522 printf("%s: data packet out of bounds: %u@%u\n",
1523 sc->sc_dev.dv_xname, pkt->rm_dataoffset, pkt->rm_datalen);
1524 return;
1525 }
1526
1527 if ((m = hvn_devget(sc, buf + RNDIS_HEADER_OFFSET(sizeof(struct rndis_msghdr)) + pkt->rm_dataoffset,
1528 pkt->rm_datalen)) == NULL((void *)0)) {
1529 ifp->if_ierrorsif_data.ifi_ierrors++;
1530 return;
1531 }
1532
1533 if (pkt->rm_pktinfooffset + pkt->rm_pktinfolen > len) {
1534 printf("%s: pktinfo is out of bounds: %u@%u vs %u\n",
1535 sc->sc_dev.dv_xname, pkt->rm_pktinfolen,
1536 pkt->rm_pktinfooffset, len);
1537 goto done;
1538 }
1539 pi = (struct rndis_pktinfo *)((caddr_t)pkt + RNDIS_HEADER_OFFSET(sizeof(struct rndis_msghdr)) +
1540 pkt->rm_pktinfooffset);
1541 while (pkt->rm_pktinfolen > 0) {
1542 if (pi->rm_size > pkt->rm_pktinfolen) {
1543 printf("%s: invalid pktinfo size: %u/%u\n",
1544 sc->sc_dev.dv_xname, pi->rm_size,
1545 pkt->rm_pktinfolen);
1546 break;
1547 }
1548 switch (pi->rm_type) {
1549 case NDIS_PKTINFO_TYPE_CSUM0:
1550 memcpy(&csum, pi->rm_data, sizeof(csum))__builtin_memcpy((&csum), (pi->rm_data), (sizeof(csum)
))
;
1551 if (csum & NDIS_RXCSUM_INFO_IPCS_OK0x0020)
1552 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK0x0008;
1553 if (csum & NDIS_RXCSUM_INFO_TCPCS_OK0x0008)
1554 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK0x0020;
1555 if (csum & NDIS_RXCSUM_INFO_UDPCS_OK0x0010)
1556 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK0x0080;
1557 break;
1558 case NDIS_PKTINFO_TYPE_VLAN6:
1559 memcpy(&vlan, pi->rm_data, sizeof(vlan))__builtin_memcpy((&vlan), (pi->rm_data), (sizeof(vlan)
))
;
1560#if NVLAN1 > 0
1561 if (vlan != 0xffffffff) {
1562 m->m_pkthdrM_dat.MH.MH_pkthdr.ether_vtag =
1563 NDIS_VLAN_INFO_ID(vlan)(((vlan) & 0xfff0) >> 4) |
1564 (NDIS_VLAN_INFO_PRI(vlan)( (vlan) & 0x0007) << EVL_PRIO_BITS13);
1565 m->m_flagsm_hdr.mh_flags |= M_VLANTAG0x0020;
1566 }
1567#endif
1568 break;
1569 default:
1570 DPRINTF("%s: unhandled pktinfo type %u\n",
1571 sc->sc_dev.dv_xname, pi->rm_type);
1572 }
1573 pkt->rm_pktinfolen -= pi->rm_size;
1574 pi = (struct rndis_pktinfo *)((caddr_t)pi + pi->rm_size);
1575 }
1576
1577 done:
1578 ml_enqueue(ml, m);
1579}
1580
1581void
1582hvn_rndis_complete(struct hvn_softc *sc, caddr_t buf, uint32_t len)
1583{
1584 struct rndis_cmd *rc;
1585 uint32_t id;
1586
1587 memcpy(&id, buf + RNDIS_HEADER_OFFSET, sizeof(id))__builtin_memcpy((&id), (buf + (sizeof(struct rndis_msghdr
))), (sizeof(id)))
;
1588 if ((rc = hvn_complete_cmd(sc, id)) != NULL((void *)0)) {
1589 if (len < rc->rc_cmplen)
1590 printf("%s: RNDIS response %u too short: %u\n",
1591 sc->sc_dev.dv_xname, id, len);
1592 else
1593 memcpy(&rc->rc_cmp, buf, rc->rc_cmplen)__builtin_memcpy((&rc->rc_cmp), (buf), (rc->rc_cmplen
))
;
1594 if (len > rc->rc_cmplen &&
1595 len - rc->rc_cmplen > HVN_RNDIS_BUFSIZE512)
1596 printf("%s: RNDIS response %u too large: %u\n",
1597 sc->sc_dev.dv_xname, id, len);
1598 else if (len > rc->rc_cmplen)
1599 memcpy(&rc->rc_cmpbuf, buf + rc->rc_cmplen,__builtin_memcpy((&rc->rc_cmpbuf), (buf + rc->rc_cmplen
), (len - rc->rc_cmplen))
1600 len - rc->rc_cmplen)__builtin_memcpy((&rc->rc_cmpbuf), (buf + rc->rc_cmplen
), (len - rc->rc_cmplen))
;
1601 rc->rc_done = 1;
1602 wakeup_one(rc)wakeup_n((rc), 1);
1603 } else
1604 DPRINTF("%s: failed to complete RNDIS request id %u\n",
1605 sc->sc_dev.dv_xname, id);
1606}
1607
1608int
1609hvn_rndis_output(struct hvn_softc *sc, struct hvn_tx_desc *txd)
1610{
1611 uint64_t rid = (uint64_t)txd->txd_id << 32;
1612 int rv;
1613
1614 rv = hv_channel_send_sgl(sc->sc_chan, txd->txd_sgl, txd->txd_nsge,
1615 &sc->sc_data_msg, sizeof(sc->sc_data_msg), rid);
1616 if (rv) {
1617 DPRINTF("%s: RNDIS data send error %d\n",
1618 sc->sc_dev.dv_xname, rv);
1619 return (rv);
1620 }
1621
1622 return (0);
1623}
1624
1625void
1626hvn_rndis_status(struct hvn_softc *sc, caddr_t buf, uint32_t len)
1627{
1628 uint32_t status;
1629
1630 memcpy(&status, buf + RNDIS_HEADER_OFFSET, sizeof(status))__builtin_memcpy((&status), (buf + (sizeof(struct rndis_msghdr
))), (sizeof(status)))
;
1631 switch (status) {
1632 case RNDIS_STATUS_MEDIA_CONNECT0x4001000BL:
1633 sc->sc_link_state = LINK_STATE_UP4;
1634 break;
1635 case RNDIS_STATUS_MEDIA_DISCONNECT0x4001000CL:
1636 sc->sc_link_state = LINK_STATE_DOWN2;
1637 break;
1638 /* Ignore these */
1639 case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG0x40020006:
1640 return;
1641 default:
1642 DPRINTF("%s: unhandled status %#x\n", sc->sc_dev.dv_xname,
1643 status);
1644 return;
1645 }
1646 KERNEL_LOCK()_kernel_lock();
1647 hvn_link_status(sc);
1648 KERNEL_UNLOCK()_kernel_unlock();
1649}
1650
1651int
1652hvn_rndis_query(struct hvn_softc *sc, uint32_t oid, void *res, size_t *length)
1653{
1654 struct rndis_cmd *rc;
1655 struct rndis_query_req *req;
1656 struct rndis_query_comp *cmp;
1657 size_t olength = *length;
1658 int rv;
1659
1660 rc = hvn_alloc_cmd(sc);
1661
1662 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x01))
1663 BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x01))
;
1664
1665 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid)_atomic_add_int_nv((&sc->sc_rndisrid), 1);
1666
1667 req = rc->rc_req;
1668 req->rm_type = REMOTE_NDIS_QUERY_MSG0x00000004;
1669 req->rm_len = sizeof(*req);
1670 req->rm_rid = rc->rc_id;
1671 req->rm_oid = oid;
1672 req->rm_infobufoffset = sizeof(*req) - RNDIS_HEADER_OFFSET(sizeof(struct rndis_msghdr));
1673
1674 rc->rc_cmplen = sizeof(*cmp);
1675
1676 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x04))
1677 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x04))
;
1678
1679 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) {
1680 DPRINTF("%s: QUERY_MSG failed, error %d\n",
1681 sc->sc_dev.dv_xname, rv);
1682 hvn_free_cmd(sc, rc);
1683 return (rv);
1684 }
1685
1686 cmp = (struct rndis_query_comp *)&rc->rc_cmp;
1687 switch (cmp->rm_status) {
1688 case RNDIS_STATUS_SUCCESS0x00000000L:
1689 if (cmp->rm_infobuflen > olength) {
1690 rv = EINVAL22;
1691 break;
1692 }
1693 memcpy(res, rc->rc_cmpbuf, cmp->rm_infobuflen)__builtin_memcpy((res), (rc->rc_cmpbuf), (cmp->rm_infobuflen
))
;
1694 *length = cmp->rm_infobuflen;
1695 break;
1696 default:
1697 *length = 0;
1698 rv = EIO5;
1699 }
1700
1701 hvn_free_cmd(sc, rc);
1702
1703 return (rv);
1704}
1705
1706int
1707hvn_rndis_set(struct hvn_softc *sc, uint32_t oid, void *data, size_t length)
1708{
1709 struct rndis_cmd *rc;
1710 struct rndis_set_req *req;
1711 struct rndis_set_comp *cmp;
1712 int rv;
1713
1714 rc = hvn_alloc_cmd(sc);
1715
1716 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x01))
1717 BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x01))
;
1718
1719 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid)_atomic_add_int_nv((&sc->sc_rndisrid), 1);
1720
1721 req = rc->rc_req;
1722 req->rm_type = REMOTE_NDIS_SET_MSG0x00000005;
1723 req->rm_len = sizeof(*req) + length;
1724 req->rm_rid = rc->rc_id;
1725 req->rm_oid = oid;
1726 req->rm_infobufoffset = sizeof(*req) - RNDIS_HEADER_OFFSET(sizeof(struct rndis_msghdr));
1727
1728 rc->rc_cmplen = sizeof(*cmp);
1729
1730 if (length > 0) {
1731 KASSERT(sizeof(*req) + length < PAGE_SIZE)((sizeof(*req) + length < (1 << 12)) ? (void)0 : __assert
("diagnostic ", "/usr/src/sys/dev/pv/if_hvn.c", 1731, "sizeof(*req) + length < PAGE_SIZE"
))
;
1732 req->rm_infobuflen = length;
1733 memcpy((caddr_t)(req + 1), data, length)__builtin_memcpy(((caddr_t)(req + 1)), (data), (length));
1734 }
1735
1736 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x04))
1737 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x04))
;
1738
1739 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) {
1740 DPRINTF("%s: SET_MSG failed, error %d\n",
1741 sc->sc_dev.dv_xname, rv);
1742 hvn_free_cmd(sc, rc);
1743 return (rv);
1744 }
1745
1746 cmp = (struct rndis_set_comp *)&rc->rc_cmp;
1747 if (cmp->rm_status != RNDIS_STATUS_SUCCESS0x00000000L)
1748 rv = EIO5;
1749
1750 hvn_free_cmd(sc, rc);
1751
1752 return (rv);
1753}
1754
1755int
1756hvn_rndis_close(struct hvn_softc *sc)
1757{
1758 uint32_t filter = 0;
1759 int rv;
1760
1761 rv = hvn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER0x0001010E,
1762 &filter, sizeof(filter));
1763 if (rv)
1764 DPRINTF("%s: failed to clear RNDIS filter\n",
1765 sc->sc_dev.dv_xname);
1766 return (rv);
1767}
1768
1769void
1770hvn_rndis_detach(struct hvn_softc *sc)
1771{
1772 struct rndis_cmd *rc;
1773 struct rndis_halt_req *req;
1774 int rv;
1775
1776 rc = hvn_alloc_cmd(sc);
1777
1778 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x01))
1779 BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x01))
;
1780
1781 rc->rc_id = atomic_inc_int_nv(&sc->sc_rndisrid)_atomic_add_int_nv((&sc->sc_rndisrid), 1);
1782
1783 req = rc->rc_req;
1784 req->rm_type = REMOTE_NDIS_HALT_MSG0x00000003;
1785 req->rm_len = sizeof(*req);
1786 req->rm_rid = rc->rc_id;
1787
1788 bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x04))
1789 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rc->
rc_dmap), (0), ((1 << 12)), (0x04))
;
1790
1791 if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0)
Although the value stored to 'rv' is used in the enclosing expression, the value is never actually read from 'rv'
1792 DPRINTF("%s: HALT_MSG failed, error %d\n",
1793 sc->sc_dev.dv_xname, rv);
1794
1795 hvn_free_cmd(sc, rc);
1796}