Date: Mon, 17 Oct 2016 06:47:35 +0000 (UTC) From: Sepherosa Ziehau <sephe@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r307480 - stable/11/sys/dev/hyperv/netvsc Message-ID: <201610170647.u9H6lZti094094@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Mon Oct 17 06:47:34 2016 New Revision: 307480 URL: https://svnweb.freebsd.org/changeset/base/307480 Log: MFC 304441,304444,304446,304447,304591,304593-304595 304441 hyperv/hn: Move NVS version to softc Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7553 304444 hyperv/hn: Remove assign-only struct field Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7554 304446 hyperv/hn: Remove the useless num_channel Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7555 304447 hyperv/hn: Move RXBUF to hn_softc And don't recreate RXBUF for each primary channel open, it is now created in device_attach DEVMETHOD and destroyed in device_detach DEVMETHOD. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7556 304591 hyperv/hn: Move chimney sending buffer to hn_softc And don't recreate chimney sending buffer for each primary channel open, it is now created in device_attach DEVMETHOD and destroyed in device_detach DEVMETHOD. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7574 304593 hyperv/hn: Get rid of netvsc_dev Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7575 304594 hyperv/hn: Factor out function to execute NVS transactions. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7577 304595 hyperv/hn: Factor out function to simplify NVS request sending Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7578 Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.h stable/11/sys/dev/hyperv/netvsc/if_hnvar.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c ============================================================================== --- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c Mon Oct 17 06:18:10 2016 (r307479) +++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c Mon Oct 17 06:47:34 2016 (r307480) @@ -37,6 +37,7 @@ #include <sys/param.h> #include <sys/kernel.h> #include <sys/socket.h> +#include <sys/limits.h> #include <sys/lock.h> #include <net/if.h> #include <net/if_var.h> @@ -59,85 +60,78 @@ MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper static void hv_nv_on_channel_callback(struct vmbus_channel *chan, void *xrxr); static int hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc); -static int hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *); -static int hv_nv_destroy_send_buffer(netvsc_dev *net_dev); -static int hv_nv_destroy_rx_buffer(netvsc_dev *net_dev); +static int hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *, int); +static int hv_nv_destroy_send_buffer(struct hn_softc *sc); +static int hv_nv_destroy_rx_buffer(struct hn_softc *sc); static int hv_nv_connect_to_vsp(struct hn_softc *sc); -static void hv_nv_on_send_completion(netvsc_dev *net_dev, +static void hv_nv_on_send_completion(struct hn_softc *sc, struct vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt); static void hv_nv_on_receive_completion(struct vmbus_channel *chan, uint64_t tid); -static void hv_nv_on_receive(netvsc_dev *net_dev, +static void hv_nv_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkt); static void hn_nvs_sent_none(struct hn_send_ctx *sndc, - struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, + struct hn_softc *, struct vmbus_channel *chan, const void *, int); +static void hn_nvs_sent_xact(struct hn_send_ctx *, struct hn_softc *sc, + struct vmbus_channel *, const void *, int); static struct hn_send_ctx hn_send_ctx_none = HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL); -/* - * - */ -static inline netvsc_dev * -hv_nv_alloc_net_device(struct hn_softc *sc) +uint32_t +hn_chim_alloc(struct hn_softc *sc) { - netvsc_dev *net_dev; + int i, bmap_cnt = sc->hn_chim_bmap_cnt; + u_long *bmap = sc->hn_chim_bmap; + uint32_t ret = HN_NVS_CHIM_IDX_INVALID; - net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_WAITOK | M_ZERO); + for (i = 0; i < bmap_cnt; ++i) { + int idx; - net_dev->sc = sc; - net_dev->destroy = FALSE; - sc->net_dev = net_dev; + idx = ffsl(~bmap[i]); + if (idx == 0) + continue; - return (net_dev); -} + --idx; /* ffsl is 1-based */ + KASSERT(i * LONG_BIT + idx < sc->hn_chim_cnt, + ("invalid i %d and idx %d", i, idx)); -/* - * XXX unnecessary; nuke it. - */ -static inline netvsc_dev * -hv_nv_get_outbound_net_device(struct hn_softc *sc) -{ - return sc->net_dev; -} + if (atomic_testandset_long(&bmap[i], idx)) + continue; -/* - * XXX unnecessary; nuke it. - */ -static inline netvsc_dev * -hv_nv_get_inbound_net_device(struct hn_softc *sc) -{ - return sc->net_dev; + ret = i * LONG_BIT + idx; + break; + } + return (ret); } -int -hv_nv_get_next_send_section(netvsc_dev *net_dev) +const void * +hn_nvs_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, + void *req, int reqlen, size_t *resp_len) { - unsigned long bitsmap_words = net_dev->bitsmap_words; - unsigned long *bitsmap = net_dev->send_section_bitsmap; - unsigned long idx; - int ret = HN_NVS_CHIM_IDX_INVALID; - int i; - - for (i = 0; i < bitsmap_words; i++) { - idx = ffsl(~bitsmap[i]); - if (0 == idx) - continue; - - idx--; - KASSERT(i * BITS_PER_LONG + idx < net_dev->send_section_count, - ("invalid i %d and idx %lu", i, idx)); + struct hn_send_ctx sndc; + int error; - if (atomic_testandset_long(&bitsmap[i], idx)) - continue; + hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); + vmbus_xact_activate(xact); - ret = i * BITS_PER_LONG + idx; - break; + error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, + req, reqlen, &sndc); + if (error) { + vmbus_xact_deactivate(xact); + return NULL; } + return (vmbus_xact_wait(xact, resp_len)); +} - return (ret); +static __inline int +hn_nvs_req_send(struct hn_softc *sc, void *req, int reqlen) +{ + + return (hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE, + req, reqlen, &hn_send_ctx_none)); } /* @@ -147,29 +141,17 @@ hv_nv_get_next_send_section(netvsc_dev * * Hyper-V extensible switch and the synthetic data path. */ static int -hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) +hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc, int rxbuf_size) { - struct vmbus_xact *xact; + struct vmbus_xact *xact = NULL; struct hn_nvs_rxbuf_conn *conn; const struct hn_nvs_rxbuf_connresp *resp; size_t resp_len; - struct hn_send_ctx sndc; - netvsc_dev *net_dev; uint32_t status; int error; - net_dev = hv_nv_get_outbound_net_device(sc); - if (!net_dev) { - return (ENODEV); - } - - net_dev->rx_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), - PAGE_SIZE, 0, net_dev->rx_buf_size, &net_dev->rxbuf_dma, - BUS_DMA_WAITOK | BUS_DMA_ZERO); - if (net_dev->rx_buf == NULL) { - device_printf(sc->hn_dev, "allocate rxbuf failed\n"); - return (ENOMEM); - } + KASSERT(rxbuf_size <= NETVSC_RECEIVE_BUFFER_SIZE, + ("invalid rxbuf size %d", rxbuf_size)); /* * Connect the RXBUF GPADL to the primary channel. @@ -179,8 +161,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct * just share this RXBUF. */ error = vmbus_chan_gpadl_connect(sc->hn_prichan, - net_dev->rxbuf_dma.hv_paddr, net_dev->rx_buf_size, - &net_dev->rx_buf_gpadl_handle); + sc->hn_rxbuf_dma.hv_paddr, rxbuf_size, &sc->hn_rxbuf_gpadl); if (error) { if_printf(sc->hn_ifp, "rxbuf gpadl connect failed: %d\n", error); @@ -197,55 +178,47 @@ hv_nv_init_rx_buffer_with_net_vsp(struct error = ENXIO; goto cleanup; } - conn = vmbus_xact_req_data(xact); conn->nvs_type = HN_NVS_TYPE_RXBUF_CONN; - conn->nvs_gpadl = net_dev->rx_buf_gpadl_handle; + conn->nvs_gpadl = sc->hn_rxbuf_gpadl; conn->nvs_sig = HN_NVS_RXBUF_SIG; - hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); - vmbus_xact_activate(xact); - - error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, - conn, sizeof(*conn), &sndc); - if (error != 0) { - if_printf(sc->hn_ifp, "send nvs rxbuf conn failed: %d\n", - error); - vmbus_xact_deactivate(xact); - vmbus_xact_put(xact); + resp = hn_nvs_xact_execute(sc, xact, conn, sizeof(*conn), &resp_len); + if (resp == NULL) { + if_printf(sc->hn_ifp, "exec rxbuf conn failed\n"); + error = EIO; goto cleanup; } - - resp = vmbus_xact_wait(xact, &resp_len); if (resp_len < sizeof(*resp)) { if_printf(sc->hn_ifp, "invalid rxbuf conn resp length %zu\n", resp_len); - vmbus_xact_put(xact); error = EINVAL; goto cleanup; } if (resp->nvs_type != HN_NVS_TYPE_RXBUF_CONNRESP) { if_printf(sc->hn_ifp, "not rxbuf conn resp, type %u\n", resp->nvs_type); - vmbus_xact_put(xact); error = EINVAL; goto cleanup; } status = resp->nvs_status; vmbus_xact_put(xact); + xact = NULL; if (status != HN_NVS_STATUS_OK) { if_printf(sc->hn_ifp, "rxbuf conn failed: %x\n", status); error = EIO; goto cleanup; } - net_dev->rx_section_count = 1; + sc->hn_flags |= HN_FLAG_RXBUF_CONNECTED; return (0); cleanup: - hv_nv_destroy_rx_buffer(net_dev); + if (xact != NULL) + vmbus_xact_put(xact); + hv_nv_destroy_rx_buffer(sc); return (error); } @@ -255,28 +228,13 @@ cleanup: static int hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) { - struct hn_send_ctx sndc; - struct vmbus_xact *xact; + struct vmbus_xact *xact = NULL; struct hn_nvs_chim_conn *chim; const struct hn_nvs_chim_connresp *resp; size_t resp_len; uint32_t status, sectsz; - netvsc_dev *net_dev; int error; - net_dev = hv_nv_get_outbound_net_device(sc); - if (!net_dev) { - return (ENODEV); - } - - net_dev->send_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), - PAGE_SIZE, 0, net_dev->send_buf_size, &net_dev->txbuf_dma, - BUS_DMA_WAITOK | BUS_DMA_ZERO); - if (net_dev->send_buf == NULL) { - device_printf(sc->hn_dev, "allocate chimney txbuf failed\n"); - return (ENOMEM); - } - /* * Connect chimney sending buffer GPADL to the primary channel. * @@ -285,8 +243,8 @@ hv_nv_init_send_buffer_with_net_vsp(stru * Sub-channels just share this chimney sending buffer. */ error = vmbus_chan_gpadl_connect(sc->hn_prichan, - net_dev->txbuf_dma.hv_paddr, net_dev->send_buf_size, - &net_dev->send_buf_gpadl_handle); + sc->hn_chim_dma.hv_paddr, NETVSC_SEND_BUFFER_SIZE, + &sc->hn_chim_gpadl); if (error) { if_printf(sc->hn_ifp, "chimney sending buffer gpadl " "connect failed: %d\n", error); @@ -303,37 +261,26 @@ hv_nv_init_send_buffer_with_net_vsp(stru error = ENXIO; goto cleanup; } - chim = vmbus_xact_req_data(xact); chim->nvs_type = HN_NVS_TYPE_CHIM_CONN; - chim->nvs_gpadl = net_dev->send_buf_gpadl_handle; + chim->nvs_gpadl = sc->hn_chim_gpadl; chim->nvs_sig = HN_NVS_CHIM_SIG; - hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); - vmbus_xact_activate(xact); - - error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, - chim, sizeof(*chim), &sndc); - if (error) { - if_printf(sc->hn_ifp, "send nvs chim conn failed: %d\n", - error); - vmbus_xact_deactivate(xact); - vmbus_xact_put(xact); + resp = hn_nvs_xact_execute(sc, xact, chim, sizeof(*chim), &resp_len); + if (resp == NULL) { + if_printf(sc->hn_ifp, "exec chim conn failed\n"); + error = EIO; goto cleanup; } - - resp = vmbus_xact_wait(xact, &resp_len); if (resp_len < sizeof(*resp)) { if_printf(sc->hn_ifp, "invalid chim conn resp length %zu\n", resp_len); - vmbus_xact_put(xact); error = EINVAL; goto cleanup; } if (resp->nvs_type != HN_NVS_TYPE_CHIM_CONNRESP) { if_printf(sc->hn_ifp, "not chim conn resp, type %u\n", resp->nvs_type); - vmbus_xact_put(xact); error = EINVAL; goto cleanup; } @@ -341,6 +288,7 @@ hv_nv_init_send_buffer_with_net_vsp(stru status = resp->nvs_status; sectsz = resp->nvs_sectsz; vmbus_xact_put(xact); + xact = NULL; if (status != HN_NVS_STATUS_OK) { if_printf(sc->hn_ifp, "chim conn failed: %x\n", status); @@ -353,23 +301,33 @@ hv_nv_init_send_buffer_with_net_vsp(stru return 0; } - net_dev->send_section_size = sectsz; - net_dev->send_section_count = - net_dev->send_buf_size / net_dev->send_section_size; - net_dev->bitsmap_words = howmany(net_dev->send_section_count, - BITS_PER_LONG); - net_dev->send_section_bitsmap = - malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC, - M_WAITOK | M_ZERO); + sc->hn_chim_szmax = sectsz; + sc->hn_chim_cnt = NETVSC_SEND_BUFFER_SIZE / sc->hn_chim_szmax; + if (NETVSC_SEND_BUFFER_SIZE % sc->hn_chim_szmax != 0) { + if_printf(sc->hn_ifp, "chimney sending sections are " + "not properly aligned\n"); + } + if (sc->hn_chim_cnt % LONG_BIT != 0) { + if_printf(sc->hn_ifp, "discard %d chimney sending sections\n", + sc->hn_chim_cnt % LONG_BIT); + } + + sc->hn_chim_bmap_cnt = sc->hn_chim_cnt / LONG_BIT; + sc->hn_chim_bmap = malloc(sc->hn_chim_bmap_cnt * sizeof(u_long), + M_NETVSC, M_WAITOK | M_ZERO); + /* Done! */ + sc->hn_flags |= HN_FLAG_CHIM_CONNECTED; if (bootverbose) { - if_printf(sc->hn_ifp, "chimney sending buffer %u/%u\n", - net_dev->send_section_size, net_dev->send_section_count); + if_printf(sc->hn_ifp, "chimney sending buffer %d/%d\n", + sc->hn_chim_szmax, sc->hn_chim_cnt); } return 0; cleanup: - hv_nv_destroy_send_buffer(net_dev); + if (xact != NULL) + vmbus_xact_put(xact); + hv_nv_destroy_send_buffer(sc); return (error); } @@ -377,11 +335,11 @@ cleanup: * Net VSC destroy receive buffer */ static int -hv_nv_destroy_rx_buffer(netvsc_dev *net_dev) +hv_nv_destroy_rx_buffer(struct hn_softc *sc) { int ret = 0; - if (net_dev->rx_section_count) { + if (sc->hn_flags & HN_FLAG_RXBUF_CONNECTED) { struct hn_nvs_rxbuf_disconn disconn; /* @@ -392,37 +350,28 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_ disconn.nvs_sig = HN_NVS_RXBUF_SIG; /* NOTE: No response. */ - ret = hn_nvs_send(net_dev->sc->hn_prichan, - VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn), - &hn_send_ctx_none); + ret = hn_nvs_req_send(sc, &disconn, sizeof(disconn)); if (ret != 0) { - if_printf(net_dev->sc->hn_ifp, + if_printf(sc->hn_ifp, "send rxbuf disconn failed: %d\n", ret); return (ret); } - net_dev->rx_section_count = 0; + sc->hn_flags &= ~HN_FLAG_RXBUF_CONNECTED; } - /* Tear down the gpadl on the vsp end */ - if (net_dev->rx_buf_gpadl_handle) { - ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan, - net_dev->rx_buf_gpadl_handle); + if (sc->hn_rxbuf_gpadl != 0) { /* - * If we failed here, we might as well return and have a leak - * rather than continue and a bugchk + * Disconnect RXBUF from primary channel. */ + ret = vmbus_chan_gpadl_disconnect(sc->hn_prichan, + sc->hn_rxbuf_gpadl); if (ret != 0) { + if_printf(sc->hn_ifp, + "rxbuf disconn failed: %d\n", ret); return (ret); } - net_dev->rx_buf_gpadl_handle = 0; - } - - if (net_dev->rx_buf) { - /* Free up the receive buffer */ - hyperv_dmamem_free(&net_dev->rxbuf_dma, net_dev->rx_buf); - net_dev->rx_buf = NULL; + sc->hn_rxbuf_gpadl = 0; } - return (ret); } @@ -430,11 +379,11 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_ * Net VSC destroy send buffer */ static int -hv_nv_destroy_send_buffer(netvsc_dev *net_dev) +hv_nv_destroy_send_buffer(struct hn_softc *sc) { int ret = 0; - if (net_dev->send_section_size) { + if (sc->hn_flags & HN_FLAG_CHIM_CONNECTED) { struct hn_nvs_chim_disconn disconn; /* @@ -445,80 +394,62 @@ hv_nv_destroy_send_buffer(netvsc_dev *ne disconn.nvs_sig = HN_NVS_CHIM_SIG; /* NOTE: No response. */ - ret = hn_nvs_send(net_dev->sc->hn_prichan, - VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn), - &hn_send_ctx_none); + ret = hn_nvs_req_send(sc, &disconn, sizeof(disconn)); if (ret != 0) { - if_printf(net_dev->sc->hn_ifp, + if_printf(sc->hn_ifp, "send chim disconn failed: %d\n", ret); return (ret); } + sc->hn_flags &= ~HN_FLAG_CHIM_CONNECTED; } - /* Tear down the gpadl on the vsp end */ - if (net_dev->send_buf_gpadl_handle) { - ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan, - net_dev->send_buf_gpadl_handle); - + if (sc->hn_chim_gpadl != 0) { /* - * If we failed here, we might as well return and have a leak - * rather than continue and a bugchk + * Disconnect chimney sending buffer from primary channel. */ + ret = vmbus_chan_gpadl_disconnect(sc->hn_prichan, + sc->hn_chim_gpadl); if (ret != 0) { + if_printf(sc->hn_ifp, + "chim disconn failed: %d\n", ret); return (ret); } - net_dev->send_buf_gpadl_handle = 0; - } - - if (net_dev->send_buf) { - /* Free up the receive buffer */ - hyperv_dmamem_free(&net_dev->txbuf_dma, net_dev->send_buf); - net_dev->send_buf = NULL; + sc->hn_chim_gpadl = 0; } - if (net_dev->send_section_bitsmap) { - free(net_dev->send_section_bitsmap, M_NETVSC); + if (sc->hn_chim_bmap != NULL) { + free(sc->hn_chim_bmap, M_NETVSC); + sc->hn_chim_bmap = NULL; } return (ret); } static int -hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev, - uint32_t nvs_ver) +hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, uint32_t nvs_ver) { - struct hn_send_ctx sndc; struct vmbus_xact *xact; struct hn_nvs_init *init; const struct hn_nvs_init_resp *resp; size_t resp_len; uint32_t status; - int error; xact = vmbus_xact_get(sc->hn_xact, sizeof(*init)); if (xact == NULL) { if_printf(sc->hn_ifp, "no xact for nvs init\n"); return (ENXIO); } - init = vmbus_xact_req_data(xact); init->nvs_type = HN_NVS_TYPE_INIT; init->nvs_ver_min = nvs_ver; init->nvs_ver_max = nvs_ver; - vmbus_xact_activate(xact); - hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); - - error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, - init, sizeof(*init), &sndc); - if (error) { - if_printf(sc->hn_ifp, "send nvs init failed: %d\n", error); - vmbus_xact_deactivate(xact); + resp = hn_nvs_xact_execute(sc, xact, init, sizeof(*init), &resp_len); + if (resp == NULL) { + if_printf(sc->hn_ifp, "exec init failed\n"); vmbus_xact_put(xact); - return (error); + return (EIO); } - - resp = vmbus_xact_wait(xact, &resp_len); if (resp_len < sizeof(*resp)) { if_printf(sc->hn_ifp, "invalid init resp length %zu\n", resp_len); @@ -560,8 +491,7 @@ hv_nv_send_ndis_config(struct hn_softc * conf.nvs_caps = HN_NVS_NDIS_CONF_VLAN; /* NOTE: No response. */ - error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE, - &conf, sizeof(conf), &hn_send_ctx_none); + error = hn_nvs_req_send(sc, &conf, sizeof(conf)); if (error) if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error); return (error); @@ -573,7 +503,6 @@ hv_nv_send_ndis_config(struct hn_softc * static int hv_nv_connect_to_vsp(struct hn_softc *sc) { - netvsc_dev *net_dev; uint32_t protocol_list[] = { NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2, NVSP_PROTOCOL_VERSION_4, @@ -584,19 +513,18 @@ hv_nv_connect_to_vsp(struct hn_softc *sc device_t dev = sc->hn_dev; struct ifnet *ifp = sc->hn_ifp; struct hn_nvs_ndis_init ndis; - - net_dev = hv_nv_get_outbound_net_device(sc); + int rxbuf_size; /* * Negotiate the NVSP version. Try the latest NVSP first. */ for (i = protocol_number - 1; i >= 0; i--) { - if (hv_nv_negotiate_nvsp_protocol(sc, net_dev, - protocol_list[i]) == 0) { - net_dev->nvsp_version = protocol_list[i]; - if (bootverbose) - device_printf(dev, "Netvsc: got version 0x%x\n", - net_dev->nvsp_version); + if (hv_nv_negotiate_nvsp_protocol(sc, protocol_list[i]) == 0) { + sc->hn_nvs_ver = protocol_list[i]; + if (bootverbose) { + device_printf(dev, "NVS version 0x%x\n", + sc->hn_nvs_ver); + } break; } } @@ -612,7 +540,7 @@ hv_nv_connect_to_vsp(struct hn_softc *sc * Set the MTU if supported by this NVSP protocol version * This needs to be right after the NVSP init message per Haiyang */ - if (net_dev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) + if (sc->hn_nvs_ver >= NVSP_PROTOCOL_VERSION_2) ret = hv_nv_send_ndis_config(sc, ifp->if_mtu); /* @@ -622,27 +550,25 @@ hv_nv_connect_to_vsp(struct hn_softc *sc memset(&ndis, 0, sizeof(ndis)); ndis.nvs_type = HN_NVS_TYPE_NDIS_INIT; ndis.nvs_ndis_major = NDIS_VERSION_MAJOR_6; - if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_4) + if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_1; else ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_30; /* NOTE: No response. */ - ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE, - &ndis, sizeof(ndis), &hn_send_ctx_none); + ret = hn_nvs_req_send(sc, &ndis, sizeof(ndis)); if (ret != 0) { if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", ret); goto cleanup; } /* Post the big receive buffer to NetVSP */ - if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_2) - net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; + if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_2) + rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; else - net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; - net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE; + rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE; - ret = hv_nv_init_rx_buffer_with_net_vsp(sc); + ret = hv_nv_init_rx_buffer_with_net_vsp(sc, rxbuf_size); if (ret == 0) ret = hv_nv_init_send_buffer_with_net_vsp(sc); @@ -654,10 +580,10 @@ cleanup: * Net VSC disconnect from VSP */ static void -hv_nv_disconnect_from_vsp(netvsc_dev *net_dev) +hv_nv_disconnect_from_vsp(struct hn_softc *sc) { - hv_nv_destroy_rx_buffer(net_dev); - hv_nv_destroy_send_buffer(net_dev); + hv_nv_destroy_rx_buffer(sc); + hv_nv_destroy_send_buffer(sc); } void @@ -676,20 +602,12 @@ hv_nv_subchan_attach(struct vmbus_channe * * Callback when the device belonging to this driver is added */ -netvsc_dev * -hv_nv_on_device_add(struct hn_softc *sc, void *additional_info, - struct hn_rx_ring *rxr) +int +hv_nv_on_device_add(struct hn_softc *sc, struct hn_rx_ring *rxr) { struct vmbus_channel *chan = sc->hn_prichan; - netvsc_dev *net_dev; int ret = 0; - net_dev = hv_nv_alloc_net_device(sc); - if (net_dev == NULL) - return NULL; - - /* Initialize the NetVSC channel extension */ - /* * Open the channel */ @@ -709,20 +627,13 @@ hv_nv_on_device_add(struct hn_softc *sc, if (ret != 0) goto close; - return (net_dev); + return (0); close: /* Now, we can close the channel safely */ vmbus_chan_close(chan); - cleanup: - /* - * Free the packet buffers on the netvsc device packet queue. - * Release other resources. - */ - free(net_dev, M_NETVSC); - - return (NULL); + return (ret); } /* @@ -731,27 +642,19 @@ cleanup: int hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) { - netvsc_dev *net_dev = sc->net_dev;; - /* Stop outbound traffic ie sends and receives completions */ - net_dev->destroy = TRUE; - - hv_nv_disconnect_from_vsp(net_dev); - - /* At this point, no one should be accessing net_dev except in here */ + hv_nv_disconnect_from_vsp(sc); /* Now, we can close the channel safely */ vmbus_chan_close(sc->hn_prichan); - free(net_dev, M_NETVSC); - return (0); } -void +static void hn_nvs_sent_xact(struct hn_send_ctx *sndc, - struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused, + struct hn_softc *sc __unused, struct vmbus_channel *chan __unused, const void *data, int dlen) { @@ -760,42 +663,42 @@ hn_nvs_sent_xact(struct hn_send_ctx *snd static void hn_nvs_sent_none(struct hn_send_ctx *sndc __unused, - struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused, + struct hn_softc *sc __unused, struct vmbus_channel *chan __unused, const void *data __unused, int dlen __unused) { /* EMPTY */ } void -hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx) +hn_chim_free(struct hn_softc *sc, uint32_t chim_idx) { u_long mask; uint32_t idx; - idx = chim_idx / BITS_PER_LONG; - KASSERT(idx < net_dev->bitsmap_words, + idx = chim_idx / LONG_BIT; + KASSERT(idx < sc->hn_chim_bmap_cnt, ("invalid chimney index 0x%x", chim_idx)); - mask = 1UL << (chim_idx % BITS_PER_LONG); - KASSERT(net_dev->send_section_bitsmap[idx] & mask, + mask = 1UL << (chim_idx % LONG_BIT); + KASSERT(sc->hn_chim_bmap[idx] & mask, ("index bitmap 0x%lx, chimney index %u, " "bitmap idx %d, bitmask 0x%lx", - net_dev->send_section_bitsmap[idx], chim_idx, idx, mask)); + sc->hn_chim_bmap[idx], chim_idx, idx, mask)); - atomic_clear_long(&net_dev->send_section_bitsmap[idx], mask); + atomic_clear_long(&sc->hn_chim_bmap[idx], mask); } /* * Net VSC on send completion */ static void -hv_nv_on_send_completion(netvsc_dev *net_dev, struct vmbus_channel *chan, +hv_nv_on_send_completion(struct hn_softc *sc, struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkt) { struct hn_send_ctx *sndc; sndc = (struct hn_send_ctx *)(uintptr_t)pkt->cph_xactid; - sndc->hn_cb(sndc, net_dev, chan, VMBUS_CHANPKT_CONST_DATA(pkt), + sndc->hn_cb(sndc, sc, chan, VMBUS_CHANPKT_CONST_DATA(pkt), VMBUS_CHANPKT_DATALEN(pkt)); /* * NOTE: @@ -839,7 +742,7 @@ hv_nv_on_send(struct vmbus_channel *chan * with virtual addresses. */ static void -hv_nv_on_receive(netvsc_dev *net_dev, struct hn_rx_ring *rxr, +hv_nv_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) { const struct vmbus_chanpkt_rxbuf *pkt; @@ -867,8 +770,8 @@ hv_nv_on_receive(netvsc_dev *net_dev, st /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */ for (i = 0; i < count; i++) { - hv_rf_on_receive(net_dev, rxr, - (const uint8_t *)net_dev->rx_buf + pkt->cp_rxbuf[i].rb_ofs, + hv_rf_on_receive(sc, rxr, + rxr->hn_rxbuf + pkt->cp_rxbuf[i].rb_ofs, pkt->cp_rxbuf[i].rb_len); } @@ -934,14 +837,9 @@ hv_nv_on_channel_callback(struct vmbus_c { struct hn_rx_ring *rxr = xrxr; struct hn_softc *sc = rxr->hn_ifp->if_softc; - netvsc_dev *net_dev; void *buffer; int bufferlen = NETVSC_PACKET_SIZE; - net_dev = hv_nv_get_inbound_net_device(sc); - if (net_dev == NULL) - return; - buffer = rxr->hn_rdbuf; do { struct vmbus_chanpkt_hdr *pkt = buffer; @@ -954,11 +852,10 @@ hv_nv_on_channel_callback(struct vmbus_c if (bytes_rxed > 0) { switch (pkt->cph_type) { case VMBUS_CHANPKT_TYPE_COMP: - hv_nv_on_send_completion(net_dev, chan, - pkt); + hv_nv_on_send_completion(sc, chan, pkt); break; case VMBUS_CHANPKT_TYPE_RXBUF: - hv_nv_on_receive(net_dev, rxr, chan, pkt); + hv_nv_on_receive(sc, rxr, chan, pkt); break; case VMBUS_CHANPKT_TYPE_INBAND: hn_proc_notify(sc, pkt); Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h ============================================================================== --- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h Mon Oct 17 06:18:10 2016 (r307479) +++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h Mon Oct 17 06:47:34 2016 (r307480) @@ -212,40 +212,6 @@ typedef struct rndis_recv_scale_param_ { * Data types */ -/* - * Per netvsc channel-specific - */ -typedef struct netvsc_dev_ { - struct hn_softc *sc; - - /* Send buffer allocated by us but manages by NetVSP */ - void *send_buf; - uint32_t send_buf_size; - uint32_t send_buf_gpadl_handle; - uint32_t send_section_size; - uint32_t send_section_count; - unsigned long bitsmap_words; - unsigned long *send_section_bitsmap; - - /* Receive buffer allocated by us but managed by NetVSP */ - void *rx_buf; - uint32_t rx_buf_size; - uint32_t rx_buf_gpadl_handle; - uint32_t rx_section_count; - - /* Holds rndis device info */ - void *extension; - - uint8_t destroy; - /* Negotiated NVSP version */ - uint32_t nvsp_version; - - uint32_t num_channel; - - struct hyperv_dma rxbuf_dma; - struct hyperv_dma txbuf_dma; -} netvsc_dev; - struct vmbus_channel; typedef void (*pfn_on_send_rx_completion)(struct vmbus_channel *, void *); @@ -268,12 +234,6 @@ typedef void (*pfn_on_send_rx_completion #define TRANSPORT_TYPE_IPV6_TCP ((TYPE_IPV6 << 16) | TYPE_TCP) #define TRANSPORT_TYPE_IPV6_UDP ((TYPE_IPV6 << 16) | TYPE_UDP) -#ifdef __LP64__ -#define BITS_PER_LONG 64 -#else -#define BITS_PER_LONG 32 -#endif - typedef struct { uint8_t mac_addr[6]; /* Assumption unsigned long */ uint8_t link_state; @@ -292,6 +252,7 @@ struct hn_rx_ring { struct ifnet *hn_ifp; struct hn_tx_ring *hn_txr; void *hn_rdbuf; + uint8_t *hn_rxbuf; /* shadow sc->hn_rxbuf */ int hn_rx_idx; /* Trust csum verification on host side */ @@ -345,7 +306,7 @@ struct hn_tx_ring { struct vmbus_channel *hn_chan; int hn_direct_tx_size; - int hn_tx_chimney_size; + int hn_chim_size; bus_dma_tag_t hn_tx_data_dtag; uint64_t hn_csum_assist; @@ -383,7 +344,7 @@ typedef struct hn_softc { int hn_initdone; /* See hv_netvsc_drv_freebsd.c for rules on how to use */ int temp_unusable; - netvsc_dev *net_dev; + struct rndis_device_ *rndis_dev; struct vmbus_channel *hn_prichan; int hn_rx_ring_cnt; @@ -394,14 +355,31 @@ typedef struct hn_softc { int hn_tx_ring_inuse; struct hn_tx_ring *hn_tx_ring; + uint8_t *hn_chim; + u_long *hn_chim_bmap; + int hn_chim_bmap_cnt; + int hn_chim_cnt; + int hn_chim_szmax; + int hn_cpu; - int hn_tx_chimney_max; struct taskqueue *hn_tx_taskq; struct sysctl_oid *hn_tx_sysctl_tree; struct sysctl_oid *hn_rx_sysctl_tree; struct vmbus_xact_ctx *hn_xact; + uint32_t hn_nvs_ver; + + uint32_t hn_flags; + void *hn_rxbuf; + uint32_t hn_rxbuf_gpadl; + struct hyperv_dma hn_rxbuf_dma; + + uint32_t hn_chim_gpadl; + struct hyperv_dma hn_chim_dma; } hn_softc_t; +#define HN_FLAG_RXBUF_CONNECTED 0x0001 +#define HN_FLAG_CHIM_CONNECTED 0x0002 + /* * Externs */ @@ -409,13 +387,11 @@ extern int hv_promisc_mode; struct hn_send_ctx; void netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status); -netvsc_dev *hv_nv_on_device_add(struct hn_softc *sc, - void *additional_info, struct hn_rx_ring *rxr); +int hv_nv_on_device_add(struct hn_softc *sc, struct hn_rx_ring *rxr); int hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel); int hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt); -int hv_nv_get_next_send_section(netvsc_dev *net_dev); void hv_nv_subchan_attach(struct vmbus_channel *chan, struct hn_rx_ring *rxr); Modified: stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Oct 17 06:18:10 2016 (r307479) +++ stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Oct 17 06:47:34 2016 (r307480) @@ -328,7 +328,7 @@ static int hn_lro_lenlim_sysctl(SYSCTL_H static int hn_lro_ackcnt_sysctl(SYSCTL_HANDLER_ARGS); #endif static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS); -static int hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_chim_size_sysctl(SYSCTL_HANDLER_ARGS); static int hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); static int hn_rx_stat_u64_sysctl(SYSCTL_HANDLER_ARGS); static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS); @@ -342,9 +342,9 @@ static void hn_start_taskfunc(void *, in static void hn_start_txeof_taskfunc(void *, int); static void hn_stop_tx_tasks(struct hn_softc *); static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **); -static void hn_create_rx_data(struct hn_softc *sc, int); +static int hn_create_rx_data(struct hn_softc *sc, int); static void hn_destroy_rx_data(struct hn_softc *sc); -static void hn_set_tx_chimney_size(struct hn_softc *, int); +static void hn_set_chim_size(struct hn_softc *, int); static void hn_channel_attach(struct hn_softc *, struct vmbus_channel *); static void hn_subchan_attach(struct hn_softc *, struct vmbus_channel *); static void hn_subchan_setup(struct hn_softc *); @@ -504,7 +504,9 @@ netvsc_attach(device_t dev) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610170647.u9H6lZti094094>