summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/hyperv/netvsc/hv_net_vsc.c30
-rw-r--r--sys/dev/hyperv/netvsc/hv_net_vsc.h11
-rw-r--r--sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c116
-rw-r--r--sys/dev/hyperv/netvsc/hv_rndis_filter.c5
-rw-r--r--sys/dev/hyperv/netvsc/if_hnvar.h28
5 files changed, 98 insertions, 92 deletions
diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c
index 557c15b..40cc56a 100644
--- a/sys/dev/hyperv/netvsc/hv_net_vsc.c
+++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c
@@ -116,7 +116,7 @@ hn_nvs_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact,
/*
* Execute the xact setup by the caller.
*/
- hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
+ hn_send_ctx_init(&sndc, hn_nvs_sent_xact, xact);
vmbus_xact_activate(xact);
error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC,
@@ -668,34 +668,6 @@ hn_chim_free(struct hn_softc *sc, uint32_t chim_idx)
atomic_clear_long(&sc->hn_chim_bmap[idx], mask);
}
-/*
- * Net VSC on send
- * Sends a packet on the specified Hyper-V device.
- * Returns 0 on success, non-zero on failure.
- */
-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)
-{
- struct hn_nvs_rndis rndis;
- int ret;
-
- rndis.nvs_type = HN_NVS_TYPE_RNDIS;
- rndis.nvs_rndis_mtype = rndis_mtype;
- rndis.nvs_chim_idx = sndc->hn_chim_idx;
- rndis.nvs_chim_sz = sndc->hn_chim_sz;
-
- if (gpa_cnt) {
- ret = hn_nvs_send_sglist(chan, gpa, gpa_cnt,
- &rndis, sizeof(rndis), sndc);
- } else {
- ret = hn_nvs_send(chan, VMBUS_CHANPKT_FLAG_RC,
- &rndis, sizeof(rndis), sndc);
- }
-
- return (ret);
-}
-
int
hn_nvs_alloc_subchans(struct hn_softc *sc, int *nsubch0)
{
diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h
index 91a5eec..7d4f7bc 100644
--- a/sys/dev/hyperv/netvsc/hv_net_vsc.h
+++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h
@@ -104,8 +104,8 @@ struct vmbus_channel;
#define HN_XACT_REQ_SIZE (HN_XACT_REQ_PGCNT * PAGE_SIZE)
#define HN_XACT_RESP_SIZE (HN_XACT_RESP_PGCNT * PAGE_SIZE)
-#ifndef HN_USE_TXDESC_BUFRING
struct hn_txdesc;
+#ifndef HN_USE_TXDESC_BUFRING
SLIST_HEAD(hn_txdesc_list, hn_txdesc);
#else
struct buf_ring;
@@ -179,6 +179,7 @@ struct hn_tx_ring {
bus_dma_tag_t hn_tx_data_dtag;
uint64_t hn_csum_assist;
+ int (*hn_sendpkt)(struct hn_tx_ring *, struct hn_txdesc *);
int hn_suspended;
int hn_gpa_cnt;
struct vmbus_gpa hn_gpa[NETVSC_PACKET_MAXPAGE];
@@ -277,13 +278,5 @@ struct hn_softc {
#define HN_LINK_FLAG_LINKUP 0x0001
#define HN_LINK_FLAG_NETCHG 0x0002
-/*
- * Externs
- */
-struct hn_send_ctx;
-
-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);
-
#endif /* __HV_NET_VSC_H__ */
diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
index 50173f4..8bdf6e5 100644
--- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -171,6 +171,8 @@ struct hn_txdesc {
int refs;
uint32_t flags; /* HN_TXD_FLAG_ */
struct hn_send_ctx send_ctx;
+ uint32_t chim_index;
+ int chim_size;
bus_dmamap_t data_dmap;
@@ -365,6 +367,8 @@ static void hn_tx_resume(struct hn_softc *, int);
static void hn_tx_ring_qflush(struct hn_tx_ring *);
static int netvsc_detach(device_t dev);
static void hn_link_status(struct hn_softc *);
+static int hn_sendpkt_rndis_sglist(struct hn_tx_ring *, struct hn_txdesc *);
+static int hn_sendpkt_rndis_chim(struct hn_tx_ring *, struct hn_txdesc *);
static void hn_nvs_handle_notify(struct hn_softc *sc,
const struct vmbus_chanpkt_hdr *pkt);
@@ -401,6 +405,57 @@ hn_set_lro_lenlim(struct hn_softc *sc, int lenlim)
}
#endif
+static __inline int
+hn_nvs_send_rndis_sglist1(struct vmbus_channel *chan, uint32_t rndis_mtype,
+ struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt)
+{
+ struct hn_nvs_rndis rndis;
+
+ rndis.nvs_type = HN_NVS_TYPE_RNDIS;
+ rndis.nvs_rndis_mtype = rndis_mtype;
+ rndis.nvs_chim_idx = HN_NVS_CHIM_IDX_INVALID;
+ rndis.nvs_chim_sz = 0;
+
+ return (hn_nvs_send_sglist(chan, gpa, gpa_cnt,
+ &rndis, sizeof(rndis), sndc));
+}
+
+int
+hn_nvs_send_rndis_ctrl(struct vmbus_channel *chan,
+ struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt)
+{
+
+ return hn_nvs_send_rndis_sglist1(chan, HN_NVS_RNDIS_MTYPE_CTRL,
+ sndc, gpa, gpa_cnt);
+}
+
+static int
+hn_sendpkt_rndis_sglist(struct hn_tx_ring *txr, struct hn_txdesc *txd)
+{
+
+ KASSERT(txd->chim_index == HN_NVS_CHIM_IDX_INVALID &&
+ txd->chim_size == 0, ("invalid rndis sglist txd"));
+ return (hn_nvs_send_rndis_sglist1(txr->hn_chan, HN_NVS_RNDIS_MTYPE_DATA,
+ &txd->send_ctx, txr->hn_gpa, txr->hn_gpa_cnt));
+}
+
+static int
+hn_sendpkt_rndis_chim(struct hn_tx_ring *txr, struct hn_txdesc *txd)
+{
+ struct hn_nvs_rndis rndis;
+
+ KASSERT(txd->chim_index != HN_NVS_CHIM_IDX_INVALID &&
+ txd->chim_size > 0, ("invalid rndis chim txd"));
+
+ rndis.nvs_type = HN_NVS_TYPE_RNDIS;
+ rndis.nvs_rndis_mtype = HN_NVS_RNDIS_MTYPE_DATA;
+ rndis.nvs_chim_idx = txd->chim_index;
+ rndis.nvs_chim_sz = txd->chim_size;
+
+ return (hn_nvs_send(txr->hn_chan, VMBUS_CHANPKT_FLAG_RC,
+ &rndis, sizeof(rndis), &txd->send_ctx));
+}
+
static int
hn_get_txswq_depth(const struct hn_tx_ring *txr)
{
@@ -912,6 +967,8 @@ hn_txdesc_dmamap_load(struct hn_tx_ring *txr, struct hn_txdesc *txd,
struct mbuf *m = *m_head;
int error;
+ KASSERT(txd->chim_index == HN_NVS_CHIM_IDX_INVALID, ("txd uses chim"));
+
error = bus_dmamap_load_mbuf_sg(txr->hn_tx_data_dtag, txd->data_dmap,
m, segs, nsegs, BUS_DMA_NOWAIT);
if (error == EFBIG) {
@@ -935,19 +992,6 @@ hn_txdesc_dmamap_load(struct hn_tx_ring *txr, struct hn_txdesc *txd,
return error;
}
-static __inline void
-hn_txdesc_dmamap_unload(struct hn_tx_ring *txr, struct hn_txdesc *txd)
-{
-
- if (txd->flags & HN_TXD_FLAG_DMAMAP) {
- bus_dmamap_sync(txr->hn_tx_data_dtag,
- txd->data_dmap, BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(txr->hn_tx_data_dtag,
- txd->data_dmap);
- txd->flags &= ~HN_TXD_FLAG_DMAMAP;
- }
-}
-
static __inline int
hn_txdesc_put(struct hn_tx_ring *txr, struct hn_txdesc *txd)
{
@@ -959,14 +1003,25 @@ hn_txdesc_put(struct hn_tx_ring *txr, struct hn_txdesc *txd)
if (atomic_fetchadd_int(&txd->refs, -1) != 1)
return 0;
- hn_txdesc_dmamap_unload(txr, txd);
+ if (txd->chim_index != HN_NVS_CHIM_IDX_INVALID) {
+ KASSERT((txd->flags & HN_TXD_FLAG_DMAMAP) == 0,
+ ("chim txd uses dmamap"));
+ hn_chim_free(txr->hn_sc, txd->chim_index);
+ txd->chim_index = HN_NVS_CHIM_IDX_INVALID;
+ } else if (txd->flags & HN_TXD_FLAG_DMAMAP) {
+ bus_dmamap_sync(txr->hn_tx_data_dtag,
+ txd->data_dmap, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(txr->hn_tx_data_dtag,
+ txd->data_dmap);
+ txd->flags &= ~HN_TXD_FLAG_DMAMAP;
+ }
+
if (txd->m != NULL) {
m_freem(txd->m);
txd->m = NULL;
}
txd->flags |= HN_TXD_FLAG_ONLIST;
-
#ifndef HN_USE_TXDESC_BUFRING
mtx_lock_spin(&txr->hn_txlist_spin);
KASSERT(txr->hn_txdesc_avail >= 0 &&
@@ -1007,7 +1062,9 @@ hn_txdesc_get(struct hn_tx_ring *txr)
atomic_subtract_int(&txr->hn_txdesc_avail, 1);
#endif
KASSERT(txd->m == NULL && txd->refs == 0 &&
- (txd->flags & HN_TXD_FLAG_ONLIST), ("invalid txd"));
+ txd->chim_index == HN_NVS_CHIM_IDX_INVALID &&
+ (txd->flags & HN_TXD_FLAG_ONLIST) &&
+ (txd->flags & HN_TXD_FLAG_DMAMAP) == 0, ("invalid txd"));
txd->flags &= ~HN_TXD_FLAG_ONLIST;
txd->refs = 1;
}
@@ -1054,9 +1111,6 @@ hn_tx_done(struct hn_send_ctx *sndc, struct hn_softc *sc,
struct hn_txdesc *txd = sndc->hn_cbarg;
struct hn_tx_ring *txr;
- if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
- hn_chim_free(sc, sndc->hn_chim_idx);
-
txr = txd->txr;
KASSERT(txr->hn_chan == chan,
("channel mismatch, on chan%u, should be chan%u",
@@ -1118,9 +1172,8 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
int error, nsegs, i;
struct mbuf *m_head = *m_head0;
struct rndis_packet_msg *pkt;
- uint32_t send_buf_section_idx;
- int send_buf_section_size, pktlen;
uint32_t *pi_data;
+ int pktlen;
/*
* extension points to the area reserved for the
@@ -1233,18 +1286,19 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
*/
if (pkt->rm_len < txr->hn_chim_size) {
txr->hn_tx_chimney_tried++;
- send_buf_section_idx = hn_chim_alloc(txr->hn_sc);
- if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) {
+ txd->chim_index = hn_chim_alloc(txr->hn_sc);
+ if (txd->chim_index != HN_NVS_CHIM_IDX_INVALID) {
uint8_t *dest = txr->hn_sc->hn_chim +
- (send_buf_section_idx * txr->hn_sc->hn_chim_szmax);
+ (txd->chim_index * txr->hn_sc->hn_chim_szmax);
memcpy(dest, pkt, pktlen);
dest += pktlen;
m_copydata(m_head, 0, m_head->m_pkthdr.len, dest);
- send_buf_section_size = pkt->rm_len;
+ txd->chim_size = pkt->rm_len;
txr->hn_gpa_cnt = 0;
txr->hn_tx_chimney++;
+ txr->hn_sendpkt = hn_sendpkt_rndis_chim;
goto done;
}
}
@@ -1289,14 +1343,14 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
gpa->gpa_len = segs[i].ds_len;
}
- send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID;
- send_buf_section_size = 0;
+ txd->chim_index = HN_NVS_CHIM_IDX_INVALID;
+ txd->chim_size = 0;
+ txr->hn_sendpkt = hn_sendpkt_rndis_sglist;
done:
txd->m = m_head;
/* Set the completion routine */
- hn_send_ctx_init(&txd->send_ctx, hn_tx_done, txd,
- send_buf_section_idx, send_buf_section_size);
+ hn_send_ctx_init(&txd->send_ctx, hn_tx_done, txd);
return 0;
}
@@ -1316,8 +1370,7 @@ again:
* Make sure that txd is not freed before ETHER_BPF_MTAP.
*/
hn_txdesc_hold(txd);
- error = hv_nv_on_send(txr->hn_chan, HN_NVS_RNDIS_MTYPE_DATA,
- &txd->send_ctx, txr->hn_gpa, txr->hn_gpa_cnt);
+ error = txr->hn_sendpkt(txr, txd);
if (!error) {
ETHER_BPF_MTAP(ifp, txd->m);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
@@ -2786,6 +2839,7 @@ hn_create_tx_ring(struct hn_softc *sc, int id)
struct hn_txdesc *txd = &txr->hn_txdesc[i];
txd->txr = txr;
+ txd->chim_index = HN_NVS_CHIM_IDX_INVALID;
/*
* Allocate and load RNDIS packet message.
diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c
index dd9ba03..ce6c18f 100644
--- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c
+++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c
@@ -586,8 +586,7 @@ hn_rndis_xact_exec1(struct hn_softc *sc, struct vmbus_xact *xact, size_t reqlen,
* message.
*/
vmbus_xact_activate(xact);
- error = hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL, sndc,
- gpa, gpa_cnt);
+ error = hn_nvs_send_rndis_ctrl(sc->hn_prichan, sndc, gpa, gpa_cnt);
if (error) {
vmbus_xact_deactivate(xact);
if_printf(sc->hn_ifp, "RNDIS ctrl send failed: %d\n", error);
@@ -1166,7 +1165,7 @@ hn_rndis_halt(struct hn_softc *sc)
halt->rm_rid = hn_rndis_rid(sc);
/* No RNDIS completion; rely on NVS message send completion */
- hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
+ hn_send_ctx_init(&sndc, hn_nvs_sent_xact, xact);
hn_rndis_xact_exec1(sc, xact, sizeof(*halt), &sndc, &comp_len);
vmbus_xact_put(xact);
diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h
index d25d5f2..9e73a2d 100644
--- a/sys/dev/hyperv/netvsc/if_hnvar.h
+++ b/sys/dev/hyperv/netvsc/if_hnvar.h
@@ -46,8 +46,6 @@ typedef void (*hn_sent_callback_t)
struct hn_send_ctx {
hn_sent_callback_t hn_cb;
void *hn_cbarg;
- uint32_t hn_chim_idx;
- int hn_chim_sz;
};
struct rndis_hash_info;
@@ -66,31 +64,18 @@ struct hn_recvinfo {
uint32_t hash_value;
};
-#define HN_SEND_CTX_INITIALIZER(cb, cbarg) \
-{ \
- .hn_cb = cb, \
- .hn_cbarg = cbarg, \
- .hn_chim_idx = HN_NVS_CHIM_IDX_INVALID, \
- .hn_chim_sz = 0 \
+#define HN_SEND_CTX_INITIALIZER(cb, cbarg) \
+{ \
+ .hn_cb = cb, \
+ .hn_cbarg = cbarg \
}
static __inline void
-hn_send_ctx_init(struct hn_send_ctx *sndc, hn_sent_callback_t cb,
- void *cbarg, uint32_t chim_idx, int chim_sz)
+hn_send_ctx_init(struct hn_send_ctx *sndc, hn_sent_callback_t cb, void *cbarg)
{
sndc->hn_cb = cb;
sndc->hn_cbarg = cbarg;
- sndc->hn_chim_idx = chim_idx;
- sndc->hn_chim_sz = chim_sz;
-}
-
-static __inline void
-hn_send_ctx_init_simple(struct hn_send_ctx *sndc, hn_sent_callback_t cb,
- void *cbarg)
-{
-
- hn_send_ctx_init(sndc, cb, cbarg, HN_NVS_CHIM_IDX_INVALID, 0);
}
static __inline int
@@ -134,6 +119,9 @@ void hn_nvs_detach(struct hn_softc *sc);
int hn_nvs_alloc_subchans(struct hn_softc *sc, int *nsubch);
void hn_nvs_sent_xact(struct hn_send_ctx *sndc, struct hn_softc *sc,
struct vmbus_channel *chan, const void *data, int dlen);
+int hn_nvs_send_rndis_ctrl(struct vmbus_channel *chan,
+ struct hn_send_ctx *sndc, struct vmbus_gpa *gpa,
+ int gpa_cnt);
int hn_rxpkt(struct hn_rx_ring *rxr, const void *data, int dlen,
const struct hn_recvinfo *info);
OpenPOWER on IntegriCloud