Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146734605
D7556.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D7556.id.diff
View Options
Index: head/sys/dev/hyperv/netvsc/hv_net_vsc.h
===================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.h
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h
@@ -227,16 +227,9 @@
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 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 @@
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
*/
Index: head/sys/dev/hyperv/netvsc/hv_net_vsc.c
===================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.c
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.c
@@ -59,9 +59,9 @@
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 @@
* 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 @@
* 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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
/* 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 @@
* 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 @@
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 @@
/* 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);
}
Index: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
===================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -342,7 +342,7 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 6, 3:34 AM (4 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29309635
Default Alt Text
D7556.id.diff (9 KB)
Attached To
Mode
D7556: hyperv/hn: Move RXBUF to hn_softc
Attached
Detach File
Event Timeline
Log In to Comment