Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Mar 2018 11:23:14 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r330648 - in head/sys: conf dev/mlx5 dev/mlx5/mlx5_core dev/mlx5/mlx5_ib modules/mlx5ib
Message-ID:  <201803081123.w28BNE6M080559@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Thu Mar  8 11:23:14 2018
New Revision: 330648
URL: https://svnweb.freebsd.org/changeset/base/330648

Log:
  Add support for explicit congestion notification, ECN, to mlx5ib(4).
  
  ECN configuration and statistics is available through a set of sysctl(8)
  nodes under sys.class.infiniband.mlx5_X.cong . The ECN configuration
  nodes can also be used as loader tunables.
  
  MFC after:	1 week
  Sponsored by:	Mellanox Technologies

Added:
  head/sys/dev/mlx5/cmd.h   (contents, props changed)
  head/sys/dev/mlx5/mlx5_ib/mlx5_ib_cong.c   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
  head/sys/dev/mlx5/mlx5_ib/mlx5_ib.h
  head/sys/dev/mlx5/mlx5_ib/mlx5_ib_main.c
  head/sys/dev/mlx5/mlx5_ifc.h
  head/sys/modules/mlx5ib/Makefile

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Thu Mar  8 10:43:42 2018	(r330647)
+++ head/sys/conf/files	Thu Mar  8 11:23:14 2018	(r330648)
@@ -4692,6 +4692,8 @@ dev/mlx4/mlx4_en/mlx4_en_tx.c			optional mlx4en pci in
 
 dev/mlx5/mlx5_ib/mlx5_ib_ah.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
+dev/mlx5/mlx5_ib/mlx5_ib_cong.c			optional mlx5ib pci ofed \
+	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_cq.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_doorbell.c		optional mlx5ib pci ofed \

Added: head/sys/dev/mlx5/cmd.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/mlx5/cmd.h	Thu Mar  8 11:23:14 2018	(r330648)
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2013-2017, Mellanox Technologies, Ltd.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef MLX5_CMD_H
+#define MLX5_CMD_H
+
+#include <linux/types.h>
+
+struct manage_pages_layout {
+	u64	ptr;
+	u32	reserved;
+	u16	num_entries;
+	u16	func_id;
+};
+
+
+struct mlx5_cmd_alloc_uar_imm_out {
+	u32	rsvd[3];
+	u32	uarn;
+};
+
+struct mlx5_core_dev;
+int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev,
+                                bool reset, void *out, int out_size);
+int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point,
+                               void *out, int out_size);
+int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *mdev,
+                                void *in, int in_size);
+struct mlx5_core_dev;
+int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev,
+                                bool reset, void *out, int out_size);
+int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point,
+                               void *out, int out_size);
+int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *mdev,
+                                void *in, int in_size);
+#endif /* MLX5_CMD_H */

Modified: head/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
==============================================================================
--- head/sys/dev/mlx5/mlx5_core/mlx5_cmd.c	Thu Mar  8 10:43:42 2018	(r330647)
+++ head/sys/dev/mlx5/mlx5_core/mlx5_cmd.c	Thu Mar  8 11:23:14 2018	(r330648)
@@ -36,6 +36,7 @@
 #include <linux/hardirq.h>
 #include <linux/ktime.h>
 #include <dev/mlx5/driver.h>
+#include <dev/mlx5/cmd.h>
 
 #include "mlx5_core.h"
 
@@ -1566,3 +1567,37 @@ void mlx5_cmd_cleanup(struct mlx5_core_dev *dev)
 	free_cmd_page(dev, cmd);
 }
 EXPORT_SYMBOL(mlx5_cmd_cleanup);
