From d958ad14b65442aeb5dc15e5fb08fd2dabfeb549 Mon Sep 17 00:00:00 2001 From: mikeb Date: Thu, 18 Aug 2016 15:56:54 +0000 Subject: [PATCH] Update NVS protocol structure definitions to the 2016 version Microsoft has considerably cleaned up the style and it makes sense to keep in sync with the maintained upstream version in FreeBSD. --- sys/dev/pv/if_hvn.c | 273 ++++++------- sys/dev/pv/if_hvnreg.h | 873 ++++++----------------------------------- 2 files changed, 249 insertions(+), 897 deletions(-) diff --git a/sys/dev/pv/if_hvn.c b/sys/dev/pv/if_hvn.c index 2e3408f7439..3383dffbaa9 100644 --- a/sys/dev/pv/if_hvn.c +++ b/sys/dev/pv/if_hvn.c @@ -74,6 +74,9 @@ #define HVN_DEBUG 1 +#define HVN_NVS_BUFSIZE PAGE_SIZE +#define HVN_NVS_MSGSIZE 32 + /* * RNDIS control interface */ @@ -82,28 +85,22 @@ struct rndis_cmd { uint32_t rc_id; + struct hvn_nvs_rndis rc_msg; struct rndis *rc_req; bus_dmamap_t rc_dmap; uint64_t rc_pfn; struct rndis rc_cmp; uint32_t rc_cmplen; uint8_t rc_cmpbuf[HVN_RNDIS_CMPBUFSZ]; - struct nvsp rc_nvsp; struct mutex rc_mtx; TAILQ_ENTRY(rndis_cmd) rc_entry; }; TAILQ_HEAD(rndis_queue, rndis_cmd); -/* - * Rx ring - */ -#define HVN_RX_BUFID 0xcafe - /* * Tx ring */ #define HVN_TX_DESC 128 -#define HVN_TX_BUFID 0xface struct hvn_softc { struct device sc_dev; @@ -116,13 +113,12 @@ struct hvn_softc { int sc_link_state; int sc_promisc; - /* NVSP protocol */ + /* NVS protocol */ int sc_proto; - uint32_t sc_nvsptid; - struct nvsp sc_nvsp; - uint8_t *sc_nvspbuf; -#define HVN_NVSP_BUFSIZE (PAGE_SIZE * 4) - struct mutex sc_nvsplck; + uint32_t sc_nvstid; + uint8_t sc_nvsrsp[HVN_NVS_MSGSIZE]; + uint8_t *sc_nvsbuf; + struct mutex sc_nvslck; /* RNDIS protocol */ uint32_t sc_rndisrid; @@ -166,15 +162,15 @@ void hvn_get_link_status(struct hvn_softc *); void hvn_link_status(struct hvn_softc *); /* NSVP */ -int hvn_nvsp_attach(struct hvn_softc *); -void hvn_nvsp_intr(void *); -int hvn_nvsp_output(struct hvn_softc *, struct nvsp *, uint64_t, int); -int hvn_nvsp_ack(struct hvn_softc *, struct nvsp *, uint64_t); -void hvn_nvsp_detach(struct hvn_softc *); +int hvn_nvs_attach(struct hvn_softc *); +void hvn_nvs_intr(void *); +int hvn_nvs_cmd(struct hvn_softc *, void *, size_t, uint64_t, int); +int hvn_nvs_ack(struct hvn_softc *, uint64_t); +void hvn_nvs_detach(struct hvn_softc *); /* RNDIS */ int hvn_rndis_attach(struct hvn_softc *); -int hvn_rndis_ctloutput(struct hvn_softc *, struct rndis_cmd *, int); +int hvn_rndis_cmd(struct hvn_softc *, struct rndis_cmd *, int); void hvn_rndis_filter(struct hvn_softc *sc, uint64_t, void *); void hvn_rndis_input(struct hvn_softc *, caddr_t, uint32_t, struct mbuf_list *); @@ -220,7 +216,7 @@ hvn_attach(struct device *parent, struct device *self, void *aux) DPRINTF("\n"); - if (hvn_nvsp_attach(sc)) { + if (hvn_nvs_attach(sc)) { printf(": failed to init NVSP\n"); return; } @@ -277,7 +273,7 @@ hvn_attach(struct device *parent, struct device *self, void *aux) detach: hvn_rx_ring_destroy(sc); hvn_tx_ring_destroy(sc); - hvn_nvsp_detach(sc); + hvn_nvs_detach(sc); if (ifp->if_start) if_detach(ifp); } @@ -434,12 +430,11 @@ hvn_txeof(struct hvn_softc *sc, uint64_t tid) int hvn_rx_ring_create(struct hvn_softc *sc) { - struct nvsp *pkt = &sc->sc_nvsp; - struct nvsp_send_rx_buf *msg; - struct nvsp_send_rx_buf_comp *cmp; + struct hvn_nvs_rxbuf_conn cmd; + struct hvn_nvs_rxbuf_conn_resp *rsp; uint64_t tid; - if (sc->sc_proto <= NVSP_PROTOCOL_VERSION_2) + if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_2) sc->sc_rx_size = 15 * 1024 * 1024; /* 15MB */ else sc->sc_rx_size = 16 * 1024 * 1024; /* 16MB */ @@ -457,25 +452,24 @@ hvn_rx_ring_create(struct hvn_softc *sc) goto errout; } - memset(pkt, 0, sizeof(*pkt)); - pkt->msg_type = nvsp_type_send_rx_buf; - msg = (struct nvsp_send_rx_buf *)&pkt->msg; - msg->gpadl_handle = sc->sc_rx_hndl; - msg->id = HVN_RX_BUFID; + memset(&cmd, 0, sizeof(cmd)); + cmd.nvs_type = HVN_NVS_TYPE_RXBUF_CONN; + cmd.nvs_gpadl = sc->sc_rx_hndl; + cmd.nvs_sig = HVN_NVS_RXBUF_SIG; - tid = atomic_inc_int_nv(&sc->sc_nvsptid); - if (hvn_nvsp_output(sc, pkt, tid, 100)) + tid = atomic_inc_int_nv(&sc->sc_nvstid); + if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) goto errout; - cmp = (struct nvsp_send_rx_buf_comp *)&pkt->msg; - if (cmp->status != nvsp_status_success) { + rsp = (struct hvn_nvs_rxbuf_conn_resp *)&sc->sc_nvsrsp; + if (rsp->nvs_status != HVN_NVS_STATUS_OK) { DPRINTF("%s: failed to set up the Rx ring\n", sc->sc_dev.dv_xname); goto errout; } - if (cmp->num_sections > 1) { + if (rsp->nvs_nsect > 1) { DPRINTF("%s: invalid number of Rx ring sections: %d\n", - sc->sc_dev.dv_xname, cmp->num_sections); + sc->sc_dev.dv_xname, rsp->nvs_nsect); hvn_rx_ring_destroy(sc); return (-1); } @@ -496,20 +490,18 @@ hvn_rx_ring_create(struct hvn_softc *sc) int hvn_rx_ring_destroy(struct hvn_softc *sc) { - struct nvsp *pkt = &sc->sc_nvsp; - struct nvsp_revoke_rx_buf *msg; + struct hvn_nvs_rxbuf_disconn cmd; uint64_t tid; if (sc->sc_rx_ring == NULL) return (0); - memset(pkt, 0, sizeof(*pkt)); - pkt->msg_type = nvsp_type_revoke_rx_buf; - msg = (struct nvsp_revoke_rx_buf *)&pkt->msg; - msg->id = HVN_RX_BUFID; + memset(&cmd, 0, sizeof(cmd)); + cmd.nvs_type = HVN_NVS_TYPE_RXBUF_DISCONN; + cmd.nvs_sig = HVN_NVS_RXBUF_SIG; - tid = atomic_inc_int_nv(&sc->sc_nvsptid); - if (hvn_nvsp_output(sc, pkt, tid, 0)) + tid = atomic_inc_int_nv(&sc->sc_nvstid); + if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 0)) return (-1); delay(100); @@ -527,9 +519,8 @@ hvn_rx_ring_destroy(struct hvn_softc *sc) int hvn_tx_ring_create(struct hvn_softc *sc) { - struct nvsp *pkt = &sc->sc_nvsp; - struct nvsp_send_tx_buf *msg; - struct nvsp_send_tx_buf_comp *cmp; + struct hvn_nvs_chim_conn cmd; + struct hvn_nvs_chim_conn_resp *rsp; uint64_t tid; sc->sc_tx_size = 15 * 1024 * 1024; /* 15MB */ @@ -547,18 +538,17 @@ hvn_tx_ring_create(struct hvn_softc *sc) goto errout; } - memset(pkt, 0, sizeof(*pkt)); - pkt->msg_type = nvsp_type_send_tx_buf; - msg = (struct nvsp_send_tx_buf *)&pkt->msg; - msg->gpadl_handle = sc->sc_tx_hndl; - msg->id = HVN_TX_BUFID; + memset(&cmd, 0, sizeof(cmd)); + cmd.nvs_type = HVN_NVS_TYPE_CHIM_CONN; + cmd.nvs_gpadl = sc->sc_tx_hndl; + cmd.nvs_sig = HVN_NVS_CHIM_SIG; - tid = atomic_inc_int_nv(&sc->sc_nvsptid); - if (hvn_nvsp_output(sc, pkt, tid, 100)) + tid = atomic_inc_int_nv(&sc->sc_nvstid); + if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) goto errout; - cmp = (struct nvsp_send_tx_buf_comp *)&pkt->msg; - if (cmp->status != nvsp_status_success) { + rsp = (struct hvn_nvs_chim_conn_resp *)&sc->sc_nvsrsp; + if (rsp->nvs_status != HVN_NVS_STATUS_OK) { DPRINTF("%s: failed to set up the Tx ring\n", sc->sc_dev.dv_xname); goto errout; @@ -580,20 +570,18 @@ hvn_tx_ring_create(struct hvn_softc *sc) int hvn_tx_ring_destroy(struct hvn_softc *sc) { - struct nvsp *pkt = &sc->sc_nvsp; - struct nvsp_revoke_tx_buf *msg; + struct hvn_nvs_chim_disconn cmd; uint64_t tid; if (sc->sc_tx_ring == NULL) return (0); - memset(pkt, 0, sizeof(*pkt)); - pkt->msg_type = nvsp_type_revoke_tx_buf; - msg = (struct nvsp_revoke_tx_buf *)&pkt->msg; - msg->id = HVN_TX_BUFID; + memset(&cmd, 0, sizeof(cmd)); + cmd.nvs_type = HVN_NVS_TYPE_CHIM_DISCONN; + cmd.nvs_sig = HVN_NVS_CHIM_SIG; - tid = atomic_inc_int_nv(&sc->sc_nvsptid); - if (hvn_nvsp_output(sc, pkt, tid, 0)) + tid = atomic_inc_int_nv(&sc->sc_nvstid); + if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 0)) return (-1); delay(100); @@ -604,7 +592,6 @@ hvn_tx_ring_destroy(struct hvn_softc *sc) km_free(sc->sc_tx_ring, sc->sc_tx_size, &kv_any, &kp_zero); sc->sc_tx_ring = NULL; - return (0); } @@ -642,24 +629,23 @@ hvn_get_link_status(struct hvn_softc *sc) } int -hvn_nvsp_attach(struct hvn_softc *sc) +hvn_nvs_attach(struct hvn_softc *sc) { const uint32_t protos[] = { - NVSP_PROTOCOL_VERSION_5, NVSP_PROTOCOL_VERSION_4, - NVSP_PROTOCOL_VERSION_2, NVSP_PROTOCOL_VERSION_1 + HVN_NVS_PROTO_VERSION_5, HVN_NVS_PROTO_VERSION_4, + HVN_NVS_PROTO_VERSION_2, HVN_NVS_PROTO_VERSION_1 }; - struct nvsp *pkt = &sc->sc_nvsp; - struct nvsp_init *init; - struct nvsp_init_comp *cmp; - struct nvsp_send_ndis_version *ver; + struct hvn_nvs_init cmd; + struct hvn_nvs_init_resp *rsp; + struct hvn_nvs_ndis_init ncmd; uint64_t tid; uint32_t ndisver; int i; /* 4 page sized buffer for channel messages */ - sc->sc_nvspbuf = km_alloc(HVN_NVSP_BUFSIZE, &kv_any, &kp_zero, + sc->sc_nvsbuf = km_alloc(HVN_NVS_BUFSIZE, &kv_any, &kp_zero, (cold ? &kd_nowait : &kd_waitok)); - if (sc->sc_nvspbuf == NULL) { + if (sc->sc_nvsbuf == NULL) { DPRINTF("%s: failed to allocate channel data buffer\n", sc->sc_dev.dv_xname); return (-1); @@ -667,25 +653,23 @@ hvn_nvsp_attach(struct hvn_softc *sc) sc->sc_chan->ch_buflen = PAGE_SIZE * 4; /* Associate our interrupt handler with the channel */ - if (hv_channel_open(sc->sc_chan, NULL, 0, hvn_nvsp_intr, sc)) { + if (hv_channel_open(sc->sc_chan, NULL, 0, hvn_nvs_intr, sc)) { DPRINTF("%s: failed to open channel\n", sc->sc_dev.dv_xname); - km_free(sc->sc_nvspbuf, HVN_NVSP_BUFSIZE, &kv_any, &kp_zero); + km_free(sc->sc_nvsbuf, HVN_NVS_BUFSIZE, &kv_any, &kp_zero); return (-1); } - mtx_init(&sc->sc_nvsplck, IPL_NET); - - memset(pkt, 0, sizeof(*pkt)); - pkt->msg_type = nvsp_type_init; - init = (struct nvsp_init *)&pkt->msg; + mtx_init(&sc->sc_nvslck, IPL_NET); + memset(&cmd, 0, sizeof(cmd)); + cmd.nvs_type = HVN_NVS_TYPE_INIT; for (i = 0; i < nitems(protos); i++) { - init->protocol_version = init->protocol_version_2 = protos[i]; - tid = atomic_inc_int_nv(&sc->sc_nvsptid); - if (hvn_nvsp_output(sc, pkt, tid, 100)) + cmd.nvs_ver_min = cmd.nvs_ver_max = protos[i]; + tid = atomic_inc_int_nv(&sc->sc_nvstid); + if (hvn_nvs_cmd(sc, &cmd, sizeof(cmd), tid, 100)) return (-1); - cmp = (struct nvsp_init_comp *)&pkt->msg; - if (cmp->status == nvsp_status_success) { + rsp = (struct hvn_nvs_init_resp *)&sc->sc_nvsrsp; + if (rsp->nvs_status == HVN_NVS_STATUS_OK) { sc->sc_proto = protos[i]; break; } @@ -696,18 +680,17 @@ hvn_nvsp_attach(struct hvn_softc *sc) return (-1); } - memset(pkt, 0, sizeof(*pkt)); - pkt->msg_type = nvsp_type_send_ndis_vers; - ver = (struct nvsp_send_ndis_version *)&pkt->msg; - if (sc->sc_proto <= NVSP_PROTOCOL_VERSION_4) + memset(&ncmd, 0, sizeof(ncmd)); + ncmd.nvs_type = HVN_NVS_TYPE_NDIS_INIT; + if (sc->sc_proto <= HVN_NVS_PROTO_VERSION_4) ndisver = NDIS_VERSION_6_1; else ndisver = NDIS_VERSION_6_30; - ver->ndis_major_vers = (ndisver & 0xffff0000) >> 16; - ver->ndis_minor_vers = (ndisver & 0x0000ffff); + ncmd.nvs_ndis_major = (ndisver & 0xffff0000) >> 16; + ncmd.nvs_ndis_minor = (ndisver & 0x0000ffff); - tid = atomic_inc_int_nv(&sc->sc_nvsptid); - if (hvn_nvsp_output(sc, pkt, tid, 100)) + tid = atomic_inc_int_nv(&sc->sc_nvstid); + if (hvn_nvs_cmd(sc, &ncmd, sizeof(ncmd), tid, 100)) return (-1); DPRINTF("%s: NVSP %u.%u, NDIS %u.%u\n", sc->sc_dev.dv_xname, @@ -718,54 +701,54 @@ hvn_nvsp_attach(struct hvn_softc *sc) } void -hvn_nvsp_intr(void *arg) +hvn_nvs_intr(void *arg) { struct hvn_softc *sc = arg; struct vmbus_chanpkt_hdr *cph; - struct nvsp *pkt; + struct hvn_nvs_hdr *nvs; uint64_t rid; uint32_t rlen; int rv; for (;;) { - rv = hv_channel_recv(sc->sc_chan, sc->sc_nvspbuf, - HVN_NVSP_BUFSIZE, &rlen, &rid, 1); + rv = hv_channel_recv(sc->sc_chan, sc->sc_nvsbuf, + HVN_NVS_BUFSIZE, &rlen, &rid, 1); if (rv != 0 || rlen == 0) { if (rv != EAGAIN) printf("%s: failed to receive an NVSP " "packet\n", sc->sc_dev.dv_xname); break; } - cph = (struct vmbus_chanpkt_hdr *)sc->sc_nvspbuf; - pkt = (struct nvsp *)VMBUS_CHANPKT_CONST_DATA(cph); + cph = (struct vmbus_chanpkt_hdr *)sc->sc_nvsbuf; + nvs = (struct hvn_nvs_hdr *)VMBUS_CHANPKT_CONST_DATA(cph); if (cph->cph_type == VMBUS_CHANPKT_TYPE_COMP) { - switch (pkt->msg_type) { - case nvsp_type_init_comp: - case nvsp_type_send_rx_buf_comp: - case nvsp_type_send_tx_buf_comp: - case nvsp_type_subchannel: + switch (nvs->nvs_type) { + case HVN_NVS_TYPE_INIT_RESP: + case HVN_NVS_TYPE_RXBUF_CONNRESP: + case HVN_NVS_TYPE_CHIM_CONNRESP: + case HVN_NVS_TYPE_SUBCH_RESP: /* copy the response back */ - memcpy(&sc->sc_nvsp, pkt, sizeof(sc->sc_nvsp)); - wakeup_one(&sc->sc_nvsp); + memcpy(&sc->sc_nvsrsp, nvs, HVN_NVS_MSGSIZE); + wakeup_one(&sc->sc_nvsrsp); break; - case nvsp_type_send_rndis_pkt_comp: + case HVN_NVS_TYPE_RNDIS_ACK: hvn_txeof(sc, cph->cph_tid); break; default: printf("%s: unhandled NVSP packet type %d " "on completion\n", sc->sc_dev.dv_xname, - pkt->msg_type); + nvs->nvs_type); } } else if (cph->cph_type == VMBUS_CHANPKT_TYPE_RXBUF) { - switch (pkt->msg_type) { - case nvsp_type_send_rndis_pkt: + switch (nvs->nvs_type) { + case HVN_NVS_TYPE_RNDIS: hvn_rndis_filter(sc, cph->cph_tid, cph); break; default: printf("%s: unhandled NVSP packet type %d " "on receive\n", sc->sc_dev.dv_xname, - pkt->msg_type); + nvs->nvs_type); } } else printf("%s: unknown NVSP packet type %u\n", @@ -774,32 +757,34 @@ hvn_nvsp_intr(void *arg) } int -hvn_nvsp_output(struct hvn_softc *sc, struct nvsp *pkt, uint64_t tid, int timo) +hvn_nvs_cmd(struct hvn_softc *sc, void *cmd, size_t cmdsize, uint64_t tid, + int timo) { + struct hvn_nvs_hdr *hdr = cmd; int tries = 10; int rv; do { - rv = hv_channel_send(sc->sc_chan, pkt, sizeof(*pkt), + rv = hv_channel_send(sc->sc_chan, cmd, cmdsize, tid, VMBUS_CHANPKT_TYPE_INBAND, timo ? VMBUS_CHANPKT_FLAG_RC : 0); if (rv == EAGAIN) { if (timo) - tsleep(pkt, PRIBIO, "hvnsend", timo / 10); + tsleep(cmd, PRIBIO, "hvnsend", timo / 10); else delay(100); } else if (rv) { DPRINTF("%s: NVSP operation %d send error %d\n", - sc->sc_dev.dv_xname, pkt->msg_type, rv); + sc->sc_dev.dv_xname, hdr->nvs_type, rv); return (rv); } } while (rv != 0 && --tries > 0); if (timo) { - mtx_enter(&sc->sc_nvsplck); - rv = msleep(&sc->sc_nvsp, &sc->sc_nvsplck, PRIBIO, "hvnvsp", + mtx_enter(&sc->sc_nvslck); + rv = msleep(&sc->sc_nvsrsp, &sc->sc_nvslck, PRIBIO, "hvnvsp", timo); - mtx_leave(&sc->sc_nvsplck); + mtx_leave(&sc->sc_nvslck); #ifdef HVN_DEBUG switch (rv) { case EINTR: @@ -807,7 +792,7 @@ hvn_nvsp_output(struct hvn_softc *sc, struct nvsp *pkt, uint64_t tid, int timo) break; case EWOULDBLOCK: printf("%s: NVSP opertaion %d timed out\n", - sc->sc_dev.dv_xname, pkt->msg_type); + sc->sc_dev.dv_xname, hdr->nvs_type); } } #endif @@ -815,13 +800,16 @@ hvn_nvsp_output(struct hvn_softc *sc, struct nvsp *pkt, uint64_t tid, int timo) } int -hvn_nvsp_ack(struct hvn_softc *sc, struct nvsp *pkt, uint64_t tid) +hvn_nvs_ack(struct hvn_softc *sc, uint64_t tid) { + struct hvn_nvs_rndis_ack cmd; int tries = 5; int rv; + cmd.nvs_type = HVN_NVS_TYPE_RNDIS_ACK; + cmd.nvs_status = HVN_NVS_STATUS_OK; do { - rv = hv_channel_send(sc->sc_chan, pkt, sizeof(*pkt), + rv = hv_channel_send(sc->sc_chan, &cmd, sizeof(cmd), tid, VMBUS_CHANPKT_TYPE_COMP, 0); if (rv == EAGAIN) delay(100); @@ -835,11 +823,11 @@ hvn_nvsp_ack(struct hvn_softc *sc, struct nvsp *pkt, uint64_t tid) } void -hvn_nvsp_detach(struct hvn_softc *sc) +hvn_nvs_detach(struct hvn_softc *sc) { if (hv_channel_close(sc->sc_chan) == 0) { - km_free(sc->sc_nvspbuf, HVN_NVSP_BUFSIZE, &kv_any, &kp_zero); - sc->sc_nvspbuf = NULL; + km_free(sc->sc_nvsbuf, HVN_NVS_BUFSIZE, &kv_any, &kp_zero); + sc->sc_nvsbuf = NULL; } } @@ -908,7 +896,7 @@ hvn_free_cmd(struct hvn_softc *sc, struct rndis_cmd *rc) { memset(rc->rc_req, 0, sizeof(*rc->rc_req)); memset(&rc->rc_cmp, 0, sizeof(rc->rc_cmp)); - memset(&rc->rc_nvsp, 0, sizeof(rc->rc_nvsp)); + memset(&rc->rc_msg, 0, sizeof(rc->rc_msg)); mtx_enter(&sc->sc_cntl_fqlck); TAILQ_INSERT_TAIL(&sc->sc_cntl_fq, rc, rc_entry); mtx_leave(&sc->sc_cntl_fqlck); @@ -978,7 +966,7 @@ hvn_rndis_attach(struct hvn_softc *sc) bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, BUS_DMASYNC_PREWRITE); - if ((rv = hvn_rndis_ctloutput(sc, rc, 500)) != 0) { + if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { DPRINTF("%s: INITIALIZE_MSG failed, error %u\n", sc->sc_dev.dv_xname, rv); hvn_free_cmd(sc, rc); @@ -1012,19 +1000,18 @@ errout: } int -hvn_rndis_ctloutput(struct hvn_softc *sc, struct rndis_cmd *rc, int timo) +hvn_rndis_cmd(struct hvn_softc *sc, struct rndis_cmd *rc, int timo) { - struct nvsp_send_rndis_pkt *msg; + struct hvn_nvs_rndis *msg = &rc->rc_msg; struct vmbus_gpa sgl[1]; int tries = 10; int rv; KASSERT(timo > 0); - rc->rc_nvsp.msg_type = nvsp_type_send_rndis_pkt; - msg = (struct nvsp_send_rndis_pkt *)&rc->rc_nvsp.msg; - msg->chan_type = 1; /* control */ - msg->send_buf_section_idx = NVSP_INVALID_SECTION_INDEX; + msg->nvs_type = HVN_NVS_TYPE_RNDIS; + msg->nvs_rndis_mtype = HVN_NVS_RNDIS_MTYPE_CTRL; + msg->nvs_chim_idx = HVN_NVS_CHIM_IDX_INVALID; sgl[0].gpa_page = rc->rc_pfn; sgl[0].gpa_len = rc->rc_req->msg_len; @@ -1033,8 +1020,8 @@ hvn_rndis_ctloutput(struct hvn_softc *sc, struct rndis_cmd *rc, int timo) hvn_submit_cmd(sc, rc); do { - rv = hv_channel_send_sgl(sc->sc_chan, sgl, 1, &rc->rc_nvsp, - sizeof(struct nvsp), rc->rc_id); + rv = hv_channel_send_sgl(sc->sc_chan, sgl, 1, &rc->rc_msg, + sizeof(struct hvn_nvs_rndis), rc->rc_id); if (rv == EAGAIN) tsleep(rc, PRIBIO, "hvnsendbuf", timo / 10); else if (rv) { @@ -1078,10 +1065,8 @@ hvn_rndis_filter(struct hvn_softc *sc, uint64_t tid, void *arg) { struct ifnet *ifp = &sc->sc_ac.ac_if; struct mbuf_list ml = MBUF_LIST_INITIALIZER(); - struct nvsp pkt; struct vmbus_chanpkt_prplist *cp = arg; - struct nvsp_send_rndis_pkt_comp *cmp; - uint32_t off, len, type, status = 0; + uint32_t off, len, type; int i; if (sc->sc_rx_ring == NULL) { @@ -1121,11 +1106,7 @@ hvn_rndis_filter(struct hvn_softc *sc, uint64_t tid, void *arg) sc->sc_dev.dv_xname, type); } } - memset(&pkt, 0, sizeof(pkt)); - pkt.msg_type = nvsp_type_send_rndis_pkt_comp; - cmp = (struct nvsp_send_rndis_pkt_comp *)&pkt.msg; - cmp->status = status; /* XXX */ - hvn_nvsp_ack(sc, &pkt, tid); + hvn_nvs_ack(sc, tid); if (MBUF_LIST_FIRST(&ml)) if_input(ifp, &ml); @@ -1308,7 +1289,7 @@ hvn_rndis_query(struct hvn_softc *sc, uint32_t oid, void *res, size_t *length) bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, BUS_DMASYNC_PREWRITE); - if ((rv = hvn_rndis_ctloutput(sc, rc, 500)) != 0) { + if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { DPRINTF("%s: QUERY_MSG failed, error %d\n", sc->sc_dev.dv_xname, rv); hvn_free_cmd(sc, rc); @@ -1367,7 +1348,7 @@ hvn_rndis_set(struct hvn_softc *sc, uint32_t oid, void *data, size_t length) bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, BUS_DMASYNC_PREWRITE); - if ((rv = hvn_rndis_ctloutput(sc, rc, 500)) != 0) { + if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) { DPRINTF("%s: SET_MSG failed, error %u\n", sc->sc_dev.dv_xname, rv); hvn_free_cmd(sc, rc); @@ -1439,7 +1420,7 @@ hvn_rndis_detach(struct hvn_softc *sc) bus_dmamap_sync(sc->sc_dmat, rc->rc_dmap, 0, PAGE_SIZE, BUS_DMASYNC_PREWRITE); - if ((rv = hvn_rndis_ctloutput(sc, rc, 500)) != 0) + if ((rv = hvn_rndis_cmd(sc, rc, 500)) != 0) DPRINTF("%s: HALT_MSG failed, error %u\n", sc->sc_dev.dv_xname, rv); diff --git a/sys/dev/pv/if_hvnreg.h b/sys/dev/pv/if_hvnreg.h index af57d44b44e..a2046171afb 100644 --- a/sys/dev/pv/if_hvnreg.h +++ b/sys/dev/pv/if_hvnreg.h @@ -1,7 +1,5 @@ /*- - * Copyright (c) 2009-2012 Microsoft Corp. - * Copyright (c) 2010-2012 Citrix Inc. - * Copyright (c) 2012 NetApp Inc. + * Copyright (c) 2016 Microsoft Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,802 +27,175 @@ #ifndef _IF_HVNREG_H_ #define _IF_HVNREG_H_ -#define NVSP_PROTOCOL_VERSION_1 0x00002 -#define NVSP_PROTOCOL_VERSION_2 0x30002 -#define NVSP_PROTOCOL_VERSION_4 0x40000 -#define NVSP_PROTOCOL_VERSION_5 0x50000 +#define HVN_NVS_PROTO_VERSION_1 0x00002 +#define HVN_NVS_PROTO_VERSION_2 0x30002 +#define HVN_NVS_PROTO_VERSION_4 0x40000 +#define HVN_NVS_PROTO_VERSION_5 0x50000 -#define VERSION_4_OFFLOAD_SIZE 22 +#define HVN_NVS_RXBUF_SIG 0x2409 +#define HVN_NVS_CHIM_SIG 0x1984 -#define NVSP_OPERATIONAL_STATUS_OK 0x00000000 -#define NVSP_OPERATIONAL_STATUS_DEGRADED 0x00000001 -#define NVSP_OPERATIONAL_STATUS_NONRECOVERABLE 0x00000002 -#define NVSP_OPERATIONAL_STATUS_NO_CONTACT 0x00000003 -#define NVSP_OPERATIONAL_STATUS_LOST_COMM 0x00000004 +#define HVN_NVS_CHIM_IDX_INVALID 0xffffffff -/* - * Maximun number of transfer pages (packets) the VSP will use on a receive - */ -#define NVSP_MAX_PACKETS_PER_RECEIVE 375 - -enum nvsp_type { - nvsp_type_none = 0, - - /* - * Init Messages - */ - nvsp_type_init = 1, - nvsp_type_init_comp = 2, - - nvsp_type_version_start = 100, - - /* - * Version 1 Messages - */ - nvsp_type_send_ndis_vers = nvsp_type_version_start, - - nvsp_type_send_rx_buf, - nvsp_type_send_rx_buf_comp, - nvsp_type_revoke_rx_buf, - - nvsp_type_send_tx_buf, - nvsp_type_send_tx_buf_comp, - nvsp_type_revoke_tx_buf, - - nvsp_type_send_rndis_pkt, - nvsp_type_send_rndis_pkt_comp, - - /* - * Version 2 Messages - */ - nvsp_type_send_chimney_delegated_buf, - nvsp_type_send_chimney_delegated_buf_comp, - nvsp_type_revoke_chimney_delegated_buf, - - nvsp_type_resume_chimney_rx_indication, - - nvsp_type_terminate_chimney, - nvsp_type_terminate_chimney_comp, - - nvsp_type_indicate_chimney_event, - - nvsp_type_send_chimney_packet, - nvsp_type_send_chimney_packet_comp, - - nvsp_type_post_chimney_rx_req, - nvsp_type_post_chimney_rx_req_comp, - - nvsp_type_alloc_rx_buf, - nvsp_type_alloc_rx_buf_comp, - - nvsp_type_free_rx_buf, - - nvsp_type_send_vmq_rndis_pkt, - nvsp_type_send_vmq_rndis_pkt_comp, - - nvsp_type_send_ndis_config, - - nvsp_type_alloc_chimney_handle, - nvsp_type_alloc_chimney_handle_comp, - - /* - * Version 4 Messages - */ - nvsp_type_send_vf_association, - nvsp_type_switch_data_path, - nvsp_type_uplink_connect_state_deprecated, - - /* - * Version 5 Messages - */ - nvsp_type_oid_query_ex, - nvsp_type_oid_query_ex_comp, - nvsp_type_subchannel, - nvsp_type_send_indirection_table, -}; - -enum nvsp_status { - nvsp_status_none = 0, - nvsp_status_success, - nvsp_status_failure, - /* Deprecated */ - nvsp_status_prot_vers_range_too_new, - /* Deprecated */ - nvsp_status_prot_vers_range_too_old, - nvsp_status_invalid_rndis_pkt, - nvsp_status_busy, - nvsp_status_max, -}; +#define HVN_NVS_RNDIS_MTYPE_DATA 0 +#define HVN_NVS_RNDIS_MTYPE_CTRL 1 /* - * Init Messages + * NVS message transacion status codes. */ +#define HVN_NVS_STATUS_OK 1 +#define HVN_NVS_STATUS_FAILED 2 /* - * This message is used by the VSC to initialize the channel - * after the channels has been opened. This message should - * never include anything other then versioning (i.e. this - * message will be the same for ever). - * - * Forever is a long time. The values have been redefined - * in Win7 to indicate major and minor protocol version - * number. + * NVS request/response message types. */ -struct nvsp_init { - uint32_t protocol_version; - uint32_t protocol_version_2; -} __packed; +#define HVN_NVS_TYPE_INIT 1 +#define HVN_NVS_TYPE_INIT_RESP 2 +#define HVN_NVS_TYPE_NDIS_INIT 100 +#define HVN_NVS_TYPE_RXBUF_CONN 101 +#define HVN_NVS_TYPE_RXBUF_CONNRESP 102 +#define HVN_NVS_TYPE_RXBUF_DISCONN 103 +#define HVN_NVS_TYPE_CHIM_CONN 104 +#define HVN_NVS_TYPE_CHIM_CONNRESP 105 +#define HVN_NVS_TYPE_CHIM_DISCONN 106 +#define HVN_NVS_TYPE_RNDIS 107 +#define HVN_NVS_TYPE_RNDIS_ACK 108 +#define HVN_NVS_TYPE_NDIS_CONF 125 +#define HVN_NVS_TYPE_VFASSOC_NOTE 128 /* notification */ +#define HVN_NVS_TYPE_SET_DATAPATH 129 +#define HVN_NVS_TYPE_SUBCH_REQ 133 +#define HVN_NVS_TYPE_SUBCH_RESP 133 /* same as SUBCH_REQ */ +#define HVN_NVS_TYPE_TXTBL_NOTE 134 /* notification */ /* - * This message is used by the VSP to complete the initialization - * of the channel. This message should never include anything other - * then versioning (i.e. this message will be the same forever). + * Any size less than this one will _not_ work, e.g. hn_nvs_init + * only has 12B valid data, however, if only 12B data were sent, + * Hypervisor would never reply. */ -struct nvsp_init_comp { - /* Deprecated */ - uint32_t negotiated_prot_vers; - uint32_t max_mdl_chain_len; - uint32_t status; -} __packed; +#define HVN_NVS_REQSIZE_MIN 32 -/* - * Version 1 Messages - */ - -/* - * This message is used by the VSC to send the NDIS version - * to the VSP. The VSP can use this information when handling - * OIDs sent by the VSC. - */ -struct nvsp_send_ndis_version { - uint32_t ndis_major_vers; - /* Deprecated */ - uint32_t ndis_minor_vers; +/* NVS message common header */ +struct hvn_nvs_hdr { + uint32_t nvs_type; } __packed; -/* - * This message is used by the VSC to send a receive buffer - * to the VSP. The VSP can then use the receive buffer to - * send data to the VSC. - */ -struct nvsp_send_rx_buf { - uint32_t gpadl_handle; - uint16_t id; +struct hvn_nvs_init { + uint32_t nvs_type; /* HVN_NVS_TYPE_INIT */ + uint32_t nvs_ver_min; + uint32_t nvs_ver_max; + uint8_t nvs_rsvd[20]; } __packed; -struct nvsp_rx_buf_section { - uint32_t offset; - uint32_t sub_allocation_size; - uint32_t num_sub_allocations; - uint32_t end_offset; +struct hvn_nvs_init_resp { + uint32_t nvs_type; /* HVN_NVS_TYPE_INIT_RESP */ + uint32_t nvs_ver; /* deprecated */ + uint32_t nvs_rsvd; + uint32_t nvs_status; /* HVN_NVS_STATUS_ */ } __packed; -/* - * This message is used by the VSP to acknowledge a receive - * buffer send by the VSC. This message must be sent by the - * VSP before the VSP uses the receive buffer. - */ -struct nvsp_send_rx_buf_comp { - uint32_t status; - uint32_t num_sections; - - /* - * The receive buffer is split into two parts, a large - * suballocation section and a small suballocation - * section. These sections are then suballocated by a - * certain size. - * - * For example, the following break up of the receive - * buffer has 6 large suballocations and 10 small - * suballocations. - * - * | Large Section | | Small Section | - * ------------------------------------------------------------ - * | | | | | | | | | | | | | | | | | | - * | | - * LargeOffset SmallOffset - */ - struct nvsp_rx_buf_section sections[1]; +/* No reponse */ +struct hvn_nvs_ndis_conf { + uint32_t nvs_type; /* HVN_NVS_TYPE_NDIS_CONF */ + uint32_t nvs_mtu; + uint32_t nvs_rsvd; + uint64_t nvs_caps; /* HVN_NVS_NDIS_CONF_ */ + uint8_t nvs_rsvd1[12]; } __packed; -/* - * This message is sent by the VSC to revoke the receive buffer. - * After the VSP completes this transaction, the VSP should never - * use the receive buffer again. - */ -struct nvsp_revoke_rx_buf { - uint16_t id; -} __packed; +#define HVN_NVS_NDIS_CONF_SRIOV 0x0004 +#define HVN_NVS_NDIS_CONF_VLAN 0x0008 -/* - * This message is used by the VSC to send a send buffer - * to the VSP. The VSC can then use the send buffer to - * send data to the VSP. - */ -struct nvsp_send_tx_buf { - uint32_t gpadl_handle; - uint16_t id; +/* No response */ +struct hvn_nvs_ndis_init { + uint32_t nvs_type; /* HVN_NVS_TYPE_NDIS_INIT */ + uint32_t nvs_ndis_major; /* NDIS_VERSION_MAJOR_ */ + uint32_t nvs_ndis_minor; /* NDIS_VERSION_MINOR_ */ + uint8_t nvs_rsvd[20]; } __packed; -/* - * This message is used by the VSP to acknowledge a send - * buffer sent by the VSC. This message must be sent by the - * VSP before the VSP uses the sent buffer. - */ -struct nvsp_send_tx_buf_comp { - uint32_t status; - - /* - * The VSC gets to choose the size of the send buffer and - * the VSP gets to choose the sections size of the buffer. - * This was done to enable dynamic reconfigurations when - * the cost of GPA-direct buffers decreases. - */ - uint32_t section_size; +struct hvn_nvs_rxbuf_conn { + uint32_t nvs_type; /* HVN_NVS_TYPE_RXBUF_CONN */ + uint32_t nvs_gpadl; /* RXBUF vmbus GPADL */ + uint16_t nvs_sig; /* HVN_NVS_RXBUF_SIG */ + uint8_t nvs_rsvd[22]; } __packed; -/* - * This message is sent by the VSC to revoke the send buffer. - * After the VSP completes this transaction, the vsp should never - * use the send buffer again. - */ -struct nvsp_revoke_tx_buf { - uint16_t id; +struct hvn_nvs_rxbuf_sect { + uint32_t nvs_start; + uint32_t nvs_slotsz; + uint32_t nvs_slotcnt; + uint32_t nvs_end; } __packed; -/* - * This message is used by both the VSP and the VSC to send - * an RNDIS message to the opposite channel endpoint. - */ -struct nvsp_send_rndis_pkt { - /* - * This field is specified by RNIDS. They assume there's - * two different channels of communication. However, - * the Network VSP only has one. Therefore, the channel - * travels with the RNDIS packet. - */ - uint32_t chan_type; - - /* - * This field is used to send part or all of the data - * through a send buffer. This values specifies an - * index into the send buffer. If the index is - * 0xFFFFFFFF, then the send buffer is not being used - * and all of the data was sent through other VMBus - * mechanisms. - */ - uint32_t send_buf_section_idx; - uint32_t send_buf_section_size; +struct hvn_nvs_rxbuf_conn_resp { + uint32_t nvs_type; /* HVN_NVS_TYPE_RXBUF_CONNRESP */ + uint32_t nvs_status; /* HVN_NVS_STATUS_ */ + uint32_t nvs_nsect; /* # of elem in nvs_sect */ + struct hvn_nvs_rxbuf_sect nvs_sect[0]; } __packed; -/* - * This message is used by both the VSP and the VSC to complete - * a RNDIS message to the opposite channel endpoint. At this - * point, the initiator of this message cannot use any resources - * associated with the original RNDIS packet. - */ -struct nvsp_send_rndis_pkt_comp { - uint32_t status; -} __packed; - - -/* - * Version 2 Messages - */ - -/* - * This message is used by the VSC to send the NDIS version - * to the VSP. The VSP can use this information when handling - * OIDs sent by the VSC. - */ -struct nvsp_netvsc_capabilities { - union { - uint64_t as_uint64; - struct { - uint64_t vmq : 1; - uint64_t chimney : 1; - uint64_t sriov : 1; - uint64_t ieee8021q : 1; - uint64_t correlationid : 1; - uint64_t teaming : 1; - } ; - }; -} __packed; - -struct nvsp_send_ndis_config { - uint32_t mtu; - uint32_t reserved; - struct nvsp_netvsc_capabilities - capabilities; -} __packed; - -/* - * NvspMessage2TypeSendChimneyDelegatedBuffer - */ -struct nvsp_send_chimney_buf { - /* - * On WIN7 beta, delegated_obj_max_size is defined as a uint32_t - * Since WIN7 RC, it was split into two uint16_t. To have the same - * struct layout, delegated_obj_max_size shall be the first field. - */ - uint16_t delegated_obj_max_size; - - /* - * The revision # of chimney protocol used between NVSC and NVSP. - * - * This revision is NOT related to the chimney revision between - * NDIS protocol and miniport drivers. - */ - uint16_t revision; - - uint32_t gpadl_handle; -} __packed; - - -/* Unsupported chimney revision 0 (only present in WIN7 beta) */ -#define NVSP_CHIMNEY_REVISION_0 0 - -/* WIN7 Beta Chimney QFE */ -#define NVSP_CHIMNEY_REVISION_1 1 - -/* The chimney revision since WIN7 RC */ -#define NVSP_CHIMNEY_REVISION_2 2 - - -/* - * NvspMessage2TypeSendChimneyDelegatedBufferComplete - */ -struct nvsp_send_chimney_buf_comp { - uint32_t status; - - /* - * Maximum number outstanding sends and pre-posted receives. - * - * NVSC should not post more than SendQuota/ReceiveQuota packets. - * Otherwise, it can block the non-chimney path for an indefinite - * amount of time. - * (since chimney sends/receives are affected by the remote peer). - * - * Note: NVSP enforces the quota restrictions on a per-VMBCHANNEL - * basis. It doesn't enforce the restriction separately for chimney - * send/receive. If NVSC doesn't voluntarily enforce "SendQuota", - * it may kill its own network connectivity. - */ - uint32_t tx_quota; - uint32_t rx_quota; +/* No response */ +struct hvn_nvs_rxbuf_disconn { + uint32_t nvs_type; /* HVN_NVS_TYPE_RXBUF_DISCONN */ + uint16_t nvs_sig; /* HVN_NVS_RXBUF_SIG */ + uint8_t nvs_rsvd[26]; } __packed; -/* - * NvspMessage2TypeRevokeChimneyDelegatedBuffer - */ -struct nvsp_revoke_chimney_buf { - uint32_t gpadl_handle; +struct hvn_nvs_chim_conn { + uint32_t nvs_type; /* HVN_NVS_TYPE_CHIM_CONN */ + uint32_t nvs_gpadl; /* chimney buf vmbus GPADL */ + uint16_t nvs_sig; /* NDIS_NVS_CHIM_SIG */ + uint8_t nvs_rsvd[22]; } __packed; - -#define NVSP_CHIMNEY_OBJECT_TYPE_NEIGHBOR 0 -#define NVSP_CHIMNEY_OBJECT_TYPE_PATH4 1 -#define NVSP_CHIMNEY_OBJECT_TYPE_PATH6 2 -#define NVSP_CHIMNEY_OBJECT_TYPE_TCP 3 - -/* - * NvspMessage2TypeAllocateChimneyHandle - */ -struct nvsp_alloc_chimney_handle { - uint64_t vsc_context; - uint32_t object_type; +struct hvn_nvs_chim_conn_resp { + uint32_t nvs_type; /* HVN_NVS_TYPE_CHIM_CONNRESP */ + uint32_t nvs_status; /* HVN_NVS_STATUS_ */ + uint32_t nvs_sectsz; /* section size */ } __packed; -/* - * NvspMessage2TypeAllocateChimneyHandleComplete - */ -struct nvsp_alloc_chimney_handle_comp { - uint32_t vsp_handle; -} __packed; - - -/* - * NvspMessage2TypeResumeChimneyRXIndication - */ -struct nvsp_resume_chimney_rx_indication { - /* - * Handle identifying the offloaded connection - */ - uint32_t vsp_tcp_handle; +/* No response */ +struct hvn_nvs_chim_disconn { + uint32_t nvs_type; /* HVN_NVS_TYPE_CHIM_DISCONN */ + uint16_t nvs_sig; /* HVN_NVS_CHIM_SIG */ + uint8_t nvs_rsvd[26]; } __packed; -/* - * NvspMessage2TypeTerminateChimney - */ -struct nvsp_terminate_chimney { - /* - * Handle identifying the offloaded object - */ - uint32_t vsp_handle; +#define HVN_NVS_SUBCH_OP_ALLOC 1 - /* - * Terminate Offload Flags - * Bit 0: - * When set to 0, terminate the offload at the destination NIC - * Bit 1-31: Reserved, shall be zero - */ - uint32_t flags; - - union { - /* - * This field is valid only when bit 0 of flags is clear. - * It specifies the index into the premapped delegated - * object buffer. The buffer was sent through the - * NvspMessage2TypeSendChimneyDelegatedBuffer - * message at initialization time. - * - * NVSP will write the delegated state into the delegated - * buffer upon upload completion. - */ - uint32_t index; - - /* - * This field is valid only when bit 0 of flags is set. - * - * The seqence number of the most recently accepted RX - * indication when VSC sets its TCP context into - * "terminating" state. - * - * This allows NVSP to determines if there are any in-flight - * RX indications for which the acceptance state is still - * undefined. - */ - uint64_t last_accepted_rx_seq_no; - }; +struct hvn_nvs_subch_req { + uint32_t nvs_type; /* HVN_NVS_TYPE_SUBCH_REQ */ + uint32_t nvs_op; /* HVN_NVS_SUBCH_OP_ */ + uint32_t nvs_nsubch; + uint8_t nvs_rsvd[20]; } __packed; -/* - * NvspMessage2TypeTerminateChimneyComplete - */ -struct nvsp_terminate_chimney_comp { - uint64_t vsc_context; - uint32_t flags; +struct hvn_nvs_subch_resp { + uint32_t nvs_type; /* HVN_NVS_TYPE_SUBCH_RESP */ + uint32_t nvs_status; /* HVN_NVS_STATUS_ */ + uint32_t nvs_nsubch; } __packed; -/* - * NvspMessage2TypeIndicateChimneyEvent - */ -struct nvsp_indicate_chimney_event { - /* - * When VscTcpContext is 0, event_type is an NDIS_STATUS; - * Otherwise, EventType is an TCP connection event (defined - * in NdisTcpOffloadEventHandler chimney DDK document). - */ - uint32_t event_type; - +struct hvn_nvs_rndis { + uint32_t nvs_type; /* HVN_NVS_TYPE_RNDIS */ + uint32_t nvs_rndis_mtype;/* HVN_NVS_RNDIS_MTYPE_ */ /* - * When VscTcpContext is 0, EventType is an NDIS_STATUS; - * Otherwise, EventType is an TCP connection event specific - * information (defined in NdisTcpOffloadEventHandler - * chimney DDK document). - */ - uint32_t event_specific_info; - - /* - * If not 0, the event is per-TCP connection event. This field - * contains the VSC's TCP context. If 0, the event indication is - * global. - */ - uint64_t vsc_tcp_context; -} __packed; - - -#define NVSP_INVALID_OOB_INDEX 0xffffu -#define NVSP_INVALID_SECTION_INDEX 0xffffffff - -/* - * NvspMessage2TypeSendChimneyPacket - */ -struct nvsp_send_chimney_pkt { - /* - * Identify the TCP connection for which this chimney send is - */ - uint32_t vsp_tcp_handle; - - /* - * This field is used to send part or all of the data - * through a send buffer. This values specifies an - * index into the send buffer. If the index is - * 0xFFFF, then the send buffer is not being used - * and all of the data was sent through other VMBus - * mechanisms. - */ - uint16_t send_buf_section_index; - uint16_t send_buf_section_size; - - /* - * OOB Data Index - * This an index to the OOB data buffer. If the index is 0xFFFFFFFF, - * then there is no OOB data. - * - * This field shall be always 0xFFFFFFFF for now. It is reserved for - * the future. - */ - uint16_t oob_data_index; - - /* - * DisconnectFlags = 0 - * Normal chimney send. See MiniportTcpOffloadSend for details. - * - * DisconnectFlags = TCP_DISCONNECT_GRACEFUL_CLOSE (0x01) - * Graceful disconnect. See MiniportTcpOffloadDisconnect for details. - * - * DisconnectFlags = TCP_DISCONNECT_ABORTIVE_CLOSE (0x02) - * Abortive disconnect. See MiniportTcpOffloadDisconnect for details. - */ - uint16_t disconnect_flags; - - uint32_t seq_no; -} __packed; - -/* - * NvspMessage2TypeSendChimneyPacketComplete - */ -struct nvsp_send_chimney_pkt_comp { - /* - * The NDIS_STATUS for the chimney send - */ - uint32_t status; - - /* - * Number of bytes that have been sent to the peer (and ACKed by the peer). - */ - uint32_t bytes_transferred; -} __packed; - -/* - * NvspMessage2TypePostChimneyRecvRequest - */ -struct nvsp_post_chimney_rx_req { - /* - * Identify the TCP connection which this chimney receive request - * is for. - */ - uint32_t vsp_tcp_handle; - - /* - * OOB Data Index - * This an index to the OOB data buffer. If the index is 0xFFFFFFFF, - * then there is no OOB data. + * Chimney sending buffer index and size. * - * This field shall be always 0xFFFFFFFF for now. It is reserved for - * the future. - */ - uint32_t oob_data_index; - - /* - * Bit 0 - * When it is set, this is a "no-push" receive. - * When it is clear, this is a "push" receive. - * - * Bit 1-15: Reserved and shall be zero - */ - uint16_t flags; - - /* - * For debugging and diagnoses purpose. - * The SeqNo is per TCP connection and starts from 0. - */ - uint32_t seq_no; -} __packed; - -/* - * NvspMessage2TypePostChimneyRecvRequestComplete - */ -struct nvsp_post_chimney_rx_req_comp { - /* - * The NDIS_STATUS for the chimney send - */ - uint32_t status; - - /* - * Number of bytes that have been sent to the peer (and ACKed by - * the peer). - */ - uint32_t bytes_xferred; -} __packed; - -/* - * NvspMessage2TypeAllocateReceiveBuffer - */ -struct nvsp_alloc_rx_buf { - /* - * Allocation ID to match the allocation request and response - */ - uint32_t allocation_id; - - /* - * Length of the VM shared memory receive buffer that needs to - * be allocated - */ - uint32_t length; -} __packed; - -/* - * NvspMessage2TypeAllocateReceiveBufferComplete - */ -struct nvsp_alloc_rx_buf_comp { - /* - * The NDIS_STATUS code for buffer allocation - */ - uint32_t status; - - /* - * Allocation ID from NVSP_MESSAGE_ALLOCATE_RECEIVE_BUFFER - */ - uint32_t allocation_id; - - /* - * GPADL handle for the allocated receive buffer - */ - uint32_t gpadl_handle; - - /* - * Receive buffer ID that is further used in - * NvspMessage2SendVmqRndisPacket - */ - uint64_t rx_buf_id; -} __packed; - -/* - * NvspMessage2TypeFreeReceiveBuffer - */ -struct nvsp_free_rx_buf { - /* - * Receive buffer ID previous returned in - * NvspMessage2TypeAllocateReceiveBufferComplete message - */ - uint64_t rx_buf_id; -} __packed; - -/* - * This structure is used in defining the buffers in - * NVSP_MESSAGE_SEND_VMQ_RNDIS_PACKET structure - */ -struct nvsp_xfer_page_range { - /* - * Specifies the ID of the receive buffer that has the buffer. This - * ID can be the general receive buffer ID specified in - * NvspMessage1TypeSendReceiveBuffer or it can be the shared memory - * receive buffer ID allocated by the VSC and specified in - * NvspMessage2TypeAllocateReceiveBufferComplete message - */ - uint64_t xfer_page_set_id; - - /* - * Number of bytes - */ - uint32_t byte_count; - - /* - * Offset in bytes from the beginning of the buffer - */ - uint32_t byte_offset; -} __packed; - -/* - * NvspMessage2SendVmqRndisPacket - */ -struct nvsp_send_vmq_rndis_pkt { - /* - * This field is specified by RNIDS. They assume there's - * two different channels of communication. However, - * the Network VSP only has one. Therefore, the channel - * travels with the RNDIS packet. It must be RMC_DATA - */ - uint32_t channel_type; - - /* - * Only the Range element corresponding to the RNDIS header of - * the first RNDIS message in the multiple RNDIS messages sent - * in one NVSP message. Information about the data portions as well - * as the subsequent RNDIS messages in the same NVSP message are - * embedded in the RNDIS header itself - */ - struct nvsp_xfer_page_range range; -} __packed; - -/* - * This message is used by the VSC to complete - * a RNDIS VMQ message to the VSP. At this point, - * the initiator of this message can use any resources - * associated with the original RNDIS VMQ packet. - */ -struct nvsp_send_vmq_rndis_pkt_comp { - uint32_t status; -} __packed; - -/* - * Version 5 messages - */ -enum nvsp_subchannel_operation { - NVSP_SUBCHANNEL_NONE = 0, - NVSP_SUBCHANNE_ALLOCATE, - NVSP_SUBCHANNE_MAX -}; - -struct nvsp_subchannel_req { - uint32_t op; - uint32_t num_subchannels; -} __packed; - -struct nvsp_subchannel_comp { - uint32_t status; - /* Actual number of subchannels allocated */ - uint32_t num_subchannels; -} __packed; - -struct nvsp_send_indirect_table { - /* The number of entries in the send indirection table */ - uint32_t count; - /* - * The offset of the send indireciton table from top of - * this struct. The send indirection table tells which channel - * to put the send traffic on. Each entry is a channel number. + * NOTE: + * If nvs_chim_idx is set to HVN_NVS_CHIM_IDX_INVALID + * and nvs_chim_sz is set to 0, then chimney sending + * buffer is _not_ used by this RNDIS message. */ - uint32_t offset; + uint32_t nvs_chim_idx; + uint32_t nvs_chim_sz; + uint8_t nvs_rsvd[16]; } __packed; -/* - * All messages - */ -struct nvsp { - uint32_t msg_type; - - union { - struct nvsp_init init; - struct nvsp_init_comp init_compl; - - /* Version 1 */ - struct nvsp_send_ndis_version send_ndis_vers; - - struct nvsp_send_rx_buf send_rx_buf; - struct nvsp_send_rx_buf_comp send_rx_buf_comp; - struct nvsp_revoke_rx_buf revoke_rx_buf; - - struct nvsp_send_tx_buf send_tx_buf; - struct nvsp_send_tx_buf_comp send_tx_buf_comp; - struct nvsp_revoke_tx_buf revoke_tx_buf; - - struct nvsp_send_rndis_pkt send_rndis_pkt; - struct nvsp_send_rndis_pkt_comp send_rndis_pkt_comp; - - /* Version 2 */ - struct nvsp_send_ndis_config send_ndis_config; - - struct nvsp_send_chimney_buf send_chimney_buf; - struct nvsp_send_chimney_buf_comp send_chimney_buf_comp; - struct nvsp_revoke_chimney_buf revoke_chimney_buf; - - struct nvsp_resume_chimney_rx_indication resume_chimney_rx_indication; - struct nvsp_terminate_chimney terminate_chimney; - struct nvsp_terminate_chimney_comp terminate_chimney_comp; - struct nvsp_indicate_chimney_event indicate_chimney_event; - - struct nvsp_send_chimney_pkt send_chimney_packet; - struct nvsp_send_chimney_pkt_comp send_chimney_packet_comp; - struct nvsp_post_chimney_rx_req post_chimney_rx_req; - struct nvsp_post_chimney_rx_req_comp post_chimney_rx_req_comp; - - struct nvsp_alloc_rx_buf alloc_rx_buffer; - struct nvsp_alloc_rx_buf_comp alloc_rx_buffer_comp; - struct nvsp_free_rx_buf free_rx_buffer; - - struct nvsp_send_vmq_rndis_pkt send_vmq_rndis_pkt; - struct nvsp_send_vmq_rndis_pkt_comp send_vmq_rndis_pkt_comp; - struct nvsp_alloc_chimney_handle alloc_chimney_handle; - struct nvsp_alloc_chimney_handle_comp alloc_chimney_handle_comp; - - /* Version 5 */ - struct nvsp_subchannel_req subchannel_req; - struct nvsp_subchannel_comp subchn_comp; - struct nvsp_send_indirect_table send_table; - } msg; +struct hvn_nvs_rndis_ack { + uint32_t nvs_type; /* HVN_NVS_TYPE_RNDIS_ACK */ + uint32_t nvs_status; /* HVN_NVS_STATUS_ */ + uint8_t nvs_rsvd[24]; } __packed; #endif /* _IF_HVNREG_H_ */ -- 2.20.1