Author: sephe
Date: Fri Nov 11 03:09:15 2016
New Revision: 308495
URL: https://svnweb.freebsd.org/changeset/base/308495

Log:
  MFC 307838,307839
  
  307838
      hyperv/hn: Move chimney buffer index and size to txdesc.
  
      All RNDIS control messages have used SG list for a while.  This makes
      the send context suitable for further refactoring.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8308
  
  307839
      hyperv/hn: Fix chimney sending buffer leakage upon NVS sending failure.
  
      This will not happen in real world, since TX consumption of the vmbus
      TX bufring is limitted.  Better safe than sorry.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8309

Modified:
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c        Fri Nov 11 03:03:54 
2016        (r308494)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c        Fri Nov 11 03:09:15 
2016        (r308495)
@@ -116,7 +116,7 @@ hn_nvs_xact_execute(struct hn_softc *sc,
        /*
         * 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
        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)
 {

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h        Fri Nov 11 03:03:54 
2016        (r308494)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h        Fri Nov 11 03:09:15 
2016        (r308495)
@@ -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__ */
 

Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Fri Nov 11 
03:03:54 2016        (r308494)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Fri Nov 11 
03:09:15 2016        (r308495)
@@ -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
 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, i
 }
 #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 
        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 
        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, st
        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, str
        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 
        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 
         */
        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 
                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, i
                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.

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c   Fri Nov 11 03:03:54 
2016        (r308494)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c   Fri Nov 11 03:09:15 
2016        (r308495)
@@ -586,8 +586,7 @@ hn_rndis_xact_exec1(struct hn_softc *sc,
         * 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);

Modified: stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/if_hnvar.h  Fri Nov 11 03:03:54 2016        
(r308494)
+++ stable/10/sys/dev/hyperv/netvsc/if_hnvar.h  Fri Nov 11 03:09:15 2016        
(r308495)
@@ -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);
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to