+
+int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev,
+                                bool reset, void *out, int out_size)
+{
+        u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = { };
+
+        MLX5_SET(query_cong_statistics_in, in, opcode,
+                 MLX5_CMD_OP_QUERY_CONG_STATISTICS);
+        MLX5_SET(query_cong_statistics_in, in, clear, reset);
+        return mlx5_cmd_exec(dev, in, sizeof(in), out, out_size);
+}
+EXPORT_SYMBOL(mlx5_cmd_query_cong_counter);
+
+int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point,
+			       void *out, int out_size)
+{
+	u32 in[MLX5_ST_SZ_DW(query_cong_params_in)] = { };
+
+	MLX5_SET(query_cong_params_in, in, opcode,
+		 MLX5_CMD_OP_QUERY_CONG_PARAMS);
+	MLX5_SET(query_cong_params_in, in, cong_protocol, cong_point);
+
+	return mlx5_cmd_exec(dev, in, sizeof(in), out, out_size);
+}
+EXPORT_SYMBOL(mlx5_cmd_query_cong_params);
+
+int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *dev,
+				void *in, int in_size)
+{
+	u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = { };
+
+	return mlx5_cmd_exec(dev, in, in_size, out, sizeof(out));
+}
+EXPORT_SYMBOL(mlx5_cmd_modify_cong_params);

Modified: head/sys/dev/mlx5/mlx5_ib/mlx5_ib.h
==============================================================================
--- head/sys/dev/mlx5/mlx5_ib/mlx5_ib.h	Thu Mar  8 10:43:42 2018	(r330647)
+++ head/sys/dev/mlx5/mlx5_ib/mlx5_ib.h	Thu Mar  8 11:23:14 2018	(r330648)
@@ -605,6 +605,56 @@ struct mlx5_roce {
 	atomic_t		next_port;
 };
 
