summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/hyperv/include/vmbus.h10
-rw-r--r--sys/dev/hyperv/netvsc/hv_net_vsc.h3
-rw-r--r--sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c38
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_chan.c65
4 files changed, 89 insertions, 27 deletions
diff --git a/sys/dev/hyperv/include/vmbus.h b/sys/dev/hyperv/include/vmbus.h
index a4c4286..ce5656c 100644
--- a/sys/dev/hyperv/include/vmbus.h
+++ b/sys/dev/hyperv/include/vmbus.h
@@ -109,6 +109,13 @@ struct vmbus_chanpkt_rxbuf {
struct vmbus_rxbuf_desc cp_rxbuf[];
} __packed;
+struct vmbus_chan_br {
+ void *cbr;
+ bus_addr_t cbr_paddr;
+ int cbr_txsz;
+ int cbr_rxsz;
+};
+
struct vmbus_channel;
struct hyperv_guid;
@@ -123,6 +130,9 @@ vmbus_get_channel(device_t dev)
int vmbus_chan_open(struct vmbus_channel *chan,
int txbr_size, int rxbr_size, const void *udata, int udlen,
vmbus_chan_callback_t cb, void *cbarg);
+int vmbus_chan_open_br(struct vmbus_channel *chan,
+ const struct vmbus_chan_br *cbr, const void *udata,
+ int udlen, vmbus_chan_callback_t cb, void *cbarg);
void vmbus_chan_close(struct vmbus_channel *chan);
int vmbus_chan_gpadl_connect(struct vmbus_channel *chan,
diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h
index 3c139f5..c2363f9 100644
--- a/sys/dev/hyperv/netvsc/hv_net_vsc.h
+++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h
@@ -136,6 +136,9 @@ struct hn_rx_ring {
/* Rarely used stuffs */
struct sysctl_oid *hn_rx_sysctl_tree;
int hn_rx_flags;
+
+ void *hn_br; /* TX/RX bufring */
+ struct hyperv_dma hn_br_dma;
} __aligned(CACHE_LINE_SIZE);
#define HN_TRUST_HCSUM_IP 0x0001
diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
index 5ec261c..0ae8762 100644
--- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -2378,7 +2378,8 @@ hn_create_rx_data(struct hn_softc *sc, int ring_cnt)
lroent_cnt = hn_lro_entry_count;
if (lroent_cnt < TCP_LRO_ENTRIES)
lroent_cnt = TCP_LRO_ENTRIES;
- device_printf(dev, "LRO: entry count %d\n", lroent_cnt);
+ if (bootverbose)
+ device_printf(dev, "LRO: entry count %d\n", lroent_cnt);
#endif
#endif /* INET || INET6 */
@@ -2392,6 +2393,16 @@ hn_create_rx_data(struct hn_softc *sc, int ring_cnt)
for (i = 0; i < sc->hn_rx_ring_cnt; ++i) {
struct hn_rx_ring *rxr = &sc->hn_rx_ring[i];
+ rxr->hn_br = hyperv_dmamem_alloc(bus_get_dma_tag(dev),
+ PAGE_SIZE, 0,
+ NETVSC_DEVICE_RING_BUFFER_SIZE +
+ NETVSC_DEVICE_RING_BUFFER_SIZE,
+ &rxr->hn_br_dma, BUS_DMA_WAITOK);
+ if (rxr->hn_br == NULL) {
+ device_printf(dev, "allocate bufring failed\n");
+ return (ENOMEM);
+ }
+
if (hn_trust_hosttcp)
rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_TCP;
if (hn_trust_hostudp)
@@ -2540,6 +2551,11 @@ hn_destroy_rx_data(struct hn_softc *sc)
for (i = 0; i < sc->hn_rx_ring_cnt; ++i) {
struct hn_rx_ring *rxr = &sc->hn_rx_ring[i];
+ if (rxr->hn_br == NULL)
+ continue;
+ hyperv_dmamem_free(&rxr->hn_br_dma, rxr->hn_br);
+ rxr->hn_br = NULL;
+
#if defined(INET) || defined(INET6)
tcp_lro_free(&rxr->hn_lro);
#endif
@@ -3145,6 +3161,7 @@ hn_xmit_txeof_taskfunc(void *xtxr, int pending __unused)
static int
hn_chan_attach(struct hn_softc *sc, struct vmbus_channel *chan)
{
+ struct vmbus_chan_br cbr;
struct hn_rx_ring *rxr;
struct hn_tx_ring *txr = NULL;
int idx, error;
@@ -3183,9 +3200,14 @@ hn_chan_attach(struct hn_softc *sc, struct vmbus_channel *chan)
/* Bind this channel to a proper CPU. */
vmbus_chan_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus);
- /* Open this channel */
- error = vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
- NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, hn_chan_callback, rxr);
+ /*
+ * Open this channel
+ */
+ cbr.cbr = rxr->hn_br;
+ cbr.cbr_paddr = rxr->hn_br_dma.hv_paddr;
+ cbr.cbr_txsz = NETVSC_DEVICE_RING_BUFFER_SIZE;
+ cbr.cbr_rxsz = NETVSC_DEVICE_RING_BUFFER_SIZE;
+ error = vmbus_chan_open_br(chan, &cbr, NULL, 0, hn_chan_callback, rxr);
if (error) {
if_printf(sc->hn_ifp, "open chan%u failed: %d\n",
vmbus_chan_id(chan), error);
@@ -3328,8 +3350,10 @@ hn_synth_alloc_subchans(struct hn_softc *sc, int *nsubch)
*nsubch = 0;
return (0);
}
- if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n",
- rxr_cnt, nchan);
+ if (bootverbose) {
+ if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n",
+ rxr_cnt, nchan);
+ }
if (nchan > rxr_cnt)
nchan = rxr_cnt;
@@ -3338,7 +3362,7 @@ hn_synth_alloc_subchans(struct hn_softc *sc, int *nsubch)
*nsubch = 0;
return (0);
}
-
+
/*
* Allocate sub-channels from NVS.
*/
diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c
index 9365db3..cfc7121 100644
--- a/sys/dev/hyperv/vmbus/vmbus_chan.c
+++ b/sys/dev/hyperv/vmbus/vmbus_chan.c
@@ -196,13 +196,45 @@ int
vmbus_chan_open(struct vmbus_channel *chan, int txbr_size, int rxbr_size,
const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg)
{
+ struct vmbus_chan_br cbr;
+ int error;
+
+ /*
+ * Allocate the TX+RX bufrings.
+ */
+ KASSERT(chan->ch_bufring == NULL, ("bufrings are allocated"));
+ chan->ch_bufring = hyperv_dmamem_alloc(bus_get_dma_tag(chan->ch_dev),
+ PAGE_SIZE, 0, txbr_size + rxbr_size, &chan->ch_bufring_dma,
+ BUS_DMA_WAITOK);
+ if (chan->ch_bufring == NULL) {
+ device_printf(chan->ch_dev, "bufring allocation failed\n");
+ return (ENOMEM);
+ }
+
+ cbr.cbr = chan->ch_bufring;
+ cbr.cbr_paddr = chan->ch_bufring_dma.hv_paddr;
+ cbr.cbr_txsz = txbr_size;
+ cbr.cbr_rxsz = rxbr_size;
+
+ error = vmbus_chan_open_br(chan, &cbr, udata, udlen, cb, cbarg);
+ if (error) {
+ hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring);
+ chan->ch_bufring = NULL;
+ }
+ return (error);
+}
+
+int
+vmbus_chan_open_br(struct vmbus_channel *chan, const struct vmbus_chan_br *cbr,
+ const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg)
+{
struct vmbus_softc *sc = chan->ch_vmbus;
const struct vmbus_chanmsg_chopen_resp *resp;
const struct vmbus_message *msg;
struct vmbus_chanmsg_chopen *req;
struct vmbus_msghc *mh;
uint32_t status;
- int error;
+ int error, txbr_size, rxbr_size;
uint8_t *br;
if (udlen > VMBUS_CHANMSG_CHOPEN_UDATA_SIZE) {
@@ -210,10 +242,21 @@ vmbus_chan_open(struct vmbus_channel *chan, int txbr_size, int rxbr_size,
"invalid udata len %d for chan%u\n", udlen, chan->ch_id);
return EINVAL;
}
+
+ br = cbr->cbr;
+ txbr_size = cbr->cbr_txsz;
+ rxbr_size = cbr->cbr_rxsz;
KASSERT((txbr_size & PAGE_MASK) == 0,
("send bufring size is not multiple page"));
KASSERT((rxbr_size & PAGE_MASK) == 0,
("recv bufring size is not multiple page"));
+ KASSERT((cbr->cbr_paddr & PAGE_MASK) == 0,
+ ("bufring is not page aligned"));
+
+ /*
+ * Zero out the TX/RX bufrings, in case that they were used before.
+ */
+ memset(br, 0, txbr_size + rxbr_size);
if (atomic_testandset_int(&chan->ch_stflags,
VMBUS_CHAN_ST_OPENED_SHIFT))
@@ -230,20 +273,6 @@ vmbus_chan_open(struct vmbus_channel *chan, int txbr_size, int rxbr_size,
else
TASK_INIT(&chan->ch_task, 0, vmbus_chan_task_nobatch, chan);
- /*
- * Allocate the TX+RX bufrings.
- * XXX should use ch_dev dtag
- */
- br = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
- PAGE_SIZE, 0, txbr_size + rxbr_size, &chan->ch_bufring_dma,
- BUS_DMA_WAITOK | BUS_DMA_ZERO);
- if (br == NULL) {
- device_printf(sc->vmbus_dev, "bufring allocation failed\n");
- error = ENOMEM;
- goto failed;
- }
- chan->ch_bufring = br;
-
/* TX bufring comes first */
vmbus_txbr_setup(&chan->ch_txbr, br, txbr_size);
/* RX bufring immediately follows TX bufring */
@@ -255,7 +284,7 @@ vmbus_chan_open(struct vmbus_channel *chan, int txbr_size, int rxbr_size,
/*
* Connect the bufrings, both RX and TX, to this channel.
*/
- error = vmbus_chan_gpadl_connect(chan, chan->ch_bufring_dma.hv_paddr,
+ error = vmbus_chan_gpadl_connect(chan, cbr->cbr_paddr,
txbr_size + rxbr_size, &chan->ch_bufring_gpadl);
if (error) {
device_printf(sc->vmbus_dev,
@@ -316,10 +345,6 @@ failed:
vmbus_chan_gpadl_disconnect(chan, chan->ch_bufring_gpadl);
chan->ch_bufring_gpadl = 0;
}
- if (chan->ch_bufring != NULL) {
- hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring);
- chan->ch_bufring = NULL;
- }
atomic_clear_int(&chan->ch_stflags, VMBUS_CHAN_ST_OPENED);
return error;
}
OpenPOWER on IntegriCloud