svn commit: r308167 - head/sys/dev/hyperv/netvsc

Sepherosa Ziehau sephe at FreeBSD.org
Tue Nov 1 08:20:34 UTC 2016


Author: sephe
Date: Tue Nov  1 08:20:33 2016
New Revision: 308167
URL: https://svnweb.freebsd.org/changeset/base/308167

Log:
  hyperv/hn: Directly fill chimney sending buffer for small packets.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D8394

Modified:
  head/sys/dev/hyperv/netvsc/if_hn.c

Modified: head/sys/dev/hyperv/netvsc/if_hn.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hn.c	Tue Nov  1 07:41:26 2016	(r308166)
+++ head/sys/dev/hyperv/netvsc/if_hn.c	Tue Nov  1 08:20:33 2016	(r308167)
@@ -1394,15 +1394,28 @@ hn_encap(struct hn_tx_ring *txr, struct 
 	struct mbuf *m_head = *m_head0;
 	struct rndis_packet_msg *pkt;
 	uint32_t *pi_data;
+	void *chim = NULL;
 	int pktlen;
 
-	/*
-	 * extension points to the area reserved for the
-	 * rndis_filter_packet, which is placed just after
-	 * the netvsc_packet (and rppi struct, if present;
-	 * length is updated later).
-	 */
 	pkt = txd->rndis_pkt;
+	if (m_head->m_pkthdr.len + HN_RNDIS_PKT_LEN < txr->hn_chim_size) {
+		/*
+		 * This packet is small enough to fit into a chimney sending
+		 * buffer.  Try allocating one chimney sending buffer now.
+		 */
+		txr->hn_tx_chimney_tried++;
+		txd->chim_index = hn_chim_alloc(txr->hn_sc);
+		if (txd->chim_index != HN_NVS_CHIM_IDX_INVALID) {
+			chim = txr->hn_sc->hn_chim +
+			    (txd->chim_index * txr->hn_sc->hn_chim_szmax);
+			/*
+			 * Directly fill the chimney sending buffer w/ the
+			 * RNDIS packet message.
+			 */
+			pkt = chim;
+		}
+	}
+
 	pkt->rm_type = REMOTE_NDIS_PACKET_MSG;
 	pkt->rm_len = sizeof(*pkt) + m_head->m_pkthdr.len;
 	pkt->rm_dataoffset = sizeof(*pkt);
@@ -1475,26 +1488,25 @@ hn_encap(struct hn_tx_ring *txr, struct 
 	pkt->rm_pktinfooffset = hn_rndis_pktmsg_offset(pkt->rm_pktinfooffset);
 
 	/*
-	 * Chimney send, if the packet could fit into one chimney buffer.
+	 * Fast path: Chimney sending.
 	 */
-	if (pkt->rm_len < txr->hn_chim_size) {
-		txr->hn_tx_chimney_tried++;
-		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 +
-			    (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);
-
-			txd->chim_size = pkt->rm_len;
-			txr->hn_gpa_cnt = 0;
-			txr->hn_tx_chimney++;
-			txr->hn_sendpkt = hn_txpkt_chim;
-			goto done;
-		}
-	}
+	if (chim != NULL) {
+		KASSERT(txd->chim_index != HN_NVS_CHIM_IDX_INVALID,
+		    ("chimney buffer is not used"));
+		KASSERT(pkt == chim, ("RNDIS pkt not in chimney buffer"));
+
+		m_copydata(m_head, 0, m_head->m_pkthdr.len,
+		    ((uint8_t *)chim) + pktlen);
+
+		txd->chim_size = pkt->rm_len;
+		txr->hn_gpa_cnt = 0;
+		txr->hn_tx_chimney++;
+		txr->hn_sendpkt = hn_txpkt_chim;
+		goto done;
+	}
+	KASSERT(txd->chim_index == HN_NVS_CHIM_IDX_INVALID,
+	    ("chimney buffer is used"));
+	KASSERT(pkt == txd->rndis_pkt, ("RNDIS pkt not in txdesc"));
 
 	error = hn_txdesc_dmamap_load(txr, txd, &m_head, segs, &nsegs);
 	if (error) {


More information about the svn-src-head mailing list