svn commit: r304447 - head/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Fri Aug 19 05:43:30 UTC 2016
Author: sephe
Date: Fri Aug 19 05:43:28 2016
New Revision: 304447
URL: https://svnweb.freebsd.org/changeset/base/304447
Log:
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.
MFC after: 1 week
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7556
Modified:
head/sys/dev/hyperv/netvsc/hv_net_vsc.c
head/sys/dev/hyperv/netvsc/hv_net_vsc.h
head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.c Fri Aug 19 05:30:39 2016 (r304446)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.c Fri Aug 19 05:43:28 2016 (r304447)
@@ -59,9 +59,9 @@ 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_init_rx_buffer_with_net_vsp(struct hn_softc *, int);
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_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,
struct vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt);
@@ -146,29 +146,18 @@ 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 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 +167,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);
@@ -199,7 +187,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct
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);
@@ -239,12 +227,12 @@ hv_nv_init_rx_buffer_with_net_vsp(struct
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);
+ hv_nv_destroy_rx_buffer(sc);
return (error);
}
@@ -376,11 +364,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 +379,30 @@ 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,
+ ret = hn_nvs_send(sc->hn_prichan,
VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn),
&hn_send_ctx_none);
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;
+ sc->hn_rxbuf_gpadl = 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;
- }
-
return (ret);
}
@@ -583,6 +564,7 @@ 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;
+ int rxbuf_size;
net_dev = hv_nv_get_outbound_net_device(sc);
@@ -637,12 +619,12 @@ hv_nv_connect_to_vsp(struct hn_softc *sc
/* Post the big receive buffer to NetVSP */
if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_2)
- net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY;
+ rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY;
else
- net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
+ rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE;
net_dev->send_buf_size = NETVSC_SEND_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 +636,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->net_dev);
}
void
@@ -731,17 +713,14 @@ cleanup:
int
hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
{
- netvsc_dev *net_dev = sc->net_dev;;
- 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);
+ free(sc->net_dev, M_NETVSC);
return (0);
}
@@ -865,7 +844,7 @@ 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,
+ rxr->hn_rxbuf + pkt->cp_rxbuf[i].rb_ofs,
pkt->cp_rxbuf[i].rb_len);
}
Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.h Fri Aug 19 05:30:39 2016 (r304446)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h Fri Aug 19 05:43:28 2016 (r304447)
@@ -227,16 +227,9 @@ typedef struct netvsc_dev_ {
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;
- struct hyperv_dma rxbuf_dma;
struct hyperv_dma txbuf_dma;
} netvsc_dev;
@@ -286,6 +279,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 */
@@ -395,8 +389,15 @@ typedef struct hn_softc {
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;
} hn_softc_t;
+#define HN_FLAG_RXBUF_CONNECTED 0x0001
+
/*
* Externs
*/
Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Fri Aug 19 05:30:39 2016 (r304446)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Fri Aug 19 05:43:28 2016 (r304447)
@@ -342,7 +342,7 @@ 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_channel_attach(struct hn_softc *, struct vmbus_channel *);
@@ -504,7 +504,9 @@ netvsc_attach(device_t dev)
error = hn_create_tx_data(sc, tx_ring_cnt);
if (error)
goto failed;
- hn_create_rx_data(sc, ring_cnt);
+ error = hn_create_rx_data(sc, ring_cnt);
+ if (error)
+ goto failed;
/*
* Associate the first TX/RX ring w/ the primary channel.
@@ -2176,7 +2178,7 @@ hn_check_iplen(const struct mbuf *m, int
return ip->ip_p;
}
-static void
+static int
hn_create_rx_data(struct hn_softc *sc, int ring_cnt)
{
struct sysctl_oid_list *child;
@@ -2189,6 +2191,22 @@ hn_create_rx_data(struct hn_softc *sc, i
#endif
int i;
+ /*
+ * Create RXBUF for reception.
+ *
+ * NOTE:
+ * - It is shared by all channels.
+ * - A large enough buffer is allocated, certain version of NVSes
+ * may further limit the usable space.
+ */
+ sc->hn_rxbuf = hyperv_dmamem_alloc(bus_get_dma_tag(dev),
+ PAGE_SIZE, 0, NETVSC_RECEIVE_BUFFER_SIZE, &sc->hn_rxbuf_dma,
+ BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ if (sc->hn_rxbuf == NULL) {
+ device_printf(sc->hn_dev, "allocate rxbuf failed\n");
+ return (ENOMEM);
+ }
+
sc->hn_rx_ring_cnt = ring_cnt;
sc->hn_rx_ring_inuse = sc->hn_rx_ring_cnt;
@@ -2225,6 +2243,7 @@ hn_create_rx_data(struct hn_softc *sc, i
rxr->hn_txr = &sc->hn_tx_ring[i];
rxr->hn_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK);
rxr->hn_rx_idx = i;
+ rxr->hn_rxbuf = sc->hn_rxbuf;
/*
* Initialize LRO.
@@ -2331,6 +2350,8 @@ hn_create_rx_data(struct hn_softc *sc, i
CTLFLAG_RD, &sc->hn_rx_ring_cnt, 0, "# created RX rings");
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "rx_ring_inuse",
CTLFLAG_RD, &sc->hn_rx_ring_inuse, 0, "# used RX rings");
+
+ return (0);
}
static void
@@ -2354,6 +2375,11 @@ hn_destroy_rx_data(struct hn_softc *sc)
sc->hn_rx_ring_cnt = 0;
sc->hn_rx_ring_inuse = 0;
+
+ if (sc->hn_rxbuf != NULL) {
+ hyperv_dmamem_free(&sc->hn_rxbuf_dma, sc->hn_rxbuf);
+ sc->hn_rxbuf = NULL;
+ }
}
static int
More information about the svn-src-head
mailing list