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 */
ecore_map_q_cos(struct _lm_device_t * pdev,u32_t q_num,u32_t new_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 */
ecore_dcb_config_qm(struct _lm_device_t * pdev,enum cos_mode mode,struct priority_cos * traffic_cos)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
ecore_init_max(const struct cmng_init_input * input_data,u32_t r_param,struct cmng_init * ram_data)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
ecore_init_max_per_vn(u16_t vnic_max_rate,struct rate_shaping_vars_per_vn * ram_data)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
ecore_init_min(const struct cmng_init_input * input_data,u32_t r_param,struct cmng_init * ram_data)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
ecore_init_fw_wrr(const struct cmng_init_input * input_data,u32_t r_param,struct cmng_init * ram_data)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
ecore_init_safc(const struct cmng_init_input * input_data,struct cmng_init * ram_data)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 */
ecore_init_cmng(const struct cmng_init_input * input_data,struct cmng_init * ram_data)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