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