Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 May 2017 21:34:40 +0000 (UTC)
From:      David C Somayajulu <davidcs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r318382 - in head/sys: dev/qlnx/qlnxe modules/qlnx/qlnxe
Message-ID:  <201705162134.v4GLYe8d043042@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: davidcs
Date: Tue May 16 21:34:40 2017
New Revision: 318382
URL: https://svnweb.freebsd.org/changeset/base/318382

Log:
  1. Move Rx Processing to fp_taskqueue(). With this CPU utilization for processing interrupts drops to around 1% for 100G and under 1% for other speeds.
  2. Use sysctls for TRACE_LRO_CNT and TRACE_TSO_PKT_LEN
  3. remove unused mtx tx_lock
  4. bind taskqueue kernel thread to the appropriate cpu core
  5. when tx_ring is full, stop further transmits till at least 1/16th of the Tx Ring is empty. In our case 1K entries. Also if there are rx_pkts to process, put the taskqueue thread to sleep for 100ms, before enabling interrupts.
  6. Use rx_pkt_threshold of 128.
  
  MFC after:3 days

Modified:
  head/sys/dev/qlnx/qlnxe/qlnx_def.h
  head/sys/dev/qlnx/qlnxe/qlnx_os.c
  head/sys/dev/qlnx/qlnxe/qlnx_os.h
  head/sys/modules/qlnx/qlnxe/Makefile

