xref: /titanic_51/usr/src/uts/common/io/bnxe/577xx/drivers/common/lm/fw/bnxe_fw_funcs.c (revision d14abf155341d55053c76eeec58b787a456b753b)
1 
2 
3 
4 
5 #include "lm5710.h"
6 #include "init_defs.h"
7 
8 /* Vnics per mode */
9 #define ECORE_PORT2_MODE_NUM_VNICS 4
10 
11 
12 /* QM queue numbers */
13 #define ECORE_ETH_Q		0
14 #define ECORE_TOE_Q		3
15 #define ECORE_TOE_ACK_Q		6
16 #define ECORE_ISCSI_Q		9
17 #define ECORE_ISCSI_ACK_Q	11
18 #define ECORE_FCOE_Q		10
19 
20 /* Vnics per mode */
21 #define ECORE_PORT4_MODE_NUM_VNICS 2
22 
23 /* COS offset for port1 in E3 B0 4port mode */
24 #define ECORE_E3B0_PORT1_COS_OFFSET 3
25 
26 /* QM Register addresses */
27 #define ECORE_Q_VOQ_REG_ADDR(pf_q_num)\
28 	(QM_REG_QVOQIDX_0 + 4 * (pf_q_num))
29 #define ECORE_VOQ_Q_REG_ADDR(cos, pf_q_num)\
30 	(QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5)))
31 #define ECORE_Q_CMDQ_REG_ADDR(pf_q_num)\
32 	(QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4))
33 
34 /* extracts the QM queue number for the specified port and vnic */
35 #define ECORE_PF_Q_NUM(q_num, port, vnic)\
36 	((((port) << 1) | (vnic)) * 16 + (q_num))
37 
38 
39 /* Maps the specified queue to the specified COS */
40 void ecore_map_q_cos(struct _lm_device_t *pdev, u32_t q_num, u32_t new_cos)
41 {
42 	/* find current COS mapping */
43 	u32_t curr_cos = REG_RD(pdev, QM_REG_QVOQIDX_0 + q_num * 4);
44 
45 	/* check if queue->COS mapping has changed */
46 	if (curr_cos != new_cos) {
47 		u32_t num_vnics = ECORE_PORT2_MODE_NUM_VNICS;
48 		u32_t reg_addr, reg_bit_map, vnic;
49 
50 		/* update parameters for 4port mode */
51 		if (INIT_MODE_FLAGS(pdev) & MODE_PORT4) {
52 			num_vnics = ECORE_PORT4_MODE_NUM_VNICS;
53 			if (PORT_ID(pdev)) {
54 				curr_cos += ECORE_E3B0_PORT1_COS_OFFSET;
55 				new_cos += ECORE_E3B0_PORT1_COS_OFFSET;
56 			}
57 		}
58 
59 		/* change queue mapping for each VNIC */
60 		for (vnic = 0; vnic < num_vnics; vnic++) {
61 			u32_t pf_q_num =
62 				ECORE_PF_Q_NUM(q_num, PORT_ID(pdev), vnic);
63 			u32_t q_bit_map = 1 << (pf_q_num & 0x1f);
64 
65 			/* overwrite queue->VOQ mapping */
66 			REG_WR(pdev, ECORE_Q_VOQ_REG_ADDR(pf_q_num), new_cos);
67 
68 			/* clear queue bit from current COS bit map */
69 			reg_addr = ECORE_VOQ_Q_REG_ADDR(curr_cos, pf_q_num);
70 			reg_bit_map = REG_RD(pdev, reg_addr);
71 			REG_WR(pdev, reg_addr, reg_bit_map & (~q_bit_map));
72 
73 			/* set queue bit in new COS bit map */
74 			reg_addr = ECORE_VOQ_Q_REG_ADDR(new_cos, pf_q_num);
75 			reg_bit_map = REG_RD(pdev, reg_addr);
76 			REG_WR(pdev, reg_addr, reg_bit_map | q_bit_map);
77 
78 			/* set/clear queue bit in command-queue bit map
79 			(E2/E3A0 only, valid COS values are 0/1) */
80 			if (!(INIT_MODE_FLAGS(pdev) & MODE_E3_B0)) {
81 				reg_addr = ECORE_Q_CMDQ_REG_ADDR(pf_q_num);
82 				reg_bit_map = REG_RD(pdev, reg_addr);
83 				q_bit_map = 1 << (2 * (pf_q_num & 0xf));
84 				reg_bit_map = new_cos ?
85 					      (reg_bit_map | q_bit_map) :
86 					      (reg_bit_map & (~q_bit_map));
87 				REG_WR(pdev, reg_addr, reg_bit_map);
88 			}
89 		}
90 	}
91 }
92 
93 /* Configures the QM according to the specified per-traffic-type COSes */
94 void ecore_dcb_config_qm(struct _lm_device_t *pdev, enum cos_mode mode,
95 				       struct priority_cos *traffic_cos)
96 {
97 	ecore_map_q_cos(pdev, ECORE_FCOE_Q,
98 			traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos);
99 	ecore_map_q_cos(pdev, ECORE_ISCSI_Q,
100 			traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
101 	ecore_map_q_cos(pdev, ECORE_ISCSI_ACK_Q,
102 		traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
103 	if (mode != STATIC_COS) {
104 		/* required only in OVERRIDE_COS mode */
105 		ecore_map_q_cos(pdev, ECORE_ETH_Q,
106 				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
107 		ecore_map_q_cos(pdev, ECORE_TOE_Q,
108 				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
109 		ecore_map_q_cos(pdev, ECORE_TOE_ACK_Q,
110 				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
111 	}
112 }
113 
114 
115 /*
116  * congestion managment port init api description
117  * the api works as follows:
118  * the driver should pass the cmng_init_input struct, the port_init function
119  * will prepare the required internal ram structure which will be passed back
120  * to the driver (cmng_init) that will write it into the internal ram.
121  *
122  * IMPORTANT REMARKS:
123  * 1. the cmng_init struct does not represent the contiguous internal ram
124  *    structure. the driver should use the XSTORM_CMNG_PERPORT_VARS_OFFSET
125  *    offset in order to write the port sub struct and the
126  *    PFID_FROM_PORT_AND_VNIC offset for writing the vnic sub struct (in other
127  *    words - don't use memcpy!).
128  * 2. although the cmng_init struct is filled for the maximal vnic number
129  *    possible, the driver should only write the valid vnics into the internal
130  *    ram according to the appropriate port mode.
131  */
132 #define BITS_TO_BYTES(x) ((x)/8)
133 
134 /* CMNG constants, as derived from system spec calculations */
135 
136 /* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */
137 #define DEF_MIN_RATE 100
138 
139 /* resolution of the rate shaping timer - 400 usec */
140 #define RS_PERIODIC_TIMEOUT_USEC 400
141 
142 /*
143  *  number of bytes in single QM arbitration cycle -
144  *  coefficient for calculating the fairness timer
145  */
146 #define QM_ARB_BYTES 160000
147 
148 /* resolution of Min algorithm 1:100 */
149 #define MIN_RES 100
150 
151 /*
152  *  how many bytes above threshold for
153  *  the minimal credit of Min algorithm
154  */
155 #define MIN_ABOVE_THRESH 32768
156 
157 /*
158  *  Fairness algorithm integration time coefficient -
159  *  for calculating the actual Tfair
160  */
161 #define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES)
162 
163 /* Memory of fairness algorithm - 2 cycles */
164 #define FAIR_MEM 2
165 #define SAFC_TIMEOUT_USEC 52
166 
167 #define SDM_TICKS 4
168 
169 
170 void ecore_init_max(const struct cmng_init_input *input_data,
171 				  u32_t r_param, struct cmng_init *ram_data)
172 {
173 	u32_t vnic;
174 	struct cmng_vnic *vdata = &ram_data->vnic;
175 	struct cmng_struct_per_port *pdata = &ram_data->port;
176 	/*
177 	 * rate shaping per-port variables
178 	 *  100 micro seconds in SDM ticks = 25
179 	 *  since each tick is 4 microSeconds
180 	 */
181 
182 	pdata->rs_vars.rs_periodic_timeout =
183 	RS_PERIODIC_TIMEOUT_USEC / SDM_TICKS;
184 
185 	/* this is the threshold below which no timer arming will occur.
186 	 *  1.25 coefficient is for the threshold to be a little bigger
187 	 *  then the real time to compensate for timer in-accuracy
188 	 */
189 	pdata->rs_vars.rs_threshold =
190 	(5 * RS_PERIODIC_TIMEOUT_USEC * r_param)/4;
191 
192 	/* rate shaping per-vnic variables */
193 	for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) {
194 		/* global vnic counter */
195 		vdata->vnic_max_rate[vnic].vn_counter.rate =
196 		input_data->vnic_max_rate[vnic];
197 		/*
198 		 * maximal Mbps for this vnic
199 		 * the quota in each timer period - number of bytes
200 		 * transmitted in this period
201 		 */
202 		vdata->vnic_max_rate[vnic].vn_counter.quota =
203 			RS_PERIODIC_TIMEOUT_USEC *
204 			(u32_t)vdata->vnic_max_rate[vnic].vn_counter.rate / 8;
205 	}
206 
207 }
208 
209 void ecore_init_max_per_vn(u16_t vnic_max_rate,
210 				  struct rate_shaping_vars_per_vn *ram_data)
211 {
212 	/* global vnic counter */
213 	ram_data->vn_counter.rate = vnic_max_rate;
214 
215 	/*
216 	* maximal Mbps for this vnic
217 	* the quota in each timer period - number of bytes
218 	* transmitted in this period
219 	*/
220 	ram_data->vn_counter.quota =
221 		RS_PERIODIC_TIMEOUT_USEC * (u32_t)vnic_max_rate / 8;
222 }
223 
224 void ecore_init_min(const struct cmng_init_input *input_data,
225 				  u32_t r_param, struct cmng_init *ram_data)
226 {
227 	u32_t vnic, fair_periodic_timeout_usec, vnicWeightSum, tFair;
228 	struct cmng_vnic *vdata = &ram_data->vnic;
229 	struct cmng_struct_per_port *pdata = &ram_data->port;
230 
231 	/* this is the resolution of the fairness timer */
232 	fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
233 
234 	/*
235 	 * fairness per-port variables
236 	 * for 10G it is 1000usec. for 1G it is 10000usec.
237 	 */
238 	tFair = T_FAIR_COEF / input_data->port_rate;
239 
240 	/* this is the threshold below which we won't arm the timer anymore */
241 	pdata->fair_vars.fair_threshold = QM_ARB_BYTES;
242 
243 	/*
244 	 *  we multiply by 1e3/8 to get bytes/msec. We don't want the credits
245 	 *  to pass a credit of the T_FAIR*FAIR_MEM (algorithm resolution)
246 	 */
247 	pdata->fair_vars.upper_bound = r_param * tFair * FAIR_MEM;
248 
249 	/* since each tick is 4 microSeconds */
250 	pdata->fair_vars.fairness_timeout =
251 				fair_periodic_timeout_usec / SDM_TICKS;
252 
253 	/* calculate sum of weights */
254 	vnicWeightSum = 0;
255 
256 	for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++)
257 		vnicWeightSum += input_data->vnic_min_rate[vnic];
258 
259 	/* global vnic counter */
260 	if (vnicWeightSum > 0) {
261 		/* fairness per-vnic variables */
262 		for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) {
263 			/*
264 			 *  this is the credit for each period of the fairness
265 			 *  algorithm - number of bytes in T_FAIR (this vnic
266 			 *  share of the port rate)
267 			 */
268 			vdata->vnic_min_rate[vnic].vn_credit_delta =
269 				((u32_t)(input_data->vnic_min_rate[vnic]) * 100 *
270 				(T_FAIR_COEF / (8 * 100 * vnicWeightSum)));
271 			if (vdata->vnic_min_rate[vnic].vn_credit_delta <
272 			    pdata->fair_vars.fair_threshold +
273 			    MIN_ABOVE_THRESH) {
274 				vdata->vnic_min_rate[vnic].vn_credit_delta =
275 					pdata->fair_vars.fair_threshold +
276 					MIN_ABOVE_THRESH;
277 			}
278 		}
279 	}
280 }
281 
282 void ecore_init_fw_wrr(const struct cmng_init_input *input_data,
283 				     u32_t r_param, struct cmng_init *ram_data)
284 {
285 	u32_t vnic, cos;
286 	u32_t cosWeightSum = 0;
287 	struct cmng_vnic *vdata = &ram_data->vnic;
288 	struct cmng_struct_per_port *pdata = &ram_data->port;
289 
290 	for (cos = 0; cos < MAX_COS_NUMBER; cos++)
291 		cosWeightSum += input_data->cos_min_rate[cos];
292 
293 	if (cosWeightSum > 0) {
294 
295 		for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) {
296 			/*
297 			 *  Since cos and vnic shouldn't work together the rate
298 			 *  to divide between the coses is the port rate.
299 			 */
300 			u32_t *ccd = vdata->vnic_min_rate[vnic].cos_credit_delta;
301 			for (cos = 0; cos < MAX_COS_NUMBER; cos++) {
302 				/*
303 				 * this is the credit for each period of
304 				 * the fairness algorithm - number of bytes
305 				 * in T_FAIR (this cos share of the vnic rate)
306 				 */
307 				ccd[cos] =
308 				    ((u32_t)input_data->cos_min_rate[cos] * 100 *
309 				    (T_FAIR_COEF / (8 * 100 * cosWeightSum)));
310 				 if (ccd[cos] < pdata->fair_vars.fair_threshold
311 						+ MIN_ABOVE_THRESH) {
312 					ccd[cos] =
313 					    pdata->fair_vars.fair_threshold +
314 					    MIN_ABOVE_THRESH;
315 				}
316 			}
317 		}
318 	}
319 }
320 
321 void ecore_init_safc(const struct cmng_init_input *input_data,
322 				   struct cmng_init *ram_data)
323 {
324 	/* in microSeconds */
325 	ram_data->port.safc_vars.safc_timeout_usec = SAFC_TIMEOUT_USEC;
326 }
327 
328 /* Congestion management port init */
329 void ecore_init_cmng(const struct cmng_init_input *input_data,
330 				   struct cmng_init *ram_data)
331 {
332 	u32_t r_param;
333 	mm_mem_zero(ram_data,sizeof(struct cmng_init));
334 
335 	ram_data->port.flags = input_data->flags;
336 
337 	/*
338 	 *  number of bytes transmitted in a rate of 10Gbps
339 	 *  in one usec = 1.25KB.
340 	 */
341 	r_param = BITS_TO_BYTES(input_data->port_rate);
342 	ecore_init_max(input_data, r_param, ram_data);
343 	ecore_init_min(input_data, r_param, ram_data);
344 	ecore_init_fw_wrr(input_data, r_param, ram_data);
345 	ecore_init_safc(input_data, ram_data);
346 }
347 
348