+#define	MLX5_IB_STATS_COUNT(a,b,c,d) a
+#define	MLX5_IB_STATS_VAR(a,b,c,d) b;
+#define	MLX5_IB_STATS_DESC(a,b,c,d) c, d,
+
+#define	MLX5_IB_CONG_PARAMS(m) \
+  /* ECN RP */ \
+  m(+1, u64 rp_clamp_tgt_rate, "rp_clamp_tgt_rate", "If set, whenever a CNP is processed, the target rate is updated to be the current rate") \
+  m(+1, u64 rp_clamp_tgt_rate_ati, "rp_clamp_tgt_rate_ati", "If set, when receiving a CNP, the target rate should be updated if the transission rate was increased due to the timer, and not only due to the byte counter") \
+  m(+1, u64 rp_time_reset, "rp_time_reset", "Time in microseconds between rate increases if no CNPs are received") \
+  m(+1, u64 rp_byte_reset, "rp_byte_reset", "Transmitted data in bytes between rate increases if no CNP's are received. A value of zero means disabled.") \
+  m(+1, u64 rp_threshold, "rp_threshold", "The number of times rpByteStage or rpTimeStage can count before the RP rate control state machine advances states") \
+  m(+1, u64 rp_ai_rate, "rp_ai_rate", "The rate, in Mbits per second, used to increase rpTargetRate in the active increase state") \
+  m(+1, u64 rp_hai_rate, "rp_hai_rate", "The rate, in Mbits per second, used to increase rpTargetRate in the hyper increase state") \
+  m(+1, u64 rp_min_dec_fac, "rp_min_dec_fac", "The minimum factor by which the current transmit rate can be changed when processing a CNP. Value is given as a percentage, [1 .. 100]") \
+  m(+1, u64 rp_min_rate, "rp_min_rate", "The minimum value, in Mbps per second, for rate to limit") \
+  m(+1, u64 rp_rate_to_set_on_first_cnp, "rp_rate_to_set_on_first_cnp", "The rate that is set for the flow when a rate limiter is allocated to it upon first CNP received, in Mbps. A value of zero means use full port speed") \
+  m(+1, u64 rp_dce_tcp_g, "rp_dce_tcp_g", "Used to update the congestion estimator, alpha, once every dce_tcp_rtt once every dce_tcp_rtt microseconds") \
+  m(+1, u64 rp_dce_tcp_rtt, "rp_dce_tcp_rtt", "The time between updates of the aolpha value, in microseconds") \
+  m(+1, u64 rp_rate_reduce_monitor_period, "rp_rate_reduce_monitor_period", "The minimum time between two consecutive rate reductions for a single flow") \
+  m(+1, u64 rp_initial_alpha_value, "rp_initial_alpha_value", "The initial value of alpha to use when receiving the first CNP for a flow") \
+  m(+1, u64 rp_gd, "rp_gd", "If a CNP is received, the flow rate is reduced at the beginning of the next rate_reduce_monitor_period interval") \
+  /* ECN NP */ \
+  m(+1, u64 np_cnp_dscp, "np_cnp_dscp", "The DiffServ Code Point of the generated CNP for this port") \
+  m(+1, u64 np_cnp_prio_mode, "np_cnp_prio_mode", "The 802.1p priority value of the generated CNP for this port") \
+  m(+1, u64 np_cnp_prio, "np_cnp_prio", "The 802.1p priority value of the generated CNP for this port")
+
+#define	MLX5_IB_CONG_PARAMS_NUM (0 MLX5_IB_CONG_PARAMS(MLX5_IB_STATS_COUNT))
+
+#define	MLX5_IB_CONG_STATS(m) \
+  m(+1, u64 syndrome, "syndrome", "Syndrome number") \
+  m(+1, u64 rp_cur_flows, "rp_cur_flows", "Number of flows limited") \
+  m(+1, u64 sum_flows, "sum_flows", "Sum of the number of flows limited over time") \
+  m(+1, u64 rp_cnp_ignored, "rp_cnp_ignored", "Number of CNPs and CNMs ignored") \
+  m(+1, u64 rp_cnp_handled, "rp_cnp_handled", "Number of CNPs and CNMs successfully handled") \
+  m(+1, u64 time_stamp, "time_stamp", "Time stamp in microseconds") \
+  m(+1, u64 accumulators_period, "accumulators_period", "The value of X variable for accumulating counters") \
+  m(+1, u64 np_ecn_marked_roce_packets, "np_ecn_marked_roce_packets", "Number of ECN marked packets seen") \
+  m(+1, u64 np_cnp_sent, "np_cnp_sent", "Number of CNPs sent")
+
+#define	MLX5_IB_CONG_STATS_NUM (0 MLX5_IB_CONG_STATS(MLX5_IB_STATS_COUNT))
+
+struct mlx5_ib_congestion {
+	struct sysctl_ctx_list ctx;
+	struct sx lock;
+	struct delayed_work dwork;
+	u64	arg [0];
+	MLX5_IB_CONG_PARAMS(MLX5_IB_STATS_VAR)
+	MLX5_IB_CONG_STATS(MLX5_IB_STATS_VAR)
+};
+
 struct mlx5_ib_dev {
 	struct ib_device		ib_dev;
 	struct mlx5_core_dev		*mdev;
@@ -638,6 +688,7 @@ struct mlx5_ib_dev {
 	struct list_head	qp_list;
 	/* Array with num_ports elements */
 	struct mlx5_ib_port	*port;
+	struct mlx5_ib_congestion congestion;
 };
 
 static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
@@ -991,4 +1042,8 @@ static inline int get_srq_user_index(struct mlx5_ib_uc
 
 	return verify_assign_uidx(cqe_version, ucmd->uidx, user_index);
 }
+
+void mlx5_ib_cleanup_congestion(struct mlx5_ib_dev *);
+int mlx5_ib_init_congestion(struct mlx5_ib_dev *);
+
 #endif /* MLX5_IB_H */

Added: head/sys/dev/mlx5/mlx5_ib/mlx5_ib_cong.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/mlx5/mlx5_ib/mlx5_ib_cong.c	Thu Mar  8 11:23:14 2018	(r330648)
@@ -0,0 +1,460 @@
+/*-
+ * Copyright (c) 2013-2015, Mellanox Technologies, Ltd.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "mlx5_ib.h"
+
+#include <dev/mlx5/cmd.h>
+
+static const char *mlx5_ib_cong_params_desc[] = {
+	MLX5_IB_CONG_PARAMS(MLX5_IB_STATS_DESC)
+};
+
+static const char *mlx5_ib_cong_stats_desc[] = {
+	MLX5_IB_CONG_STATS(MLX5_IB_STATS_DESC)
+};
+
+#define	MLX5_IB_INDEX(field) (__offsetof(struct mlx5_ib_congestion, field) / sizeof(u64))
+#define	MLX5_IB_FLD_MAX(type, field) ((1ULL << __mlx5_bit_sz(type, field)) - 1ULL)
+#define	MLX5_IB_SET_CLIPPED(type, ptr, field, var) do { \
+  /* rangecheck */					\
+  if ((var) > MLX5_IB_FLD_MAX(type, field))		\
+	(var) = MLX5_IB_FLD_MAX(type, field);		\
+  /* set value */					\
+  MLX5_SET(type, ptr, field, var);			\
+} while (0)
+
+#define	CONG_LOCK(dev) sx_xlock(&(dev)->congestion.lock)
+#define	CONG_UNLOCK(dev) sx_xunlock(&(dev)->congestion.lock)
+#define	CONG_LOCKED(dev) sx_xlocked(&(dev)->congestion.lock)
+
+#define	MLX5_IB_RP_CLAMP_TGT_RATE_ATTR			BIT(1)
+#define	MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR		BIT(2)
+#define	MLX5_IB_RP_TIME_RESET_ATTR			BIT(3)
+#define	MLX5_IB_RP_BYTE_RESET_ATTR			BIT(4)
+#define	MLX5_IB_RP_THRESHOLD_ATTR			BIT(5)
+#define	MLX5_IB_RP_AI_RATE_ATTR				BIT(7)
+#define	MLX5_IB_RP_HAI_RATE_ATTR			BIT(8)
+#define	MLX5_IB_RP_MIN_DEC_FAC_ATTR			BIT(9)
+#define	MLX5_IB_RP_MIN_RATE_ATTR			BIT(10)
+#define	MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR	BIT(11)
+#define	MLX5_IB_RP_DCE_TCP_G_ATTR			BIT(12)
+#define	MLX5_IB_RP_DCE_TCP_RTT_ATTR			BIT(13)
+#define	MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR	BIT(14)
+#define	MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR		BIT(15)
+#define	MLX5_IB_RP_GD_ATTR				BIT(16)
+
+#define	MLX5_IB_NP_CNP_DSCP_ATTR			BIT(3)
+#define	MLX5_IB_NP_CNP_PRIO_MODE_ATTR			BIT(4)
+
+enum mlx5_ib_cong_node_type {
+	MLX5_IB_RROCE_ECN_RP = 1,
+	MLX5_IB_RROCE_ECN_NP = 2,
+};
+
+static enum mlx5_ib_cong_node_type
+mlx5_ib_param_to_node(u32 index)
+{
+
+	if (index >= MLX5_IB_INDEX(rp_clamp_tgt_rate) &&
+	    index <= MLX5_IB_INDEX(rp_gd))
+		return MLX5_IB_RROCE_ECN_RP;
+	else
+		return MLX5_IB_RROCE_ECN_NP;
+}
+
+static u64
+mlx5_get_cc_param_val(void *field, u32 index)
+{
+
+	switch (index) {
+	case MLX5_IB_INDEX(rp_clamp_tgt_rate):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				clamp_tgt_rate);
+	case MLX5_IB_INDEX(rp_clamp_tgt_rate_ati):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				clamp_tgt_rate_after_time_inc);
+	case MLX5_IB_INDEX(rp_time_reset):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rpg_time_reset);
+	case MLX5_IB_INDEX(rp_byte_reset):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rpg_byte_reset);
+	case MLX5_IB_INDEX(rp_threshold):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rpg_threshold);
+	case MLX5_IB_INDEX(rp_ai_rate):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rpg_ai_rate);
+	case MLX5_IB_INDEX(rp_hai_rate):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rpg_hai_rate);
+	case MLX5_IB_INDEX(rp_min_dec_fac):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rpg_min_dec_fac);
+	case MLX5_IB_INDEX(rp_min_rate):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rpg_min_rate);
+	case MLX5_IB_INDEX(rp_rate_to_set_on_first_cnp):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rate_to_set_on_first_cnp);
+	case MLX5_IB_INDEX(rp_dce_tcp_g):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				dce_tcp_g);
+	case MLX5_IB_INDEX(rp_dce_tcp_rtt):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				dce_tcp_rtt);
+	case MLX5_IB_INDEX(rp_rate_reduce_monitor_period):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rate_reduce_monitor_period);
+	case MLX5_IB_INDEX(rp_initial_alpha_value):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				initial_alpha_value);
+	case MLX5_IB_INDEX(rp_gd):
+		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
+				rpg_gd);
+	case MLX5_IB_INDEX(np_cnp_dscp):
+		return MLX5_GET(cong_control_r_roce_ecn_np, field,
+				cnp_dscp);
+	case MLX5_IB_INDEX(np_cnp_prio_mode):
+		return MLX5_GET(cong_control_r_roce_ecn_np, field,
+				cnp_prio_mode);
+	case MLX5_IB_INDEX(np_cnp_prio):
+		return MLX5_GET(cong_control_r_roce_ecn_np, field,
+				cnp_802p_prio);
+	default:
+		return 0;
+	}
+}
+
+static void
+mlx5_ib_set_cc_param_mask_val(void *field, u32 index,
+    u64 var, u32 *attr_mask)
+{
+
+	switch (index) {
+	case MLX5_IB_INDEX(rp_clamp_tgt_rate):
+		*attr_mask |= MLX5_IB_RP_CLAMP_TGT_RATE_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 clamp_tgt_rate, var);
+		break;
+	case MLX5_IB_INDEX(rp_clamp_tgt_rate_ati):
+		*attr_mask |= MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 clamp_tgt_rate_after_time_inc, var);
+		break;
+	case MLX5_IB_INDEX(rp_time_reset):
+		*attr_mask |= MLX5_IB_RP_TIME_RESET_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rpg_time_reset, var);
+		break;
+	case MLX5_IB_INDEX(rp_byte_reset):
+		*attr_mask |= MLX5_IB_RP_BYTE_RESET_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rpg_byte_reset, var);
+		break;
+	case MLX5_IB_INDEX(rp_threshold):
+		*attr_mask |= MLX5_IB_RP_THRESHOLD_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rpg_threshold, var);
+		break;
+	case MLX5_IB_INDEX(rp_ai_rate):
+		*attr_mask |= MLX5_IB_RP_AI_RATE_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rpg_ai_rate, var);
+		break;
+	case MLX5_IB_INDEX(rp_hai_rate):
+		*attr_mask |= MLX5_IB_RP_HAI_RATE_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rpg_hai_rate, var);
+		break;
+	case MLX5_IB_INDEX(rp_min_dec_fac):
+		*attr_mask |= MLX5_IB_RP_MIN_DEC_FAC_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rpg_min_dec_fac, var);
+		break;
+	case MLX5_IB_INDEX(rp_min_rate):
+		*attr_mask |= MLX5_IB_RP_MIN_RATE_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rpg_min_rate, var);
+		break;
+	case MLX5_IB_INDEX(rp_rate_to_set_on_first_cnp):
+		*attr_mask |= MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rate_to_set_on_first_cnp, var);
+		break;
+	case MLX5_IB_INDEX(rp_dce_tcp_g):
+		*attr_mask |= MLX5_IB_RP_DCE_TCP_G_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 dce_tcp_g, var);
+		break;
+	case MLX5_IB_INDEX(rp_dce_tcp_rtt):
+		*attr_mask |= MLX5_IB_RP_DCE_TCP_RTT_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 dce_tcp_rtt, var);
+		break;
+	case MLX5_IB_INDEX(rp_rate_reduce_monitor_period):
+		*attr_mask |= MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rate_reduce_monitor_period, var);
+		break;
+	case MLX5_IB_INDEX(rp_initial_alpha_value):
+		*attr_mask |= MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 initial_alpha_value, var);
+		break;
+	case MLX5_IB_INDEX(rp_gd):
+		*attr_mask |= MLX5_IB_RP_GD_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_rp, field,
+			 rpg_gd, var);
+		break;
+	case MLX5_IB_INDEX(np_cnp_dscp):
+		*attr_mask |= MLX5_IB_NP_CNP_DSCP_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_np, field, cnp_dscp, var);
+		break;
+	case MLX5_IB_INDEX(np_cnp_prio_mode):
+		*attr_mask |= MLX5_IB_NP_CNP_PRIO_MODE_ATTR;
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_np, field, cnp_prio_mode, var);
+		break;
+	case MLX5_IB_INDEX(np_cnp_prio):
+		*attr_mask |= MLX5_IB_NP_CNP_PRIO_MODE_ATTR;
+		MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_prio_mode, 0);
+		MLX5_IB_SET_CLIPPED(cong_control_r_roce_ecn_np, field, cnp_802p_prio, var);
+		break;
+	default:
+		break;
+	}
+}
+
+static int
+mlx5_ib_get_all_cc_params(struct mlx5_ib_dev *dev)
+{
+	int outlen = MLX5_ST_SZ_BYTES(query_cong_params_out);
+	enum mlx5_ib_cong_node_type node = 0;
+	void *out;
+	void *field;
+	u32 x;
+	int err = 0;
+
+	out = kzalloc(outlen, GFP_KERNEL);
+	if (!out)
+		return -ENOMEM;
+
+	/* get the current values */
+	for (x = 0; x != MLX5_IB_CONG_PARAMS_NUM; x++) {
+		if (node != mlx5_ib_param_to_node(x)) {
+			node = mlx5_ib_param_to_node(x);
+
+			err = mlx5_cmd_query_cong_params(dev->mdev, node, out, outlen);
+			if (err)
+				break;
+		}
+		field = MLX5_ADDR_OF(query_cong_params_out, out, congestion_parameters);
+		dev->congestion.arg[x] = mlx5_get_cc_param_val(field, x);
+	}
+	kfree(out);
+	return err;
+}
+
+static int
+mlx5_ib_set_cc_params(struct mlx5_ib_dev *dev, u32 index, u64 var)
+{
+	int inlen = MLX5_ST_SZ_BYTES(modify_cong_params_in);
+	enum mlx5_ib_cong_node_type node;
+	u32 attr_mask = 0;
+	void *field;
+	void *in;
+	int err;
+
+	in = kzalloc(inlen, GFP_KERNEL);
+	if (!in)
+		return -ENOMEM;
+
+	MLX5_SET(modify_cong_params_in, in, opcode,
+		 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
+
+	node = mlx5_ib_param_to_node(index);
+	MLX5_SET(modify_cong_params_in, in, cong_protocol, node);
+
+	field = MLX5_ADDR_OF(modify_cong_params_in, in, congestion_parameters);
+	mlx5_ib_set_cc_param_mask_val(field, index, var, &attr_mask);
+
+	field = MLX5_ADDR_OF(modify_cong_params_in, in, field_select);
+	MLX5_SET(field_select_r_roce_rp, field, field_select_r_roce_rp,
+		 attr_mask);
+
+	err = mlx5_cmd_modify_cong_params(dev->mdev, in, inlen);
+	kfree(in);
+
+	return err;
+}
+
+static int
+mlx5_ib_cong_params_handler(SYSCTL_HANDLER_ARGS)
+{
+	struct mlx5_ib_dev *dev = arg1;
+	u64 value;
+	int error;
+
+	CONG_LOCK(dev);
+	value = dev->congestion.arg[arg2];
+	if (req != NULL) {
+		error = sysctl_handle_64(oidp, &value, 0, req);
+		if (error || req->newptr == NULL ||
+		    value == dev->congestion.arg[arg2])
+			goto done;
+
+		/* assign new value */
+		dev->congestion.arg[arg2] = value;
+	} else {
+		error = 0;
+	}
+	if (!MLX5_CAP_GEN(dev->mdev, cc_modify_allowed))
+		error = EPERM;
+	else {
+		error = -mlx5_ib_set_cc_params(dev, MLX5_IB_INDEX(arg[arg2]),
+		    dev->congestion.arg[arg2]);
+	}
+done:
+	CONG_UNLOCK(dev);
+
+	return (error);
+}
+
+#define	MLX5_GET_UNALIGNED_64(t,p,f) \
+    (((u64)MLX5_GET(t,p,f##_high) << 32) | MLX5_GET(t,p,f##_low))
+
+static void
+mlx5_ib_read_cong_stats(struct work_struct *work)
+{
+	struct mlx5_ib_dev *dev =
+	    container_of(work, struct mlx5_ib_dev, congestion.dwork.work);
+	const int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out);
+	void *out;
+
+	out = kzalloc(outlen, GFP_KERNEL);
+	if (!out)
+		goto done;
+
+	CONG_LOCK(dev);
+	if (mlx5_cmd_query_cong_counter(dev->mdev, 0, out, outlen))
+		memset(out, 0, outlen);
+
+	dev->congestion.syndrome =
+	    MLX5_GET(query_cong_statistics_out, out, syndrome);
+	dev->congestion.rp_cur_flows =
+	    MLX5_GET(query_cong_statistics_out, out, rp_cur_flows);
+	dev->congestion.sum_flows =
+	    MLX5_GET(query_cong_statistics_out, out, sum_flows);
+	dev->congestion.rp_cnp_ignored =
+	    MLX5_GET_UNALIGNED_64(query_cong_statistics_out, out, rp_cnp_ignored);
+	dev->congestion.rp_cnp_handled =
+	    MLX5_GET_UNALIGNED_64(query_cong_statistics_out, out, rp_cnp_handled);
+	dev->congestion.time_stamp =
+	    MLX5_GET_UNALIGNED_64(query_cong_statistics_out, out, time_stamp);
+	dev->congestion.accumulators_period =
+	    MLX5_GET(query_cong_statistics_out, out, accumulators_period);
+	dev->congestion.np_ecn_marked_roce_packets =
+	    MLX5_GET_UNALIGNED_64(query_cong_statistics_out, out, np_ecn_marked_roce_packets);
+	dev->congestion.np_cnp_sent =
+	    MLX5_GET_UNALIGNED_64(query_cong_statistics_out, out, np_cnp_sent);
+
+	CONG_UNLOCK(dev);
+	kfree(out);
+
+done:
+	schedule_delayed_work(&dev->congestion.dwork, hz);
+}
+
+void
+mlx5_ib_cleanup_congestion(struct mlx5_ib_dev *dev)
+{
+
+	cancel_delayed_work_sync(&dev->congestion.dwork);
+	sysctl_ctx_free(&dev->congestion.ctx);
+	sx_destroy(&dev->congestion.lock);
+}
+
+int
+mlx5_ib_init_congestion(struct mlx5_ib_dev *dev)
+{
+	struct sysctl_ctx_list *ctx;
+	struct sysctl_oid *parent;
+	struct sysctl_oid *node;
+	int err;
+	u32 x;
+
+	ctx = &dev->congestion.ctx;
+	sysctl_ctx_init(ctx);
+	sx_init(&dev->congestion.lock, "mlx5ibcong");
+	INIT_DELAYED_WORK(&dev->congestion.dwork, mlx5_ib_read_cong_stats);
+
+	if (!MLX5_CAP_GEN(dev->mdev, cc_query_allowed))
+		return (0);
+
+	err = mlx5_ib_get_all_cc_params(dev);
+	if (err)
+		return (err);
+
+	parent = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(dev->ib_dev.dev.kobj.oidp),
+	    OID_AUTO, "cong", CTLFLAG_RW, NULL, "Congestion control");
+	if (parent == NULL)
+		return (-ENOMEM);
+
+	node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(parent),
+	    OID_AUTO, "conf", CTLFLAG_RW, NULL, "Configuration");
+	if (node == NULL) {
+		sysctl_ctx_free(&dev->congestion.ctx);
+		return (-ENOMEM);
+	}
+
+	for (x = 0; x != MLX5_IB_CONG_PARAMS_NUM; x++) {
+		SYSCTL_ADD_PROC(ctx,
+		    SYSCTL_CHILDREN(node), OID_AUTO,
+		    mlx5_ib_cong_params_desc[2 * x],
+		    CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
+		    dev, x, &mlx5_ib_cong_params_handler, "QU",
+		    mlx5_ib_cong_params_desc[2 * x + 1]);
+	}
+
+	node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(parent),
+	    OID_AUTO, "stats", CTLFLAG_RD, NULL, "Statistics");
+	if (node == NULL) {
+		sysctl_ctx_free(&dev->congestion.ctx);
+		return (-ENOMEM);
+	}
+
+	for (x = 0; x != MLX5_IB_CONG_STATS_NUM; x++) {
+		/* read-only SYSCTLs */
+		SYSCTL_ADD_U64(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
+		    mlx5_ib_cong_stats_desc[2 * x],
+		    CTLFLAG_RD | CTLFLAG_MPSAFE,
+		    &dev->congestion.arg[x + MLX5_IB_CONG_PARAMS_NUM],
+		    0, mlx5_ib_cong_stats_desc[2 * x + 1]);
+	}
+	schedule_delayed_work(&dev->congestion.dwork, hz);
+	return (0);
+}

