svn commit: r307174 - stable/10/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Thu Oct 13 03:16:17 UTC 2016
Author: sephe
Date: Thu Oct 13 03:16:15 2016
New Revision: 307174
URL: https://svnweb.freebsd.org/changeset/base/307174
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/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h
stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c Thu Oct 13 03:10:04 2016 (r307173)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c Thu Oct 13 03:16:15 2016 (r307174)
@@ -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_arp.h>
@@ -58,85 +59,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));
}
/*
@@ -146,29 +140,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.
@@ -178,8 +160,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);
@@ -196,55 +177,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);
}
@@ -254,28 +227,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.
*
@@ -284,8 +242,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);
@@ -302,37 +260,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;
}
@@ -340,6 +287,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);
@@ -352,23 +300,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);
}
@@ -376,11 +334,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;
/*
@@ -391,37 +349,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);
}
@@ -429,11 +378,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;
/*
@@ -444,80 +393,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);
@@ -559,8 +490,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);
@@ -572,7 +502,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,
@@ -583,19 +512,18 @@ hv_nv_connect_to_vsp(struct hn_softc *sc
device_t dev = sc->hn_dev;
struct ifnet *ifp = sc->arpcom.ac_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;
}
}
@@ -611,7 +539,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);
/*
@@ -621,27 +549,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);
@@ -653,10 +579,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
@@ -675,20 +601,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
*/
@@ -708,20 +626,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);
}
/*
@@ -730,27 +641,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)
{
@@ -759,42 +662,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:
@@ -838,7 +741,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;
@@ -866,8 +769,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);
}
@@ -933,14 +836,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;
@@ -953,11 +851,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/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Thu Oct 13 03:10:04 2016 (r307173)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Thu Oct 13 03:16:15 2016 (r307174)
@@ -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;
@@ -384,7 +345,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;
@@ -395,14 +356,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
*/
@@ -410,13 +388,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/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Thu Oct 13 03:10:04 2016 (r307173)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Thu Oct 13 03:16:15 2016 (r307174)
@@ -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);
#if __FreeBSD_version < 1100095
static int hn_rx_stat_int_sysctl(SYSCTL_HANDLER_ARGS);
#else
@@ -346,9 +346,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 *);
@@ -520,7 +520,9 @@ netvsc_attach(device_t dev)
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable
mailing list