svn commit: r300280 - head/sys/dev/mlx5/mlx5_en

Hans Petter Selasky hselasky at FreeBSD.org
Fri May 20 06:59:40 UTC 2016


Author: hselasky
Date: Fri May 20 06:59:38 2016
New Revision: 300280
URL: https://svnweb.freebsd.org/changeset/base/300280

Log:
  Optimise use of doorbell and remove redundant NOPs
  
  Store the last doorbell write in the mlx5e_sq structure and write the
  doorbell to the hardware when the transmit routine finishes
  transmitting all queued mbufs.
  
  Sponsored by:	Mellanox Technologies
  Tested by:	Netflix
  MFC after:	1 week

Modified:
  head/sys/dev/mlx5/mlx5_en/en.h
  head/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
  head/sys/dev/mlx5/mlx5_en/mlx5_en_tx.c

Modified: head/sys/dev/mlx5/mlx5_en/en.h
==============================================================================
--- head/sys/dev/mlx5/mlx5_en/en.h	Fri May 20 06:56:43 2016	(r300279)
+++ head/sys/dev/mlx5/mlx5_en/en.h	Fri May 20 06:59:38 2016	(r300280)
@@ -505,6 +505,10 @@ struct mlx5e_sq {
 #define	MLX5E_CEV_STATE_SEND_NOPS 1	/* send NOPs */
 #define	MLX5E_CEV_STATE_HOLD_NOPS 2	/* don't send NOPs yet */
 	struct callout cev_callout;
+	union {
+		u32	d32[2];
+		u64	d64;
+	} doorbell;
 	struct	mlx5e_sq_stats stats;
 
 	struct	mlx5e_cq cq;
@@ -752,8 +756,7 @@ int	mlx5e_add_all_vlan_rules(struct mlx5
 void	mlx5e_del_all_vlan_rules(struct mlx5e_priv *priv);
 
 static inline void
-mlx5e_tx_notify_hw(struct mlx5e_sq *sq,
-    struct mlx5e_tx_wqe *wqe, int bf_sz)
+mlx5e_tx_notify_hw(struct mlx5e_sq *sq, u32 *wqe, int bf_sz)
 {
 	u16 ofst = MLX5_BF_OFFSET + sq->bf_offset;
 
@@ -769,13 +772,13 @@ mlx5e_tx_notify_hw(struct mlx5e_sq *sq,
 	wmb();
 
 	if (bf_sz) {
-		__iowrite64_copy(sq->uar_bf_map + ofst, &wqe->ctrl, bf_sz);
+		__iowrite64_copy(sq->uar_bf_map + ofst, wqe, bf_sz);
 
 		/* flush the write-combining mapped buffer */
 		wmb();
 
 	} else {
-		mlx5_write64((__be32 *)&wqe->ctrl, sq->uar_map + ofst, NULL);
+		mlx5_write64(wqe, sq->uar_map + ofst, NULL);
 	}
 
 	sq->bf_offset ^= sq->bf_buf_size;
@@ -795,7 +798,7 @@ void	mlx5e_create_ethtool(struct mlx5e_p
 void	mlx5e_create_stats(struct sysctl_ctx_list *,
     struct sysctl_oid_list *, const char *,
     const char **, unsigned, u64 *);
-void	mlx5e_send_nop(struct mlx5e_sq *, u32, bool);
+void	mlx5e_send_nop(struct mlx5e_sq *, u32);
 void	mlx5e_sq_cev_timeout(void *);
 int	mlx5e_refresh_channel_params(struct mlx5e_priv *);
 

Modified: head/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
==============================================================================
--- head/sys/dev/mlx5/mlx5_en/mlx5_en_main.c	Fri May 20 06:56:43 2016	(r300279)
+++ head/sys/dev/mlx5/mlx5_en/mlx5_en_main.c	Fri May 20 06:59:38 2016	(r300280)
@@ -850,7 +850,6 @@ mlx5e_open_rq(struct mlx5e_channel *c,
     struct mlx5e_rq *rq)
 {
 	int err;
-	int i;
 
 	err = mlx5e_create_rq(c, param, rq);
 	if (err)
@@ -866,12 +865,6 @@ mlx5e_open_rq(struct mlx5e_channel *c,
 
 	c->rq.enabled = 1;
 
-	/*
-	 * Test send queues, which will trigger
-	 * "mlx5e_post_rx_wqes()":
-	 */
-	for (i = 0; i != c->num_tc; i++)
-		mlx5e_send_nop(&c->sq[i], 1, true);
 	return (0);
 
 err_disable_rq:
@@ -1198,9 +1191,16 @@ mlx5e_sq_send_nops_locked(struct mlx5e_s
 				goto done;
 			}
 		}
-		mlx5e_send_nop(sq, 1, true);
+		/* send a single NOP */
+		mlx5e_send_nop(sq, 1);
+		wmb();
 	}
 done:
+	/* Check if we need to write the doorbell */
+	if (likely(sq->doorbell.d64 != 0)) {
+		mlx5e_tx_notify_hw(sq, sq->doorbell.d32, 0);
+		sq->doorbell.d64 = 0;
+	}
 	return;
 }
 

Modified: head/sys/dev/mlx5/mlx5_en/mlx5_en_tx.c
==============================================================================
--- head/sys/dev/mlx5/mlx5_en/mlx5_en_tx.c	Fri May 20 06:56:43 2016	(r300279)
+++ head/sys/dev/mlx5/mlx5_en/mlx5_en_tx.c	Fri May 20 06:59:38 2016	(r300280)
@@ -41,7 +41,7 @@ mlx5e_do_send_cqe(struct mlx5e_sq *sq)
 }
 
 void
-mlx5e_send_nop(struct mlx5e_sq *sq, u32 ds_cnt, bool notify_hw)
+mlx5e_send_nop(struct mlx5e_sq *sq, u32 ds_cnt)
 {
 	u16 pi = sq->pc & sq->wq.sz_m1;
 	struct mlx5e_tx_wqe *wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
@@ -55,12 +55,13 @@ mlx5e_send_nop(struct mlx5e_sq *sq, u32 
 	else
 		wqe->ctrl.fm_ce_se = 0;
 
+	/* Copy data for doorbell */
+	memcpy(sq->doorbell.d32, &wqe->ctrl, sizeof(sq->doorbell.d32));
+
 	sq->mbuf[pi].mbuf = NULL;
 	sq->mbuf[pi].num_bytes = 0;
 	sq->mbuf[pi].num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
 	sq->pc += sq->mbuf[pi].num_wqebbs;
-	if (notify_hw)
-		mlx5e_tx_notify_hw(sq, wqe, 0);
 }
 
 #if (__FreeBSD_version >= 1100000)
@@ -221,7 +222,7 @@ mlx5e_sq_xmit(struct mlx5e_sq *sq, struc
 	pi = ((~sq->pc) & sq->wq.sz_m1);
 	if (pi < (MLX5_SEND_WQE_MAX_WQEBBS - 1)) {
 		/* Send one multi NOP message instead of many */
-		mlx5e_send_nop(sq, (pi + 1) * MLX5_SEND_WQEBB_NUM_DS, false);
+		mlx5e_send_nop(sq, (pi + 1) * MLX5_SEND_WQEBB_NUM_DS);
 		pi = ((~sq->pc) & sq->wq.sz_m1);
 		if (pi < (MLX5_SEND_WQE_MAX_WQEBBS - 1)) {
 			m_freem(mb);
@@ -360,6 +361,9 @@ skip_dma:
 	else
 		wqe->ctrl.fm_ce_se = 0;
 
+	/* Copy data for doorbell */
+	memcpy(sq->doorbell.d32, &wqe->ctrl, sizeof(sq->doorbell.d32));
+
 	/* Store pointer to mbuf */
 	sq->mbuf[pi].mbuf = mb;
 	sq->mbuf[pi].num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
@@ -369,8 +373,6 @@ skip_dma:
 	if (mb != NULL)
 		bus_dmamap_sync(sq->dma_tag, sq->mbuf[pi].dma_map, BUS_DMASYNC_PREWRITE);
 
-	mlx5e_tx_notify_hw(sq, wqe, 0);
-
 	sq->stats.packets++;
 	return (0);
 
@@ -474,6 +476,11 @@ mlx5e_xmit_locked(struct ifnet *ifp, str
 		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
 			break;
 	}
+	/* Check if we need to write the doorbell */
+	if (likely(sq->doorbell.d64 != 0)) {
+		mlx5e_tx_notify_hw(sq, sq->doorbell.d32, 0);
+		sq->doorbell.d64 = 0;
+	}
 	/*
 	 * Check if we need to start the event timer which flushes the
 	 * transmit ring on timeout:


More information about the svn-src-all mailing list