Modified: head/sys/dev/mlx5/mlx5_ib/mlx5_ib_main.c
==============================================================================
--- head/sys/dev/mlx5/mlx5_ib/mlx5_ib_main.c	Thu Mar  8 10:43:42 2018	(r330647)
+++ head/sys/dev/mlx5/mlx5_ib/mlx5_ib_main.c	Thu Mar  8 11:23:14 2018	(r330648)
@@ -3151,6 +3151,10 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
 			goto err_umrc;
 	}
 
+	err = mlx5_ib_init_congestion(dev);
+	if (err)
+		goto err_umrc;
+
 	dev->ib_active = true;
 
 	return dev;
@@ -3190,6 +3194,7 @@ static void mlx5_ib_remove(struct mlx5_core_dev *mdev,
 	struct mlx5_ib_dev *dev = context;
 	enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev, 1);
 
+	mlx5_ib_cleanup_congestion(dev);
 	mlx5_remove_roce_notifier(dev);
 	ib_unregister_device(&dev->ib_dev);
 	mlx5_ib_dealloc_q_counters(dev);

Modified: head/sys/dev/mlx5/mlx5_ifc.h
==============================================================================
--- head/sys/dev/mlx5/mlx5_ifc.h	Thu Mar  8 10:43:42 2018	(r330647)
+++ head/sys/dev/mlx5/mlx5_ifc.h	Thu Mar  8 11:23:14 2018	(r330648)
@@ -4865,17 +4865,17 @@ struct mlx5_ifc_query_cong_statistics_out_bits {
 
 	u8         reserved_1[0x40];
 
-	u8         cur_flows[0x20];
+	u8         rp_cur_flows[0x20];
 
 	u8         sum_flows[0x20];
 
-	u8         cnp_ignored_high[0x20];
+	u8         rp_cnp_ignored_high[0x20];
 
-	u8         cnp_ignored_low[0x20];
+	u8         rp_cnp_ignored_low[0x20];
 
-	u8         cnp_handled_high[0x20];
+	u8         rp_cnp_handled_high[0x20];
 
-	u8         cnp_handled_low[0x20];
+	u8         rp_cnp_handled_low[0x20];
 
 	u8         reserved_2[0x100];
 
@@ -4885,13 +4885,13 @@ struct mlx5_ifc_query_cong_statistics_out_bits {
 
 	u8         accumulators_period[0x20];
 
-	u8         ecn_marked_roce_packets_high[0x20];
+	u8         np_ecn_marked_roce_packets_high[0x20];
 
-	u8         ecn_marked_roce_packets_low[0x20];
+	u8         np_ecn_marked_roce_packets_low[0x20];
 
-	u8         cnps_sent_high[0x20];
+	u8         np_cnp_sent_high[0x20];
 
-	u8         cnps_sent_low[0x20];
+	u8         np_cnp_sent_low[0x20];
 
 	u8         reserved_3[0x560];
 };

Modified: head/sys/modules/mlx5ib/Makefile
==============================================================================
--- head/sys/modules/mlx5ib/Makefile	Thu Mar  8 10:43:42 2018	(r330647)
+++ head/sys/modules/mlx5ib/Makefile	Thu Mar  8 11:23:14 2018	(r330648)
@@ -4,6 +4,7 @@
 KMOD=mlx5ib
 SRCS= \
 mlx5_ib_ah.c \
+mlx5_ib_cong.c \
 mlx5_ib_cq.c \
 mlx5_ib_doorbell.c \
 mlx5_ib_gsi.c \



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