diff options
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_net_vsc.c | 30 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_net_vsc.h | 11 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 116 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_rndis_filter.c | 5 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/if_hnvar.h | 28 |
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); |