Modified: head/sys/dev/qlnx/qlnxe/qlnx_def.h
==============================================================================
--- head/sys/dev/qlnx/qlnxe/qlnx_def.h	Tue May 16 19:54:47 2017	(r318381)
+++ head/sys/dev/qlnx/qlnxe/qlnx_def.h	Tue May 16 21:34:40 2017	(r318382)
@@ -191,6 +191,7 @@ struct qlnx_fastpath {
 	struct mtx		tx_mtx;
 	char			tx_mtx_name[32];
 	struct buf_ring		*tx_br;
+	uint32_t		tx_ring_full;
 
 	struct task		fp_task;
 	struct taskqueue	*fp_taskqueue;
@@ -364,6 +365,8 @@ struct qlnx_host {
 	/* debug */
 
 	uint32_t                dbg_level;
+	uint32_t                dbg_trace_lro_cnt;
+	uint32_t                dbg_trace_tso_pkt_len;
 	uint32_t                dp_level;
 	uint32_t                dp_module;
 
@@ -386,7 +389,6 @@ struct qlnx_host {
 
 	/* tx related */
 	struct callout		tx_callout;
-	struct mtx		tx_lock;
 	uint32_t		txr_idx;
 
 	/* rx related */

Modified: head/sys/dev/qlnx/qlnxe/qlnx_os.c
==============================================================================
--- head/sys/dev/qlnx/qlnxe/qlnx_os.c	Tue May 16 19:54:47 2017	(r318381)
+++ head/sys/dev/qlnx/qlnxe/qlnx_os.c	Tue May 16 21:34:40 2017	(r318382)
@@ -382,16 +382,77 @@ qlnx_fp_taskqueue(void *context, int pen
         struct ifnet		*ifp;
         struct mbuf		*mp;
         int			ret;
+	int			lro_enable, tc;
+	int			rx_int = 0, total_rx_count = 0;
+	struct thread		*cthread;
 
         fp = context;
 
         if (fp == NULL)
                 return;
 
+	cthread = curthread;
+
+	thread_lock(cthread);
+
+	if (!sched_is_bound(cthread))
+		sched_bind(cthread, fp->rss_id);
+
+	thread_unlock(cthread);
+
         ha = (qlnx_host_t *)fp->edev;
 
         ifp = ha->ifp;
 
+	lro_enable = ha->ifp->if_capenable & IFCAP_LRO;
+
+	rx_int = qlnx_rx_int(ha, fp, ha->rx_pkt_threshold, lro_enable);
+
+	if (rx_int) {
+		fp->rx_pkts += rx_int;
+		total_rx_count += rx_int;
+	}
+
+#ifdef QLNX_SOFT_LRO
+	{
+		struct lro_ctrl *lro;
+
+		lro = &fp->rxq->lro;
+
+		if (lro_enable && total_rx_count) {
+
+#if (__FreeBSD_version >= 1100101) || (defined QLNX_QSORT_LRO)
+
+			if (ha->dbg_trace_lro_cnt) {
+				if (lro->lro_mbuf_count & ~1023)
+					fp->lro_cnt_1024++;
+				else if (lro->lro_mbuf_count & ~511)
+					fp->lro_cnt_512++;
+				else if (lro->lro_mbuf_count & ~255)
+					fp->lro_cnt_256++;
+				else if (lro->lro_mbuf_count & ~127)
+					fp->lro_cnt_128++;
+				else if (lro->lro_mbuf_count & ~63)
+					fp->lro_cnt_64++;
+			}
+			tcp_lro_flush_all(lro);
+
+#else
+			struct lro_entry *queued;
+
+			while ((!SLIST_EMPTY(&lro->lro_active))) {
+				queued = SLIST_FIRST(&lro->lro_active);
+				SLIST_REMOVE_HEAD(&lro->lro_active, next);
+				tcp_lro_flush(lro, queued);
+			}
+#endif /* #if (__FreeBSD_version >= 1100101) || (defined QLNX_QSORT_LRO) */
+		}
+	}
+#endif /* #ifdef QLNX_SOFT_LRO */
+
+	ecore_sb_update_sb_idx(fp->sb_info);
+	rmb();
+
         mtx_lock(&fp->tx_mtx);
 
         if (((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
@@ -401,13 +462,19 @@ qlnx_fp_taskqueue(void *context, int pen
                 goto qlnx_fp_taskqueue_exit;
         }
 
-        (void)qlnx_tx_int(ha, fp, fp->txq[0]);
+	for (tc = 0; tc < ha->num_tc; tc++) {
+		(void)qlnx_tx_int(ha, fp, fp->txq[tc]);
+	}
 
         mp = drbr_peek(ifp, fp->tx_br);
 
         while (mp != NULL) {
 
-                ret = qlnx_send(ha, fp, &mp);
+		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+			ret = qlnx_send(ha, fp, &mp);
+		} else {
+			ret = -1;
+		}
 
                 if (ret) {
 
@@ -428,14 +495,28 @@ qlnx_fp_taskqueue(void *context, int pen
                         fp->tx_pkts_processed++;
                 }
 
+		if (fp->tx_ring_full)
+			break;
+
                 mp = drbr_peek(ifp, fp->tx_br);
         }
 
-        (void)qlnx_tx_int(ha, fp, fp->txq[0]);
+	for (tc = 0; tc < ha->num_tc; tc++) {
+		(void)qlnx_tx_int(ha, fp, fp->txq[tc]);
+	}
 
         mtx_unlock(&fp->tx_mtx);
 
 qlnx_fp_taskqueue_exit:
+	if (rx_int) {
+		if (fp->fp_taskqueue != NULL)
+			taskqueue_enqueue(fp->fp_taskqueue, &fp->fp_task);
+	} else {
+		if (fp->tx_ring_full) {
+			qlnx_mdelay(__func__, 100);
+		}
+		ecore_sb_ack(fp->sb_info, IGU_INT_ENABLE, 1);
+	}
 
         QL_DPRINT2(ha, (ha->pci_dev, "%s: exit ret = %d\n", __func__, ret));
         return;
@@ -504,7 +585,9 @@ qlnx_drain_fp_taskqueues(qlnx_host_t *ha
                 fp = &ha->fp_array[i];
 
 		if (fp->fp_taskqueue != NULL) {
+			QLNX_UNLOCK(ha);
 			taskqueue_drain(fp->fp_taskqueue, &fp->fp_task);
+			QLNX_LOCK(ha);
 		}
 	}
 	return;
@@ -540,7 +623,6 @@ qlnx_pci_attach(device_t dev)
         ha->pci_dev = dev;
 
 	mtx_init(&ha->hw_lock, "qlnx_hw_lock", MTX_NETWORK_LOCK, MTX_DEF);
-        mtx_init(&ha->tx_lock, "qlnx_tx_lock", MTX_NETWORK_LOCK, MTX_DEF);
 
         ha->flags.lock_init = 1;
 
@@ -944,7 +1026,6 @@ qlnx_release(qlnx_host_t *ha)
                 pci_release_msi(dev);
 
         if (ha->flags.lock_init) {
-                mtx_destroy(&ha->tx_lock);
                 mtx_destroy(&ha->hw_lock);
         }
 
@@ -1226,7 +1307,6 @@ qlnx_add_fp_stats_sysctls(qlnx_host_t *h
 			CTLFLAG_RD, &ha->fp_array[i].err_tx_cons_idx_conflict,
 			"err_tx_cons_idx_conflict");
 
-#ifdef QLNX_TRACE_LRO_CNT
 		SYSCTL_ADD_QUAD(ctx, node_children,
 			OID_AUTO, "lro_cnt_64",
 			CTLFLAG_RD, &ha->fp_array[i].lro_cnt_64,
@@ -1251,7 +1331,6 @@ qlnx_add_fp_stats_sysctls(qlnx_host_t *h
 			OID_AUTO, "lro_cnt_1024",
 			CTLFLAG_RD, &ha->fp_array[i].lro_cnt_1024,
 			"lro_cnt_1024");
-#endif /* #ifdef QLNX_TRACE_LRO_CNT */
 
 		/* Rx Related */
 
@@ -1710,6 +1789,18 @@ qlnx_add_sysctls(qlnx_host_t *ha)
                 OID_AUTO, "dp_level", CTLFLAG_RW,
                 &ha->dp_level, ha->dp_level, "DP Level");
 
+        ha->dbg_trace_lro_cnt = 0;
+        SYSCTL_ADD_UINT(ctx, children,
+                OID_AUTO, "dbg_trace_lro_cnt", CTLFLAG_RW,
+                &ha->dbg_trace_lro_cnt, ha->dbg_trace_lro_cnt,
+		"Trace LRO Counts");
+
+        ha->dbg_trace_tso_pkt_len = 0;
+        SYSCTL_ADD_UINT(ctx, children,
+                OID_AUTO, "dbg_trace_tso_pkt_len", CTLFLAG_RW,
+                &ha->dbg_trace_tso_pkt_len, ha->dbg_trace_tso_pkt_len,
+		"Trace TSO packet lengths");
+
         ha->dp_module = 0;
         SYSCTL_ADD_UINT(ctx, children,
                 OID_AUTO, "dp_module", CTLFLAG_RW,
@@ -1755,7 +1846,7 @@ qlnx_add_sysctls(qlnx_host_t *ha)
                 &ha->tx_coalesce_usecs, ha->tx_coalesce_usecs,
 		"tx_coalesce_usecs");
 
-	ha->rx_pkt_threshold = 32;
+	ha->rx_pkt_threshold = 128;
         SYSCTL_ADD_UINT(ctx, children,
                 OID_AUTO, "rx_pkt_threshold", CTLFLAG_RW,
                 &ha->rx_pkt_threshold, ha->rx_pkt_threshold,
@@ -2162,7 +2253,7 @@ qlnx_ioctl(struct ifnet *ifp, u_long cmd
 			ifp->if_mtu = ifr->ifr_mtu;
 			ha->max_frame_size =
 				ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
-			if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 				qlnx_init_locked(ha);
 			}
 
@@ -2178,7 +2269,7 @@ qlnx_ioctl(struct ifnet *ifp, u_long cmd
 		QLNX_LOCK(ha);
 
 		if (ifp->if_flags & IFF_UP) {
-			if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 				if ((ifp->if_flags ^ ha->if_flags) &
 					IFF_PROMISC) {
 					ret = qlnx_set_promisc(ha);
@@ -2712,6 +2803,16 @@ qlnx_send(qlnx_host_t *ha, struct qlnx_f
 	tx_data_bd	= NULL;
 
 	txq = fp->txq[0];
+
+	if (fp->tx_ring_full) {
+		elem_left = ecore_chain_get_elem_left(&txq->tx_pbl);
+
+		if (elem_left < (TX_RING_SIZE >> 4)) 
+			return (-1);
+		else 
+			fp->tx_ring_full = 0;
+	}
+
 	idx = txq->sw_tx_prod;
 
 	map = txq->sw_tx_ring[idx].map;
@@ -2720,20 +2821,18 @@ qlnx_send(qlnx_host_t *ha, struct qlnx_f
 	ret = bus_dmamap_load_mbuf_sg(ha->tx_tag, map, m_head, segs, &nsegs,
 			BUS_DMA_NOWAIT);
 
-#ifdef QLNX_TRACE_TSO_PKT_LEN
-
-	if (!fp->tx_tso_min_pkt_len) {
-		fp->tx_tso_min_pkt_len = m_head->m_pkthdr.len;
-		fp->tx_tso_min_pkt_len = m_head->m_pkthdr.len;
-	} else {
-		if (fp->tx_tso_min_pkt_len > m_head->m_pkthdr.len)
+	if (ha->dbg_trace_tso_pkt_len) {
+		if (!fp->tx_tso_min_pkt_len) {
 			fp->tx_tso_min_pkt_len = m_head->m_pkthdr.len;
-		if (fp->tx_tso_max_pkt_len < m_head->m_pkthdr.len)
-			fp->tx_tso_max_pkt_len = m_head->m_pkthdr.len;
+			fp->tx_tso_min_pkt_len = m_head->m_pkthdr.len;
+		} else {
+			if (fp->tx_tso_min_pkt_len > m_head->m_pkthdr.len)
+				fp->tx_tso_min_pkt_len = m_head->m_pkthdr.len;
+			if (fp->tx_tso_max_pkt_len < m_head->m_pkthdr.len)
+				fp->tx_tso_max_pkt_len = m_head->m_pkthdr.len;
+		}
 	}
 
-#endif /* #ifdef QLNX_TRACE_TSO_PKT_LEN */
-
 	if (m_head->m_pkthdr.csum_flags & CSUM_TSO)
 		offset = qlnx_tcp_offset(ha, m_head);
 
@@ -2815,14 +2914,12 @@ qlnx_send(qlnx_host_t *ha, struct qlnx_f
 
 	QL_ASSERT(ha, (nsegs != 0), ("qlnx_send: empty packet"));
 
-#ifdef QLNX_TRACE_TSO_PKT_LEN
-
-	if (nsegs < QLNX_FP_MAX_SEGS)
-		fp->tx_pkts[(nsegs - 1)]++;
-	else
-		fp->tx_pkts[(QLNX_FP_MAX_SEGS - 1)]++; 
-
-#endif /* #ifdef QLNX_TRACE_TSO_PKT_LEN */
+	if (ha->dbg_trace_tso_pkt_len) {
+		if (nsegs < QLNX_FP_MAX_SEGS)
+			fp->tx_pkts[(nsegs - 1)]++;
+		else
+			fp->tx_pkts[(QLNX_FP_MAX_SEGS - 1)]++; 
+	}
 
 	if ((nsegs + QLNX_TX_ELEM_RESERVE) >
 		(int)(elem_left = ecore_chain_get_elem_left(&txq->tx_pbl))) {
@@ -2843,6 +2940,7 @@ qlnx_send(qlnx_host_t *ha, struct qlnx_f
 				__func__, nsegs, elem_left, fp->rss_id));
 
 			fp->err_tx_nsegs_gt_elem_left++;
+			fp->tx_ring_full = 1;
 			ha->storm_stats_enable = 1;
 			return (ENOBUFS);
 		}
@@ -3051,15 +3149,13 @@ qlnx_send(qlnx_host_t *ha, struct qlnx_f
 
 	first_bd->data.nbds = nbd;
 
-#ifdef QLNX_TRACE_TSO_PKT_LEN
-
-	if (fp->tx_tso_max_nsegs < nsegs)
-		fp->tx_tso_max_nsegs = nsegs;
-
-	if ((nsegs < fp->tx_tso_min_nsegs) || (!fp->tx_tso_min_nsegs))
-		fp->tx_tso_min_nsegs = nsegs;
+	if (ha->dbg_trace_tso_pkt_len) {
+		if (fp->tx_tso_max_nsegs < nsegs)
+			fp->tx_tso_max_nsegs = nsegs;
 
-#endif /* #ifdef QLNX_TRACE_TSO_PKT_LEN */
+		if ((nsegs < fp->tx_tso_min_nsegs) || (!fp->tx_tso_min_nsegs))
+			fp->tx_tso_min_nsegs = nsegs;
+	}
 
 	txq->sw_tx_ring[idx].nsegs = nsegs;
 	txq->sw_tx_prod = (txq->sw_tx_prod + 1) & (TX_RING_SIZE - 1);
@@ -4188,11 +4284,9 @@ qlnx_fp_isr(void *arg)
         qlnx_ivec_t		*ivec = arg;
         qlnx_host_t		*ha;
         struct qlnx_fastpath	*fp = NULL;
-        int			idx, lro_enable, tc;
-        int			rx_int = 0, total_rx_count = 0;
+        int			idx;
 
         ha = ivec->ha;
-        lro_enable = ha->ifp->if_capenable & IFCAP_LRO;
 
         if (ha->state != QLNX_STATE_OPEN) {
                 return;
@@ -4214,73 +4308,8 @@ qlnx_fp_isr(void *arg)
                 ha->err_fp_null++;
         } else {
                 ecore_sb_ack(fp->sb_info, IGU_INT_DISABLE, 0);
-
-                do {
-                        for (tc = 0; tc < ha->num_tc; tc++) {
-                                if (mtx_trylock(&fp->tx_mtx)) {
-                                        qlnx_tx_int(ha, fp, fp->txq[tc]);
-                                        mtx_unlock(&fp->tx_mtx);
-                                }
-                        }
-
-                        rx_int = qlnx_rx_int(ha, fp, ha->rx_pkt_threshold,
-                                        lro_enable);
-
-                        if (rx_int) {
-                                fp->rx_pkts += rx_int;
-				total_rx_count += rx_int;
-			}
-
-                } while (rx_int);
-
-
-#ifdef QLNX_SOFT_LRO
-                {
-                        struct lro_ctrl *lro;
-
-                        lro = &fp->rxq->lro;
-
-                        if (lro_enable && total_rx_count) {
-
-#if (__FreeBSD_version >= 1100101) || (defined QLNX_QSORT_LRO)
-
-#ifdef QLNX_TRACE_LRO_CNT
-				if (lro->lro_mbuf_count & ~1023)
-					fp->lro_cnt_1024++;
-				else if (lro->lro_mbuf_count & ~511)
-					fp->lro_cnt_512++;
-				else if (lro->lro_mbuf_count & ~255)
-					fp->lro_cnt_256++;
-				else if (lro->lro_mbuf_count & ~127)
-					fp->lro_cnt_128++;
-				else if (lro->lro_mbuf_count & ~63)
-					fp->lro_cnt_64++;
-#endif /* #ifdef QLNX_TRACE_LRO_CNT */
-
-                                tcp_lro_flush_all(lro);
-
-#else
-                                struct lro_entry *queued;
-
-                                while ((!SLIST_EMPTY(&lro->lro_active))) {
-                                        queued = SLIST_FIRST(&lro->lro_active);
-                                        SLIST_REMOVE_HEAD(&lro->lro_active, \
-						next);
-                                        tcp_lro_flush(lro, queued);
-                                }
-#endif /* #if (__FreeBSD_version >= 1100101) || (defined QLNX_QSORT_LRO) */
-                        }
-                }
-#endif /* #ifdef QLNX_SOFT_LRO */
-
-                if (fp->fp_taskqueue != NULL)
-                        taskqueue_enqueue(fp->fp_taskqueue, &fp->fp_task);
-
-                ecore_sb_update_sb_idx(fp->sb_info);
-                rmb();
-                ecore_sb_ack(fp->sb_info, IGU_INT_ENABLE, 1);
-
-                return;
+		if (fp->fp_taskqueue != NULL)
+			taskqueue_enqueue(fp->fp_taskqueue, &fp->fp_task);
         }
 
         return;
@@ -5150,6 +5179,8 @@ qlnx_init_fp(qlnx_host_t *ha)
 		snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", qlnx_name_str,
 			rss_id);
 
+		fp->tx_ring_full = 0;
+
 		/* reset all the statistics counters */
 
 		fp->tx_pkts_processed = 0;

Modified: head/sys/dev/qlnx/qlnxe/qlnx_os.h
==============================================================================
--- head/sys/dev/qlnx/qlnxe/qlnx_os.h	Tue May 16 19:54:47 2017	(r318381)
+++ head/sys/dev/qlnx/qlnxe/qlnx_os.h	Tue May 16 21:34:40 2017	(r318382)
@@ -92,6 +92,7 @@
 #include <sys/kthread.h>
 #include <sys/libkern.h>
 #include <sys/smp.h>
+#include <sys/sched.h>
 
 static __inline int qlnx_ms_to_hz(int ms)
 {
@@ -138,10 +139,6 @@ MALLOC_DECLARE(M_QLNXBUF);
 #define QLNX_LOCK(ha)		mtx_lock(&ha->hw_lock)
 #define QLNX_UNLOCK(ha)		mtx_unlock(&ha->hw_lock)
 
- 
-#define QLNX_TX_LOCK(ha)	mtx_lock(&ha->tx_lock);
-#define QLNX_TX_UNLOCK(ha)	mtx_unlock(&ha->tx_lock);
-
 /*
  * structure encapsulating a DMA buffer
  */

Modified: head/sys/modules/qlnx/qlnxe/Makefile
==============================================================================
--- head/sys/modules/qlnx/qlnxe/Makefile	Tue May 16 19:54:47 2017	(r318381)
+++ head/sys/modules/qlnx/qlnxe/Makefile	Tue May 16 21:34:40 2017	(r318382)
@@ -65,8 +65,6 @@ CFLAGS+= -I${SRCTOP}/sys/compat/linuxkpi
 #CFLAGS += -DQLNX_SOFT_LRO
 #CFLAGS += -DQLNX_QSORT_LRO
 #CFLAGS += -DQLNX_MAX_COALESCE
-#CFLAGS += -DQLNX_TRACE_LRO_CNT
-#CFLAGS += -DQLNX_TRACE_TSO_PKT_LEN
 
 
 .include <bsd.kmod.mk>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705162134.v4GLYe8d043042>