xref: /netbsd-src/sys/dev/pci/ixgbe/ixgbe_dcb_82598.c (revision 4ab64dd8558009744b547d27ef7493447654442b)
1 /* $NetBSD: ixgbe_dcb_82598.c,v 1.13 2023/10/06 14:48:08 msaitoh Exp $ */
2 /******************************************************************************
3   SPDX-License-Identifier: BSD-3-Clause
4 
5   Copyright (c) 2001-2020, Intel Corporation
6   All rights reserved.
7 
8   Redistribution and use in source and binary forms, with or without
9   modification, are permitted provided that the following conditions are met:
10 
11    1. Redistributions of source code must retain the above copyright notice,
12       this list of conditions and the following disclaimer.
13 
14    2. Redistributions in binary form must reproduce the above copyright
15       notice, this list of conditions and the following disclaimer in the
16       documentation and/or other materials provided with the distribution.
17 
18    3. Neither the name of the Intel Corporation nor the names of its
19       contributors may be used to endorse or promote products derived from
20       this software without specific prior written permission.
21 
22   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32   POSSIBILITY OF SUCH DAMAGE.
33 
34 ******************************************************************************/
35 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_dcb_82598.c 331224 2018-03-19 20:55:05Z erj $*/
36 
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: ixgbe_dcb_82598.c,v 1.13 2023/10/06 14:48:08 msaitoh Exp $");
39 
40 #include "ixgbe_type.h"
41 #include "ixgbe_dcb.h"
42 #include "ixgbe_dcb_82598.h"
43 
44 /**
45  * ixgbe_dcb_get_tc_stats_82598 - Return status data for each traffic class
46  * @hw: pointer to hardware structure
47  * @stats: pointer to statistics structure
48  * @tc_count:  Number of elements in bwg_array.
49  *
50  * This function returns the status data for each of the Traffic Classes in use.
51  */
ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw * hw,struct ixgbe_hw_stats * stats,u8 tc_count)52 s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw,
53 				 struct ixgbe_hw_stats *stats,
54 				 u8 tc_count)
55 {
56 	int tc;
57 
58 	DEBUGFUNC("dcb_get_tc_stats");
59 
60 	if (tc_count > IXGBE_DCB_MAX_TRAFFIC_CLASS)
61 		return IXGBE_ERR_PARAM;
62 
63 	/* Statistics pertaining to each traffic class */
64 	for (tc = 0; tc < tc_count; tc++) {
65 		/* Transmitted Packets */
66 		stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc));
67 		/* Transmitted Bytes */
68 		stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc));
69 		/* Received Packets */
70 		stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc));
71 		/* Received Bytes */
72 		stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc));
73 	}
74 
75 	return IXGBE_SUCCESS;
76 }
77 
78 /**
79  * ixgbe_dcb_get_pfc_stats_82598 - Returns CBFC status data
80  * @hw: pointer to hardware structure
81  * @stats: pointer to statistics structure
82  * @tc_count:  Number of elements in bwg_array.
83  *
84  * This function returns the CBFC status data for each of the Traffic Classes.
85  */
ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw * hw,struct ixgbe_hw_stats * stats,u8 tc_count)86 s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *hw,
87 				  struct ixgbe_hw_stats *stats,
88 				  u8 tc_count)
89 {
90 	int tc;
91 
92 	DEBUGFUNC("dcb_get_pfc_stats");
93 
94 	if (tc_count > IXGBE_DCB_MAX_TRAFFIC_CLASS)
95 		return IXGBE_ERR_PARAM;
96 
97 	for (tc = 0; tc < tc_count; tc++) {
98 		/* Priority XOFF Transmitted */
99 		stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc));
100 		/* Priority XOFF Received */
101 		stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(tc));
102 	}
103 
104 	return IXGBE_SUCCESS;
105 }
106 
107 /**
108  * ixgbe_dcb_config_rx_arbiter_82598 - Config Rx data arbiter
109  * @hw: pointer to hardware structure
110  * @refill: refill credits index by traffic class
111  * @max: max credits index by traffic class
112  * @tsa: transmission selection algorithm indexed by traffic class
113  *
114  * Configure Rx Data Arbiter and credits for each traffic class.
115  */
ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw * hw,u16 * refill,u16 * max,u8 * tsa)116 s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw, u16 *refill,
117 				      u16 *max, u8 *tsa)
118 {
119 	u32 reg = 0;
120 	u32 credit_refill = 0;
121 	u32 credit_max = 0;
122 	u8 i = 0;
123 
124 	reg = IXGBE_READ_REG(hw, IXGBE_RUPPBMR) | IXGBE_RUPPBMR_MQA;
125 	IXGBE_WRITE_REG(hw, IXGBE_RUPPBMR, reg);
126 
127 	reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
128 	/* Enable Arbiter */
129 	reg &= ~IXGBE_RMCS_ARBDIS;
130 	/* Enable Receive Recycle within the BWG */
131 	reg |= IXGBE_RMCS_RRM;
132 	/* Enable Deficit Fixed Priority arbitration*/
133 	reg |= IXGBE_RMCS_DFP;
134 
135 	IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
136 
137 	/* Configure traffic class credits and priority */
138 	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
139 		credit_refill = refill[i];
140 		credit_max = max[i];
141 
142 		reg = credit_refill | (credit_max << IXGBE_RT2CR_MCL_SHIFT);
143 
144 		if (tsa[i] == ixgbe_dcb_tsa_strict)
145 			reg |= IXGBE_RT2CR_LSP;
146 
147 		IXGBE_WRITE_REG(hw, IXGBE_RT2CR(i), reg);
148 	}
149 
150 	reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
151 	reg |= IXGBE_RDRXCTL_RDMTS_1_2;
152 	reg |= IXGBE_RDRXCTL_MPBEN;
153 	reg |= IXGBE_RDRXCTL_MCEN;
154 	IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg);
155 
156 	reg = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
157 	/* Make sure there is enough descriptors before arbitration */
158 	reg &= ~IXGBE_RXCTRL_DMBYPS;
159 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg);
160 
161 	return IXGBE_SUCCESS;
162 }
163 
164 /**
165  * ixgbe_dcb_config_tx_desc_arbiter_82598 - Config Tx Desc. arbiter
166  * @hw: pointer to hardware structure
167  * @refill: refill credits index by traffic class
168  * @max: max credits index by traffic class
169  * @bwg_id: bandwidth grouping indexed by traffic class
170  * @tsa: transmission selection algorithm indexed by traffic class
171  *
172  * Configure Tx Descriptor Arbiter and credits for each traffic class.
173  */
ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw * hw,u16 * refill,u16 * max,u8 * bwg_id,u8 * tsa)174 s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
175 					   u16 *refill, u16 *max, u8 *bwg_id,
176 					   u8 *tsa)
177 {
178 	u32 reg, max_credits;
179 	u8 i;
180 
181 	reg = IXGBE_READ_REG(hw, IXGBE_DPMCS);
182 
183 	/* Enable arbiter */
184 	reg &= ~IXGBE_DPMCS_ARBDIS;
185 	reg |= IXGBE_DPMCS_TSOEF;
186 
187 	/* Configure Max TSO packet size 34KB including payload and headers */
188 	reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT);
189 
190 	IXGBE_WRITE_REG(hw, IXGBE_DPMCS, reg);
191 
192 	/* Configure traffic class credits and priority */
193 	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
194 		max_credits = max[i];
195 		reg = max_credits << IXGBE_TDTQ2TCCR_MCL_SHIFT;
196 		reg |= (u32)(refill[i]);
197 		reg |= (u32)(bwg_id[i]) << IXGBE_TDTQ2TCCR_BWG_SHIFT;
198 
199 		if (tsa[i] == ixgbe_dcb_tsa_group_strict_cee)
200 			reg |= IXGBE_TDTQ2TCCR_GSP;
201 
202 		if (tsa[i] == ixgbe_dcb_tsa_strict)
203 			reg |= IXGBE_TDTQ2TCCR_LSP;
204 
205 		IXGBE_WRITE_REG(hw, IXGBE_TDTQ2TCCR(i), reg);
206 	}
207 
208 	return IXGBE_SUCCESS;
209 }
210 
211 /**
212  * ixgbe_dcb_config_tx_data_arbiter_82598 - Config Tx data arbiter
213  * @hw: pointer to hardware structure
214  * @refill: refill credits index by traffic class
215  * @max: max credits index by traffic class
216  * @bwg_id: bandwidth grouping indexed by traffic class
217  * @tsa: transmission selection algorithm indexed by traffic class
218  *
219  * Configure Tx Data Arbiter and credits for each traffic class.
220  */
ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw * hw,u16 * refill,u16 * max,u8 * bwg_id,u8 * tsa)221 s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
222 					   u16 *refill, u16 *max, u8 *bwg_id,
223 					   u8 *tsa)
224 {
225 	u32 reg;
226 	u8 i;
227 
228 	reg = IXGBE_READ_REG(hw, IXGBE_PDPMCS);
229 	/* Enable Data Plane Arbiter */
230 	reg &= ~IXGBE_PDPMCS_ARBDIS;
231 	/* Enable DFP and Transmit Recycle Mode */
232 	reg |= (IXGBE_PDPMCS_TPPAC | IXGBE_PDPMCS_TRM);
233 
234 	IXGBE_WRITE_REG(hw, IXGBE_PDPMCS, reg);
235 
236 	/* Configure traffic class credits and priority */
237 	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
238 		reg = refill[i];
239 		reg |= (u32)(max[i]) << IXGBE_TDPT2TCCR_MCL_SHIFT;
240 		reg |= (u32)(bwg_id[i]) << IXGBE_TDPT2TCCR_BWG_SHIFT;
241 
242 		if (tsa[i] == ixgbe_dcb_tsa_group_strict_cee)
243 			reg |= IXGBE_TDPT2TCCR_GSP;
244 
245 		if (tsa[i] == ixgbe_dcb_tsa_strict)
246 			reg |= IXGBE_TDPT2TCCR_LSP;
247 
248 		IXGBE_WRITE_REG(hw, IXGBE_TDPT2TCCR(i), reg);
249 	}
250 
251 	/* Enable Tx packet buffer division */
252 	reg = IXGBE_READ_REG(hw, IXGBE_DTXCTL);
253 	reg |= IXGBE_DTXCTL_ENDBUBD;
254 	IXGBE_WRITE_REG(hw, IXGBE_DTXCTL, reg);
255 
256 	return IXGBE_SUCCESS;
257 }
258 
259 /**
260  * ixgbe_dcb_config_pfc_82598 - Config priority flow control
261  * @hw: pointer to hardware structure
262  * @pfc_en: enabled pfc bitmask
263  *
264  * Configure Priority Flow Control for each traffic class.
265  */
ixgbe_dcb_config_pfc_82598(struct ixgbe_hw * hw,u8 pfc_en)266 s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
267 {
268 	u32 fcrtl, reg;
269 	u8 i;
270 
271 	/* Enable Transmit Priority Flow Control */
272 	reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
273 	reg &= ~IXGBE_RMCS_TFCE_802_3X;
274 	reg |= IXGBE_RMCS_TFCE_PRIORITY;
275 	IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
276 
277 	/* Enable Receive Priority Flow Control */
278 	reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
279 	reg &= ~(IXGBE_FCTRL_RPFCE | IXGBE_FCTRL_RFCE);
280 
281 	if (pfc_en)
282 		reg |= IXGBE_FCTRL_RPFCE;
283 
284 	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
285 
286 	/* Configure PFC Tx thresholds per TC */
287 	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
288 		if (!(pfc_en & (1 << i))) {
289 			IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0);
290 			IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0);
291 			continue;
292 		}
293 
294 		fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
295 		reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
296 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
297 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
298 	}
299 
300 	/* Configure pause time */
301 	reg = hw->fc.pause_time | (hw->fc.pause_time << 16);
302 	for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++)
303 		IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
304 
305 	/* Configure flow control refresh threshold value */
306 	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
307 
308 	return IXGBE_SUCCESS;
309 }
310 
311 /**
312  * ixgbe_dcb_config_tc_stats_82598 - Configure traffic class statistics
313  * @hw: pointer to hardware structure
314  *
315  * Configure queue statistics registers, all queues belonging to same traffic
316  * class uses a single set of queue statistics counters.
317  */
ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw * hw)318 s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
319 {
320 	u32 reg = 0;
321 	u8 i = 0;
322 	u8 j = 0;
323 
324 	/* Receive Queues stats setting -  8 queues per statistics reg */
325 	for (i = 0, j = 0; i < 15 && j < 8; i = i + 2, j++) {
326 		reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i));
327 		reg |= ((0x1010101) * j);
328 		IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), reg);
329 		reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i + 1));
330 		reg |= ((0x1010101) * j);
331 		IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i + 1), reg);
332 	}
333 	/* Transmit Queues stats setting -  4 queues per statistics reg*/
334 	for (i = 0; i < 8; i++) {
335 		reg = IXGBE_READ_REG(hw, IXGBE_TQSMR(i));
336 		reg |= ((0x1010101) * i);
337 		IXGBE_WRITE_REG(hw, IXGBE_TQSMR(i), reg);
338 	}
339 
340 	return IXGBE_SUCCESS;
341 }
342 
343 /**
344  * ixgbe_dcb_hw_config_82598 - Config and enable DCB
345  * @hw: pointer to hardware structure
346  * @link_speed: unused
347  * @refill: refill credits index by traffic class
348  * @max: max credits index by traffic class
349  * @bwg_id: bandwidth grouping indexed by traffic class
350  * @tsa: transmission selection algorithm indexed by traffic class
351  *
352  * Configure dcb settings and enable dcb mode.
353  */
ixgbe_dcb_hw_config_82598(struct ixgbe_hw * hw,int link_speed,u16 * refill,u16 * max,u8 * bwg_id,u8 * tsa)354 s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, int link_speed,
355 			      u16 *refill, u16 *max, u8 *bwg_id,
356 			      u8 *tsa)
357 {
358 	UNREFERENCED_1PARAMETER(link_speed);
359 
360 	ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, tsa);
361 	ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max, bwg_id,
362 					       tsa);
363 	ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max, bwg_id,
364 					       tsa);
365 	ixgbe_dcb_config_tc_stats_82598(hw);
366 
367 	return IXGBE_SUCCESS;
368 }
369