1 /*******************************************************************************
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright 2014 QLogic Corporation
22 * The contents of this file are subject to the terms of the
23 * QLogic End User License (the "License").
24 * You may not use this file except in compliance with the License.
25 *
26 * You can obtain a copy of the License at
27 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
28 * QLogic_End_User_Software_License.txt
29 * See the License for the specific language governing permissions
30 * and limitations under the License.
31 *
32 *
33 * Module Description:
34 *
35 *
36 * History:
37 * 01/10/10 Shay Haroush Inception.
38 ******************************************************************************/
39
40 #include "lm5710.h"
41 #include "license.h"
42 #include "mcp_shmem.h"
43 #include "577xx_int_offsets.h"
44 #include "command.h"
45
46
47 #define DCBX_ILLEGAL_PG (0xFF)
48 typedef struct _pg_entry_help_data_t
49 {
50 u8_t num_of_dif_pri;
51 u8_t pg;
52 u32_t pg_priority;
53 }pg_entry_help_data_t;
54
55 typedef struct _pg_help_data_t
56 {
57 pg_entry_help_data_t pg_entry_data[LLFC_DRIVER_TRAFFIC_TYPE_MAX];
58 u8_t num_of_pg;
59 }pg_help_data_t;
60
61 // Used for IE classification debugging
62 typedef struct _lm_dcbx_ie_classif_dbg_t
63 {
64 u16_t pri;
65 u8_t num_entries;
66 }lm_dcbx_ie_classif_dbg_t;
67
68 #define DCBX_INVALID_COS_BW (0xFFFFFFFF)
69 #define DCBX_MAX_COS_BW (0xFF)
70
71
72 #define DCBX_MIB_IS_APP_ENABLED(_app_en,_mib_error_filed) \
73 ((TRUE == _app_en) && \
74 (!GET_FLAGS(_mib_error_filed,(DCBX_LOCAL_APP_ERROR| DCBX_LOCAL_APP_MISMATCH))))
75
76 #define DCBX_MIB_IS_ETS_ENABLED(_app_en,_mib_error_filed,_mib_ets_en_filed) \
77 ((TRUE == _app_en)&& \
78 (!GET_FLAGS(_mib_error_filed,DCBX_LOCAL_ETS_ERROR))&& \
79 _mib_ets_en_filed)
80
81 #define DCBX_MIB_IS_PFC_ENABLED(_app_en,_mib_error_filed,_mib_pfc_en_filed) \
82 ((TRUE == _app_en)&& \
83 (!GET_FLAGS(_mib_error_filed,(DCBX_LOCAL_PFC_ERROR | DCBX_LOCAL_PFC_MISMATCH)))&& \
84 _mib_pfc_en_filed)
85
86
87 typedef struct _cos_entry_help_data_t
88 {
89 u32_t pri_join_mask;
90 u32_t cos_bw;
91 u8_t s_pri;
92 u8_t b_pausable;
93 }cos_entry_help_data_t;
94
95 typedef struct _cos_help_data_t
96 {
97 cos_entry_help_data_t entry_data[DCBX_COS_MAX_NUM];
98 u8_t num_of_cos;
99 }cos_help_data_t;
100
101 /**********************foreword declaration************************************/
102 /**
103 * @description
104 * Function is needed for PMF migration in order to synchronize
105 * the new PMF that DCBX results has ended.
106 * @param pdev
107 *
108 * @return u8_t
109 * This function returns TRUE if DCBX completion received on
110 * this port
111 */
112 STATIC u8_t
113 lm_dcbx_check_drv_flags(
114 IN struct _lm_device_t *pdev,
115 IN const u32_t flags_bits_to_check);
116
117 /*******************************************************************************
118 * Description: Parse ets_pri_pg data and spread it from nibble to 32 bits.
119 *
120 * Return:
121 ******************************************************************************/
122 STATIC void
123 lm_dcbx_get_ets_pri_pg_tbl(struct _lm_device_t * pdev,
124 OUT u32_t * set_configuration_ets_pg,
125 IN const u32_t * mcp_pri_pg_tbl,
126 IN const u8_t set_priority_app_size,
127 IN const u8_t mcp_pri_pg_tbl_size);
128
129
130 void lm_dcbx_update_lpme_set_params(struct _lm_device_t *pdev);
131
132 STATIC void
133 lm_dcbx_ie_ets_cee_to_ieee_unparse(
134 INOUT lm_device_t *pdev,
135 IN const dcbx_ets_feature_t *cee_ets,
136 OUT dcb_ets_tsa_param_t *ieee_ets,
137 OUT u32_t *flags
138 );
139
140 STATIC lm_status_t
141 lm_dcbx_read_admin_mib( IN lm_device_t *pdev,
142 OUT lldp_admin_mib_t *p_admin_mib,
143 OUT u32_t *p_admin_mib_offset);
144
145 /**********************Start of PFC code**************************************/
146
147 /**
148 * Check if DCB is configured.
149 * In SF is_dcbx_neg_received is always valid.
150 * DRV_FLAGS_DCB_CONFIGURED is always valid.
151 * @param pdev
152 *
153 * @return u8_t
154 */
155 u8_t
lm_dcbx_is_dcb_config(IN lm_device_t * pdev)156 lm_dcbx_is_dcb_config(IN lm_device_t *pdev)
157 {
158 // Valid in SF
159 u8_t const dcb_config_sf = pdev->dcbx_info.is_dcbx_neg_received;
160 // Always valid.
161 u8_t const dcb_config = lm_dcbx_check_drv_flags(pdev, DRV_FLAGS_DCB_CONFIGURED);
162
163 if(FALSE == IS_MULTI_VNIC(pdev))
164 {
165 DbgBreakIf(dcb_config != dcb_config_sf);
166 }
167
168 return dcb_config;
169 }
170 /*******************************************************************************
171 * Description: Fill Fw struct that will be sent in DCBX start ramrod
172 *
173 * Return:
174 ******************************************************************************/
175 void
lm_dcbx_print_cos_params(IN OUT lm_device_t * pdev,IN struct flow_control_configuration * pfc_fw_cfg)176 lm_dcbx_print_cos_params(
177 IN OUT lm_device_t *pdev,
178 IN struct flow_control_configuration *pfc_fw_cfg)
179 {
180 #if DBG
181 u8_t pri = 0;
182 u8_t cos = 0;
183
184 DbgMessage(pdev, INFORM, "******************DCBX configuration******************************\n");
185 DbgMessage(pdev, INFORM, "pfc_fw_cfg->dcb_version %x\n",pfc_fw_cfg->dcb_version);
186 DbgMessage(pdev, INFORM, "pdev->params.dcbx_port_params.pfc.priority_non_pauseable_mask %x\n",
187 pdev->params.dcbx_port_params.pfc.priority_non_pauseable_mask);
188
189 for( cos =0 ; cos < pdev->params.dcbx_port_params.ets.num_of_cos ; cos++)
190 {
191 DbgMessage(pdev, INFORM, "pdev->params.dcbx_port_params.ets.cos_params[%d].pri_bitmask %x\n",cos,
192 pdev->params.dcbx_port_params.ets.cos_params[cos].pri_bitmask);
193
194 DbgMessage(pdev, INFORM, "pdev->params.dcbx_port_params.ets.cos_params[%d].bw_tbl %x\n",cos,
195 pdev->params.dcbx_port_params.ets.cos_params[cos].bw_tbl);
196
197 DbgMessage(pdev, INFORM, "pdev->params.dcbx_port_params.ets.cos_params[%d].strict %x\n",cos,
198 pdev->params.dcbx_port_params.ets.cos_params[cos].s_pri);
199
200 DbgMessage(pdev, INFORM, "pdev->params.dcbx_port_params.ets.cos_params[%d].pauseable %x\n",cos,
201 pdev->params.dcbx_port_params.ets.cos_params[cos].pauseable);
202 }
203
204 for (pri = 0; pri < ARRSIZE(pdev->params.dcbx_port_params.app.traffic_type_priority); pri++)
205 {
206 DbgMessage(pdev, INFORM, "pfc_fw_cfg->traffic_type_to_priority_cos[%d].priority %x\n",pri,
207 pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority);
208
209 DbgMessage(pdev, INFORM, "pfc_fw_cfg->traffic_type_to_priority_cos[%d].cos %x\n",pri,
210 pfc_fw_cfg->traffic_type_to_priority_cos[pri].cos);
211 }
212
213 #endif //DBG
214 }
215 /*******************************************************************************
216 * Description: Fill Fw struct that will be sent in DCBX start ramrod
217 *
218 * Return:
219 ******************************************************************************/
220 void
lm_dcbx_fw_struct(IN OUT lm_device_t * pdev)221 lm_dcbx_fw_struct(
222 IN OUT lm_device_t *pdev)
223 {
224 struct flow_control_configuration *pfc_fw_cfg = NULL;
225 u16_t pri_bit = 0;
226 u8_t cos = 0;
227 u8_t pri = 0;
228
229 if(CHK_NULL(pdev->dcbx_info.pfc_fw_cfg_virt))
230 {
231 DbgBreakMsg("lm_pfc_fw_struct_e2:pfc_fw_cfg_virt was not allocated DCBX should have been disabled ");
232 return;
233 }
234 pfc_fw_cfg = (struct flow_control_configuration*)pdev->dcbx_info.pfc_fw_cfg_virt;
235 mm_mem_zero(pfc_fw_cfg, sizeof(struct flow_control_configuration));
236
237 pfc_fw_cfg->dcb_version = 0; // Reserved field
238
239 // If priority tagging (app ID) isn't enabled then DCB should be disabled.
240 if(FALSE == pdev->params.dcbx_port_params.app.enabled)
241 {
242 // Disabled DCB at FW.
243 pfc_fw_cfg->dcb_enabled = 0;
244 return;
245 }
246
247 DbgBreakIf(FALSE == pdev->params.dcbx_port_params.dcbx_enabled);
248
249 // Enable priority tagging and DCB at FW
250 pfc_fw_cfg->dcb_enabled = 1;
251 pfc_fw_cfg->dont_add_pri_0 = 1;
252
253 // Default initialization
254 for (pri = 0; pri < ARRSIZE(pfc_fw_cfg->traffic_type_to_priority_cos) ; pri++)
255 {
256 pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
257 pfc_fw_cfg->traffic_type_to_priority_cos[pri].cos = 0;
258 }
259
260 // Fill priority parameters
261 for (pri = 0; pri < ARRSIZE(pdev->params.dcbx_port_params.app.traffic_type_priority); pri++)
262 {
263 DbgBreakIf(pdev->params.dcbx_port_params.app.traffic_type_priority[pri] >= MAX_PFC_PRIORITIES);
264 pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority =
265 (u8_t)pdev->params.dcbx_port_params.app.traffic_type_priority[pri];
266
267 pri_bit = 1 << pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority;
268 // Fill COS parameters based on COS calculated to make it more generally for future use
269 for( cos =0 ; cos < pdev->params.dcbx_port_params.ets.num_of_cos ; cos++)
270 {
271 if (pdev->params.dcbx_port_params.ets.cos_params[cos].pri_bitmask & pri_bit)
272 {
273 pfc_fw_cfg->traffic_type_to_priority_cos[pri].cos = cos;
274 }
275 }
276 }
277 lm_dcbx_print_cos_params(pdev,
278 pfc_fw_cfg);
279
280 }
281 /*******************************************************************************
282 * Description:
283 *
284 * Return:
285 ******************************************************************************/
286 static void
lm_pfc_clear(lm_device_t * pdev)287 lm_pfc_clear(lm_device_t *pdev)
288 {
289 u8_t elink_status = ELINK_STATUS_OK;
290
291 MM_ACQUIRE_PHY_LOCK(pdev);
292 RESET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_PFC_ENABLED);
293 elink_status = elink_update_pfc(&pdev->params.link, &pdev->vars.link, 0);
294 DbgBreakIf(ELINK_STATUS_OK != elink_status);
295 MM_RELEASE_PHY_LOCK(pdev);
296 }
297 /*******************************************************************************
298 * Description:
299 *
300 * Return:
301 ******************************************************************************/
lm_pfc_set_clc(lm_device_t * pdev)302 static void lm_pfc_set_clc(lm_device_t *pdev)
303 {
304 struct elink_nig_brb_pfc_port_params pfc_params = {0};
305 pg_params_t *ets = &pdev->params.dcbx_port_params.ets;
306 u32_t val = 0;
307 u32_t pri_bit = 0;
308 u8_t i = 0;
309 u8_t elink_status = ELINK_STATUS_OK;
310 const u32_t class_rx_pause = 0;
311 const u32_t class_rx_nonpause = 1;
312
313 DbgBreakIf(class_rx_pause == class_rx_nonpause);
314 DbgBreakIf((0 != class_rx_pause) && (1 != class_rx_pause));
315 DbgBreakIf((0 != class_rx_nonpause) && (1 != class_rx_nonpause));
316
317 // Tx COS configuration
318 // Here COS == pri
319 pfc_params.num_of_rx_cos_priority_mask = ets->num_of_cos;
320
321 for(i = 0 ; i < ets->num_of_cos ; i++)
322 {
323 // We configured in this register only the pause-able bits.(non pause-able aren't configure at all)
324 // it is done to avoid false pauses from network.
325 pfc_params.rx_cos_priority_mask[i] =
326 ets->cos_params[i].pri_bitmask & LM_DCBX_PFC_PRI_PAUSE_MASK(pdev);
327 }
328
329 // Rx COS configuration
330 // Changing PFC RX configuration . In RX COS0 will always be configured to lossless
331 // and COS1 to lossy.
332 // Here i == pri
333 for(i = 0 ; i < MAX_PFC_PRIORITIES ; i++)
334 {
335 pri_bit = 1 << i;
336
337 if(pri_bit & LM_DCBX_PFC_PRI_PAUSE_MASK(pdev))
338 {
339 val |= class_rx_pause << (i * 4);
340 }
341 else
342 {
343 val |= class_rx_nonpause << (i * 4);
344 }
345 }
346
347 pfc_params.pkt_priority_to_cos = val;
348
349 if(0 == class_rx_pause)
350 {
351 // RX Classs0: On BRB class0 trigger PFC TX. Classes are low-priority for port #. When PFC is triggered on class 0 send PFC with this priorities to stop
352 pfc_params.llfc_low_priority_classes = LM_DCBX_PFC_PRI_PAUSE_MASK(pdev);
353 // RX Classs1: On BRB class1 trigger PFC TX. Classes are low-priority for port #. When PFC is triggered on class 1 send PFC with this priorities to stop
354 pfc_params.llfc_high_priority_classes = 0;
355 }
356 else
357 {
358 DbgBreakIf(1 != class_rx_pause);
359 pfc_params.llfc_low_priority_classes = 0;
360 pfc_params.llfc_high_priority_classes = LM_DCBX_PFC_PRI_PAUSE_MASK(pdev);
361 }
362
363 MM_ACQUIRE_PHY_LOCK(pdev);
364 SET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_PFC_ENABLED);
365 elink_status = elink_update_pfc(&pdev->params.link, &pdev->vars.link, &pfc_params);
366 DbgBreakIf(ELINK_STATUS_OK != elink_status);
367 MM_RELEASE_PHY_LOCK(pdev);
368 }
369 /*******************************************************************************
370 * Description:
371 *
372 * Return:
373 ******************************************************************************/
374 void
lm_pfc_set_pfc(lm_device_t * pdev)375 lm_pfc_set_pfc(
376 lm_device_t *pdev)
377 {
378 DbgBreakIf(CHIP_IS_E1x(pdev));
379 //1. Fills up common PFC structures if required.
380 //2. Configure BRB
381 //3. Configure NIG.
382 //4. Configure the MAC via the CLC:
383 //" CLC must first check if BMAC is not in reset and only then configures the BMAC
384 //" Or, configure EMAC.
385 lm_pfc_set_clc(pdev);
386 }
387
388 /*******************************************************************************
389 * Description:
390 *
391 * Return:
392 ******************************************************************************/
393 void
lm_pfc_handle_pfc(lm_device_t * pdev)394 lm_pfc_handle_pfc(
395 lm_device_t *pdev)
396 {
397 DbgBreakIf(CHIP_IS_E1x(pdev));
398 // Only for testing DCBX client the registry key won't be 0 or 1
399 // Only a call from lm_chip_init can be not 0 or 1
400 if(TRUE == pdev->params.dcbx_port_params.pfc.enabled)
401 {// PFC enabled
402 lm_pfc_set_pfc(pdev);
403 }
404 else
405 {// PFC disabled go back to pause if needed
406 lm_pfc_clear(pdev);
407 }
408 }
409
410 void
lm_dcbx_2cos_limit_update_ets_config(lm_device_t * pdev)411 lm_dcbx_2cos_limit_update_ets_config(
412 lm_device_t *pdev)
413 {
414
415 pg_params_t *ets = &(pdev->params.dcbx_port_params.ets);
416 u8_t elink_status = ELINK_STATUS_OK;
417 u32_t bw_tbl_0 = 0;
418 u32_t bw_tbl_1 = 0;
419
420 if ((0 == ets->num_of_cos ) ||
421 (DCBX_COS_MAX_NUM_E2E3A0 < ets->num_of_cos))
422 {
423 DbgMessage(pdev, FATAL, " illegal num of cos= %x",ets->num_of_cos);
424 DbgBreakIf(1);
425 return;
426 }
427 //valid COS entries
428 if( 1 == ets->num_of_cos)
429 {// No ETS
430 return;
431 }
432 DbgBreakIf(2 != ets->num_of_cos);
433
434 if(((DCBX_S_PRI_INVALID == ets->cos_params[0].s_pri)&&
435 (DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
436 ((DCBX_S_PRI_INVALID == ets->cos_params[1].s_pri)&&
437 (DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl)))
438 {
439 DbgMessage(pdev, FATAL, "We expect all the COS to have at least bw_limit or strict"
440 "ets->cos_params[0].strict= %x"
441 "ets->cos_params[0].bw_tbl= %x"
442 "ets->cos_params[1].strict= %x"
443 "ets->cos_params[1].bw_tbl= %x"
444 ,ets->cos_params[0].s_pri, ets->cos_params[0].bw_tbl
445 ,ets->cos_params[1].s_pri, ets->cos_params[1].bw_tbl);
446
447 // CQ47518,CQ47504 Assert in the eVBD because of illegal ETS parameters reception. When
448 //switch changes configuration in runtime it sends several packets that
449 //contain illegal configuration until the actual configuration is merged.
450 //DbgBreakIf(1);
451 return;
452 }
453 // If we join a group and there is bw_tbl and strict then bw rules.
454 if ((DCBX_INVALID_COS_BW != ets->cos_params[0].bw_tbl) &&
455 (DCBX_INVALID_COS_BW != ets->cos_params[1].bw_tbl))
456 {
457 DbgBreakIf(0 == (ets->cos_params[0].bw_tbl + ets->cos_params[1].bw_tbl));
458 // ETS 0 100 PBF bug.
459 bw_tbl_0 = ets->cos_params[0].bw_tbl;
460 bw_tbl_1 = ets->cos_params[1].bw_tbl;
461
462 if((0 == bw_tbl_0)||
463 (0 == bw_tbl_1))
464 {
465 if(0 == bw_tbl_0)
466 {
467 bw_tbl_0 = 1;
468 bw_tbl_1 = 99;
469 }
470 else
471 {
472 bw_tbl_0 = 99;
473 bw_tbl_1 = 1;
474 }
475
476 }
477 // The priority is assign as BW
478 ets->cos_params[0].s_pri = DCBX_S_PRI_INVALID;
479 ets->cos_params[1].s_pri = DCBX_S_PRI_INVALID;
480 elink_ets_bw_limit(&pdev->params.link,
481 bw_tbl_0,
482 bw_tbl_1);
483 }
484 else
485 {
486 ets->cos_params[0].bw_tbl = DCBX_INVALID_COS_BW;
487 ets->cos_params[1].bw_tbl = DCBX_INVALID_COS_BW;
488 // The priority is assign as Strict
489 DbgBreakIf(ets->cos_params[0].s_pri == ets->cos_params[1].s_pri);
490 if(DCBX_S_PRI_COS_HIGHEST == ets->cos_params[0].s_pri)
491 {
492 ets->cos_params[1].s_pri =
493 DCBX_S_PRI_COS_NEXT_LOWER_PRI(DCBX_S_PRI_COS_HIGHEST);
494 elink_status = elink_ets_strict(&pdev->params.link,0);
495 }
496 else if(DCBX_S_PRI_COS_HIGHEST == ets->cos_params[1].s_pri)
497 {
498 ets->cos_params[0].s_pri =
499 DCBX_S_PRI_COS_NEXT_LOWER_PRI(DCBX_S_PRI_COS_HIGHEST);
500 elink_status = elink_ets_strict(&pdev->params.link,1);
501 }
502
503 if(ELINK_STATUS_OK != elink_status)
504 {
505 DbgBreakMsg("lm_dcbx_update_ets_params: elinc_ets_strict failed ");
506 }
507 }
508 }
509 /**
510 * @description
511 * Set ETS configuration in E3B0.
512 * In E3B0 the configuration may have more than 2 COS.
513 * @param pdev
514 */
515 void
lm_dcbx_update_ets_config(IN lm_device_t * pdev)516 lm_dcbx_update_ets_config(
517 IN lm_device_t *pdev)
518 {
519 pg_params_t *ets = &(pdev->params.dcbx_port_params.ets);
520 struct elink_ets_params ets_params = {0};
521 u8_t elink_status = ELINK_STATUS_OK;
522 u8_t i = 0;
523
524 ets_params.num_of_cos = ets->num_of_cos;
525
526 for(i = 0 ; i < ets->num_of_cos; i++)
527 {
528 if(DCBX_S_PRI_INVALID != ets->cos_params[i].s_pri)
529 {// COS is SP
530 if(DCBX_INVALID_COS_BW != ets->cos_params[i].bw_tbl)
531 {
532 DbgBreakMsg("lm_dcbx_update_ets_e3b0_params :COS can't be not BW and not SP");
533 return;
534 }
535 ets_params.cos[i].state = elink_cos_state_strict;
536 ets_params.cos[i].params.sp_params.pri = ets->cos_params[i].s_pri;
537 }
538 else
539 {// COS is BW
540 if(DCBX_INVALID_COS_BW == ets->cos_params[i].bw_tbl)
541 {
542 DbgBreakMsg("lm_dcbx_update_ets_e3b0_params :COS can't be not BW and not SP");
543 return;
544 }
545 ets_params.cos[i].state = elink_cos_state_bw;
546 ets_params.cos[i].params.bw_params.bw = (u8_t)ets->cos_params[i].bw_tbl;
547 }
548
549 }
550
551 // Configure the ETS in HW.
552 elink_status = elink_ets_e3b0_config(&pdev->params.link,
553 &pdev->vars.link,
554 &ets_params);
555
556 if(ELINK_STATUS_OK != elink_status)
557 {
558 DbgBreakMsg("lm_dcbx_update_ets_e3b0_params: ets_e3b0_config failed ");
559 elink_status = elink_ets_disabled(&pdev->params.link,
560 &pdev->vars.link);
561 }
562 }
563 /*******************************************************************************
564 * Description:
565 *
566 * Return:
567 ******************************************************************************/
568 void
lm_dcbx_update_ets_params(IN lm_device_t * pdev)569 lm_dcbx_update_ets_params(
570 IN lm_device_t *pdev)
571 {
572 pg_params_t *ets = &(pdev->params.dcbx_port_params.ets);
573 u8_t elink_status = ELINK_STATUS_OK;
574
575 elink_status = elink_ets_disabled(&pdev->params.link,
576 &pdev->vars.link);
577
578 if(ELINK_STATUS_OK != elink_status)
579 {
580 DbgBreakMsg("lm_dcbx_update_ets_params the function elink_ets_disabled failed");
581 return;
582 }
583
584 if(FALSE == ets->enabled)
585 {
586 return;
587 }
588
589 if(CHIP_IS_E3B0(pdev))
590 {
591 lm_dcbx_update_ets_config(pdev);
592 }
593 else
594 {
595 DbgBreakIf(FALSE == CHIP_IS_E2E3A0(pdev));
596 lm_dcbx_2cos_limit_update_ets_config(pdev);
597 }
598
599 }
600 /**********************End of PFC code**************************************/
601 /**********************start DCBX Common FUNCTIONS**************************************/
602 #define ETH_TYPE_FCOE (0x8906)
603 #define TCP_PORT_ISCSI (0xCBC)
604
605
606 /*******************************************************************************
607 * Description:
608 * Runtime changes can take more than 1 second and can't be handled
609 * from DPC.
610 * When the PMF detects a DCBX update it will schedule a WI that
611 * will handle the job.
612 * Also the function lm_dcbx_stop_HW_TX/lm_dcbx_resume_HW_TX must be
613 * called in mutual exclusion.
614 * lm_mcp_cmd_send_recieve must be called from default DPC, so when the
615 * WI will finish the processing an interrupt that will be called from
616 * The WI will cause us to enter this function again and send the Ack.
617 *
618 * Return:
619 ******************************************************************************/
620 void
lm_dcbx_event(lm_device_t * pdev,u32_t drv_status)621 lm_dcbx_event(lm_device_t *pdev,
622 u32_t drv_status)
623 {
624
625 u32_t fw_resp = 0;
626 lm_status_t lm_status = LM_STATUS_SUCCESS ;
627
628 if(IS_PMF(pdev))
629 {
630 if( GET_FLAGS( drv_status, DRV_STATUS_DCBX_NEGOTIATION_RESULTS))
631 {
632 switch(pdev->dcbx_info.dcbx_update_lpme_task_state)
633 {
634 case DCBX_UPDATE_TASK_STATE_FREE:
635 // free: this is the first time we saw
636 // this DRV_STATUS_DCBX_NEGOTIATION_RES
637 if(FALSE == IS_DCB_ENABLED(pdev))
638 {
639 return;
640 }
641 pdev->dcbx_info.dcbx_update_lpme_task_state =
642 DCBX_UPDATE_TASK_STATE_SCHEDULE;
643 lm_status = MM_REGISTER_LPME(pdev,
644 lm_dcbx_update_lpme_set_params,
645 TRUE,
646 FALSE);// DCBX sends ramrods
647
648 if (LM_STATUS_SUCCESS != lm_status)
649 {
650 pdev->dcbx_info.dcbx_update_lpme_task_state =
651 DCBX_UPDATE_TASK_STATE_FREE;
652 if(LM_STATUS_REQUEST_NOT_ACCEPTED == lm_status)
653 {// DCBX MM_REGISTER_LPME can fail
654 pdev->dcbx_info.lpme_failed_cnt++;
655 return;
656 }
657 pdev->dcbx_info.dcbx_error |= DCBX_ERROR_REGISTER_LPME;
658 // No rollback
659 // Problem because we won't get to DCBX_UPDATE_TASK_STATE_HANDLED (we won't schedule an interrupt)
660 DbgBreakMsg("lm_dcbx_int : The chip QM queues are stuck until an interrupt from MCP");
661 //Free the MCP
662 lm_status = lm_mcp_cmd_send_recieve( pdev,
663 lm_mcp_mb_header,
664 DRV_MSG_CODE_DCBX_PMF_DRV_OK,
665 0,
666 MCP_CMD_DEFAULT_TIMEOUT,
667 &fw_resp ) ;
668
669 DbgBreakIf( lm_status != LM_STATUS_SUCCESS );
670
671 }
672 break;
673
674 case DCBX_UPDATE_TASK_STATE_SCHEDULE:
675 // Schedule: We saw before that DRV_STATUS_DCBX_NEGOTIATION_RES
676 // is set before, and didn�t handle it yet
677 break;
678
679 case DCBX_UPDATE_TASK_STATE_HANDLED:
680 // handled: the WI handled was handled ,The MCP needs to updated
681 pdev->dcbx_info.dcbx_update_lpme_task_state =
682 DCBX_UPDATE_TASK_STATE_FREE;
683
684 lm_status = lm_mcp_cmd_send_recieve( pdev,
685 lm_mcp_mb_header,
686 DRV_MSG_CODE_DCBX_PMF_DRV_OK,
687 0,
688 MCP_CMD_DEFAULT_TIMEOUT,
689 &fw_resp ) ;
690
691 DbgBreakIf( lm_status != LM_STATUS_SUCCESS );
692 break;
693 default:
694 DbgBreakMsg("illegal value for dcbx_update_lpme_task_state");
695 break;
696 }
697 }
698 }
699 }
700
701 /*******************************************************************************
702 * Description: Calculate the number of priority PG.
703 * The number of priority pg should be derived from the available traffic type
704 * and pg_pri_orginal_spread configured priorities
705 *
706 * Return:
707 ******************************************************************************/
708 STATIC void
lm_dcbx_cee_get_num_of_pg_traf_type(IN lm_device_t * pdev,IN u32_t pg_pri_orginal_spread[DCBX_MAX_NUM_PRI_PG_ENTRIES],OUT pg_help_data_t * pg_help_data)709 lm_dcbx_cee_get_num_of_pg_traf_type(
710 IN lm_device_t *pdev,
711 IN u32_t pg_pri_orginal_spread[DCBX_MAX_NUM_PRI_PG_ENTRIES],
712 OUT pg_help_data_t *pg_help_data)
713 {
714 u8_t i = 0;
715 u8_t b_pg_found = FALSE;
716 u8_t search_traf_type = 0;
717 u8_t add_traf_type = 0;
718 u8_t add_pg = 0;
719
720 ASSERT_STATIC( DCBX_MAX_NUM_PRI_PG_ENTRIES == 8);
721
722 // Set to invalid
723 for (i = 0; i < ARRSIZE(pg_help_data->pg_entry_data); i++)
724 {
725 pg_help_data->pg_entry_data[i].pg = DCBX_ILLEGAL_PG;
726 }
727
728 for (add_traf_type = 0; add_traf_type < ARRSIZE(pg_help_data->pg_entry_data); add_traf_type++)
729 {
730 ASSERT_STATIC(ARRSIZE(pg_help_data->pg_entry_data) ==
731 ARRSIZE(pdev->params.dcbx_port_params.app.traffic_type_priority));
732
733 b_pg_found = FALSE;
734 if (pdev->params.dcbx_port_params.app.traffic_type_priority[add_traf_type] < MAX_PFC_PRIORITIES)
735 {
736 add_pg = (u8_t)pg_pri_orginal_spread[pdev->params.dcbx_port_params.app.traffic_type_priority[add_traf_type]];
737 for (search_traf_type = 0; search_traf_type < ARRSIZE(pg_help_data->pg_entry_data); search_traf_type++)
738 {
739 if (pg_help_data->pg_entry_data[search_traf_type].pg == add_pg)
740 {
741 if(0 == (pg_help_data->pg_entry_data[search_traf_type].pg_priority &
742 (1 << pdev->params.dcbx_port_params.app.traffic_type_priority[add_traf_type])))
743 {
744 pg_help_data->pg_entry_data[search_traf_type].num_of_dif_pri++;
745 }
746 pg_help_data->pg_entry_data[search_traf_type].pg_priority |=
747 (1 << pdev->params.dcbx_port_params.app.traffic_type_priority[add_traf_type]);
748
749 b_pg_found = TRUE;
750 break;
751 }
752 }
753 if(FALSE == b_pg_found)
754 {
755 pg_help_data->pg_entry_data[pg_help_data->num_of_pg].pg = add_pg;
756 pg_help_data->pg_entry_data[pg_help_data->num_of_pg].pg_priority = (1 << pdev->params.dcbx_port_params.app.traffic_type_priority[add_traf_type]);
757 pg_help_data->pg_entry_data[pg_help_data->num_of_pg].num_of_dif_pri = 1;
758 pg_help_data->num_of_pg++;
759 }
760 }
761 }
762 DbgBreakIf(pg_help_data->num_of_pg > LLFC_DRIVER_TRAFFIC_TYPE_MAX);
763 }
764 /*******************************************************************************
765 * Description: Still
766 *
767 * Return:
768 ******************************************************************************/
769 STATIC void
lm_dcbx_fill_cos_entry(lm_device_t * pdev,dcbx_cos_params_t * cos_params,const u32_t pri_join_mask,const u32_t bw,const u8_t pauseable,const u8_t strict)770 lm_dcbx_fill_cos_entry(
771 lm_device_t *pdev,
772 dcbx_cos_params_t *cos_params,
773 const u32_t pri_join_mask,
774 const u32_t bw,
775 const u8_t pauseable,
776 const u8_t strict)
777 {
778 cos_params->s_pri = strict;
779 cos_params->bw_tbl = bw;
780 cos_params->pri_bitmask = pri_join_mask;
781
782
783 // This filed is only for debbuging in CHIP_IS_E2E3A0(pdev)
784 cos_params->pauseable = pauseable;
785
786 if((DCBX_INVALID_COS_BW != bw)||
787 (DCBX_S_PRI_INVALID != strict))
788 {
789 DbgBreakIf(0 == pri_join_mask);
790
791 if(CHIP_IS_E2E3A0(pdev))
792 {
793 if(pauseable)
794 {
795 DbgBreakIf(0 != LM_DCBX_PFC_PRI_GET_NON_PAUSE(pdev,cos_params->pri_bitmask));
796 }
797 else
798 {
799 DbgBreakIf(0 != LM_DCBX_PFC_PRI_GET_PAUSE(pdev,cos_params->pri_bitmask));
800 }
801 }
802 }
803 }
804
805 /**
806 * @description
807 * Disable ETS.
808 * @param pdev
809 *
810 * @return STATIC void
811 */
812 STATIC void
lm_dcbx_ets_disable(INOUT lm_device_t * pdev)813 lm_dcbx_ets_disable(
814 INOUT lm_device_t *pdev)
815 {
816 pg_params_t *ets = &pdev->params.dcbx_port_params.ets;
817
818 ets->enabled = FALSE;
819 ets->num_of_cos = 1;
820
821 ets->cos_params[0].pri_bitmask = 0xFF;
822 ets->cos_params[0].bw_tbl = DCBX_INVALID_COS_BW;
823 ets->cos_params[0].s_pri = DCBX_S_PRI_COS_HIGHEST;
824 ets->cos_params[0].pauseable =
825 LM_DCBX_IS_PFC_PRI_SOME_PAUSE(pdev,ets->cos_params[0].pri_bitmask);
826 }
827 /**
828 * @description
829 * Clean up old settings of ets and initialize the COS param
830 * struct.
831 * @param pdev
832 * @param ets
833 *
834 * @return STATIC void
835 */
836 STATIC void
lm_dcbx_init_ets_internal_param(lm_device_t * pdev,pg_params_t * ets)837 lm_dcbx_init_ets_internal_param(
838 lm_device_t *pdev,
839 pg_params_t *ets)
840 {
841 u8_t i = 0;
842 ets->enabled = FALSE;
843 ets->num_of_cos = 0 ;
844
845 for(i=0; i < ARRSIZE(ets->cos_params) ; i++)
846 {
847 lm_dcbx_fill_cos_entry(pdev,
848 &ets->cos_params[i],
849 0,
850 DCBX_INVALID_COS_BW,
851 FALSE,
852 DCBX_S_PRI_INVALID);
853 }
854 }
855 /*******************************************************************************
856 * Description: single priority group
857 *
858 * Return:
859 ******************************************************************************/
860 STATIC void
lm_dcbx_ets_disabled_entry_data(IN lm_device_t * pdev,OUT cos_help_data_t * cos_data,IN const u32_t pri_join_mask)861 lm_dcbx_ets_disabled_entry_data(
862 IN lm_device_t *pdev,
863 OUT cos_help_data_t *cos_data,
864 IN const u32_t pri_join_mask)
865 {
866 // Only one priority than only one COS
867 cos_data->entry_data[0].b_pausable = LM_DCBX_IS_PFC_PRI_ONLY_PAUSE(pdev,pri_join_mask);
868 cos_data->entry_data[0].pri_join_mask = pri_join_mask;
869 cos_data->entry_data[0].cos_bw = 100;
870 cos_data->num_of_cos = 1;
871 }
872
873 /*******************************************************************************
874 * Description: Updating the cos bw.
875 *
876 * Return:
877 ******************************************************************************/
878 STATIC void
lm_dcbx_add_to_cos_bw(IN lm_device_t * pdev,OUT cos_entry_help_data_t * entry_data,IN u8_t pg_bw)879 lm_dcbx_add_to_cos_bw(
880 IN lm_device_t *pdev,
881 OUT cos_entry_help_data_t *entry_data,
882 IN u8_t pg_bw)
883 {
884
885 if(DCBX_INVALID_COS_BW == entry_data->cos_bw )
886 {
887
888 entry_data->cos_bw = pg_bw;
889 }
890 else
891 {
892 entry_data->cos_bw += pg_bw;
893 }
894 DbgBreakIf(entry_data->cos_bw > DCBX_MAX_COS_BW);
895 }
896 /*******************************************************************************
897 * Description: single priority group
898 *
899 * Return:
900 ******************************************************************************/
901 STATIC void
lm_dcbx_separate_pauseable_from_non(IN lm_device_t * pdev,OUT cos_help_data_t * cos_data,IN const u32_t * pg_pri_orginal_spread,IN const dcbx_ets_feature_t * ets)902 lm_dcbx_separate_pauseable_from_non(
903 IN lm_device_t *pdev,
904 OUT cos_help_data_t *cos_data,
905 IN const u32_t *pg_pri_orginal_spread,
906 IN const dcbx_ets_feature_t *ets
907 )
908 {
909 u32_t pri_tested = 0;
910 u8_t i = 0;
911 u8_t entry = 0;
912 u8_t pg_entry = 0;
913 const u8_t num_of_pri = ARRSIZE(pdev->params.dcbx_port_params.app.traffic_type_priority);
914
915 cos_data->entry_data[0].b_pausable = TRUE;
916 cos_data->entry_data[1].b_pausable = FALSE;
917 cos_data->entry_data[0].pri_join_mask = cos_data->entry_data[1].pri_join_mask = 0;
918
919 for(i=0 ; i < num_of_pri ; i++)
920 {
921 DbgBreakIf(pdev->params.dcbx_port_params.app.traffic_type_priority[i] >= MAX_PFC_PRIORITIES);
922 pri_tested = 1 << pdev->params.dcbx_port_params.app.traffic_type_priority[i];
923
924 if(pri_tested & LM_DCBX_PFC_PRI_NON_PAUSE_MASK(pdev))
925 {
926 cos_data->entry_data[1].pri_join_mask |= pri_tested;
927 entry = 1;
928 }
929 else
930 {
931 cos_data->entry_data[0].pri_join_mask |= pri_tested;
932 entry = 0;
933
934 }
935 pg_entry = (u8_t)pg_pri_orginal_spread[pdev->params.dcbx_port_params.app.traffic_type_priority[i]];
936 // There can be only one strict pg
937 if( pg_entry < DCBX_MAX_NUM_PRI_PG_ENTRIES)
938 {
939 lm_dcbx_add_to_cos_bw(pdev,
940 &(cos_data->entry_data[entry]),
941 DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry));
942 }
943 else
944 {
945 // If we join a group and one is strict than the bw rulls
946 cos_data->entry_data[entry].s_pri = DCBX_S_PRI_COS_HIGHEST;
947 }
948 }//end of for
949 // Both groups must have priorities
950 DbgBreakIf(( 0 == cos_data->entry_data[0].pri_join_mask) && ( 0 == cos_data->entry_data[1].pri_join_mask));
951 }
952
953 /**
954 * @description
955 * if the number of requested PG-s in CEE is greater than
956 * expected then the results are not determined since this is a
957 * violation of the standard.
958 * @param pdev
959 * @param pg_help_data
960 * @param required_num_of_pg
961 *
962 * @return STATIC lm_status_t
963 * If we weren't successful in reducing the number of PGs to
964 * required_num_of_pg.
965 */
966 STATIC lm_status_t
lm_dcbx_join_pgs(IN lm_device_t * pdev,IN dcbx_ets_feature_t * ets,INOUT pg_help_data_t * pg_help_data,IN const u8_t required_num_of_pg)967 lm_dcbx_join_pgs(
968 IN lm_device_t *pdev,
969 IN dcbx_ets_feature_t *ets,
970 INOUT pg_help_data_t *pg_help_data,
971 IN const u8_t required_num_of_pg)
972 {
973 lm_status_t lm_status = LM_STATUS_SUCCESS;
974 u8_t entry_joined = pg_help_data->num_of_pg -1;
975 u8_t entry_removed = entry_joined + 1;
976 u8_t pg_joined = 0;
977
978 // Algorithm below limitation (-2)
979 if((required_num_of_pg < 2 )||
980 (ARRSIZE(pg_help_data->pg_entry_data) <= pg_help_data->num_of_pg)||
981 ( pg_help_data->num_of_pg <= required_num_of_pg))
982 {
983 DbgBreakMsg("lm_dcbx_join_pg_data required_num_of_pg can't be zero");
984 return LM_STATUS_FAILURE;
985 }
986
987 while(required_num_of_pg < pg_help_data->num_of_pg)
988 {
989 entry_joined = pg_help_data->num_of_pg -2;
990 entry_removed = entry_joined + 1;
991
992 pg_help_data->pg_entry_data[entry_joined].pg_priority |=
993 pg_help_data->pg_entry_data[entry_removed].pg_priority;
994
995 pg_help_data->pg_entry_data[entry_joined].num_of_dif_pri +=
996 pg_help_data->pg_entry_data[entry_removed].num_of_dif_pri;
997
998 if((DCBX_STRICT_PRI_PG == pg_help_data->pg_entry_data[entry_joined].pg ) ||
999 (DCBX_STRICT_PRI_PG == pg_help_data->pg_entry_data[entry_removed].pg))
1000 {
1001 // Entries joined strict priority rules
1002 pg_help_data->pg_entry_data[entry_joined].pg = DCBX_STRICT_PRI_PG;
1003 }
1004 else
1005 {
1006 // Entries can be joined join BW
1007 pg_joined = DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_help_data->pg_entry_data[entry_joined].pg) +
1008 DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_help_data->pg_entry_data[entry_removed].pg);
1009
1010 DCBX_PG_BW_SET(ets->pg_bw_tbl, pg_help_data->pg_entry_data[entry_joined].pg,pg_joined);
1011 }
1012 // Joined the entries
1013 pg_help_data->num_of_pg--;
1014 }
1015 return lm_status;
1016 }
1017 /**
1018 * @description
1019 * Fill pause entries in entry_data
1020 * @param pdev
1021 * @param entry_data
1022 *
1023 * @return STATIC void
1024 */
1025 STATIC void
lm_dcbx_ets_fill_cos_entry_data_as_pause(IN lm_device_t * pdev,OUT cos_entry_help_data_t * entry_data,IN const u32_t pri_join_mask)1026 lm_dcbx_ets_fill_cos_entry_data_as_pause(
1027 IN lm_device_t *pdev,
1028 OUT cos_entry_help_data_t *entry_data,
1029 IN const u32_t pri_join_mask
1030 )
1031 {
1032 entry_data->b_pausable = TRUE;
1033 entry_data->pri_join_mask = LM_DCBX_PFC_PRI_GET_PAUSE(pdev,pri_join_mask);
1034 }
1035
1036 /**
1037 * @description
1038 * Fill pause entries in entry_data
1039 * @param pdev
1040 * @param entry_data
1041 *
1042 * @return STATIC void
1043 */
1044 STATIC void
lm_dcbx_ets_fill_cos_entry_data_as_non_pause(IN lm_device_t * pdev,OUT cos_entry_help_data_t * entry_data,IN const u32_t pri_join_mask)1045 lm_dcbx_ets_fill_cos_entry_data_as_non_pause(
1046 IN lm_device_t *pdev,
1047 OUT cos_entry_help_data_t *entry_data,
1048 IN const u32_t pri_join_mask
1049 )
1050 {
1051 entry_data->b_pausable = FALSE;
1052 entry_data->pri_join_mask = LM_DCBX_PFC_PRI_GET_NON_PAUSE(pdev,pri_join_mask);
1053 }
1054 /*******************************************************************************
1055 * Description: single priority group
1056 *
1057 * Return:
1058 ******************************************************************************/
1059 STATIC void
lm_dcbx_2cos_limit_cee_single_pg_to_cos_params(IN lm_device_t * pdev,IN pg_help_data_t * pg_help_data,OUT cos_help_data_t * cos_data,IN const u32_t pri_join_mask,IN const u8_t num_of_dif_pri)1060 lm_dcbx_2cos_limit_cee_single_pg_to_cos_params(
1061 IN lm_device_t *pdev,
1062 IN pg_help_data_t *pg_help_data,
1063 OUT cos_help_data_t *cos_data,
1064 IN const u32_t pri_join_mask,
1065 IN const u8_t num_of_dif_pri
1066 )
1067 {
1068 u8_t i = 0;
1069 u32_t pri_tested = 0;
1070 u32_t pri_mask_without_pri = 0;
1071
1072 if(1 == num_of_dif_pri)
1073 {
1074 // Only one priority than only one COS
1075 lm_dcbx_ets_disabled_entry_data(pdev,cos_data,pri_join_mask);
1076 return;
1077 }
1078
1079 if( pg_help_data->pg_entry_data[0].pg < DCBX_MAX_NUM_PG_BW_ENTRIES)
1080 {// BW limited
1081 // If there are both pauseable and non-pauseable priorities, the pauseable priorities go to the first queue and the non-pauseable
1082 // priorities go to the second queue.
1083 if(LM_DCBX_IS_PFC_PRI_MIX_PAUSE(pdev,pri_join_mask))
1084 {
1085 DbgBreakIf( 1 == num_of_dif_pri );
1086 // Pause able
1087 lm_dcbx_ets_fill_cos_entry_data_as_pause(
1088 pdev,
1089 &cos_data->entry_data[0],
1090 pri_join_mask);
1091 // Non pause able.
1092 lm_dcbx_ets_fill_cos_entry_data_as_non_pause(
1093 pdev,
1094 &cos_data->entry_data[1],
1095 pri_join_mask);
1096
1097 if(2 == num_of_dif_pri)
1098 {
1099 cos_data->entry_data[0].cos_bw = 50;
1100 cos_data->entry_data[1].cos_bw = 50;
1101 }
1102 if (3 == num_of_dif_pri)
1103 {
1104 // We need to find out how has only one priority and how has two priorities.
1105 // If the pri_bitmask is a power of 2 than there is only one priority.
1106 if(POWER_OF_2(LM_DCBX_PFC_PRI_GET_PAUSE(pdev,pri_join_mask)))
1107 {
1108 DbgBreakIf(POWER_OF_2(LM_DCBX_PFC_PRI_GET_NON_PAUSE(pdev,pri_join_mask)));
1109 cos_data->entry_data[0].cos_bw = 33;
1110 cos_data->entry_data[1].cos_bw = 67;
1111 }
1112 else
1113 {
1114 DbgBreakIf(FALSE == POWER_OF_2(LM_DCBX_PFC_PRI_GET_NON_PAUSE(pdev,pri_join_mask)));
1115 cos_data->entry_data[0].cos_bw = 67;
1116 cos_data->entry_data[1].cos_bw = 33;
1117 }
1118 }
1119 }
1120 else if(LM_DCBX_IS_PFC_PRI_ONLY_PAUSE(pdev,pri_join_mask))
1121 {// If there are only pauseable priorities, then one/two priorities go
1122 // to the first queue and one priority goes to the second queue.
1123 if(2 == num_of_dif_pri)
1124 {
1125 cos_data->entry_data[0].cos_bw = 50;
1126 cos_data->entry_data[1].cos_bw = 50;
1127 }
1128 else
1129 {
1130 DbgBreakIf(3 != num_of_dif_pri);
1131 cos_data->entry_data[0].cos_bw = 67;
1132 cos_data->entry_data[1].cos_bw = 33;
1133 }
1134 cos_data->entry_data[0].b_pausable = cos_data->entry_data[1].b_pausable = TRUE;
1135 // All priorities except FCOE
1136 cos_data->entry_data[0].pri_join_mask = (pri_join_mask & ((u8_t)~(1 << pdev->params.dcbx_port_params.app.traffic_type_priority[LLFC_TRAFFIC_TYPE_FCOE])));
1137 // Only FCOE priority.
1138 cos_data->entry_data[1].pri_join_mask = (1 << pdev->params.dcbx_port_params.app.traffic_type_priority[LLFC_TRAFFIC_TYPE_FCOE]);
1139 }
1140 else
1141 {//If there are only non-pauseable priorities, they will all go to the same queue.
1142 DbgBreakIf(FALSE == LM_DCBX_IS_PFC_PRI_ONLY_NON_PAUSE(pdev,pri_join_mask));
1143 lm_dcbx_ets_disabled_entry_data(pdev,cos_data,pri_join_mask);
1144 }
1145 }
1146 else
1147 {
1148 // priority group which is not BW limited (PG#15):
1149 DbgBreakIf(DCBX_STRICT_PRI_PG != pg_help_data->pg_entry_data[0].pg);
1150 if(LM_DCBX_IS_PFC_PRI_MIX_PAUSE(pdev,pri_join_mask))
1151 {
1152 // If there are both pauseable and non-pauseable priorities, the pauseable priorities go
1153 // to the first queue and the non-pauseable priorities go to the second queue.
1154 if(LM_DCBX_PFC_PRI_GET_PAUSE(pdev,pri_join_mask) > LM_DCBX_PFC_PRI_GET_NON_PAUSE(pdev,pri_join_mask))
1155 {
1156 cos_data->entry_data[0].s_pri = DCBX_S_PRI_COS_HIGHEST;
1157 cos_data->entry_data[1].s_pri = DCBX_S_PRI_COS_NEXT_LOWER_PRI(DCBX_S_PRI_COS_HIGHEST);
1158 }
1159 else
1160 {
1161 cos_data->entry_data[1].s_pri = DCBX_S_PRI_COS_HIGHEST;
1162 cos_data->entry_data[0].s_pri = DCBX_S_PRI_COS_NEXT_LOWER_PRI(DCBX_S_PRI_COS_HIGHEST);
1163 }
1164 // Pause able
1165 lm_dcbx_ets_fill_cos_entry_data_as_pause(
1166 pdev,
1167 &cos_data->entry_data[0],
1168 pri_join_mask);
1169 // Non pause-able.
1170 lm_dcbx_ets_fill_cos_entry_data_as_non_pause(
1171 pdev,
1172 &cos_data->entry_data[1],
1173 pri_join_mask);
1174 }
1175 else
1176 {
1177 // If there are only pauseable priorities or only non-pauseable, the lower priorities
1178 // go to the first queue and the higher priorities go to the second queue.
1179 cos_data->entry_data[0].b_pausable = cos_data->entry_data[1].b_pausable = LM_DCBX_IS_PFC_PRI_ONLY_PAUSE(pdev,pri_join_mask);
1180
1181 for(i=0 ; i < ARRSIZE(pdev->params.dcbx_port_params.app.traffic_type_priority) ; i++)
1182 {
1183 DbgBreakIf(pdev->params.dcbx_port_params.app.traffic_type_priority[i] >= MAX_PFC_PRIORITIES);
1184 pri_tested = 1 << pdev->params.dcbx_port_params.app.traffic_type_priority[i];
1185 // Remove priority tested
1186 pri_mask_without_pri = (pri_join_mask & ((u8_t)(~pri_tested)));
1187 if( pri_mask_without_pri < pri_tested )
1188 {
1189 break;
1190 }
1191 }
1192
1193 if(i == ARRSIZE(pdev->params.dcbx_port_params.app.traffic_type_priority))
1194 {
1195 DbgBreakMsg("lm_dcbx_fill_cos_params : Invalid value for pri_join_mask could not find a priority \n");
1196 }
1197 cos_data->entry_data[0].pri_join_mask = pri_mask_without_pri;
1198 cos_data->entry_data[1].pri_join_mask = pri_tested;
1199 // Both queues are strict priority, and that with the highest priority
1200 // gets the highest strict priority in the arbiter.
1201 cos_data->entry_data[1].s_pri = DCBX_S_PRI_COS_HIGHEST;
1202 cos_data->entry_data[0].s_pri = DCBX_S_PRI_COS_NEXT_LOWER_PRI(DCBX_S_PRI_COS_HIGHEST);
1203 }
1204 }
1205
1206 }
1207 /*******************************************************************************
1208 * Description: Still
1209 *
1210 * Return:
1211 ******************************************************************************/
1212 STATIC void
lm_dcbx_2cos_limit_cee_two_pg_to_cos_params(IN lm_device_t * pdev,IN pg_help_data_t * pg_help_data,IN const dcbx_ets_feature_t * ets,OUT cos_help_data_t * cos_data,IN const u32_t * pg_pri_orginal_spread,IN u32_t pri_join_mask,IN u8_t num_of_dif_pri)1213 lm_dcbx_2cos_limit_cee_two_pg_to_cos_params(
1214 IN lm_device_t *pdev,
1215 IN pg_help_data_t *pg_help_data,
1216 IN const dcbx_ets_feature_t *ets,
1217 OUT cos_help_data_t *cos_data,
1218 IN const u32_t *pg_pri_orginal_spread,
1219 IN u32_t pri_join_mask,
1220 IN u8_t num_of_dif_pri)
1221 {
1222 u8_t i = 0;
1223 u8_t pg[DCBX_COS_MAX_NUM_E2E3A0] = {0};
1224
1225 // If there are both pauseable and non-pauseable priorities, the pauseable priorities
1226 // go to the first queue and the non-pauseable priorities go to the second queue.
1227 if(LM_DCBX_IS_PFC_PRI_MIX_PAUSE(pdev,pri_join_mask))
1228 {
1229 if(LM_DCBX_IS_PFC_PRI_MIX_PAUSE(pdev, pg_help_data->pg_entry_data[0].pg_priority) ||
1230 LM_DCBX_IS_PFC_PRI_MIX_PAUSE(pdev, pg_help_data->pg_entry_data[1].pg_priority))
1231 {
1232 // If one PG contains both pauseable and non-pauseable priorities then ETS is disabled.
1233 DbgMessage(pdev, WARN, "lm_dcbx_fill_cos_params : PG contains both pauseable and non-pauseable "
1234 "priorities -> ETS is disabled. \n");
1235 lm_dcbx_separate_pauseable_from_non(pdev,cos_data,pg_pri_orginal_spread,ets);
1236 // ETS disabled wrong configuration
1237 pdev->params.dcbx_port_params.ets.enabled = FALSE;
1238 return;
1239 }
1240
1241 // Pause-able
1242 cos_data->entry_data[0].b_pausable = TRUE;
1243 // Non pause-able.
1244 cos_data->entry_data[1].b_pausable = FALSE;
1245 if(LM_DCBX_IS_PFC_PRI_ONLY_PAUSE(pdev, pg_help_data->pg_entry_data[0].pg_priority))
1246 {// 0 is pause-able
1247 cos_data->entry_data[0].pri_join_mask = pg_help_data->pg_entry_data[0].pg_priority;
1248 pg[0] = pg_help_data->pg_entry_data[0].pg;
1249 cos_data->entry_data[1].pri_join_mask = pg_help_data->pg_entry_data[1].pg_priority;
1250 pg[1] = pg_help_data->pg_entry_data[1].pg;
1251 }
1252 else
1253 {// 1 is pause-able
1254 cos_data->entry_data[0].pri_join_mask = pg_help_data->pg_entry_data[1].pg_priority;
1255 pg[0] = pg_help_data->pg_entry_data[1].pg;
1256 cos_data->entry_data[1].pri_join_mask = pg_help_data->pg_entry_data[0].pg_priority;
1257 pg[1] = pg_help_data->pg_entry_data[0].pg;
1258 }
1259 }
1260 else
1261 {
1262 //If there are only pauseable priorities or only non-pauseable, each PG goes to a queue.
1263 cos_data->entry_data[0].b_pausable = cos_data->entry_data[1].b_pausable = LM_DCBX_IS_PFC_PRI_ONLY_PAUSE(pdev,pri_join_mask);
1264 cos_data->entry_data[0].pri_join_mask = pg_help_data->pg_entry_data[0].pg_priority;
1265 pg[0] = pg_help_data->pg_entry_data[0].pg;
1266 cos_data->entry_data[1].pri_join_mask = pg_help_data->pg_entry_data[1].pg_priority;
1267 pg[1] = pg_help_data->pg_entry_data[1].pg;
1268 }
1269
1270 // There can be only one strict pg
1271 for(i=0 ; i < ARRSIZE(pg) ; i++)
1272 {
1273 if( pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
1274 {
1275 cos_data->entry_data[i].cos_bw = DCBX_PG_BW_GET( ets->pg_bw_tbl,pg[i]);
1276 }
1277 else
1278 {
1279 cos_data->entry_data[i].s_pri = DCBX_S_PRI_COS_HIGHEST;
1280 }
1281 }
1282 }
1283
1284 /*******************************************************************************
1285 * Description: Still
1286 *
1287 * Return:
1288 ******************************************************************************/
1289 STATIC void
lm_dcbx_2cos_limit_cee_three_pg_to_cos_params(IN lm_device_t * pdev,IN pg_help_data_t * pg_help_data,IN const dcbx_ets_feature_t * ets,OUT cos_help_data_t * cos_data,IN const u32_t * pg_pri_orginal_spread,IN u32_t pri_join_mask,IN u8_t num_of_dif_pri)1290 lm_dcbx_2cos_limit_cee_three_pg_to_cos_params(
1291 IN lm_device_t *pdev,
1292 IN pg_help_data_t *pg_help_data,
1293 IN const dcbx_ets_feature_t *ets,
1294 OUT cos_help_data_t *cos_data,
1295 IN const u32_t *pg_pri_orginal_spread,
1296 IN u32_t pri_join_mask,
1297 IN u8_t num_of_dif_pri)
1298 {
1299 u8_t i = 0;
1300 u32_t pri_tested = 0;
1301 u8_t entry = 0;
1302 u8_t pg_entry = 0;
1303 u8_t b_found_strict = FALSE;
1304 u8_t num_of_pri = ARRSIZE(pdev->params.dcbx_port_params.app.traffic_type_priority);
1305 DbgBreakIf(3 != num_of_pri);
1306 cos_data->entry_data[0].pri_join_mask = cos_data->entry_data[1].pri_join_mask = 0;
1307 //- If there are both pauseable and non-pauseable priorities, the pauseable priorities go to the first
1308 // queue and the non-pauseable priorities go to the second queue.
1309 if(LM_DCBX_IS_PFC_PRI_MIX_PAUSE(pdev,pri_join_mask))
1310 {
1311 lm_dcbx_separate_pauseable_from_non(pdev,cos_data,pg_pri_orginal_spread,ets);
1312 }
1313 else
1314 {
1315 DbgBreakIf(!(LM_DCBX_IS_PFC_PRI_ONLY_NON_PAUSE(pdev,pri_join_mask) ||
1316 LM_DCBX_IS_PFC_PRI_ONLY_PAUSE(pdev,pri_join_mask)));
1317
1318 //- If two BW-limited PG-s were combined to one queue, the BW is their sum.
1319 //- If there are only pauseable priorities or only non-pauseable, and there are both BW-limited and
1320 // non-BW-limited PG-s, the BW-limited PG/s go to one queue and the non-BW-limited PG/s go to the
1321 // second queue.
1322 //- If there are only pauseable priorities or only non-pauseable and all are BW limited, then
1323 // two priorities go to the first queue and one priority goes to the second queue.
1324
1325 // We will join this two cases:
1326 // if one is BW limited he will go to the secoend queue otherwise the last priority will get it
1327
1328 cos_data->entry_data[0].b_pausable = cos_data->entry_data[1].b_pausable = LM_DCBX_IS_PFC_PRI_ONLY_PAUSE(pdev,pri_join_mask);
1329
1330 for(i=0 ; i < num_of_pri; i++)
1331 {
1332 DbgBreakIf(pdev->params.dcbx_port_params.app.traffic_type_priority[i] >= MAX_PFC_PRIORITIES);
1333 pri_tested = 1 << pdev->params.dcbx_port_params.app.traffic_type_priority[i];
1334 pg_entry = (u8_t)pg_pri_orginal_spread[pdev->params.dcbx_port_params.app.traffic_type_priority[i]];
1335
1336 if(pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES)
1337 {
1338 entry = 0;
1339
1340 if((i == (num_of_pri-1))&&
1341 (FALSE == b_found_strict) )
1342 {/* last entry will be handled separately */
1343 // If no priority is strict than last enty goes to last queue.
1344 entry = 1;
1345 }
1346 cos_data->entry_data[entry].pri_join_mask |= pri_tested;
1347 lm_dcbx_add_to_cos_bw(pdev, &(cos_data->entry_data[entry]), DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry));
1348 }
1349 else
1350 {
1351 DbgBreakIf(TRUE == b_found_strict );
1352 b_found_strict = TRUE;
1353 cos_data->entry_data[1].pri_join_mask |= pri_tested;
1354 // If we join a group and one is strict than the bw rulls
1355 cos_data->entry_data[1].s_pri = DCBX_S_PRI_COS_HIGHEST;
1356 }
1357
1358 }//end of for
1359 }
1360 }
1361 /**
1362 * @description
1363 * Also for e3 and e2.
1364 * @param pdev
1365 * @param pg_help_data
1366 * @param ets
1367 * @param cos_data
1368 * @param pg_pri_orginal_spread
1369 * @param pri_join_mask
1370 * @param num_of_dif_pri
1371 *
1372 * @return STATIC void
1373 */
1374 STATIC void
lm_dcbx_2cos_limit_cee_fill_cos_params(IN lm_device_t * pdev,IN pg_help_data_t * pg_help_data,IN dcbx_ets_feature_t * ets,OUT cos_help_data_t * cos_data,IN const u32_t * pg_pri_orginal_spread,IN u32_t pri_join_mask,IN u8_t num_of_dif_pri)1375 lm_dcbx_2cos_limit_cee_fill_cos_params(
1376 IN lm_device_t *pdev,
1377 IN pg_help_data_t *pg_help_data,
1378 IN dcbx_ets_feature_t *ets,
1379 OUT cos_help_data_t *cos_data,
1380 IN const u32_t *pg_pri_orginal_spread,
1381 IN u32_t pri_join_mask,
1382 IN u8_t num_of_dif_pri)
1383 {
1384 DbgBreakIf(FALSE == CHIP_IS_E2E3A0(pdev));
1385
1386 // Default settings
1387 cos_data->num_of_cos = DCBX_COS_MAX_NUM_E2E3A0;
1388
1389 switch(pg_help_data->num_of_pg)
1390 {
1391 case 1:
1392 //single priority group
1393 lm_dcbx_2cos_limit_cee_single_pg_to_cos_params(
1394 pdev,
1395 pg_help_data,
1396 cos_data,
1397 pri_join_mask,
1398 num_of_dif_pri);
1399 break;
1400 case 2:
1401 lm_dcbx_2cos_limit_cee_two_pg_to_cos_params(
1402 pdev,
1403 pg_help_data,
1404 ets,
1405 cos_data,
1406 pg_pri_orginal_spread,
1407 pri_join_mask,
1408 num_of_dif_pri);
1409 break;
1410
1411 case 3:
1412 // Three pg must mean three priorities.
1413 lm_dcbx_2cos_limit_cee_three_pg_to_cos_params(
1414 pdev,
1415 pg_help_data,
1416 ets,
1417 cos_data,
1418 pg_pri_orginal_spread,
1419 pri_join_mask,
1420 num_of_dif_pri);
1421
1422 break;
1423 default:
1424 DbgBreakMsg("lm_dcbx_fill_cos_params :Wrong pg_help_data->num_of_pg \n");
1425 lm_dcbx_ets_disabled_entry_data(pdev,cos_data,pri_join_mask);
1426 }
1427 }
1428 /**
1429 * @description
1430 * Fill cos params in E3B0 A VOQ is PFC enabled if there is one
1431 * or more priorities mapped to it which is PFC enabled.
1432 * @param pdev
1433 * @param entry_data
1434 * @param pri_join_mask
1435 * @param bw
1436 * @param sp
1437 *
1438 * @return STATIC void
1439 */
1440 STATIC void
lm_dcbx_fill_cos(IN lm_device_t * pdev,OUT cos_entry_help_data_t * entry_data,IN const u32_t pri_join_mask,IN const u32_t bw,IN const u8_t s_pri)1441 lm_dcbx_fill_cos(
1442 IN lm_device_t *pdev,
1443 OUT cos_entry_help_data_t *entry_data,
1444 IN const u32_t pri_join_mask,
1445 IN const u32_t bw,
1446 IN const u8_t s_pri)
1447 {
1448
1449 DbgBreakIf(FALSE == CHIP_IS_E3B0(pdev));
1450
1451 entry_data->cos_bw = bw;
1452 entry_data->s_pri = s_pri;
1453 //Set the entry it wasn't set before
1454 entry_data->pri_join_mask = pri_join_mask;
1455
1456 // A VOQ is PFC enabled if there is one or more priorities
1457 // mapped to it which is PFC enabled.
1458 entry_data->b_pausable =
1459 LM_DCBX_IS_PFC_PRI_SOME_PAUSE(pdev, entry_data->pri_join_mask);
1460
1461 }
1462
1463 /**
1464 * @description
1465 * Spread the strict priority according to
1466 * num_spread_of_entries.
1467 *
1468 * 2.Arbitration between the VOQ-s will be the same as the
1469 * arbitration requirements between the PG-s except that if
1470 * multiple VOQ-s are used for priorities in PG15 then there
1471 * will be strict priority ordering between them according to
1472 * the order of priorities.
1473 * @param pdev
1474 * @param cos_data
1475 * @param inout_entry
1476 * @param strict_need_num_of_entries
1477 * @param strict_app_pris
1478 *
1479 * @return STATIC lm_status_t
1480 */
1481 STATIC lm_status_t
lm_dcbx_spread_strict_pri(IN lm_device_t * pdev,OUT cos_help_data_t * cos_data,IN u8_t entry,IN u8_t num_spread_of_entries,IN u8_t strict_app_pris)1482 lm_dcbx_spread_strict_pri(
1483 IN lm_device_t *pdev,
1484 OUT cos_help_data_t *cos_data,
1485 IN u8_t entry,
1486 IN u8_t num_spread_of_entries,
1487 IN u8_t strict_app_pris)
1488 {
1489 u8_t stict_pri = DCBX_S_PRI_COS_HIGHEST;
1490 u8_t num_of_app_pri = MAX_PFC_PRIORITIES;
1491 u8_t app_pri_bit = 0;
1492 lm_status_t lm_status = LM_STATUS_SUCCESS;
1493
1494 DbgBreakIf(FALSE == CHIP_IS_E3B0(pdev));
1495
1496 while((num_spread_of_entries)&&
1497 (0 < num_of_app_pri))
1498 {
1499 app_pri_bit = 1 << (num_of_app_pri -1 );
1500 if(app_pri_bit & strict_app_pris)
1501 {
1502 num_spread_of_entries--;
1503 if(0 == num_spread_of_entries)
1504 {
1505 // last entry needed put all the entries left
1506 lm_dcbx_fill_cos(pdev,
1507 &(cos_data->entry_data[entry]),
1508 strict_app_pris,
1509 DCBX_INVALID_COS_BW,
1510 stict_pri);
1511 }
1512 else
1513 {
1514 strict_app_pris &= ~app_pri_bit;
1515 lm_dcbx_fill_cos(pdev,
1516 &(cos_data->entry_data[entry]),
1517 app_pri_bit,
1518 DCBX_INVALID_COS_BW,
1519 stict_pri);
1520 }
1521
1522 stict_pri = DCBX_S_PRI_COS_NEXT_LOWER_PRI(stict_pri);
1523 entry++;
1524 }
1525 num_of_app_pri--;
1526 }
1527
1528 if(0 != num_spread_of_entries)
1529 {
1530 DbgBreakMsg("lm_dcbx_spread_strict_pri- This is a bug ");
1531 lm_status = LM_STATUS_FAILURE;
1532 }
1533
1534 return lm_status;
1535 }
1536 /**
1537 * @description
1538 * Try to split the strict priority to num_spread_of_entries.
1539 * If not possible all of the priorities will be in one entry.
1540 * @param pdev
1541 * @param cos_data
1542 * @param entry
1543 * @param num_spread_of_entries
1544 * @param strict_app_pris
1545 *
1546 * @return STATIC u8_t
1547 * Num of entries cos_data used.
1548 */
1549 STATIC u8_t
lm_dcbx_cee_fill_strict_pri(IN lm_device_t * pdev,OUT cos_help_data_t * cos_data,INOUT u8_t entry,IN u8_t num_spread_of_entries,IN u8_t strict_app_pris)1550 lm_dcbx_cee_fill_strict_pri(
1551 IN lm_device_t *pdev,
1552 OUT cos_help_data_t *cos_data,
1553 INOUT u8_t entry,
1554 IN u8_t num_spread_of_entries,
1555 IN u8_t strict_app_pris)
1556 {
1557
1558 lm_status_t lm_status = LM_STATUS_SUCCESS;
1559
1560 DbgBreakIf(FALSE == CHIP_IS_E3B0(pdev));
1561
1562 lm_status = lm_dcbx_spread_strict_pri(pdev,
1563 cos_data,
1564 entry,
1565 num_spread_of_entries,
1566 strict_app_pris);
1567 if(LM_STATUS_SUCCESS != lm_status)
1568 {
1569 lm_dcbx_fill_cos(pdev,
1570 &(cos_data->entry_data[entry]),
1571 strict_app_pris,
1572 DCBX_INVALID_COS_BW,
1573 DCBX_S_PRI_COS_HIGHEST);
1574 return 1;
1575
1576 }
1577
1578 return num_spread_of_entries;
1579 }
1580 /**
1581 * @description
1582 * In E3 the allocation is based only on the PG configuration.
1583 * PFC will not have an effect on the mapping. The mapping is
1584 * done according to the following priorities:
1585 * 1. Allocate a single VOQ to PG15 if there is at least one
1586 * priority mapped to PG15.
1587 * 2. Allocate the rest of the VOQ-s to the other PG-s.
1588 * 3. If there are still VOQ-s which have no associated PG, then
1589 * associate these VOQ-s to PG15. These PG-s will be used for SP
1590 * between priorities on PG15.
1591 *
1592 * @param pdev
1593 * @param pg_help_data
1594 * @param ets
1595 * @param cos_data
1596 * @param pg_pri_orginal_spread
1597 * @param pri_join_mask
1598 * @param num_of_dif_pri
1599 *
1600 * @return STATIC void
1601 */
1602 STATIC void
lm_dcbx_cee_fill_cos_params(IN lm_device_t * pdev,IN pg_help_data_t * pg_help_data,IN dcbx_ets_feature_t * ets,OUT cos_help_data_t * cos_data,IN const u32_t pri_join_mask)1603 lm_dcbx_cee_fill_cos_params(
1604 IN lm_device_t *pdev,
1605 IN pg_help_data_t *pg_help_data,
1606 IN dcbx_ets_feature_t *ets,
1607 OUT cos_help_data_t *cos_data,
1608 IN const u32_t pri_join_mask)
1609 {
1610 lm_status_t lm_status = LM_STATUS_SUCCESS;
1611 u8_t need_num_of_entries = 0;
1612 u8_t i = 0;
1613 u8_t entry = 0;
1614
1615 DbgBreakIf(FALSE == CHIP_IS_E3B0(pdev));
1616
1617 // if the number of requested PG-s in CEE is greater than 3
1618 // then the results are not determined since this is a violation
1619 // of the standard.
1620 if(DCBX_COS_MAX_NUM_E3B0 < pg_help_data->num_of_pg)
1621 {
1622 DbgBreakMsg("lm_dcbx_cee_e3b0_fill_cos_params :Wrong pg_help_data->num_of_pg \n");
1623 lm_status = lm_dcbx_join_pgs(pdev,
1624 ets,
1625 pg_help_data,
1626 DCBX_COS_MAX_NUM_E3B0);
1627
1628 if(LM_STATUS_SUCCESS != lm_status)
1629 {
1630 // If we weren't successful in reducing the number of PGs we will disables ETS.
1631 lm_dcbx_ets_disabled_entry_data(pdev,cos_data,pri_join_mask);
1632 return;
1633 }
1634 }
1635
1636 for(i = 0 ; i < pg_help_data->num_of_pg; i++)
1637 {
1638
1639 if(pg_help_data->pg_entry_data[i].pg < DCBX_MAX_NUM_PG_BW_ENTRIES)
1640 {
1641 // Fill BW entry.
1642 lm_dcbx_fill_cos(pdev,
1643 &(cos_data->entry_data[entry]),
1644 pg_help_data->pg_entry_data[i].pg_priority,
1645 DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_help_data->pg_entry_data[i].pg),
1646 DCBX_S_PRI_INVALID);
1647 entry++;
1648 }
1649 else
1650 {
1651 DbgBreakIf(DCBX_STRICT_PRI_PG != pg_help_data->pg_entry_data[i].pg );
1652
1653 need_num_of_entries = min((u8_t)pg_help_data->pg_entry_data[i].num_of_dif_pri,
1654 (u8_t)(((u8_t)DCBX_COS_MAX_NUM_E3B0 - pg_help_data->num_of_pg) + 1/*current entry*/));
1655
1656 // 3. If there are still VOQ-s which have no associated PG, then
1657 // associate these VOQ-s to PG15. These PG-s will be used for SP
1658 // between priorities on PG15.
1659 entry += lm_dcbx_cee_fill_strict_pri(pdev,
1660 cos_data,
1661 entry,
1662 need_num_of_entries,
1663 (u8_t)pg_help_data->pg_entry_data[i].pg_priority);
1664
1665 }
1666
1667 }//end of for
1668
1669 // the entry will represent the number of COS used
1670 cos_data->num_of_cos = entry;
1671
1672 DbgBreakIf(DCBX_COS_MAX_NUM_E3B0 < cos_data->num_of_cos );
1673 }
1674 /**
1675 * @description
1676 * Get the COS parameters according to ETS and PFC receive
1677 * configuration
1678 * @param pdev
1679 * @param pg_help_data
1680 * @param ets
1681 * @param pg_pri_orginal_spread
1682 *
1683 * @return STATIC void
1684 */
1685 STATIC void
lm_dcbx_fill_cos_params(IN lm_device_t * pdev,IN pg_help_data_t * pg_help_data,IN dcbx_ets_feature_t * ets,IN const u32_t * pg_pri_orginal_spread)1686 lm_dcbx_fill_cos_params(
1687 IN lm_device_t *pdev,
1688 IN pg_help_data_t *pg_help_data,
1689 IN dcbx_ets_feature_t *ets,
1690 IN const u32_t *pg_pri_orginal_spread)
1691 {
1692 cos_help_data_t cos_data = {{{0}}};
1693 u8_t i = 0;
1694 u8_t j = 0;
1695 u32_t pri_join_mask = 0;
1696 u8_t num_of_dif_pri = 0;
1697
1698 // Validate the pg value
1699 for(i=0; i < pg_help_data->num_of_pg ; i++)
1700 {
1701 DbgBreakIf((DCBX_STRICT_PRI_PG != pg_help_data->pg_entry_data[i].pg) &&
1702 (DCBX_MAX_NUM_PG_BW_ENTRIES <= pg_help_data->pg_entry_data[i].pg));
1703 pri_join_mask |= pg_help_data->pg_entry_data[i].pg_priority;
1704 num_of_dif_pri += pg_help_data->pg_entry_data[i].num_of_dif_pri;
1705 }
1706
1707 //default settings
1708 cos_data.num_of_cos = 1;
1709 for(i=0; i < ARRSIZE(cos_data.entry_data) ; i++)
1710 {
1711 cos_data.entry_data[i].pri_join_mask = 0;
1712 cos_data.entry_data[i].b_pausable = FALSE;
1713 cos_data.entry_data[i].s_pri = DCBX_S_PRI_INVALID;
1714 cos_data.entry_data[i].cos_bw = DCBX_INVALID_COS_BW;
1715 }
1716
1717 DbgBreakIf((0 == num_of_dif_pri) && (3 < num_of_dif_pri));
1718 if(CHIP_IS_E3B0(pdev))
1719 {
1720 lm_dcbx_cee_fill_cos_params(
1721 pdev,
1722 pg_help_data,
1723 ets,
1724 &cos_data,
1725 pri_join_mask);
1726 }
1727 else
1728 {
1729 DbgBreakIf(FALSE == CHIP_IS_E2E3A0(pdev));
1730 lm_dcbx_2cos_limit_cee_fill_cos_params(
1731 pdev,
1732 pg_help_data,
1733 ets,
1734 &cos_data,
1735 pg_pri_orginal_spread,
1736 pri_join_mask,
1737 num_of_dif_pri);
1738 }
1739
1740 for(i=0; i < cos_data.num_of_cos ; i++)
1741 {
1742 lm_dcbx_fill_cos_entry(pdev,
1743 &pdev->params.dcbx_port_params.ets.cos_params[i],
1744 cos_data.entry_data[i].pri_join_mask,
1745 cos_data.entry_data[i].cos_bw,
1746 cos_data.entry_data[i].b_pausable,
1747 cos_data.entry_data[i].s_pri);
1748 }
1749
1750 DbgBreakIf(0 == cos_data.num_of_cos);
1751
1752 DbgBreakIf(pri_join_mask != (pdev->params.dcbx_port_params.ets.cos_params[0].pri_bitmask |
1753 pdev->params.dcbx_port_params.ets.cos_params[1].pri_bitmask |
1754 pdev->params.dcbx_port_params.ets.cos_params[2].pri_bitmask));
1755
1756 // debugging make sure the same priority isn't mapped to to COS
1757 for(i = 0 ; i < cos_data.num_of_cos; i++)
1758 {
1759 for(j = i+1 ; j < cos_data.num_of_cos; j++)
1760 {
1761 DbgBreakIf(0 != (pdev->params.dcbx_port_params.ets.cos_params[i].pri_bitmask &
1762 pdev->params.dcbx_port_params.ets.cos_params[j].pri_bitmask));
1763 }
1764 }
1765
1766 pdev->params.dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
1767 }
1768 /**
1769 * CQ60417 : If remote feature is not found, we disable the
1770 * feature unless user explicitly configured feature (copycat
1771 * switch behavior)
1772 * @param pdev
1773 * @param error - error flag sent from DCBX.
1774 * @param remote_tlv_feature_flag - Must be one of the
1775 * DCBX_REMOTE_XXX_TLV_NOT_FOUND
1776 *
1777 * @return STATIC u8_t -
1778 */
1779 STATIC u8_t
lm_dcbx_is_feature_dis_remote_tlv(INOUT lm_device_t * pdev,IN const u32_t error,IN const u32_t remote_tlv_feature_flag)1780 lm_dcbx_is_feature_dis_remote_tlv(
1781 INOUT lm_device_t *pdev,
1782 IN const u32_t error,
1783 IN const u32_t remote_tlv_feature_flag
1784 )
1785 {
1786 u8_t const mfw_config = lm_dcbx_check_drv_flags(pdev, DRV_FLAGS_DCB_MFW_CONFIGURED);
1787 u8_t const ret_feature_dis = (remote_tlv_feature_flag == GET_FLAGS(error ,remote_tlv_feature_flag)) &&
1788 (FALSE == mfw_config);
1789
1790 DbgBreakIf(0 == GET_FLAGS(remote_tlv_feature_flag ,
1791 (DCBX_REMOTE_ETS_TLV_NOT_FOUND |
1792 DCBX_REMOTE_PFC_TLV_NOT_FOUND |
1793 DCBX_REMOTE_APP_TLV_NOT_FOUND)));
1794
1795 return ret_feature_dis;
1796 }
1797
1798 /*******************************************************************************
1799 * Description: Translate from ETS parameter to COS paramters
1800 *
1801 * Return:
1802 ******************************************************************************/
1803 STATIC void
lm_dcbx_get_ets_cee_feature(INOUT lm_device_t * pdev,INOUT dcbx_ets_feature_t * ets,IN const u32_t error)1804 lm_dcbx_get_ets_cee_feature(
1805 INOUT lm_device_t *pdev,
1806 INOUT dcbx_ets_feature_t *ets,
1807 IN const u32_t error)
1808 {
1809 u32_t pg_pri_orginal_spread[DCBX_MAX_NUM_PRI_PG_ENTRIES] = {0};
1810 pg_help_data_t pg_help_data = {{{0}}};
1811 const u8_t is_ets_dis_remote_tlv = lm_dcbx_is_feature_dis_remote_tlv(
1812 pdev,
1813 error,
1814 DCBX_REMOTE_ETS_TLV_NOT_FOUND);
1815 // Clean up old settings of ets on COS
1816 lm_dcbx_init_ets_internal_param(pdev,
1817 &(pdev->params.dcbx_port_params.ets));
1818
1819 if(DCBX_MIB_IS_ETS_ENABLED(pdev->params.dcbx_port_params.app.enabled,
1820 error,ets->enabled) &&
1821 (!is_ets_dis_remote_tlv))
1822 {
1823 DbgBreakIf(FALSE == pdev->params.dcbx_port_params.dcbx_enabled);
1824 pdev->params.dcbx_port_params.ets.enabled = TRUE;
1825 }
1826 else
1827 {
1828
1829 lm_dcbx_ets_disable(pdev);
1830 return;
1831 }
1832
1833 //Parse pg_pri_orginal_spread data and spread it from nibble to 32 bits
1834 lm_dcbx_get_ets_pri_pg_tbl(pdev,
1835 pg_pri_orginal_spread,
1836 ets->pri_pg_tbl,
1837 ARRSIZE(pg_pri_orginal_spread),
1838 DCBX_MAX_NUM_PRI_PG_ENTRIES);
1839
1840 lm_dcbx_cee_get_num_of_pg_traf_type(pdev,
1841 pg_pri_orginal_spread,
1842 &pg_help_data);
1843
1844 lm_dcbx_fill_cos_params(pdev,
1845 &pg_help_data,
1846 ets,
1847 pg_pri_orginal_spread);
1848
1849 }
1850
1851 /**
1852 * @description
1853 * Mapping between TC( acording to the given parameters from
1854 * upper layer) which isn't zero based to COS which is zero
1855 * based.
1856 * COS configuration is used to the chip configuration.
1857 * @param pdev
1858 *
1859 * @return STATIC void
1860 */
1861 STATIC void
lm_dcbx_ie_get_ets_ieee_feature(INOUT lm_device_t * pdev)1862 lm_dcbx_ie_get_ets_ieee_feature(
1863 INOUT lm_device_t *pdev)
1864 {
1865 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
1866 pg_params_t *ets_drv_param = &pdev->params.dcbx_port_params.ets;
1867 dcb_ets_tsa_param_t *ieee_ets = &indicate_event->ets_ieee_params_config;
1868 // COS should be continues and zero based
1869 u8_t cee_tc_to_continues_cos[DCBX_MAX_NUM_PRI_PG_ENTRIES] = {0};
1870 u8_t i = 0;
1871 s16_t pri = 0;
1872 u8_t strict_pri = DCBX_S_PRI_COS_HIGHEST;
1873 u8_t tc_entry = 0;
1874 u8_t cos_entry = 0;
1875 const u8_t max_tc_sup = lm_dcbx_cos_max_num(pdev) ;
1876 u8_t next_free_cos_entry = 0;
1877 u8_t tc_used_bitmap = 0;
1878 #if (DBG)
1879 u8_t j = 0;
1880 u8_t pri_used_bitmap = 0;
1881 #endif //DBG
1882 /************************************ Validate Check ***************************/
1883 ASSERT_STATIC(DCBX_MAX_NUM_PRI_PG_ENTRIES == DCBX_MAX_NUM_PG_BW_ENTRIES);
1884 ASSERT_STATIC(DCBX_MAX_NUM_PRI_PG_ENTRIES == ARRSIZE(ieee_ets->priority_assignment_table));
1885 ASSERT_STATIC(DCBX_MAX_NUM_PG_BW_ENTRIES == ARRSIZE(ieee_ets->tc_bw_assignment_table));
1886 ASSERT_STATIC(DCBX_MAX_NUM_PG_BW_ENTRIES == ARRSIZE(ieee_ets->tsa_assignment_table));
1887
1888 DbgBreakIf(lm_dcbx_ets_ieee_config_not_valid == indicate_event->ets_ieee_config_state);
1889 /********************************** Init variables ***************************/
1890 // Clean up old settings of ets on COS
1891 lm_dcbx_init_ets_internal_param(pdev, ets_drv_param);
1892
1893 // If application priority isn't enabled then all DCB features must be disabled.
1894 if((FALSE == pdev->params.dcbx_port_params.app.enabled)||
1895 (LM_DCBX_IE_IS_ETS_DISABLE(ieee_ets->num_traffic_classes))||
1896 (lm_dcbx_ets_ieee_config_en != indicate_event->ets_ieee_config_state))
1897 {
1898 lm_dcbx_ets_disable(pdev);
1899 return;
1900 }
1901
1902 /*** Mapping between TC which isn't zero based to COS which is zero based*****/
1903
1904 // Count the number of TC entries given and fill the appropriate COS entry.
1905 // The for is from the higher priority down, because higher priorities should
1906 // receive higher strict priority.
1907 for (pri = (ARRSIZE(ieee_ets->priority_assignment_table) -1);
1908 0 <= pri;
1909 pri--)
1910 {
1911 tc_entry = ieee_ets->priority_assignment_table[pri];
1912
1913 if(0 == (tc_used_bitmap & (1 << tc_entry)))
1914 {
1915 // We should not reenter, this will cause a bug in strict priority.
1916 // Validate COS entry is legal
1917 if(max_tc_sup <= next_free_cos_entry )
1918 {
1919 DbgBreakMsg(" Wrong ETS settings ");
1920 lm_dcbx_ets_disable(pdev);
1921 return;
1922 }
1923
1924 tc_used_bitmap |= (1 << tc_entry);
1925 cee_tc_to_continues_cos[tc_entry] = next_free_cos_entry;
1926
1927 if(TSA_ASSIGNMENT_DCB_TSA_STRICT == ieee_ets->tsa_assignment_table[tc_entry])
1928 {
1929 ets_drv_param->cos_params[next_free_cos_entry].bw_tbl = DCBX_INVALID_COS_BW;
1930 ets_drv_param->cos_params[next_free_cos_entry].s_pri = strict_pri;
1931 // Prepare for next strict priority
1932 strict_pri = DCBX_S_PRI_COS_NEXT_LOWER_PRI(strict_pri);
1933 }
1934 else if(TSA_ASSIGNMENT_DCB_TSA_ETS == ieee_ets->tsa_assignment_table[tc_entry])
1935 {
1936 ets_drv_param->cos_params[next_free_cos_entry].bw_tbl = ieee_ets->tc_bw_assignment_table[tc_entry];
1937 ets_drv_param->cos_params[next_free_cos_entry].s_pri = DCBX_S_PRI_INVALID;
1938 }
1939 else
1940 {
1941 DbgBreakMsg("lm_dcbx_get_ets_ieee_feature parameters are check before "
1942 "this should not happen");
1943
1944 lm_dcbx_ets_disable(pdev);
1945 return;
1946 }
1947
1948 // Prepare for next entry and also represents after this while the number
1949 // of used COS entries.
1950 next_free_cos_entry++;
1951 }
1952 }
1953
1954 // Fill priority to COS mapping
1955 for (pri = 0; pri < ARRSIZE(ieee_ets->priority_assignment_table); pri++)
1956 {
1957 tc_entry = ieee_ets->priority_assignment_table[pri];
1958 cos_entry = cee_tc_to_continues_cos[tc_entry];
1959
1960 DbgBreakIf(ARRSIZE(ets_drv_param->cos_params) <= cos_entry);
1961
1962 ets_drv_param->cos_params[cos_entry].pri_bitmask |= 1<< pri;
1963
1964 ets_drv_param->cos_params[cos_entry].pauseable = LM_DCBX_IS_PFC_PRI_SOME_PAUSE(pdev,ets_drv_param->cos_params[cos_entry].pri_bitmask);
1965 }
1966
1967 DbgBreakIf( ieee_ets->num_traffic_classes < next_free_cos_entry);
1968
1969 ets_drv_param->num_of_cos = (u8_t)next_free_cos_entry;
1970 ets_drv_param->enabled = TRUE;
1971
1972 #if (DBG)
1973 pri_used_bitmap = 0;
1974 for(i = 0 ; i < ets_drv_param->num_of_cos; i++)
1975 {
1976 // All priorities must be present
1977 pri_used_bitmap |= ets_drv_param->cos_params[i].pri_bitmask;
1978 for(j = i+1 ; j < ets_drv_param->num_of_cos; j++)
1979 {
1980 // Make sure there are no intersection
1981 DbgBreakIf(0 != (ets_drv_param->cos_params[i].pri_bitmask &
1982 ets_drv_param->cos_params[j].pri_bitmask));
1983 }
1984 }
1985 DbgBreakIf(((1 << MAX_PFC_PRIORITIES) -1) != pri_used_bitmap);
1986 #endif //DBG
1987 }
1988 /**
1989 * @description
1990 * Fill priority to COS mapping.
1991 * @param pdev
1992 */
1993 void
lm_dcbx_fill_pri_to_cos_mapping(lm_device_t * pdev)1994 lm_dcbx_fill_pri_to_cos_mapping(lm_device_t *pdev)
1995 {
1996 pg_params_t *ets_drv_param = &pdev->params.dcbx_port_params.ets;
1997 u8_t pri = 0;
1998 u8_t cos = 0;
1999 u8_t pri_bit = 0;
2000
2001 ASSERT_STATIC( MAX_PFC_PRIORITIES == ARRSIZE(pdev->dcbx_info.pri_to_cos));
2002
2003 // Map all priorities to COS 0 by default
2004 mm_mem_zero(pdev->dcbx_info.pri_to_cos, sizeof(pdev->dcbx_info.pri_to_cos));
2005
2006 if(FALSE == ets_drv_param->enabled)
2007 {
2008 return;
2009 }
2010
2011 // Fill the priority to COS
2012 for (cos = 0; cos < ets_drv_param->num_of_cos; cos++)
2013 {
2014 for( pri = 0; pri < ARRSIZE(pdev->dcbx_info.pri_to_cos) ; pri++)
2015 {
2016 pri_bit = 1 << pri;
2017
2018 if (ets_drv_param->cos_params[cos].pri_bitmask & pri_bit)
2019 {
2020 pdev->dcbx_info.pri_to_cos[pri] = cos;
2021 }
2022 }
2023 }
2024 }
2025
lm_dcbx_map_nw(INOUT lm_device_t * pdev)2026 static void lm_dcbx_map_nw(INOUT lm_device_t *pdev)
2027 {
2028 u8_t i;
2029 u32_t unmapped = (1 << MAX_PFC_PRIORITIES) - 1; // all ones
2030 u32_t *ttp = pdev->params.dcbx_port_params.app.traffic_type_priority;
2031 u32_t nw_prio = 1 << ttp[LLFC_TRAFFIC_TYPE_NW];
2032 dcbx_cos_params_t *cos_params =
2033 pdev->params.dcbx_port_params.ets.cos_params;
2034
2035 // get unmapped priorities by clearing mapped bits
2036 for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
2037 unmapped &= ~(1 << ttp[i]);
2038
2039 // find cos for nw prio and extend it with unmapped
2040 for (i = 0; i < ARRSIZE(pdev->params.dcbx_port_params.ets.cos_params); i++) {
2041 if (cos_params[i].pri_bitmask & nw_prio) {
2042 // extend the bitmask with unmapped
2043 DbgMessage(pdev, INFORM,
2044 "cos %d extended with 0x%08x", i, unmapped);
2045
2046 cos_params[i].pri_bitmask |= unmapped;
2047 break;
2048 }
2049 }
2050 }
2051 /**
2052 * Pass on all priority_assignment_table cells and merge them to
2053 * the first cell of the BW until the amount of cells will be
2054 * less than max_tc_sup
2055 *
2056 * @param pdev
2057 * @param ieee_ets
2058 */
2059 void
lm_dcbx_ie_merge_bw_cells(INOUT lm_device_t * pdev,INOUT dcb_ets_tsa_param_t * ieee_ets)2060 lm_dcbx_ie_merge_bw_cells(
2061 INOUT lm_device_t *pdev,
2062 INOUT dcb_ets_tsa_param_t *ieee_ets
2063 )
2064 {
2065 const u8_t max_tc_sup = lm_dcbx_cos_max_num(pdev);
2066 const u8_t invalid_tc = ARRSIZE(ieee_ets->priority_assignment_table);
2067 u8_t tc_entry = 0;
2068 u8_t tc_entry_bit = 0;
2069 u8_t merge_tc = invalid_tc;
2070 u8_t pri = 0;
2071 u8_t pri_remap = 0;
2072 u8_t tc_used_bitmap = 0;
2073
2074 if(ieee_ets->num_traffic_classes <= max_tc_sup)
2075 {
2076 // nothing to do.
2077 return;
2078 }
2079
2080 for (pri = 0;
2081 pri < ARRSIZE(ieee_ets->priority_assignment_table);
2082 pri++)
2083 {
2084 tc_entry = ieee_ets->priority_assignment_table[pri];
2085 tc_entry_bit = (1 << tc_entry);
2086
2087 if((0 == (tc_used_bitmap & tc_entry_bit)) &&
2088 (TSA_ASSIGNMENT_DCB_TSA_ETS == ieee_ets->tsa_assignment_table[tc_entry]))
2089 {
2090 if(invalid_tc != merge_tc)
2091 {
2092 // We found already a cell to merge to
2093 DbgBreakIf(tc_entry == merge_tc);
2094
2095 // point the pri to merge_tc.
2096 ieee_ets->priority_assignment_table[pri] = merge_tc;
2097
2098 // merge the cells
2099 ieee_ets->tc_bw_assignment_table[merge_tc] += ieee_ets->tc_bw_assignment_table[tc_entry];
2100 ieee_ets->tc_bw_assignment_table[tc_entry] = 0;
2101 ieee_ets->tsa_assignment_table[tc_entry] = TSA_ASSIGNMENT_DCB_TSA_STRICT;// Don't care
2102
2103 // remapping all tc_entry => merge_tc
2104 for (pri_remap = 0;
2105 pri_remap < ARRSIZE(ieee_ets->priority_assignment_table);
2106 pri_remap++)
2107 {
2108 if(tc_entry == ieee_ets->priority_assignment_table[pri_remap])
2109 {
2110 ieee_ets->priority_assignment_table[pri_remap] = merge_tc;
2111 }
2112 }
2113
2114 ieee_ets->num_traffic_classes--;
2115 }
2116 else
2117 {
2118 // Find first BW cell
2119 merge_tc = tc_entry;
2120 }
2121 }
2122
2123 tc_used_bitmap |= tc_entry_bit;
2124
2125 if(ieee_ets->num_traffic_classes <= max_tc_sup )
2126 {
2127 break;
2128 }
2129
2130 }
2131
2132 DbgBreakIf(max_tc_sup < ieee_ets->num_traffic_classes);
2133
2134 }
2135 /**
2136 * if (admin.ETS == local.ETS)
2137 * Use OS configuration.
2138 * Else
2139 * Parse the data from CEE to IEEE .
2140 * @param pdev
2141 * @param cee_ets
2142 *
2143 * @return u8_t
2144 */
2145 u8_t
lm_dcbx_ie_is_ets_admin_eq_local(INOUT lm_device_t * pdev,IN dcbx_ets_feature_t * cee_ets)2146 lm_dcbx_ie_is_ets_admin_eq_local(
2147 INOUT lm_device_t *pdev,
2148 IN dcbx_ets_feature_t *cee_ets
2149 )
2150 {
2151 lldp_admin_mib_t admin_mib = {0};
2152 u32_t admin_mib_offset = 0;
2153 lm_status_t lm_status = LM_STATUS_SUCCESS;
2154
2155 lm_status = lm_dcbx_read_admin_mib( pdev,
2156 &admin_mib,
2157 &admin_mib_offset);
2158
2159 if(LM_STATUS_SUCCESS != lm_status)
2160 {
2161 DbgBreakMsg(" lm_dcbx_ie_admin_mib_updated_runtime lm_dcbx_read_admin_mib failed ");
2162 return FALSE;
2163 }
2164
2165 return mm_memcmp(cee_ets,
2166 &admin_mib.features.ets,
2167 sizeof(admin_mib.features.ets));
2168
2169 }
2170 /**
2171 In CEE all strict TC-s are map to PGID=15. This is how it
2172 will appear in the TLV on the wire and in local settings.
2173 As a result there is a problem in showing the correct
2174 strict TC settings of the local and remote peer side (remote
2175 configuration): a. If more than one TC (e.g. TC_0 and TC_1)
2176 will be assigned to TSA strict, on the local or remote peer
2177 side they will be merged to one TC. b. The strict TC number
2178 will not be correct on the local and remote peer side.
2179
2180 Assumption:In ETS there is no merging done by MCP we either
2181 take our configuration or the other side
2182
2183 Suggested solution: Driver will save ETS OS
2184 configuration.
2185
2186 In case of an interrupt driver will :
2187 if (admin.ETS == local.ETS)
2188 Use OS configuration.
2189 Else
2190 Parse the data from CEE to IEEE .
2191 * @param pdev
2192 * @param cee_ets
2193 */
2194 void
lm_dcbx_ie_get_ieee_config_param(INOUT lm_device_t * pdev,IN dcbx_ets_feature_t * cee_ets,IN const u32_t error)2195 lm_dcbx_ie_get_ieee_config_param(
2196 INOUT lm_device_t *pdev,
2197 IN dcbx_ets_feature_t *cee_ets,
2198 IN const u32_t error
2199 )
2200 {
2201 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
2202 u32_t flags = 0;
2203
2204 if(FALSE == DCBX_MIB_IS_ETS_ENABLED(pdev->params.dcbx_port_params.app.enabled,
2205 error,cee_ets->enabled))
2206 {
2207 indicate_event->ets_ieee_config_state = lm_dcbx_ets_ieee_config_di;
2208 mm_mem_zero(&indicate_event->ets_ieee_params_config,
2209 sizeof(indicate_event->ets_ieee_params_os));
2210 return;
2211 }
2212
2213 if(lm_dcbx_ie_is_ets_admin_eq_local(pdev,cee_ets) &&
2214 indicate_event->is_ets_ieee_params_os_valid)
2215 {
2216 indicate_event->ets_ieee_config_state = lm_dcbx_ets_ieee_config_en;
2217
2218 mm_memcpy(&indicate_event->ets_ieee_params_config,
2219 &indicate_event->ets_ieee_params_os,
2220 sizeof(indicate_event->ets_ieee_params_os));
2221 }
2222 else
2223 {
2224 lm_dcbx_ie_ets_cee_to_ieee_unparse(pdev,
2225 cee_ets,
2226 &indicate_event->ets_ieee_params_config,
2227 &flags);
2228
2229 if(GET_FLAGS(flags,DCB_PARAMS_ETS_ENABLED))
2230 {
2231 indicate_event->ets_ieee_config_state = lm_dcbx_ets_ieee_config_en;
2232 }
2233 else
2234 {
2235 indicate_event->ets_ieee_config_state = lm_dcbx_ets_ieee_config_di;
2236 }
2237
2238 lm_dcbx_ie_merge_bw_cells(pdev,
2239 &indicate_event->ets_ieee_params_config);
2240 }
2241 }
2242
2243 /**
2244 * @description
2245 *
2246 * @param pdev
2247 * @param pfc
2248 * @param error
2249 *
2250 * @return STATIC void
2251 */
2252 STATIC void
lm_dcbx_get_ets_feature(INOUT lm_device_t * pdev,IN dcbx_ets_feature_t * ets,IN const u32_t error)2253 lm_dcbx_get_ets_feature(
2254 INOUT lm_device_t *pdev,
2255 IN dcbx_ets_feature_t *ets,
2256 IN const u32_t error
2257 )
2258 {
2259 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
2260
2261 if(lm_dcbx_ets_config_state_cee == indicate_event->ets_config_state)
2262 {
2263 indicate_event->ets_ieee_config_state = lm_dcbx_ets_ieee_config_not_valid;
2264
2265 lm_dcbx_get_ets_cee_feature(
2266 pdev,
2267 ets,
2268 error);
2269
2270 lm_dcbx_map_nw(pdev);
2271
2272 DbgBreakIf(lm_dcbx_ets_ieee_config_not_valid != indicate_event->ets_ieee_config_state);
2273 }
2274 else
2275 {
2276 lm_dcbx_ie_get_ieee_config_param(pdev,
2277 ets,
2278 error);
2279
2280 //If ets is given from upper layer we don't use chip ETS configuration
2281 lm_dcbx_ie_get_ets_ieee_feature( pdev);
2282
2283 DbgBreakIf(lm_dcbx_ets_ieee_config_not_valid == indicate_event->ets_ieee_config_state);
2284 }
2285
2286 lm_dcbx_fill_pri_to_cos_mapping( pdev);
2287 }
2288 /*******************************************************************************
2289 * Description:
2290 *
2291 * Return:
2292 ******************************************************************************/
2293 STATIC void
lm_dcbx_get_pfc_feature(INOUT lm_device_t * pdev,IN const dcbx_pfc_feature_t * pfc,IN const u32_t error)2294 lm_dcbx_get_pfc_feature(
2295 INOUT lm_device_t *pdev,
2296 IN const dcbx_pfc_feature_t *pfc,
2297 IN const u32_t error
2298 )
2299 {
2300 const u8_t is_pfc_dis_remote_tlv = lm_dcbx_is_feature_dis_remote_tlv(
2301 pdev,
2302 error,
2303 DCBX_REMOTE_PFC_TLV_NOT_FOUND);
2304
2305 if(DCBX_MIB_IS_PFC_ENABLED(pdev->params.dcbx_port_params.app.enabled,
2306 error, pfc->enabled) && (!is_pfc_dis_remote_tlv))
2307 {
2308 DbgBreakIf(FALSE == pdev->params.dcbx_port_params.dcbx_enabled);
2309 pdev->params.dcbx_port_params.pfc.enabled = TRUE;
2310 pdev->params.dcbx_port_params.pfc.priority_non_pauseable_mask = (u8_t)(~(pfc->pri_en_bitmap));
2311 }
2312 else
2313 {
2314 pdev->params.dcbx_port_params.pfc.enabled = FALSE;
2315 pdev->params.dcbx_port_params.pfc.priority_non_pauseable_mask = 0;
2316 }
2317
2318 }
2319
2320 /*******************************************************************************
2321 * Description: Take the highest priority available.(This function don't do the
2322 * initialization of priority.)
2323 *
2324 * Return:
2325 ******************************************************************************/
2326 STATIC void
lm_dcbx_get_ap_priority(IN lm_device_t * pdev,INOUT u32_t * entry_pri,IN const u8_t pri_bitmap,INOUT u8_t * is_default_off_tt_set)2327 lm_dcbx_get_ap_priority(
2328 IN lm_device_t *pdev,
2329 INOUT u32_t *entry_pri,
2330 IN const u8_t pri_bitmap,
2331 INOUT u8_t *is_default_off_tt_set
2332 )
2333 {
2334 u8_t pri = MAX_PFC_PRIORITIES;
2335 u8_t index = 0 ;
2336 u8_t pri_mask = 0;
2337
2338 //Chose the highest priority the lower pri will get run over
2339 for(index = 0; index < MAX_PFC_PRIORITIES ; index++)
2340 {
2341 pri_mask = 1 <<(index);
2342 if(GET_FLAGS(pri_bitmap , pri_mask))
2343 {
2344 pri = index ;
2345 }
2346 }
2347
2348 if(pri < MAX_PFC_PRIORITIES)
2349 {
2350 if((*entry_pri < MAX_PFC_PRIORITIES) &&
2351 (FALSE == *is_default_off_tt_set))
2352 {
2353 *entry_pri = max(*entry_pri, pri);
2354 }
2355 else
2356 {
2357 *entry_pri = pri;
2358 *is_default_off_tt_set = FALSE;
2359 }
2360
2361 }
2362 }
2363 /**
2364 * Check if the entry is an ISCSI classification entry.
2365 * @param app_id
2366 * @param appBitfield
2367 *
2368 * @return STATIC u8_t
2369 */
2370 STATIC u8_t
lm_dcbx_cee_is_entry_iscsi_classif(IN const u8_t appBitfield,IN const u16_t app_id)2371 lm_dcbx_cee_is_entry_iscsi_classif(IN const u8_t appBitfield,
2372 IN const u16_t app_id)
2373 {
2374 if(GET_FLAGS(appBitfield,DCBX_APP_SF_PORT) &&
2375 (TCP_PORT_ISCSI == app_id))
2376 {
2377 return TRUE;
2378 }
2379
2380 return FALSE;
2381 }
2382 /**
2383 * Check if the entry is an FCOE classification entry.
2384 * @param app_id
2385 * @param appBitfield
2386 *
2387 * @return STATIC u8_t
2388 */
2389 STATIC u8_t
lm_dcbx_cee_is_entry_fcoe_classif(IN const u8_t appBitfield,IN const u16_t app_id)2390 lm_dcbx_cee_is_entry_fcoe_classif(IN const u8_t appBitfield,
2391 IN const u16_t app_id)
2392 {
2393 if(GET_FLAGS(appBitfield,DCBX_APP_SF_ETH_TYPE) &&
2394 (ETH_TYPE_FCOE == app_id))
2395 {
2396 return TRUE;
2397 }
2398
2399 return FALSE;
2400 }
2401
2402 /**
2403 * Look for offload app priorities for offload traffic
2404 * types:ISCSI and FCOE.
2405 * @param pdev
2406 * @param app_tbl
2407 * @param app_tbl_size
2408 *
2409 * @return STATIC void
2410 */
2411 STATIC void
lm_dcbx_get_app_pri_off_tt(lm_device_t * pdev,IN const dcbx_app_priority_entry_t * app_tbl,IN const u8_t app_tbl_size,INOUT u8_t * is_default_off_tt_used)2412 lm_dcbx_get_app_pri_off_tt(
2413 lm_device_t *pdev,
2414 IN const dcbx_app_priority_entry_t *app_tbl,
2415 IN const u8_t app_tbl_size,
2416 INOUT u8_t *is_default_off_tt_used
2417 )
2418 {
2419 u8_t index = 0;
2420
2421 for(index = 0 ;(index < app_tbl_size); index++)
2422 {
2423 if(DCBX_APP_ENTRY_VALID != GET_FLAGS(app_tbl[index].appBitfield,DCBX_APP_ENTRY_VALID))
2424 {
2425 continue;
2426 }
2427
2428 if(lm_dcbx_cee_is_entry_fcoe_classif(app_tbl[index].appBitfield, app_tbl[index].app_id))
2429 {
2430 lm_dcbx_get_ap_priority(pdev,
2431 &(pdev->params.dcbx_port_params.app.traffic_type_priority[LLFC_TRAFFIC_TYPE_FCOE]),
2432 app_tbl[index].pri_bitmap,
2433 &is_default_off_tt_used[LLFC_TRAFFIC_TYPE_FCOE]);
2434 }
2435
2436 if(lm_dcbx_cee_is_entry_iscsi_classif(app_tbl[index].appBitfield, app_tbl[index].app_id))
2437 {
2438 lm_dcbx_get_ap_priority(pdev,
2439 &(pdev->params.dcbx_port_params.app.traffic_type_priority[LLFC_TRAFFIC_TYPE_ISCSI]),
2440 app_tbl[index].pri_bitmap,
2441 &is_default_off_tt_used[LLFC_TRAFFIC_TYPE_ISCSI]);
2442 }
2443 }
2444 }
2445 /**
2446 * Update non negotiation application IDs entries.
2447 * @param pdev
2448 *
2449 * @return STATIC void
2450 */
2451 STATIC void
lm_dcbx_get_app_pri_off_tt_non_neg(INOUT lm_device_t * pdev,INOUT u8_t * is_default_off_tt_set)2452 lm_dcbx_get_app_pri_off_tt_non_neg(
2453 INOUT lm_device_t *pdev,
2454 INOUT u8_t *is_default_off_tt_set)
2455 {
2456 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
2457 // If indicate event is enabled and there is a OS configuration contained an entry
2458 // with �TCP port� = 3260 use that entry.
2459 if((TRUE == pdev->dcbx_info.is_indicate_event_en) &&
2460 (LM_DCBX_ILLEGAL_PRI != indicate_event->iscsi_tcp_pri))
2461 {
2462 pdev->params.dcbx_port_params.app.traffic_type_priority[LLFC_TRAFFIC_TYPE_ISCSI] =
2463 indicate_event->iscsi_tcp_pri;
2464
2465 is_default_off_tt_set[LLFC_TRAFFIC_TYPE_ISCSI] = FALSE;
2466 }
2467 }
2468 /*******************************************************************************
2469 * Description:
2470 * Traffic type (protocol) identification:
2471 * Networking is identified by Ether-Type = IPv4 or Ether-Type =IPv6.
2472 * iSCSI is by TCP-port = iSCSI well know port (3260)
2473 * FCoE is identified by Ether-type = FCoE
2474 * Theoretically each protocol can be associated with multiple priorities (a priority bit map). In this case we choose the highest one.
2475 * Priority assignment for networking:
2476 * 1. If IPv4 is identified, the networking priority is the IPv4 priority (highest one as mentioned above).
2477 * 2. Otherwise if IPv6 is identified, the networking priority is the IPv6 priority.
2478 * 3. Otherwise the networking priority is set 0. (All other protocol TLVs which are not iSCSI or FCoE are ignored).
2479 *
2480 * Priority assignment for iSCSI:
2481 * 1. If the operational configuration from MCP contains an entry with 'TCP or UDP port' = 3260 use that entry,
2482 * 2. Else if OS configuration contained an entry with 'TCP port' = 3260 use that entry,
2483 * 3. Else use the default configuration.
2484 *
2485 * Priority assignment for FCoE:
2486 * 1. If FCoE is identified, then obviously this is the FCoE priority (again the highest one).
2487 * 2. Otherwise FCoE priority is set to default configuration.
2488 * Return:
2489 ******************************************************************************/
2490 STATIC void
lm_dcbx_get_ap_feature(INOUT lm_device_t * pdev,IN const dcbx_app_priority_feature_t * app,IN const dcbx_app_priority_entry_t * app_tbl_ext,IN const u8_t app_tbl_ext_size,IN const u32_t error)2491 lm_dcbx_get_ap_feature(
2492 INOUT lm_device_t *pdev,
2493 IN const dcbx_app_priority_feature_t *app,
2494 IN const dcbx_app_priority_entry_t *app_tbl_ext,
2495 IN const u8_t app_tbl_ext_size,
2496 IN const u32_t error)
2497 {
2498 u8_t index = 0;
2499 u8_t const default_pri = (app->default_pri < MAX_PFC_PRIORITIES)? app->default_pri: 0;
2500 u8_t is_default_off_tt_used[MAX_TRAFFIC_TYPE] = {0};
2501 const u8_t is_app_dis_remote_tlv = lm_dcbx_is_feature_dis_remote_tlv(
2502 pdev,
2503 error,
2504 DCBX_REMOTE_APP_TLV_NOT_FOUND);
2505
2506 if((TRUE == pdev->params.dcbx_port_params.dcbx_enabled) &&
2507 DCBX_MIB_IS_APP_ENABLED(app->enabled, error) && (!is_app_dis_remote_tlv))
2508 {
2509 pdev->params.dcbx_port_params.app.enabled = TRUE;
2510
2511 // First initialize all the entries to default priority
2512 for( index=0 ; index < ARRSIZE(pdev->params.dcbx_port_params.app.traffic_type_priority) ;index++)
2513 {
2514 is_default_off_tt_used[index] = TRUE;
2515 pdev->params.dcbx_port_params.app.traffic_type_priority[index] = default_pri;
2516 }
2517 // The value of this entries is used only if there isn't a corresponding negotiated entry.
2518 lm_dcbx_get_app_pri_off_tt_non_neg(pdev, is_default_off_tt_used);
2519
2520 lm_dcbx_get_app_pri_off_tt(pdev,
2521 app->app_pri_tbl,
2522 ARRSIZE(app->app_pri_tbl),
2523 is_default_off_tt_used);
2524
2525 lm_dcbx_get_app_pri_off_tt(pdev,
2526 app_tbl_ext,
2527 app_tbl_ext_size,
2528 is_default_off_tt_used);
2529 }
2530 else
2531 {
2532 pdev->params.dcbx_port_params.app.enabled = FALSE;
2533 for( index=0 ;
2534 index < ARRSIZE(pdev->params.dcbx_port_params.app.traffic_type_priority) ;
2535 index++)
2536 {
2537 pdev->params.dcbx_port_params.app.traffic_type_priority[index] =
2538 INVALID_TRAFFIC_TYPE_PRIORITY;
2539 }
2540 }
2541 }
2542 void
lm_dcbx_get_dcbx_enabled(INOUT lm_device_t * pdev,IN const u32_t error)2543 lm_dcbx_get_dcbx_enabled(
2544 INOUT lm_device_t *pdev,
2545 IN const u32_t error)
2546 {
2547 dcbx_port_params_t *dcbx_port_params = &(pdev->params.dcbx_port_params);
2548 u8_t const mfw_config = lm_dcbx_check_drv_flags(pdev, DRV_FLAGS_DCB_MFW_CONFIGURED);
2549
2550 if((0 == GET_FLAGS(error, DCBX_REMOTE_MIB_ERROR)) ||
2551 (TRUE == mfw_config))
2552 {
2553 dcbx_port_params->dcbx_enabled = TRUE;
2554 }
2555 else
2556 {
2557 //If no configuration from OS / BACS and no DCBX received from the peer then disable DCB.
2558 dcbx_port_params->dcbx_enabled = FALSE;
2559 }
2560 }
2561 /*******************************************************************************
2562 * Description: Translate PFC/PG parameters to VBD parameters and call relevent
2563 * Function to set the parameters.
2564 *
2565 * Return:
2566 ******************************************************************************/
2567 STATIC void
lm_print_dcbx_drv_param(IN struct _lm_device_t * pdev,IN const lldp_local_mib_t * local_mib)2568 lm_print_dcbx_drv_param(IN struct _lm_device_t *pdev,
2569 IN const lldp_local_mib_t *local_mib)
2570 {
2571 #if DBG
2572 u8_t i =0;
2573 DbgMessage(pdev, INFORM, "local_mib.error %x\n",local_mib->error);
2574
2575 //Pg
2576 DbgMessage(pdev, INFORM, "local_mib.features.ets.enabled %x\n",local_mib->features.ets.enabled);
2577 for(i=0;i<DCBX_MAX_NUM_PG_BW_ENTRIES;i++)
2578 {
2579 DbgMessage(pdev, INFORM, "local_mib.features.ets.pg_bw_tbl[%x] %x\n",i,DCBX_PG_BW_GET(local_mib->features.ets.pg_bw_tbl,i));
2580 }
2581 for(i=0;i<DCBX_MAX_NUM_PRI_PG_ENTRIES;i++)
2582 {
2583 DbgMessage(pdev, INFORM,"local_mib.features.ets.pri_pg_tbl[%x] %x\n",i,DCBX_PRI_PG_GET(local_mib->features.ets.pri_pg_tbl,i));
2584 }
2585
2586 //pfc
2587 DbgMessage(pdev, INFORM, "local_mib.features.pfc.pri_en_bitmap %x\n",local_mib->features.pfc.pri_en_bitmap);
2588 DbgMessage(pdev, INFORM, "local_mib.features.pfc.pfc_caps %x\n",local_mib->features.pfc.pfc_caps);
2589 DbgMessage(pdev, INFORM, "local_mib.features.pfc.enabled %x\n",local_mib->features.pfc.enabled);
2590
2591 DbgMessage(pdev, INFORM, "local_mib.features.app.default_pri %x\n",local_mib->features.app.default_pri);
2592 DbgMessage(pdev, INFORM, "local_mib.features.app.tc_supported %x\n",local_mib->features.app.tc_supported);
2593 DbgMessage(pdev, INFORM, "local_mib.features.app.enabled %x\n",local_mib->features.app.enabled);
2594 for(i=0;i<DCBX_MAX_APP_PROTOCOL;i++)
2595 {
2596
2597 // This has no logic this is only done for supporting old bootcodes.
2598 // The boot code still expexts u8 [2] instead of u16
2599 DbgMessage(pdev, INFORM,"local_mib.features.app.app_pri_tbl[%x].app_id %x\n",
2600 i,local_mib->features.app.app_pri_tbl[i].app_id);
2601
2602 DbgMessage(pdev, INFORM, "local_mib.features.app.app_pri_tbl[%x].pri_bitmap %x\n",
2603 i,local_mib->features.app.app_pri_tbl[i].pri_bitmap);
2604 DbgMessage(pdev, INFORM, "local_mib.features.app.app_pri_tbl[%x].appBitfield %x\n",
2605 i,local_mib->features.app.app_pri_tbl[i].appBitfield);
2606 }
2607 #endif
2608 }
2609 /*******************************************************************************
2610 * Description: Translate PFC/PG parameters to VBD parameters and call relevent
2611 * Function to set the parameters.
2612 *
2613 * Return:
2614 ******************************************************************************/
2615 STATIC void
lm_get_dcbx_drv_param(INOUT lm_device_t * pdev,IN lldp_local_mib_t * local_mib,IN const lldp_local_mib_ext_t * local_mib_ext)2616 lm_get_dcbx_drv_param(INOUT lm_device_t *pdev,
2617 IN lldp_local_mib_t *local_mib,
2618 IN const lldp_local_mib_ext_t *local_mib_ext)
2619 {
2620 if(CHK_NULL(local_mib) || CHK_NULL(local_mib_ext))
2621 {
2622 DbgBreakMsg("lm_get_dcbx_drv_param wrong in parameters ");
2623 return;
2624 }
2625
2626 lm_dcbx_get_dcbx_enabled(
2627 pdev,
2628 local_mib->error);
2629
2630 lm_dcbx_get_ap_feature(
2631 pdev,
2632 &(local_mib->features.app),
2633 local_mib_ext->app_pri_tbl_ext,
2634 ARRSIZE(local_mib_ext->app_pri_tbl_ext),
2635 local_mib->error);
2636
2637 lm_dcbx_get_pfc_feature(
2638 pdev,
2639 &(local_mib->features.pfc),
2640 local_mib->error);
2641
2642 lm_dcbx_get_ets_feature(
2643 pdev,
2644 &(local_mib->features.ets),
2645 local_mib->error);
2646 }
2647 /*******************************************************************************
2648 * Description: Should be integrate with write and moved to common code
2649 *
2650 * Return:
2651 ******************************************************************************/
2652 STATIC void
lm_dcbx_read_shmem2_mcp_fields(struct _lm_device_t * pdev,u32_t offset,u32_t * val)2653 lm_dcbx_read_shmem2_mcp_fields(struct _lm_device_t * pdev,
2654 u32_t offset,
2655 u32_t * val)
2656 {
2657 u32_t shmem2_size;
2658
2659 if (pdev->hw_info.shmem_base2 != 0)
2660 {
2661 LM_SHMEM2_READ(pdev, OFFSETOF(shmem2_region_t,size), &shmem2_size);
2662 if (shmem2_size > offset)
2663 {
2664 LM_SHMEM2_READ(pdev, offset, val);
2665 }
2666 }
2667 }
2668
2669 /*******************************************************************************
2670 * Description:Should be integrate with read and moved to common code
2671 *
2672 * Return:
2673 ******************************************************************************/
2674 STATIC void
lm_dcbx_write_shmem2_mcp_fields(struct _lm_device_t * pdev,u32_t offset,u32_t val)2675 lm_dcbx_write_shmem2_mcp_fields(struct _lm_device_t *pdev,
2676 u32_t offset,
2677 u32_t val)
2678 {
2679 u32_t shmem2_size;
2680
2681 if (pdev->hw_info.shmem_base2 != 0)
2682 {
2683 LM_SHMEM2_READ(pdev, OFFSETOF(shmem2_region_t,size), &shmem2_size);
2684 if (shmem2_size > offset)
2685 {
2686 LM_SHMEM2_WRITE(pdev, offset, val);
2687 }
2688 }
2689 }
2690 /*******************************************************************************
2691 * Description:
2692 *
2693 * Return:
2694 ******************************************************************************/
2695 STATIC void
lm_dcbx_stop_hw_tx(struct _lm_device_t * pdev)2696 lm_dcbx_stop_hw_tx(struct _lm_device_t * pdev)
2697 {
2698
2699 // TODO DCBX change to cmd_id
2700 lm_eq_ramrod_post_sync(pdev,
2701 RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
2702 0,
2703 CMD_PRIORITY_MEDIUM,/* Called from WI must be done ASAP*/
2704 &(pdev->dcbx_info.dcbx_ramrod_state),
2705 FUNCTION_DCBX_STOP_POSTED,
2706 FUNCTION_DCBX_STOP_COMPLETED);
2707
2708 }
2709 /*******************************************************************************
2710 * Description:
2711 *
2712 * Return:
2713 ******************************************************************************/
2714 STATIC void
lm_dcbx_resume_hw_tx(struct _lm_device_t * pdev)2715 lm_dcbx_resume_hw_tx(struct _lm_device_t * pdev)
2716 {
2717 lm_dcbx_fw_struct(pdev);
2718
2719 lm_eq_ramrod_post_sync(pdev,
2720 RAMROD_CMD_ID_COMMON_START_TRAFFIC,
2721 pdev->dcbx_info.pfc_fw_cfg_phys.as_u64,
2722 CMD_PRIORITY_HIGH,/* Called from WI must be done ASAP*/
2723 &(pdev->dcbx_info.dcbx_ramrod_state),
2724 FUNCTION_DCBX_START_POSTED,
2725 FUNCTION_DCBX_START_COMPLETED);
2726
2727 }
2728 /*******************************************************************************
2729 * Description:
2730 *
2731 * Return:
2732 ******************************************************************************/
2733 #define DCBX_LOCAL_MIB_MAX_TRY_READ (100)
2734 STATIC lm_status_t
lm_dcbx_read_remote_local_mib(IN struct _lm_device_t * pdev,OUT u32_t * base_mib_addr,IN const dcbx_read_mib_type read_mib_type)2735 lm_dcbx_read_remote_local_mib(IN struct _lm_device_t *pdev,
2736 OUT u32_t *base_mib_addr,
2737 IN const dcbx_read_mib_type read_mib_type)
2738 {
2739 static const u8_t dcbx_local_mib_max_try_read = DCBX_LOCAL_MIB_MAX_TRY_READ;
2740 u8_t max_try_read = 0 ,i =0;
2741 u32_t * buff = NULL;
2742 u32_t mib_size = 0,prefix_seq_num = 0 ,suffix_seq_num = 0;
2743 lldp_remote_mib_t *remote_mib = NULL;
2744 lldp_local_mib_t *local_mib = NULL;
2745 const u32_t mcp_dcbx_neg_res_offset = OFFSETOF(shmem2_region_t,dcbx_neg_res_offset);
2746 const u32_t mcp_dcbx_remote_mib_offset = OFFSETOF(shmem2_region_t,dcbx_remote_mib_offset);
2747 u32_t offset = 0;
2748 // verify no wraparound on while loop
2749 ASSERT_STATIC( sizeof( max_try_read ) == sizeof(u8_t) );
2750 ASSERT_STATIC(DCBX_LOCAL_MIB_MAX_TRY_READ < ((u8_t)-1));
2751
2752 switch (read_mib_type)
2753 {
2754 case DCBX_READ_LOCAL_MIB:
2755
2756 // Get negotiation results MIB data
2757 offset = SHMEM_DCBX_NEG_RES_NONE;
2758
2759 lm_dcbx_read_shmem2_mcp_fields(pdev,
2760 mcp_dcbx_neg_res_offset,
2761 &offset);
2762
2763 if (SHMEM_DCBX_NEG_RES_NONE == offset)
2764 {
2765 DbgBreakMsg("lm_dcbx_read_remote_local_mib DCBX Negotiation result not supported");
2766 return LM_STATUS_FAILURE;
2767 }
2768 mib_size = sizeof(lldp_local_mib_t);
2769 break;
2770 case DCBX_READ_REMOTE_MIB:
2771 // Get remote MIB data
2772 offset = SHMEM_DCBX_REMOTE_MIB_NONE;
2773
2774 lm_dcbx_read_shmem2_mcp_fields(pdev,
2775 mcp_dcbx_remote_mib_offset,
2776 &offset);
2777
2778 if (SHMEM_DCBX_REMOTE_MIB_NONE == offset)
2779 {
2780 DbgBreakMsg("lm_dcbx_read_remote_local_mib DCBX Negotiation result not supported");
2781 return LM_STATUS_FAILURE;
2782 }
2783
2784 mib_size = sizeof(lldp_remote_mib_t);
2785 break;
2786 default:
2787 DbgBreakIf(1);
2788 return LM_STATUS_FAILURE;
2789 }
2790
2791 offset += PORT_ID(pdev) * mib_size;
2792
2793 do
2794 {
2795 buff = base_mib_addr;
2796
2797 for(i=0 ;i<mib_size; i+=4,buff++)
2798 {
2799 *buff = REG_RD(pdev,
2800 offset + i);
2801 }
2802 max_try_read++;
2803
2804 switch (read_mib_type)
2805 {
2806 case DCBX_READ_LOCAL_MIB:
2807 local_mib = (lldp_local_mib_t *) base_mib_addr;
2808 prefix_seq_num = local_mib->prefix_seq_num;
2809 suffix_seq_num = local_mib->suffix_seq_num;
2810 break;
2811 case DCBX_READ_REMOTE_MIB:
2812 remote_mib = (lldp_remote_mib_t *) base_mib_addr;
2813 prefix_seq_num = remote_mib->prefix_seq_num;
2814 suffix_seq_num = remote_mib->suffix_seq_num;
2815 break;
2816 default:
2817 DbgBreakIf(1);
2818 return LM_STATUS_FAILURE;
2819 }
2820 }while((prefix_seq_num != suffix_seq_num)&&
2821 (max_try_read <dcbx_local_mib_max_try_read));
2822
2823
2824 if(max_try_read >= dcbx_local_mib_max_try_read)
2825 {
2826 DbgBreakMsg("prefix_seq_num doesnt equal suffix_seq_num for to much time");
2827 return LM_STATUS_FAILURE;
2828 }
2829 return LM_STATUS_SUCCESS;
2830 }
2831 /**
2832 *
2833 * @param pdev
2834 * @param local_mib
2835 * @param local_mib_ext
2836 *
2837 * @return lm_status_t
2838 */
2839 lm_status_t
lm_dcbx_read_local_mib_fields(IN struct _lm_device_t * pdev,OUT lldp_local_mib_t * local_mib,OUT lldp_local_mib_ext_t * local_mib_ext)2840 lm_dcbx_read_local_mib_fields(
2841 IN struct _lm_device_t *pdev,
2842 OUT lldp_local_mib_t *local_mib,
2843 OUT lldp_local_mib_ext_t *local_mib_ext)
2844 {
2845 const u32_t field_res_ext_offset = OFFSETOF(shmem2_region_t,dcbx_neg_res_ext_offset);
2846 u32_t res_ext_offset = SHMEM_DCBX_NEG_RES_EXT_NONE;
2847 u8_t is_ext_sup = FALSE;
2848 u8_t max_try_read = 0;
2849 lm_status_t lm_status = LM_STATUS_SUCCESS;
2850
2851 mm_mem_zero(local_mib, sizeof(lldp_local_mib_t));
2852 mm_mem_zero(local_mib_ext, sizeof(lldp_local_mib_ext_t));
2853
2854 if(LM_SHMEM2_HAS(pdev, dcbx_neg_res_ext_offset))
2855 {
2856 lm_dcbx_read_shmem2_mcp_fields(pdev,
2857 field_res_ext_offset,
2858 &res_ext_offset);
2859 //CQ62832 - T7.0 bootcode contains the field dcbx_neg_res_ext_offset
2860 // in shmem2 but dcbx_neg_res_ext_offse isn't implemented.
2861 if (SHMEM_DCBX_NEG_RES_EXT_NONE != res_ext_offset)
2862 {
2863 res_ext_offset += PORT_ID(pdev) * sizeof(lldp_local_mib_ext_t);
2864 is_ext_sup = TRUE;
2865 }
2866 }
2867
2868 do
2869 {
2870 lm_status = lm_dcbx_read_remote_local_mib(pdev,
2871 (u32_t *)local_mib,
2872 DCBX_READ_LOCAL_MIB);
2873 if (LM_STATUS_SUCCESS != lm_status)
2874 {
2875 DbgBreakMsg("lm_dcbx_read_remote_local_mib DCBX Negotiation result not supported");
2876 return lm_status;
2877 }
2878
2879 if(FALSE == is_ext_sup)
2880 {
2881 break;
2882 }
2883
2884 lm_reg_rd_blk(pdev,
2885 res_ext_offset,
2886 (u32_t *)local_mib_ext,
2887 (sizeof(lldp_local_mib_ext_t)/sizeof(u32_t)));
2888
2889 if((local_mib->prefix_seq_num == local_mib->suffix_seq_num ) &&
2890 (local_mib_ext->prefix_seq_num == local_mib_ext->suffix_seq_num ) &&
2891 (local_mib_ext->suffix_seq_num == local_mib->suffix_seq_num ))
2892 {
2893 break;
2894 }
2895
2896 max_try_read++;
2897
2898 }while(max_try_read < DCBX_LOCAL_MIB_MAX_TRY_READ);
2899
2900
2901 if(max_try_read >= DCBX_LOCAL_MIB_MAX_TRY_READ)
2902 {
2903 DbgBreakMsg("lm_dcbx_read_local_mib_fields : prefix_seq_num doesnt equal suffix_seq_num for to much time");
2904 return LM_STATUS_FAILURE;
2905 }
2906
2907 return lm_status;
2908 }
2909 /**
2910 * Use parameters given for first calculate VBD settings for
2911 * each feature.
2912 * Use VBD settings to configure HW.
2913 * @param pdev
2914 * @param local_mib Not const because ETS parameters can be
2915 * changed (merge)
2916 * @param local_mib_ext
2917 * @param is_local_ets_change
2918 * @param b_can_update_ie - Update indiacate enent if indicate
2919 * event is valid and b_can_update_ie.
2920 *
2921 * @return lm_status_t
2922 */
2923 lm_status_t
lm_dcbx_set_params(IN lm_device_t * pdev,IN lldp_local_mib_t * local_mib,IN lldp_local_mib_ext_t * local_mib_ext,IN const u8_t is_local_ets_change,IN const u8_t b_can_update_ie)2924 lm_dcbx_set_params(
2925 IN lm_device_t *pdev,
2926 IN /*const*/ lldp_local_mib_t *local_mib,
2927 IN /*const*/ lldp_local_mib_ext_t *local_mib_ext,
2928 IN const u8_t is_local_ets_change,
2929 IN const u8_t b_can_update_ie
2930 )
2931 {
2932 lm_status_t lm_status = LM_STATUS_SUCCESS;
2933
2934 if(!IS_PMF(pdev))
2935 {
2936 DbgBreakMsg("lm_dcbx_update_lpme_set_params error");
2937 return LM_STATUS_FAILURE;
2938 }
2939
2940
2941 if(FALSE == pdev->dcbx_info.is_dcbx_neg_received)
2942 {
2943 pdev->dcbx_info.is_dcbx_neg_received = TRUE;
2944 // Setting the completion bit to TRUE can be
2945 // done only once but will done on each PMF
2946 // migration because is_dcbx_neg_received is
2947 // per function.
2948 lm_dcbx_config_drv_flags(pdev, lm_dcbx_drv_flags_set_bit, DRV_FLAGS_DCB_CONFIGURED);
2949 }
2950
2951 lm_print_dcbx_drv_param(pdev,
2952 local_mib);
2953
2954 lm_get_dcbx_drv_param(pdev,
2955 local_mib,
2956 local_mib_ext);
2957
2958 MM_ACQUIRE_PHY_LOCK(pdev);
2959 lm_cmng_update(pdev);
2960 MM_RELEASE_PHY_LOCK(pdev);
2961
2962 lm_dcbx_stop_hw_tx(pdev);
2963
2964 lm_pfc_handle_pfc(pdev);
2965
2966 lm_dcbx_update_ets_params(pdev);
2967
2968 lm_dcbx_resume_hw_tx(pdev);
2969
2970 if((TRUE == pdev->dcbx_info.is_indicate_event_en) &&
2971 (TRUE == b_can_update_ie))
2972 {
2973 lm_status = lm_dcbx_ie_check_if_param_change(pdev,
2974 local_mib,
2975 local_mib_ext,
2976 is_local_ets_change);
2977 }
2978
2979 return lm_status;
2980 }
2981 /**
2982 * Read data from MCP and configure DCBX in HW and FW.
2983 * @param pdev
2984 * @param is_local_ets_change
2985 * @param b_can_update_ie Update indiacate enent if indicate
2986 * event is valid and b_can_update_ie.
2987 *
2988 * @return lm_status_t
2989 */
2990 lm_status_t
lm_dcbx_set_params_and_read_mib(IN lm_device_t * pdev,IN const u8_t is_local_ets_change,IN const u8_t b_can_update_ie)2991 lm_dcbx_set_params_and_read_mib(
2992 IN lm_device_t *pdev,
2993 IN const u8_t is_local_ets_change,
2994 IN const u8_t b_can_update_ie
2995 )
2996 {
2997 lldp_local_mib_t local_mib = {0};
2998 lldp_local_mib_ext_t local_mib_ext = {0};
2999 lm_status_t lm_status = LM_STATUS_SUCCESS;
3000
3001 // No current flow should support this.
3002 DbgBreakIf(FALSE == b_can_update_ie);
3003
3004 if(!IS_PMF(pdev))
3005 {
3006 DbgBreakMsg("lm_dcbx_update_lpme_set_params error");
3007 return LM_STATUS_FAILURE;
3008 }
3009
3010 lm_status = lm_dcbx_read_local_mib_fields(pdev,
3011 &local_mib,
3012 &local_mib_ext);
3013
3014 if(lm_status != LM_STATUS_SUCCESS)
3015 {
3016
3017 DbgBreakMsg("lm_dcbx_set_params: couldn't read local_mib");
3018 return lm_status;
3019 }
3020 /******************************start Debbuging code not to submit**************************************/
3021 mm_memcpy(&pdev->dcbx_info.local_mib_last, &local_mib, sizeof(local_mib));
3022 /******************************end Debbuging code not to submit****************************************/
3023
3024 lm_status = lm_dcbx_set_params(pdev,
3025 &local_mib,
3026 &local_mib_ext,
3027 is_local_ets_change,
3028 b_can_update_ie);
3029
3030 return lm_status;
3031 }
3032 /**
3033 * Disable DCBX in HW and FW.
3034 * @param pdev
3035 * @param b_can_update_ie - Update indiacate enent if indicate
3036 * event is valid and b_can_update_ie.
3037 *
3038 * @return lm_status_t
3039 */
3040 lm_status_t
lm_dcbx_disable_dcb_at_fw_and_hw(IN lm_device_t * pdev,IN const u8_t b_can_update_ie)3041 lm_dcbx_disable_dcb_at_fw_and_hw(
3042 IN lm_device_t *pdev,
3043 IN const u8_t b_can_update_ie
3044 )
3045 {
3046 lldp_local_mib_t local_mib = {0};
3047 lldp_local_mib_ext_t local_mib_ext = {0};
3048 lm_status_t lm_status = LM_STATUS_SUCCESS;
3049
3050 // No current flow should support this.
3051 DbgBreakIf(TRUE == b_can_update_ie);
3052
3053 if(!IS_PMF(pdev))
3054 {
3055 DbgBreakMsg("lm_dcbx_update_lpme_set_params error");
3056 return LM_STATUS_FAILURE;
3057 }
3058
3059 lm_status = lm_dcbx_set_params(pdev,
3060 &local_mib,
3061 &local_mib_ext,
3062 FALSE,
3063 b_can_update_ie);
3064
3065 return lm_status;
3066 }
3067 /**********************start DCBX INIT FUNCTIONS**************************************/
3068
3069 /*******************************************************************************
3070 * Description:
3071 *
3072 * Return:
3073 ******************************************************************************/
3074 STATIC lm_status_t
lm_dcbx_init_check_params_valid(INOUT lm_device_t * pdev,OUT u32_t * buff_check,IN const u32_t buff_size)3075 lm_dcbx_init_check_params_valid(INOUT lm_device_t *pdev,
3076 OUT u32_t *buff_check,
3077 IN const u32_t buff_size)
3078 {
3079 u32_t i=0;
3080 lm_status_t ret_val = LM_STATUS_SUCCESS;
3081
3082 for (i=0 ; i < buff_size ; i++,buff_check++)
3083 {
3084 if( DCBX_CONFIG_INV_VALUE == *buff_check)
3085 {
3086 ret_val = LM_STATUS_INVALID_PARAMETER;
3087 }
3088 }
3089 return ret_val;
3090 }
3091 /*******************************************************************************
3092 * Description: Read lldp parameters.
3093 * Return:
3094 ******************************************************************************/
3095 lm_status_t
lm_dcbx_lldp_read_params(struct _lm_device_t * pdev,b10_lldp_params_get_t * lldp_params)3096 lm_dcbx_lldp_read_params(struct _lm_device_t * pdev,
3097 b10_lldp_params_get_t * lldp_params)
3098 {
3099 lldp_params_t mcp_lldp_params = {0};
3100 lldp_dcbx_stat_t mcp_dcbx_stat = {{0}};
3101 u32_t i = 0;
3102 u32_t *buff = NULL ;
3103 u32_t offset = 0;
3104 lm_status_t lm_status = LM_STATUS_SUCCESS;
3105 const u32_t mcp_dcbx_lldp_params_offset = OFFSETOF(shmem2_region_t,dcbx_lldp_params_offset);
3106 const u32_t mcp_dcbx_lldp_dcbx_stat_offset = OFFSETOF(shmem2_region_t,dcbx_lldp_dcbx_stat_offset);
3107
3108 mm_mem_zero(lldp_params, sizeof(b10_lldp_params_get_t));
3109
3110
3111 offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
3112
3113 lm_dcbx_read_shmem2_mcp_fields(pdev,
3114 mcp_dcbx_lldp_params_offset,
3115 &offset);
3116
3117 if((!IS_DCB_ENABLED(pdev)) ||
3118 (SHMEM_LLDP_DCBX_PARAMS_NONE == offset))
3119 {//DCBX isn't supported on E1
3120 return LM_STATUS_FAILURE;
3121 }
3122
3123 lldp_params->config_lldp_params.overwrite_settings =
3124 pdev->params.lldp_config_params.overwrite_settings;
3125
3126 if (SHMEM_LLDP_DCBX_PARAMS_NONE != offset)
3127 {
3128 offset += PORT_ID(pdev) * sizeof(lldp_params_t);
3129
3130 //Read the data first
3131 buff = (u32_t *)&mcp_lldp_params;
3132 for(i=0 ;i<sizeof(lldp_params_t); i+=4,buff++)
3133 {
3134 *buff = REG_RD(pdev,
3135 (offset + i));
3136 }
3137 lldp_params->ver_num = LLDP_PARAMS_VER_NUM;
3138 lldp_params->config_lldp_params.msg_tx_hold = mcp_lldp_params.msg_tx_hold;
3139 lldp_params->config_lldp_params.msg_fast_tx = mcp_lldp_params.msg_fast_tx_interval;
3140 lldp_params->config_lldp_params.tx_credit_max = mcp_lldp_params.tx_crd_max;
3141 lldp_params->config_lldp_params.msg_tx_interval = mcp_lldp_params.msg_tx_interval;
3142 lldp_params->config_lldp_params.tx_fast = mcp_lldp_params.tx_fast;
3143
3144
3145 // Preparation for new shmem
3146 ASSERT_STATIC(ARRSIZE(lldp_params->remote_chassis_id) >= ARRSIZE(mcp_lldp_params.peer_chassis_id));
3147 ASSERT_STATIC(sizeof(lldp_params->remote_chassis_id[0]) == sizeof(mcp_lldp_params.peer_chassis_id[0]));
3148 for(i=0 ; i< ARRSIZE(mcp_lldp_params.peer_chassis_id) ; i++)
3149 {
3150 lldp_params->remote_chassis_id[i] = mcp_lldp_params.peer_chassis_id[i];
3151 }
3152
3153 ASSERT_STATIC(sizeof(lldp_params->remote_port_id[0]) == sizeof(mcp_lldp_params.peer_port_id[0]));
3154 ASSERT_STATIC(ARRSIZE(lldp_params->remote_port_id) > ARRSIZE(mcp_lldp_params.peer_port_id));
3155 for(i=0 ; i<ARRSIZE(mcp_lldp_params.peer_port_id) ; i++)
3156 {
3157 lldp_params->remote_port_id[i] = mcp_lldp_params.peer_port_id[i];
3158 }
3159
3160 lldp_params->admin_status = mcp_lldp_params.admin_status;
3161 }
3162 else
3163 {// DCBX not supported in MCP
3164 DbgBreakMsg("DCBX DCBX params supported");
3165 lm_status= LM_STATUS_FAILURE;
3166 }
3167
3168 offset = SHMEM_LLDP_DCBX_STAT_NONE;
3169
3170 lm_dcbx_read_shmem2_mcp_fields(pdev,
3171 mcp_dcbx_lldp_dcbx_stat_offset,
3172 &offset);
3173
3174 if (SHMEM_LLDP_DCBX_STAT_NONE != offset)
3175 {
3176 offset += PORT_ID(pdev) * sizeof(mcp_dcbx_stat);
3177
3178 //Read the data first
3179 buff = (u32_t *)&mcp_dcbx_stat;
3180 for(i=0 ;i<sizeof(mcp_dcbx_stat); i+=4,buff++)
3181 {
3182 *buff = REG_RD(pdev,
3183 (offset + i));
3184 }
3185 // Preparation for new shmem
3186
3187 ASSERT_STATIC(ARRSIZE(lldp_params->local_chassis_id) >= ARRSIZE(mcp_dcbx_stat.local_chassis_id));
3188 ASSERT_STATIC(sizeof(lldp_params->local_chassis_id[0]) >= sizeof(mcp_dcbx_stat.local_chassis_id[0]));
3189 for(i=0 ; i< ARRSIZE(mcp_dcbx_stat.local_chassis_id) ; i++)
3190 {
3191 lldp_params->local_chassis_id[i] = mcp_dcbx_stat.local_chassis_id[i];
3192 }
3193
3194 ASSERT_STATIC(ARRSIZE(lldp_params->local_port_id) >= ARRSIZE(mcp_dcbx_stat.local_port_id));
3195 ASSERT_STATIC(sizeof(lldp_params->local_port_id[0]) >= sizeof(mcp_dcbx_stat.local_port_id[0]));
3196 for(i=0 ; i< ARRSIZE(mcp_dcbx_stat.local_port_id) ; i++)
3197 {
3198 lldp_params->local_port_id[i] = mcp_dcbx_stat.local_port_id[i];
3199 }
3200 }
3201 else
3202 {// DCBX not supported in MCP
3203 DbgBreakMsg("DCBX DCBX stats supported");
3204 lm_status= LM_STATUS_FAILURE;
3205 }
3206
3207 return lm_status;
3208 }
3209 /*******************************************************************************
3210 * Description:
3211 * mcp_pg_bw_tbl_size: In elements.
3212 * set_configuration_bw_size: In elements.
3213 * Return:
3214 ******************************************************************************/
3215 STATIC void
lm_dcbx_get_bw_percentage_tbl(struct _lm_device_t * pdev,OUT u32_t * set_configuration_bw,IN u32_t * mcp_pg_bw_tbl,IN const u8_t set_configuration_bw_size,IN const u8_t mcp_pg_bw_tbl_size)3216 lm_dcbx_get_bw_percentage_tbl(struct _lm_device_t * pdev,
3217 OUT u32_t * set_configuration_bw,
3218 IN u32_t * mcp_pg_bw_tbl,
3219 IN const u8_t set_configuration_bw_size,
3220 IN const u8_t mcp_pg_bw_tbl_size)
3221 {
3222
3223 u8_t i = 0;
3224 const u8_t mcp_pg_bw_tbl_size_in_bytes = (sizeof(*mcp_pg_bw_tbl)*(mcp_pg_bw_tbl_size));
3225
3226 DbgBreakIf(set_configuration_bw_size != mcp_pg_bw_tbl_size);
3227
3228 DbgBreakIf(0 != (mcp_pg_bw_tbl_size_in_bytes % sizeof(u32_t)));
3229 for(i=0 ;i<set_configuration_bw_size ;i++)
3230 {
3231 set_configuration_bw[i] = DCBX_PG_BW_GET(mcp_pg_bw_tbl,i);
3232 }
3233 }
3234 /*******************************************************************************
3235 * Description: Parse ets_pri_pg data and spread it from nibble to 32 bits.
3236 *
3237 * Return:
3238 ******************************************************************************/
3239 STATIC void
lm_dcbx_get_ets_pri_pg_tbl(struct _lm_device_t * pdev,OUT u32_t * set_configuration_ets_pg,IN const u32_t * mcp_pri_pg_tbl,IN const u8_t set_priority_app_size,IN const u8_t mcp_pri_pg_tbl_size)3240 lm_dcbx_get_ets_pri_pg_tbl(struct _lm_device_t * pdev,
3241 OUT u32_t * set_configuration_ets_pg,
3242 IN const u32_t * mcp_pri_pg_tbl,
3243 IN const u8_t set_priority_app_size,
3244 IN const u8_t mcp_pri_pg_tbl_size)
3245 {
3246 u8_t i = 0;
3247 const u8_t mcp_pri_pg_tbl_size_in_bytes = (sizeof(*mcp_pri_pg_tbl)*(mcp_pri_pg_tbl_size));
3248
3249 DbgBreakIf(set_priority_app_size != (mcp_pri_pg_tbl_size));
3250
3251 // Arrays that there cell are less than 32 bit are still
3252 // in big endian mode.
3253 DbgBreakIf(0 != (mcp_pri_pg_tbl_size_in_bytes % sizeof(u32_t)));
3254
3255 // Nibble handling
3256 for(i=0 ; i < set_priority_app_size ; i++)
3257 {
3258 set_configuration_ets_pg[i] = DCBX_PRI_PG_GET(mcp_pri_pg_tbl,i);
3259 }
3260 }
3261 /*******************************************************************************
3262 * Description: Parse priority app data.
3263 *
3264 * Return:
3265 ******************************************************************************/
3266 STATIC void
lm_dcbx_get_priority_app_table(struct _lm_device_t * pdev,OUT struct _admin_priority_app_table_t * set_priority_app,IN dcbx_app_priority_entry_t * mcp_array,IN const u8_t set_priority_app_size,IN const u8_t mcp_array_size)3267 lm_dcbx_get_priority_app_table(struct _lm_device_t * pdev,
3268 OUT struct _admin_priority_app_table_t * set_priority_app,
3269 IN dcbx_app_priority_entry_t * mcp_array,
3270 IN const u8_t set_priority_app_size,
3271 IN const u8_t mcp_array_size)
3272 {
3273 u8_t i = 0;
3274
3275 if(set_priority_app_size > mcp_array_size)
3276 {
3277 DbgBreakIf(1);
3278 return;
3279 }
3280
3281 for(i=0 ;i<set_priority_app_size ;i++)
3282 {
3283 if(GET_FLAGS(mcp_array[i].appBitfield,DCBX_APP_ENTRY_VALID))
3284 {
3285 set_priority_app[i].valid = TRUE;
3286 }
3287
3288 if(GET_FLAGS(mcp_array[i].appBitfield,DCBX_APP_SF_ETH_TYPE))
3289 {
3290 set_priority_app[i].traffic_type = TRAFFIC_TYPE_ETH;
3291 }
3292 else
3293 {
3294 set_priority_app[i].traffic_type = TRAFFIC_TYPE_PORT;
3295 }
3296 set_priority_app[i].priority = mcp_array[i].pri_bitmap;
3297
3298
3299 // This has no logic this is only done for supporting old bootcodes.
3300 // The boot code still expexts u8 [2] instead of u16
3301 set_priority_app[i].app_id = mcp_array[i].app_id;
3302 }
3303
3304 }
3305 /**
3306 * @description
3307 * Fill the operational parameters.
3308 * @param pdev
3309 * @param dcbx_params
3310 *
3311 * @return STATIC void
3312 */
3313 STATIC void
lm_dcbx_read_params_fill_oper_state(struct _lm_device_t * pdev,b10_dcbx_params_get_t * dcbx_params)3314 lm_dcbx_read_params_fill_oper_state(struct _lm_device_t * pdev,
3315 b10_dcbx_params_get_t * dcbx_params)
3316 {
3317 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
3318
3319 if(TRUE == pdev->params.dcbx_port_params.app.enabled)
3320 {
3321 SET_FLAGS(dcbx_params->dcb_current_oper_state_bitmap,PRIORITY_TAGGING_IS_CURRENTLY_OPERATIONAL);
3322 }
3323
3324 if(TRUE == pdev->params.dcbx_port_params.pfc.enabled)
3325 {
3326 SET_FLAGS(dcbx_params->dcb_current_oper_state_bitmap,PFC_IS_CURRENTLY_OPERATIONAL);
3327 }
3328
3329 if(TRUE == pdev->params.dcbx_port_params.ets.enabled)
3330 {
3331 SET_FLAGS(dcbx_params->dcb_current_oper_state_bitmap,ETS_IS_CURRENTLY_OPERATIONAL);
3332 }
3333
3334 if(GET_FLAGS(indicate_event->dcb_current_oper_state_bitmap,
3335 DCB_STATE_CONFIGURED_BY_OS_QOS))
3336 {
3337 SET_FLAGS(dcbx_params->dcb_current_oper_state_bitmap,
3338 DRIVER_CONFIGURED_BY_OS_QOS);
3339 }
3340
3341 if(GET_FLAGS(indicate_event->dcb_current_oper_state_bitmap,
3342 DCB_STATE_CONFIGURED_BY_OS_QOS_TO_WILLING))
3343 {
3344 SET_FLAGS(dcbx_params->dcb_current_oper_state_bitmap,
3345 DRIVER_CONFIGURED_BY_OS_QOS_TO_WILLING);
3346 }
3347 }
3348 /*******************************************************************************
3349 * Description: Read DCBX parameters from admin/local and remote MIBs.
3350 *
3351 * Return:
3352 * LM_STATUS_FAILURE - All/Some of the parameters could not be read.
3353 * LM_STATUS_SUCCESS - All the MIBs where read successfully.
3354 ******************************************************************************/
3355 lm_status_t
lm_dcbx_read_params(struct _lm_device_t * pdev,b10_dcbx_params_get_t * dcbx_params)3356 lm_dcbx_read_params(struct _lm_device_t * pdev,
3357 b10_dcbx_params_get_t * dcbx_params)
3358 {
3359 lldp_admin_mib_t admin_mib = {0};
3360 lldp_local_mib_t local_mib = {0};
3361 lldp_remote_mib_t remote_mib = {0};
3362 lldp_dcbx_stat_t mcp_dcbx_stat = {{0}};
3363 lm_dcbx_stat dcbx_stat = {0};
3364 u32_t pfc_frames_sent[2] = {0};
3365 u32_t pfc_frames_received[2] = {0};
3366 u32_t i = 0;
3367 u32_t *buff = NULL;
3368 u32_t offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
3369 lm_status_t lm_status = LM_STATUS_SUCCESS;
3370 const u32_t mcp_dcbx_lldp_params_offset = OFFSETOF(shmem2_region_t,dcbx_lldp_params_offset);
3371 const u32_t mcp_dcbx_lldp_dcbx_stat_offset = OFFSETOF(shmem2_region_t,dcbx_lldp_dcbx_stat_offset);
3372
3373 mm_mem_zero(dcbx_params, sizeof(b10_dcbx_params_get_t));
3374
3375 lm_dcbx_read_params_fill_oper_state(pdev,dcbx_params);
3376
3377 lm_dcbx_read_shmem2_mcp_fields(pdev,
3378 mcp_dcbx_lldp_params_offset,
3379 &offset);
3380
3381 if((!IS_DCB_ENABLED(pdev)) ||
3382 (SHMEM_LLDP_DCBX_PARAMS_NONE == offset))
3383 {//DCBX isn't supported on E1
3384 return LM_STATUS_FAILURE;
3385 }
3386
3387 dcbx_params->config_dcbx_params.overwrite_settings =
3388 pdev->params.dcbx_config_params.overwrite_settings;
3389
3390 // E3.0 might be 4...not supported in current shmem
3391 ASSERT_STATIC( 2 == PORT_MAX );
3392
3393 if (SHMEM_LLDP_DCBX_PARAMS_NONE != offset)
3394 {
3395 offset = LM_DCBX_ADMIN_MIB_OFFSET(pdev ,offset);
3396
3397 //Read the data first
3398 buff = (u32_t *)&admin_mib;
3399 for(i=0 ;i<sizeof(lldp_admin_mib_t); i+=4,buff++)
3400 {
3401 *buff = REG_RD(pdev,
3402 (offset + i));
3403 }
3404
3405 dcbx_params->config_dcbx_params.dcb_enable = IS_DCB_ENABLED(pdev) ;
3406
3407 if(GET_FLAGS(admin_mib.ver_cfg_flags,DCBX_DCBX_ENABLED))
3408 {
3409 dcbx_params->config_dcbx_params.admin_dcbx_enable = 1 ;
3410 }
3411
3412 if(GET_FLAGS(admin_mib.ver_cfg_flags,DCBX_VERSION_CEE))
3413 {
3414 dcbx_params->config_dcbx_params.admin_dcbx_version = ADMIN_DCBX_VERSION_CEE;
3415 }
3416 else if(GET_FLAGS(admin_mib.ver_cfg_flags,DCBX_VERSION_IEEE))
3417 {
3418 dcbx_params->config_dcbx_params.admin_dcbx_version = ADMIN_DCBX_VERSION_IEEE;
3419 }
3420 else
3421 {
3422 dcbx_params->config_dcbx_params.admin_dcbx_version = OVERWRITE_SETTINGS_INVALID;
3423 DbgMessage(pdev, WARN, " unknown DCBX version ");
3424 }
3425
3426 dcbx_params->config_dcbx_params.admin_ets_enable = admin_mib.features.ets.enabled;
3427
3428 dcbx_params->config_dcbx_params.admin_pfc_enable = admin_mib.features.pfc.enabled;
3429
3430 //FOR IEEE pdev->params.dcbx_config_params.admin_tc_supported_tx_enable
3431 if(GET_FLAGS(admin_mib.ver_cfg_flags,DCBX_ETS_CONFIG_TX_ENABLED))
3432 {
3433 dcbx_params->config_dcbx_params.admin_ets_configuration_tx_enable = TRUE;
3434 }
3435 //For IEEE admin_ets_recommendation_tx_enable
3436
3437 if(GET_FLAGS(admin_mib.ver_cfg_flags,DCBX_PFC_CONFIG_TX_ENABLED))
3438 {
3439 dcbx_params->config_dcbx_params.admin_pfc_tx_enable = TRUE;
3440 }
3441
3442 if(GET_FLAGS(admin_mib.ver_cfg_flags,DCBX_APP_CONFIG_TX_ENABLED))
3443 {
3444 dcbx_params->config_dcbx_params.admin_application_priority_tx_enable = TRUE;
3445 }
3446
3447
3448 if(GET_FLAGS(admin_mib.ver_cfg_flags,DCBX_ETS_WILLING))
3449 {
3450 dcbx_params->config_dcbx_params.admin_ets_willing = TRUE;
3451 }
3452
3453 //For IEEE admin_ets_reco_valid
3454
3455 if(GET_FLAGS(admin_mib.ver_cfg_flags,DCBX_PFC_WILLING))
3456 {
3457 dcbx_params->config_dcbx_params.admin_pfc_willing = TRUE;
3458 }
3459
3460
3461 if(GET_FLAGS(admin_mib.ver_cfg_flags,DCBX_APP_WILLING))
3462 {
3463 dcbx_params->config_dcbx_params.admin_app_priority_willing = TRUE;
3464 }
3465
3466
3467 lm_dcbx_get_bw_percentage_tbl(pdev,
3468 dcbx_params->config_dcbx_params.admin_configuration_bw_percentage,
3469 admin_mib.features.ets.pg_bw_tbl,
3470 ARRSIZE(dcbx_params->config_dcbx_params.admin_configuration_bw_percentage),
3471 DCBX_MAX_NUM_PG_BW_ENTRIES);
3472
3473 lm_dcbx_get_ets_pri_pg_tbl(pdev,
3474 dcbx_params->config_dcbx_params.admin_configuration_ets_pg,
3475 admin_mib.features.ets.pri_pg_tbl,
3476 ARRSIZE(dcbx_params->config_dcbx_params.admin_configuration_ets_pg),
3477 DCBX_MAX_NUM_PRI_PG_ENTRIES);
3478
3479
3480 //For IEEE admin_recommendation_bw_percentage
3481 //For IEEE admin_recommendation_ets_pg
3482 dcbx_params->config_dcbx_params.admin_pfc_bitmap = admin_mib.features.pfc.pri_en_bitmap;
3483
3484 lm_dcbx_get_priority_app_table(pdev,
3485 dcbx_params->config_dcbx_params.admin_priority_app_table,
3486 admin_mib.features.app.app_pri_tbl,
3487 ARRSIZE(dcbx_params->config_dcbx_params.admin_priority_app_table),
3488 ARRSIZE(admin_mib.features.app.app_pri_tbl));
3489
3490 dcbx_params->config_dcbx_params.admin_default_priority = admin_mib.features.app.default_pri;
3491 }
3492 else
3493 {// DCBX not supported in MCP
3494 DbgBreakMsg("DCBX DCBX params not supported");
3495 lm_status= LM_STATUS_FAILURE;
3496 }
3497
3498 lm_status = lm_dcbx_read_remote_local_mib(pdev,
3499 (u32_t *)&local_mib,
3500 DCBX_READ_LOCAL_MIB);
3501
3502 if (LM_STATUS_SUCCESS == lm_status)
3503 {
3504
3505 if(0 == GET_FLAGS(local_mib.error,DCBX_REMOTE_MIB_ERROR))
3506 {
3507 SET_FLAGS(dcbx_params->dcb_current_oper_state_bitmap,DCBX_CURRENT_STATE_IS_SYNC);
3508 }
3509
3510 dcbx_params->ver_num = DCBX_PARAMS_VER_NUM;
3511 dcbx_params->local_tc_supported = local_mib.features.app.tc_supported;
3512 dcbx_params->local_pfc_caps = local_mib.features.pfc.pfc_caps;
3513 dcbx_params->local_ets_enable = local_mib.features.ets.enabled;
3514 dcbx_params->local_pfc_enable = local_mib.features.pfc.enabled;
3515
3516 lm_dcbx_get_bw_percentage_tbl(pdev,
3517 dcbx_params->local_configuration_bw_percentage,
3518 local_mib.features.ets.pg_bw_tbl,
3519 ARRSIZE(dcbx_params->local_configuration_bw_percentage),
3520 DCBX_MAX_NUM_PG_BW_ENTRIES);
3521
3522 lm_dcbx_get_ets_pri_pg_tbl(pdev,
3523 dcbx_params->local_configuration_ets_pg,
3524 local_mib.features.ets.pri_pg_tbl,
3525 ARRSIZE(dcbx_params->local_configuration_ets_pg),
3526 DCBX_MAX_NUM_PRI_PG_ENTRIES);
3527
3528 dcbx_params->local_pfc_bitmap = local_mib.features.pfc.pri_en_bitmap;
3529
3530 lm_dcbx_get_priority_app_table(pdev,
3531 dcbx_params->local_priority_app_table,
3532 local_mib.features.app.app_pri_tbl,
3533 ARRSIZE(dcbx_params->local_priority_app_table),
3534 ARRSIZE(local_mib.features.app.app_pri_tbl));
3535
3536 if(GET_FLAGS(local_mib.error,DCBX_LOCAL_PFC_MISMATCH))
3537 {
3538 dcbx_params->pfc_mismatch = TRUE;
3539 }
3540
3541 if(GET_FLAGS(local_mib.error,DCBX_LOCAL_APP_MISMATCH))
3542 {
3543 dcbx_params->priority_app_mismatch = TRUE;
3544 }
3545 }
3546 else
3547 {// DCBX not supported in MCP
3548 DbgBreakMsg("DCBX Negotiation result not supported");
3549 lm_status= LM_STATUS_FAILURE;
3550 }
3551 // Get remote MIB data
3552
3553 lm_status = lm_dcbx_read_remote_local_mib(pdev,
3554 (u32_t *)&remote_mib,
3555 DCBX_READ_REMOTE_MIB);
3556 if (LM_STATUS_SUCCESS == lm_status)
3557 {
3558
3559 dcbx_params->remote_tc_supported = remote_mib.features.app.tc_supported;
3560 dcbx_params->remote_pfc_cap = remote_mib.features.pfc.pfc_caps;
3561 if(GET_FLAGS(remote_mib.flags,DCBX_REMOTE_ETS_RECO_VALID))
3562 {
3563 dcbx_params->remote_ets_reco_valid = TRUE;
3564 }
3565
3566 if(GET_FLAGS(remote_mib.flags,DCBX_ETS_REM_WILLING))
3567 {
3568 dcbx_params->remote_ets_willing = TRUE;
3569 }
3570
3571 if(GET_FLAGS(remote_mib.flags,DCBX_PFC_REM_WILLING))
3572 {
3573 dcbx_params->remote_pfc_willing = TRUE;
3574 }
3575
3576 if(GET_FLAGS(remote_mib.flags,DCBX_APP_REM_WILLING))
3577 {
3578 dcbx_params->remote_app_priority_willing = TRUE;
3579 }
3580
3581 lm_dcbx_get_bw_percentage_tbl(pdev,
3582 dcbx_params->remote_configuration_bw_percentage,
3583 remote_mib.features.ets.pg_bw_tbl,
3584 ARRSIZE(dcbx_params->remote_configuration_bw_percentage),
3585 DCBX_MAX_NUM_PG_BW_ENTRIES);
3586
3587 lm_dcbx_get_ets_pri_pg_tbl(pdev,
3588 dcbx_params->remote_configuration_ets_pg,
3589 remote_mib.features.ets.pri_pg_tbl,
3590 ARRSIZE(dcbx_params->remote_configuration_ets_pg),
3591 DCBX_MAX_NUM_PRI_PG_ENTRIES);
3592 // For IEEE remote_recommendation_bw_percentage
3593 // For IEEE remote_recommendation_ets_pg
3594
3595 dcbx_params->remote_pfc_bitmap = remote_mib.features.pfc.pri_en_bitmap;
3596
3597 lm_dcbx_get_priority_app_table(pdev,
3598 dcbx_params->remote_priority_app_table,
3599 remote_mib.features.app.app_pri_tbl,
3600 ARRSIZE(dcbx_params->remote_priority_app_table),
3601 ARRSIZE(remote_mib.features.app.app_pri_tbl));
3602 }
3603 else
3604 {// DCBX not supported in MCP
3605 DbgBreakMsg("DCBX remote MIB not supported");
3606 lm_status= LM_STATUS_FAILURE;
3607 }
3608
3609 // Get negotiation results MIB data
3610 offset = SHMEM_LLDP_DCBX_STAT_NONE;
3611
3612 lm_dcbx_read_shmem2_mcp_fields(pdev,
3613 mcp_dcbx_lldp_dcbx_stat_offset,
3614 &offset);
3615
3616 // E3.0 might be 4...not supported in current shmem
3617 ASSERT_STATIC( 2 == PORT_MAX );
3618
3619 if (SHMEM_LLDP_DCBX_STAT_NONE != offset)
3620 {
3621 offset += PORT_ID(pdev) * sizeof(mcp_dcbx_stat);
3622
3623 //Read the data first
3624 buff = (u32_t *)&mcp_dcbx_stat;
3625 for(i=0 ;i<sizeof(mcp_dcbx_stat); i+=4,buff++)
3626 {
3627 *buff = REG_RD(pdev,
3628 (offset + i));
3629 }
3630
3631 dcbx_params->dcbx_frames_sent = mcp_dcbx_stat.num_tx_dcbx_pkts;
3632 dcbx_params->dcbx_frames_received = mcp_dcbx_stat.num_rx_dcbx_pkts;
3633 }
3634 else
3635 {// DCBX not supported in MCP
3636 DbgBreakMsg("DCBX statistic not supported");
3637 lm_status= LM_STATUS_FAILURE;
3638 }
3639 // TODO - Move to lm_stat
3640
3641
3642 if(pdev->vars.mac_type == MAC_TYPE_EMAC)
3643 {
3644 MM_ACQUIRE_PHY_LOCK(pdev);
3645 // EMAC stats are not collected through statitic code.
3646 elink_pfc_statistic(&pdev->params.link, &pdev->vars.link,
3647 pfc_frames_sent, pfc_frames_received);
3648
3649 MM_RELEASE_PHY_LOCK(pdev);
3650
3651 dcbx_stat.pfc_frames_sent = ((u64_t)(pfc_frames_sent[1]) << 32) + pfc_frames_sent[0];
3652
3653 dcbx_stat.pfc_frames_received = ((u64_t)(pfc_frames_received[1]) << 32) + pfc_frames_received[0];
3654 }
3655 else
3656 {
3657 lm_stats_get_dcb_stats( pdev, &dcbx_stat );
3658
3659 }
3660
3661 dcbx_params->pfc_frames_sent = dcbx_stat.pfc_frames_sent;
3662
3663 dcbx_params->pfc_frames_received = dcbx_stat.pfc_frames_received;
3664
3665 return lm_status;
3666 }
3667 /*******************************************************************************
3668 * Description:
3669 *
3670 * Return:
3671 ******************************************************************************/
3672 void
lm_dcbx_init_lpme_set_params(struct _lm_device_t * pdev)3673 lm_dcbx_init_lpme_set_params(struct _lm_device_t *pdev)
3674 {
3675 lm_status_t lm_status = LM_STATUS_SUCCESS;
3676
3677 if( TRUE == pdev->dcbx_info.is_dcbx_neg_received)
3678 {
3679 // DCBX negotiation ended normaly.
3680 return;
3681 }
3682 //DbgBreakMsg(" lm_dcbx_init_lpme_set_params : DCBX timer configuration \n");
3683 //DbgMessage(pdev, FATAL, "lm_dcbx_init_lpme_set_params : DCBX timer configuration \n");
3684 // DCBX negotiation didn�t ended normaly yet.
3685 // No lock is needed to be taken because lm_dcbx_set_params is only called from a WI
3686 lm_status = lm_dcbx_set_params_and_read_mib(pdev,
3687 FALSE,
3688 TRUE);
3689
3690 DbgBreakIf(LM_STATUS_SUCCESS != lm_status);
3691 }
3692 /**
3693 * look for an entry that isn't iSCSI or FCoE and return it's
3694 * position.
3695 * @param pdev
3696 * @param app
3697 *
3698 * @return STATIC u8_t
3699 */
3700 STATIC u8_t
lm_dcbx_app_find_non_off_tt_entry(IN lm_device_t * pdev,INOUT dcbx_app_priority_feature_t * app)3701 lm_dcbx_app_find_non_off_tt_entry(
3702 IN lm_device_t *pdev,
3703 INOUT dcbx_app_priority_feature_t *app
3704 )
3705 {
3706 dcbx_app_priority_entry_t *app_priority_entry = NULL;
3707 u8_t entry = 0;
3708
3709 for(entry = 0; entry < ARRSIZE(app->app_pri_tbl); entry++)
3710 {
3711 app_priority_entry = &(app->app_pri_tbl[entry]);
3712
3713 if(lm_dcbx_cee_is_entry_fcoe_classif(app_priority_entry->appBitfield,
3714 app_priority_entry->app_id))
3715 {
3716 DbgMessage(pdev, INFORM, "lm_dcbx_app_find_non_off_tt_entry :FCOE entry");
3717 }
3718 else if(lm_dcbx_cee_is_entry_iscsi_classif(app_priority_entry->appBitfield,
3719 app_priority_entry->app_id))
3720 {
3721 DbgMessage(pdev, INFORM, "lm_dcbx_app_find_non_off_tt_entry :ISCSI entry");
3722 }
3723 else
3724 {
3725 // Found an entry that isn't ISCSI or FCOE
3726 break;
3727 }
3728 }
3729
3730 return entry;
3731 }
3732 /**
3733 * @description
3734 *
3735 * @param pdev
3736 * @param app
3737 * @param other_traf_type_entry - For entries that are not
3738 * predefined
3739 * @param app_id
3740 * @param traffic_type
3741 * @param priority
3742 *
3743 * @return STATIC lm_status_t
3744 */
3745 STATIC lm_status_t
lm_dcbx_admin_mib_update_app_pri(IN lm_device_t * pdev,INOUT dcbx_app_priority_feature_t * app,INOUT u8_t * next_free_app_id_entry,IN const u16_t app_id,IN const u8_t traffic_type,IN const u8_t priority)3746 lm_dcbx_admin_mib_update_app_pri(
3747 IN lm_device_t *pdev,
3748 INOUT dcbx_app_priority_feature_t *app,
3749 INOUT u8_t *next_free_app_id_entry,
3750 IN const u16_t app_id,
3751 IN const u8_t traffic_type,
3752 IN const u8_t priority)
3753 {
3754 lm_status_t lm_status = LM_STATUS_SUCCESS;
3755 u8_t traf_type_entry = 0;
3756 u8_t app_bit_field = DCBX_APP_ENTRY_VALID;
3757
3758 switch(traffic_type)
3759 {
3760 case TRAFFIC_TYPE_ETH:
3761 app_bit_field |= DCBX_APP_SF_ETH_TYPE;
3762 break;
3763 case TRAFFIC_TYPE_PORT:
3764 app_bit_field |= DCBX_APP_SF_PORT;
3765 break;
3766 default:
3767 DbgBreakMsg("lm_dcbx_admin_mib_update_app_pri illegal traffic_type entry ");
3768 return LM_STATUS_INVALID_PARAMETER;
3769 }
3770
3771 if(ARRSIZE(app->app_pri_tbl) <= (*next_free_app_id_entry) )
3772 {
3773 // Reserve two entries to iSCSI and FCoE (in case they will
3774 // be received after the 16th application priority entry).
3775 if(lm_dcbx_cee_is_entry_iscsi_classif(
3776 app_bit_field,
3777 app_id ) ||
3778 lm_dcbx_cee_is_entry_fcoe_classif(
3779 app_bit_field,
3780 app_id))
3781 {
3782 traf_type_entry = lm_dcbx_app_find_non_off_tt_entry(pdev, app);
3783
3784 if (ARRSIZE(app->app_pri_tbl) <= traf_type_entry)
3785 {
3786 DbgBreakMsg("lm_dcbx_admin_mib_update_app_pri : traf_type_entry contains an invalid value ");
3787 return lm_status;
3788 }
3789 }
3790 else
3791 {
3792 return lm_status;
3793 }
3794 }
3795 else
3796 {
3797 DbgBreakIf(ARRSIZE(app->app_pri_tbl) <= (*next_free_app_id_entry));
3798 traf_type_entry = (*next_free_app_id_entry)++;
3799 }
3800
3801 DbgBreakIf(ARRSIZE(app->app_pri_tbl) <= traf_type_entry );
3802
3803 app->app_pri_tbl[traf_type_entry].app_id = app_id;
3804
3805 app->app_pri_tbl[traf_type_entry].pri_bitmap =(u8_t)(1 << priority);
3806
3807 app->app_pri_tbl[traf_type_entry].appBitfield = app_bit_field;
3808
3809 return lm_status;
3810 }
3811 /**
3812 * @description
3813 * Update admin MIB classification entries with OS DCBX
3814 * classification configuration.
3815 * @param pdev
3816 * @param admin_mib
3817 * @param dcb_params
3818 * @param classif_local_vars
3819 *
3820 * @return STATIC lm_status_t
3821 */
3822 STATIC lm_status_t
lm_dcbx_ie_admin_mib_classif(IN lm_device_t * pdev,INOUT dcbx_app_priority_feature_t * app,IN const dcb_classif_params_t * classif_params,IN const u32_t flags)3823 lm_dcbx_ie_admin_mib_classif(IN lm_device_t *pdev,
3824 INOUT dcbx_app_priority_feature_t *app,
3825 IN const dcb_classif_params_t *classif_params,
3826 IN const u32_t flags
3827 )
3828 {
3829 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
3830 dcb_classif_elem_t *p_classif_elem = (dcb_classif_elem_t *)classif_params->classif_table;
3831 u32_t i = 0;
3832 u8_t traffic_type = 0;
3833 u8_t b_update_admin = FALSE;
3834 // Other traffic type is defined as not ISCSI or FCOE
3835 u8_t next_free_app_id_entry = 0;
3836
3837 mm_mem_zero(&(app->app_pri_tbl), sizeof(app->app_pri_tbl));
3838 app->default_pri = 0;
3839 app->tc_supported = 0;
3840 indicate_event->iscsi_tcp_pri = LM_DCBX_ILLEGAL_PRI;
3841
3842 if(0 == GET_FLAGS(flags, DCB_PARAMS_CLASSIF_ENABLED))
3843 {
3844 return LM_STATUS_SUCCESS;
3845 }
3846
3847 for(i = 0; i < classif_params->num_classif_elements; i++ , p_classif_elem++)
3848 {
3849 b_update_admin = FALSE;
3850
3851 if(DCB_ACTION_PRIORITY != p_classif_elem->action_selector)
3852 {
3853 // VBD only supports condition_selector that is based on priority
3854 continue;
3855 }
3856 switch(p_classif_elem->condition_selector)
3857 {
3858 case DCB_CONDITION_DEFAULT:
3859 // If default entry exist it must be the first entry ISCSI and FCOE priority
3860 // will be update accordingly. If OS gave us an ISCSI or FCOE entry it will
3861 // overwrite this value.
3862 DbgBreakIf(0 != i);
3863 app->default_pri = (u8_t)p_classif_elem->action_field;
3864 break;
3865
3866 case DCB_CONDITION_TCP_OR_UDP_PORT:
3867 traffic_type = TRAFFIC_TYPE_PORT;
3868 b_update_admin = TRUE;
3869 break;
3870
3871 case DCB_CONDITION_ETHERTYPE:
3872 traffic_type = TRAFFIC_TYPE_ETH;
3873 b_update_admin = TRUE;
3874 break;
3875 case DCB_CONDITION_TCP_PORT:
3876 if(TCP_PORT_ISCSI == p_classif_elem->condition_field)
3877 {
3878 // Check if ISCSI prioriy changed from last time.
3879 if(LM_DCBX_ILLEGAL_PRI <= p_classif_elem->action_field )
3880 {
3881 DbgBreakMsg("lm_dcbx_ie_admin_mib_update_runtime_classif illegal action field");
3882 return LM_STATUS_FAILURE;
3883 }
3884 if(p_classif_elem->action_field !=
3885 indicate_event->iscsi_tcp_pri)
3886 {
3887 indicate_event->iscsi_tcp_pri = p_classif_elem->action_field;
3888 }
3889 }
3890 break;
3891 case DCB_CONDITION_RESERVED:
3892 case DCB_CONDITION_UDP_PORT://Fall through
3893 case DCB_CONDITION_NETDIRECT_PORT://Fall through
3894 //Not supported by VBD
3895 break;
3896 default:
3897 DbgBreakMsg("lm_dcbx_runtime_params_updated_en_classif_entries: illegal entry ");
3898 break;
3899 }
3900 if(TRUE == b_update_admin)
3901 {
3902 lm_dcbx_admin_mib_update_app_pri(pdev,
3903 app,
3904 &next_free_app_id_entry,
3905 p_classif_elem->condition_field,
3906 traffic_type,
3907 (u8_t)p_classif_elem->action_field);
3908 }
3909 }
3910
3911 app->tc_supported = next_free_app_id_entry;
3912
3913 return LM_STATUS_SUCCESS;
3914 }
3915 /**
3916 * This function is for wrapper for the function
3917 * lm_dcbx_ie_admin_mib_classif and it purpose is for telling if
3918 * DCBX configuration needs to change but MCP was not update.
3919 * @param pdev
3920 * @param app
3921 * @param classif_params
3922 * @param classif_change_mcp_not_aware
3923 * @param flags
3924 *
3925 * @return STATIC lm_device_t
3926 */
3927 STATIC lm_status_t
lm_dcbx_ie_admin_mib_classif_wrapper(IN lm_device_t * pdev,INOUT dcbx_app_priority_feature_t * app,IN const dcb_classif_params_t * classif_params,OUT u8_t * classif_change_mcp_not_aware,IN const u32_t flags)3928 lm_dcbx_ie_admin_mib_classif_wrapper(IN lm_device_t *pdev,
3929 INOUT dcbx_app_priority_feature_t *app,
3930 IN const dcb_classif_params_t *classif_params,
3931 OUT u8_t *classif_change_mcp_not_aware,
3932 IN const u32_t flags
3933 )
3934 {
3935 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
3936 lm_status_t lm_status = LM_STATUS_SUCCESS;
3937 const u16_t iscsi_tcp_pri_prev = indicate_event->iscsi_tcp_pri;
3938
3939 lm_status = lm_dcbx_ie_admin_mib_classif(pdev,app,classif_params,flags);
3940
3941 if(iscsi_tcp_pri_prev != indicate_event->iscsi_tcp_pri)
3942 {
3943 (*classif_change_mcp_not_aware) = TRUE;
3944 }
3945
3946 return lm_status;
3947 }
3948
3949 /**
3950 * @description
3951 * Update admin MIB ETS parameters.
3952 * @param pdev
3953 * @param admin_ets
3954 * @param bw_tbl
3955 * @param pri_pg
3956 * @param bw_tbl_size
3957 * @param pri_pg_size
3958 */
3959 void
lm_dcbx_admin_mib_update_ets_param(IN lm_device_t * pdev,IN dcbx_ets_feature_t * admin_ets,IN const u32_t * pg_bw_tbl,IN const u32_t * pri_pg,IN const u8_t bw_tbl_size,IN const u8_t pri_pg_size)3960 lm_dcbx_admin_mib_update_ets_param(
3961 IN lm_device_t *pdev,
3962 IN dcbx_ets_feature_t *admin_ets,
3963 IN const u32_t *pg_bw_tbl,
3964 IN const u32_t *pri_pg,
3965 IN const u8_t bw_tbl_size,
3966 IN const u8_t pri_pg_size )
3967 {
3968 u8_t i = 0;
3969
3970 DbgBreakIf(DCBX_MAX_NUM_PG_BW_ENTRIES != bw_tbl_size);
3971
3972 for(i=0; i < DCBX_MAX_NUM_PG_BW_ENTRIES ;i++)
3973 {
3974 DCBX_PG_BW_SET(admin_ets->pg_bw_tbl,
3975 i,
3976 pg_bw_tbl[i]);
3977 }
3978
3979 DbgBreakIf(DCBX_MAX_NUM_PRI_PG_ENTRIES != pri_pg_size);
3980
3981 for(i=0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++)
3982 {
3983 DCBX_PRI_PG_SET(admin_ets->pri_pg_tbl,
3984 i,
3985 pri_pg[i]);
3986 }
3987 }
3988 /**
3989 * @description
3990 *
3991 * @param pdev
3992 * @param ets
3993 * @param ets_params
3994 *
3995 * @return lm_status_t
3996 */
3997 lm_status_t
lm_dcbx_ie_admin_mib_update_runtime_ets(IN lm_device_t * pdev,OUT dcbx_ets_feature_t * admin_ets,IN const dcb_ets_tsa_param_t * os_ets_params,IN const u32_t flags)3998 lm_dcbx_ie_admin_mib_update_runtime_ets(IN lm_device_t *pdev,
3999 OUT dcbx_ets_feature_t *admin_ets,
4000 IN const dcb_ets_tsa_param_t *os_ets_params,
4001 IN const u32_t flags
4002 )
4003 {
4004 u32_t pg_bw_tbl[DCBX_MAX_NUM_PG_BW_ENTRIES] = {0};
4005 u32_t pri_pg[DCBX_MAX_NUM_PRI_PG_ENTRIES] = {0};
4006 u8_t pri = 0;
4007 u8_t tc_entry = 0;
4008
4009 ASSERT_STATIC(DCBX_MAX_NUM_PRI_PG_ENTRIES == DCBX_MAX_NUM_PG_BW_ENTRIES);
4010
4011 ASSERT_STATIC(ARRSIZE(os_ets_params->priority_assignment_table) ==
4012 DCBX_MAX_NUM_PG_BW_ENTRIES);
4013
4014 ASSERT_STATIC(ARRSIZE(os_ets_params->tc_bw_assignment_table) ==
4015 DCBX_MAX_NUM_PRI_PG_ENTRIES);
4016
4017 ASSERT_STATIC(ARRSIZE(os_ets_params->tsa_assignment_table) ==
4018 DCBX_MAX_NUM_PRI_PG_ENTRIES);
4019
4020 if(0 == GET_FLAGS(flags, DCB_PARAMS_ETS_ENABLED))
4021 {
4022 // All pri_pg point to entry 0
4023 pg_bw_tbl[0] = 100;
4024 }
4025 else
4026 {
4027 // Prepare parameters from OS to standard config.
4028 for(pri = 0 ;
4029 pri < ARRSIZE(os_ets_params->priority_assignment_table);
4030 pri++)
4031 {
4032 tc_entry = os_ets_params->priority_assignment_table[pri];
4033
4034 if(TSA_ASSIGNMENT_DCB_TSA_STRICT == os_ets_params->tsa_assignment_table[tc_entry])
4035 {
4036 // pg_bw_tbl isn't relevant for strict priority
4037 pri_pg[pri] = DCBX_STRICT_PRI_PG;
4038 }
4039 else if(TSA_ASSIGNMENT_DCB_TSA_ETS == os_ets_params->tsa_assignment_table[tc_entry])
4040 {
4041 pri_pg[pri] = tc_entry;
4042 pg_bw_tbl[tc_entry] = os_ets_params->tc_bw_assignment_table[tc_entry];
4043 }
4044 else
4045 {
4046 DbgBreakMsg("lm_dcbx_get_ets_ieee_feature parameters are check before "
4047 "this should not happen");
4048 // For retail
4049 return LM_STATUS_FAILURE;
4050 }
4051 }
4052 }
4053
4054 // Update MCP.
4055 lm_dcbx_admin_mib_update_ets_param(
4056 pdev,
4057 admin_ets,
4058 pg_bw_tbl,
4059 pri_pg,
4060 ARRSIZE(pg_bw_tbl) ,
4061 ARRSIZE(pri_pg));
4062
4063 return LM_STATUS_SUCCESS;
4064 }
4065 /**
4066 * Update PFC admin MIB
4067 * @param pdev
4068 * @param pfc
4069 * @param pfc_params
4070 * @param flags
4071 *
4072 * @return STATIC lm_status_t
4073 */
4074 STATIC lm_status_t
lm_dcbx_ie_admin_mib_pfc(IN lm_device_t * pdev,INOUT dcbx_pfc_feature_t * pfc,IN const dcb_pfc_param_t * pfc_params,IN const u32_t flags)4075 lm_dcbx_ie_admin_mib_pfc(IN lm_device_t *pdev,
4076 INOUT dcbx_pfc_feature_t *pfc,
4077 IN const dcb_pfc_param_t *pfc_params,
4078 IN const u32_t flags
4079 )
4080 {
4081 if(GET_FLAGS(flags, DCB_PARAMS_PFC_ENABLED))
4082 {
4083 pfc->pri_en_bitmap =(u8_t)pfc_params->pfc_enable;
4084 }
4085 else
4086 {
4087 pfc->pri_en_bitmap = 0;
4088 }
4089
4090 return LM_STATUS_SUCCESS;
4091 }
4092 /**
4093 *
4094 * @param pdev
4095 * @param p_admin_mib_offset
4096 *
4097 * @return STATIC lm_status_t
4098 */
4099 STATIC lm_status_t
lm_dcbx_get_admin_mib_offset(IN lm_device_t * pdev,OUT u32_t * p_admin_mib_offset)4100 lm_dcbx_get_admin_mib_offset( IN lm_device_t *pdev,
4101 OUT u32_t *p_admin_mib_offset)
4102 {
4103 u32_t dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
4104 const u32_t dcbx_lldp_params_field_offset = OFFSETOF(shmem2_region_t,dcbx_lldp_params_offset);
4105 lm_status_t lm_status = LM_STATUS_SUCCESS;
4106
4107 lm_dcbx_read_shmem2_mcp_fields( pdev,
4108 dcbx_lldp_params_field_offset,
4109 &dcbx_lldp_params_offset);
4110
4111 if (SHMEM_LLDP_DCBX_PARAMS_NONE == dcbx_lldp_params_offset)
4112 {
4113 DbgBreakMsg("lm_dcbx_read_admin_mib couldn't read mcp offset ");
4114 return LM_STATUS_FAILURE;
4115 }
4116
4117 *p_admin_mib_offset = LM_DCBX_ADMIN_MIB_OFFSET(pdev ,dcbx_lldp_params_offset);
4118
4119 return lm_status;
4120 }
4121 /**
4122 *
4123 * @param pdev
4124 * @param p_admin_mib
4125 * @param p_admin_mib_offset
4126 *
4127 * @return STATIC lm_status_t
4128 */
4129 STATIC lm_status_t
lm_dcbx_read_admin_mib(IN lm_device_t * pdev,OUT lldp_admin_mib_t * p_admin_mib,OUT u32_t * p_admin_mib_offset)4130 lm_dcbx_read_admin_mib( IN lm_device_t *pdev,
4131 OUT lldp_admin_mib_t *p_admin_mib,
4132 OUT u32_t *p_admin_mib_offset)
4133 {
4134 u32_t i = 0;
4135 u32_t *buff = NULL ;
4136 lm_status_t lm_status = LM_STATUS_SUCCESS;
4137
4138 lm_status = lm_dcbx_get_admin_mib_offset( pdev,
4139 p_admin_mib_offset);
4140
4141 if(LM_STATUS_SUCCESS != lm_status)
4142 {
4143 DbgBreakMsg("lm_dcbx_read_admin_mib: lm_dcbx_get_admin_mib_offset failed ");
4144 return lm_status;
4145 }
4146
4147 buff = (u32_t *)p_admin_mib;
4148 //Read the data first
4149 for(i=0 ;i < sizeof(lldp_admin_mib_t); i+=4, buff++)
4150 {
4151 *buff = REG_RD(pdev,
4152 ((*p_admin_mib_offset) + i));
4153 }
4154
4155 return lm_status;
4156 }
4157
4158 /**
4159 * @description
4160 * Update admin MIN and notify MCP on the changes.
4161 * @param pdev
4162 * @param dcb_params
4163 * @param mf_cfg_offset_value
4164 *
4165 * @return STATIC lm_status_t
4166 */
4167 STATIC lm_status_t
lm_dcbx_ie_admin_mib_updated_runtime(IN lm_device_t * pdev,IN const dcb_indicate_event_params_t * dcb_params,OUT u8_t * classif_change_mcp_not_aware,OUT u8_t * is_ets_admin_updated)4168 lm_dcbx_ie_admin_mib_updated_runtime(IN lm_device_t *pdev,
4169 IN const dcb_indicate_event_params_t *dcb_params,
4170 OUT u8_t *classif_change_mcp_not_aware,
4171 OUT u8_t *is_ets_admin_updated
4172 )
4173 {
4174 lldp_admin_mib_t admin_mib = {0};
4175 u32_t i = 0;
4176 u32_t *buff = NULL ;
4177 lm_status_t lm_status = LM_STATUS_SUCCESS;
4178 u32_t fw_resp = 0;
4179 u32_t admin_mib_offset = 0;
4180 u8_t is_mfw_cfg = FALSE;
4181 const u32_t willing_flags = DCBX_ETS_WILLING | DCBX_PFC_WILLING | DCBX_APP_WILLING;
4182
4183 // Use original admin MIB not updated by BACS
4184 mm_memcpy(&admin_mib, &pdev->dcbx_info.admin_mib_org, sizeof(admin_mib));
4185
4186 if(GET_FLAGS(dcb_params->flags, DCB_PARAMS_WILLING))
4187 {
4188 SET_FLAGS(admin_mib.ver_cfg_flags,willing_flags);
4189 }
4190 else
4191 {
4192 RESET_FLAGS(admin_mib.ver_cfg_flags,willing_flags);
4193 }
4194
4195 lm_status = lm_dcbx_ie_admin_mib_update_runtime_ets(pdev,
4196 &admin_mib.features.ets,
4197 &dcb_params->ets_params,
4198 dcb_params->flags);
4199
4200 if(LM_STATUS_SUCCESS != lm_status)
4201 {
4202 DbgBreakMsg("lm_dcbx_ie_admin_mib_update_runtime_ets function failed ");
4203 }
4204 else
4205 {
4206 *is_ets_admin_updated = TRUE;
4207 is_mfw_cfg = TRUE;
4208 }
4209
4210 lm_status = lm_dcbx_ie_admin_mib_pfc(pdev,
4211 &admin_mib.features.pfc,
4212 &dcb_params->pfc_params,
4213 dcb_params->flags);
4214
4215 if(LM_STATUS_SUCCESS != lm_status)
4216 {
4217 DbgBreakMsg("lm_dcbx_ie_admin_mib_update_runtime_ets function failed ");
4218 }
4219 else
4220 {
4221 is_mfw_cfg = TRUE;
4222 }
4223
4224 lm_status = lm_dcbx_ie_admin_mib_classif_wrapper(pdev,
4225 &admin_mib.features.app,
4226 &dcb_params->classif_params,
4227 classif_change_mcp_not_aware,
4228 dcb_params->flags);
4229
4230 if(LM_STATUS_SUCCESS != lm_status)
4231 {
4232 DbgBreakMsg("lm_dcbx_ie_admin_mib_update_runtime_classif function failed ");
4233 }
4234 else
4235 {
4236 is_mfw_cfg = TRUE;
4237 }
4238
4239 if(TRUE == is_mfw_cfg)
4240 {
4241 // There is a configuration done to MCP that was done by OS.
4242 lm_dcbx_config_drv_flags(
4243 pdev,
4244 lm_dcbx_drv_flags_set_bit,
4245 DRV_FLAGS_DCB_MFW_CONFIGURED);
4246
4247 lm_status = lm_dcbx_get_admin_mib_offset( pdev,
4248 &admin_mib_offset);
4249
4250 // Write the data back.
4251 buff = (u32_t *)&admin_mib;
4252 for(i=0 ; i< sizeof(lldp_admin_mib_t); i+=4,buff++)
4253 {
4254 REG_WR(pdev, (admin_mib_offset + i) , *buff);
4255 }
4256
4257 // update MCP
4258 lm_status = lm_mcp_cmd_send_recieve( pdev,
4259 lm_mcp_mb_header,
4260 DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG,
4261 0,
4262 MCP_CMD_DEFAULT_TIMEOUT,
4263 &fw_resp ) ;
4264
4265 DbgBreakIf( lm_status != LM_STATUS_SUCCESS );
4266 }
4267
4268 return lm_status;
4269 }
4270
4271 /*******************************************************************************
4272 * Description: Update admin MIB that changes deafault DCBX configuration
4273 * "admin_dcbx_enable" and "dcb_enable" are stand alone registry keys
4274 * (if present will always be valid and not ignored), for all other
4275 * DCBX registry set only if the entire DCBX registry set is present
4276 * and differ from 0xFFFFFFFF (invalid value) the DCBX registry
4277 * parameters are taken, otherwise the registry key set is ignored.)
4278 * (Expect "admin_dcbx_enable" and "dcb_enable")
4279 * Return:
4280 ******************************************************************************/
4281 STATIC void
lm_dcbx_admin_mib_updated_init(lm_device_t * pdev,u32_t mf_cfg_offset_value)4282 lm_dcbx_admin_mib_updated_init(lm_device_t * pdev,
4283 u32_t mf_cfg_offset_value)
4284 {
4285 lldp_admin_mib_t admin_mib = {0};
4286 u32_t i = 0;
4287 u8_t next_free_app_id_entry = 0; /*used for not predifined entries*/
4288 u32_t *buff = NULL ;
4289 lm_status_t lm_status = LM_STATUS_SUCCESS;
4290 u32_t offset = 0;
4291
4292 lm_status = lm_dcbx_read_admin_mib( pdev,
4293 &admin_mib,
4294 &offset);
4295
4296 if(LM_STATUS_SUCCESS != lm_status)
4297 {
4298 DbgBreakMsg(" lm_dcbx_admin_mib_updated_init lm_dcbx_read_admin_mib failed ");
4299 }
4300 DbgBreakIf(offset != LM_DCBX_ADMIN_MIB_OFFSET(pdev, mf_cfg_offset_value));
4301
4302 if(DCBX_CONFIG_INV_VALUE !=
4303 pdev->params.dcbx_config_params.admin_dcbx_enable)
4304 {
4305 if(pdev->params.dcbx_config_params.admin_dcbx_enable)
4306 {
4307 SET_FLAGS(admin_mib.ver_cfg_flags,DCBX_DCBX_ENABLED);
4308 }
4309 else
4310 {
4311 RESET_FLAGS(admin_mib.ver_cfg_flags,DCBX_DCBX_ENABLED);
4312 }
4313 }
4314 lm_status = lm_dcbx_init_check_params_valid(pdev,
4315 (u32_t *)(&(pdev->params.dcbx_config_params.overwrite_settings)),
4316 ((sizeof(pdev->params.dcbx_config_params)-
4317 OFFSETOF(config_dcbx_params_t , overwrite_settings))/sizeof(u32_t)));
4318
4319 if((LM_STATUS_SUCCESS == lm_status)&&
4320 (OVERWRITE_SETTINGS_ENABLE == pdev->params.dcbx_config_params.overwrite_settings))
4321 {
4322 RESET_FLAGS(admin_mib.ver_cfg_flags,DCBX_CEE_VERSION_MASK);
4323 admin_mib.ver_cfg_flags |=
4324 (pdev->params.dcbx_config_params.admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) & DCBX_CEE_VERSION_MASK;
4325
4326 admin_mib.features.ets.enabled = (u8_t)
4327 pdev->params.dcbx_config_params.admin_ets_enable;
4328
4329
4330 admin_mib.features.pfc.enabled =(u8_t)
4331 pdev->params.dcbx_config_params.admin_pfc_enable;
4332
4333
4334 //FOR IEEE pdev->params.dcbx_config_params.admin_tc_supported_tx_enable
4335 if(pdev->params.dcbx_config_params.admin_ets_configuration_tx_enable)
4336 {
4337 SET_FLAGS(admin_mib.ver_cfg_flags,DCBX_ETS_CONFIG_TX_ENABLED);
4338 }
4339 else
4340 {
4341 RESET_FLAGS(admin_mib.ver_cfg_flags,DCBX_ETS_CONFIG_TX_ENABLED);
4342 }
4343 //For IEEE admin_ets_recommendation_tx_enable
4344
4345 if(pdev->params.dcbx_config_params.admin_pfc_tx_enable)
4346 {
4347 SET_FLAGS(admin_mib.ver_cfg_flags,DCBX_PFC_CONFIG_TX_ENABLED);
4348 }
4349 else
4350 {
4351 RESET_FLAGS(admin_mib.ver_cfg_flags,DCBX_PFC_CONFIG_TX_ENABLED);
4352 }
4353
4354 if(pdev->params.dcbx_config_params.admin_application_priority_tx_enable)
4355 {
4356 SET_FLAGS(admin_mib.ver_cfg_flags,DCBX_APP_CONFIG_TX_ENABLED);
4357 }
4358 else
4359 {
4360 RESET_FLAGS(admin_mib.ver_cfg_flags,DCBX_APP_CONFIG_TX_ENABLED);
4361 }
4362
4363
4364 if(pdev->params.dcbx_config_params.admin_ets_willing)
4365 {
4366 SET_FLAGS(admin_mib.ver_cfg_flags,DCBX_ETS_WILLING);
4367 }
4368 else
4369 {
4370 RESET_FLAGS(admin_mib.ver_cfg_flags,DCBX_ETS_WILLING);
4371 }
4372 //For IEEE admin_ets_reco_valid
4373 if(pdev->params.dcbx_config_params.admin_pfc_willing)
4374 {
4375 SET_FLAGS(admin_mib.ver_cfg_flags,DCBX_PFC_WILLING);
4376 }
4377 else
4378 {
4379 RESET_FLAGS(admin_mib.ver_cfg_flags,DCBX_PFC_WILLING);
4380 }
4381
4382 if(pdev->params.dcbx_config_params.admin_app_priority_willing)
4383 {
4384 SET_FLAGS(admin_mib.ver_cfg_flags,DCBX_APP_WILLING);
4385 }
4386 else
4387 {
4388 RESET_FLAGS(admin_mib.ver_cfg_flags,DCBX_APP_WILLING);
4389 }
4390
4391 lm_dcbx_admin_mib_update_ets_param(
4392 pdev,
4393 &admin_mib.features.ets,
4394 pdev->params.dcbx_config_params.admin_configuration_bw_percentage,
4395 pdev->params.dcbx_config_params.admin_configuration_ets_pg,
4396 ARRSIZE(pdev->params.dcbx_config_params.admin_configuration_bw_percentage) ,
4397 ARRSIZE(pdev->params.dcbx_config_params.admin_configuration_ets_pg));
4398
4399 //For IEEE admin_recommendation_bw_percentage
4400 //For IEEE admin_recommendation_ets_pg
4401 admin_mib.features.pfc.pri_en_bitmap = (u8_t)pdev->params.dcbx_config_params.admin_pfc_bitmap;
4402
4403 for(i = 0; i<ARRSIZE(pdev->params.dcbx_config_params.admin_priority_app_table); i++)
4404 {
4405 if(pdev->params.dcbx_config_params.admin_priority_app_table[i].valid)
4406 {
4407 lm_dcbx_admin_mib_update_app_pri(pdev,
4408 &admin_mib.features.app,
4409 &next_free_app_id_entry,
4410 (u16_t)pdev->params.dcbx_config_params.admin_priority_app_table[i].app_id,
4411 (u8_t)pdev->params.dcbx_config_params.admin_priority_app_table[i].traffic_type,
4412 (u8_t)pdev->params.dcbx_config_params.admin_priority_app_table[i].priority);
4413 }
4414 }
4415
4416 admin_mib.features.app.tc_supported = next_free_app_id_entry;
4417 admin_mib.features.app.default_pri = (u8_t)pdev->params.dcbx_config_params.admin_default_priority;
4418
4419 // There is a configuration set by BACS.
4420 lm_dcbx_config_drv_flags(
4421 pdev,
4422 lm_dcbx_drv_flags_set_bit,
4423 DRV_FLAGS_DCB_MFW_CONFIGURED);
4424
4425 }
4426 else
4427 {
4428 if(OVERWRITE_SETTINGS_ENABLE == pdev->params.dcbx_config_params.overwrite_settings)
4429 {
4430 pdev->params.dcbx_config_params.overwrite_settings = OVERWRITE_SETTINGS_INVALID;
4431 }
4432
4433 }
4434
4435 //Write the data.
4436 buff = (u32_t *)&admin_mib;
4437 for(i=0 ; i < sizeof(lldp_admin_mib_t); i+=4,buff++)
4438 {
4439 REG_WR(pdev, (offset + i) , *buff);
4440 }
4441 }
4442 /*******************************************************************************
4443 * Description: Update LLDP that changes deafault LLDP configuration.
4444 * Only if the entire LLDP registry set is present and differ from
4445 * 0xFFFFFFFF (invalid value) the LLDP registry parameters are taken,
4446 * otherwise the registry keys are ignored.
4447 * Return:
4448 * LM_STATUS_FAILURE - All/Some of the parameters could not be read.
4449 * LM_STATUS_SUCCESS - All the MIBs where read successfully.
4450 ******************************************************************************/
4451 STATIC void
lm_dcbx_init_lldp_updated_params(struct _lm_device_t * pdev,u32_t mf_cfg_offset_value)4452 lm_dcbx_init_lldp_updated_params(struct _lm_device_t * pdev,
4453 u32_t mf_cfg_offset_value)
4454 {
4455
4456 lldp_params_t lldp_params = {0};
4457 u32_t i = 0;
4458 u32_t *buff = NULL ;
4459 lm_status_t lm_status = LM_STATUS_SUCCESS;
4460 u32_t offest = mf_cfg_offset_value +
4461 PORT_ID(pdev) * sizeof(lldp_params_t);
4462
4463 lm_status = lm_dcbx_init_check_params_valid(pdev,
4464 (u32_t *)(&(pdev->params.lldp_config_params)),
4465 (sizeof(pdev->params.lldp_config_params)/sizeof(u32_t)));
4466
4467 if((LM_STATUS_SUCCESS == lm_status)&&
4468 (OVERWRITE_SETTINGS_ENABLE == pdev->params.lldp_config_params.overwrite_settings))
4469 {
4470 //Read the data first
4471 buff = (u32_t *)&lldp_params;
4472 for(i=0 ;i<sizeof(lldp_params_t); i+=4,buff++)
4473 {
4474 *buff = REG_RD(pdev,
4475 (offest+ i));
4476 }
4477 lldp_params.msg_tx_hold = (u8_t)pdev->params.lldp_config_params.msg_tx_hold;
4478 lldp_params.msg_fast_tx_interval = (u8_t)pdev->params.lldp_config_params.msg_fast_tx;
4479 lldp_params.tx_crd_max = (u8_t)pdev->params.lldp_config_params.tx_credit_max;
4480 lldp_params.msg_tx_interval = (u8_t)pdev->params.lldp_config_params.msg_tx_interval;
4481 lldp_params.tx_fast = (u8_t)pdev->params.lldp_config_params.tx_fast;
4482
4483 //Write the data.
4484 buff = (u32_t *)&lldp_params;
4485 for(i=0 ;i<sizeof(lldp_params_t); i+=4,buff++)
4486 {
4487 REG_WR(pdev, (offest+ i) , *buff);//Change to write
4488 }
4489 }
4490 else
4491 {
4492 if(OVERWRITE_SETTINGS_ENABLE == pdev->params.lldp_config_params.overwrite_settings)
4493 {
4494 pdev->params.lldp_config_params.overwrite_settings = OVERWRITE_SETTINGS_INVALID;
4495 }
4496
4497 }
4498
4499 }
4500 /*******************************************************************************
4501 * Description:
4502 * Allocate physical memory for DCBX start ramrod
4503 *
4504 * Return:
4505 ******************************************************************************/
4506 lm_status_t
lm_dcbx_get_pfc_fw_cfg_phys_mem(IN struct _lm_device_t * pdev,IN const u8_t lm_cli_idx)4507 lm_dcbx_get_pfc_fw_cfg_phys_mem(
4508 IN struct _lm_device_t *pdev,
4509 IN const u8_t lm_cli_idx)
4510 {
4511 if (CHK_NULL(pdev->dcbx_info.pfc_fw_cfg_virt))
4512 {
4513 pdev->dcbx_info.pfc_fw_cfg_virt =
4514 mm_alloc_phys_mem(pdev,
4515 sizeof(struct flow_control_configuration),
4516 &pdev->dcbx_info.pfc_fw_cfg_phys,
4517 0,
4518 lm_cli_idx);
4519
4520 if CHK_NULL(pdev->dcbx_info.pfc_fw_cfg_virt)
4521 {
4522 return LM_STATUS_RESOURCE;
4523 }
4524 }
4525
4526 return LM_STATUS_SUCCESS;
4527 }
4528 /**
4529 * @description
4530 * Called to clean dcbx info after D3
4531 * @param pdev
4532 *
4533 * @return lm_status_t
4534 */
4535 lm_status_t
lm_dcbx_init_info(IN lm_device_t * pdev)4536 lm_dcbx_init_info(
4537 IN lm_device_t *pdev
4538 )
4539 {
4540 pdev->dcbx_info.is_enabled = FALSE;
4541
4542 return LM_STATUS_SUCCESS;
4543 }
4544 /*******************************************************************************
4545 * Description:
4546 *
4547 *
4548 * Return:
4549 ******************************************************************************/
4550 lm_status_t
lm_dcbx_free_resc(IN struct _lm_device_t * pdev)4551 lm_dcbx_free_resc(
4552 IN struct _lm_device_t *pdev
4553 )
4554 {
4555 pdev->dcbx_info.pfc_fw_cfg_virt = NULL;
4556 pdev->dcbx_info.is_enabled = FALSE;
4557 return LM_STATUS_SUCCESS;
4558 }
4559 /**
4560 * lm_dcbx_ie_init_event_params
4561 * @param pdev
4562 * @param params
4563 * @param classif_table_size
4564 */
4565 void
lm_dcbx_ie_init_event_params(IN struct _lm_device_t * pdev,IN dcb_indicate_event_params_t * params,IN const u32_t classif_table_size)4566 lm_dcbx_ie_init_event_params(
4567 IN struct _lm_device_t *pdev,
4568 IN dcb_indicate_event_params_t *params,
4569 IN const u32_t classif_table_size)
4570 {
4571 params->flags = 0;
4572
4573 mm_mem_zero(¶ms->ets_params, sizeof(params->ets_params));
4574
4575 mm_mem_zero(¶ms->pfc_params, sizeof(params->pfc_params));
4576
4577 params->classif_params.classif_version = DCB_CLASSIFI_VER_SIMPLE_ELEM;
4578 params->classif_params.num_classif_elements = 0;
4579
4580 if((NULL != params->classif_params.classif_table) &&
4581 classif_table_size)
4582 {
4583 mm_mem_zero( params->classif_params.classif_table,
4584 classif_table_size);
4585 }
4586 }
4587 /**
4588 * lm_dcbx_ie_init_params
4589 *
4590 * @param pdev
4591 * @param b_only_setup
4592 */
4593 void
lm_dcbx_ie_init_params(IN struct _lm_device_t * pdev,IN const u8_t b_only_setup)4594 lm_dcbx_ie_init_params(
4595 IN struct _lm_device_t *pdev,
4596 IN const u8_t b_only_setup)
4597 {
4598 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
4599
4600 if (TRUE == b_only_setup)
4601 {
4602 lm_dcbx_ie_init_event_params(pdev,
4603 &indicate_event->local_params,
4604 LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_LOCAL);
4605
4606 lm_dcbx_ie_init_event_params(pdev,
4607 &indicate_event->remote_params,
4608 LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_REMOTE);
4609
4610 lm_dcbx_ie_init_event_params(pdev,
4611 &indicate_event->dcb_params_given_dbg,
4612 LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_DBG);
4613 }
4614 else
4615 {
4616 mm_mem_zero(indicate_event, sizeof(lm_dcbx_indicate_event_t));
4617 indicate_event->lm_cli_idx = LM_CLI_IDX_MAX;
4618 }
4619
4620 indicate_event->ets_config_state = lm_dcbx_ets_config_state_cee;
4621
4622 indicate_event->is_ets_ieee_params_os_valid = FALSE;
4623 mm_mem_zero(&indicate_event->ets_ieee_params_os ,
4624 sizeof(indicate_event->ets_ieee_params_os));
4625
4626 indicate_event->ets_ieee_config_state = lm_dcbx_ets_ieee_config_not_valid;
4627 mm_mem_zero(&indicate_event->ets_ieee_params_config ,
4628 sizeof(indicate_event->ets_ieee_params_config));
4629
4630 indicate_event->iscsi_tcp_pri = LM_DCBX_ILLEGAL_PRI;
4631
4632 indicate_event->dcb_current_oper_state_bitmap = 0;
4633
4634 }
4635 /*******************************************************************************
4636 * Description:
4637 * Allocate physical memory for DCBX start ramrod
4638 *
4639 * Return:
4640 ******************************************************************************/
4641 lm_status_t
lm_dcbx_init_params(IN struct _lm_device_t * pdev,IN const u8_t b_only_setup)4642 lm_dcbx_init_params(
4643 IN struct _lm_device_t *pdev,
4644 IN const u8_t b_only_setup)
4645 {
4646 lm_status_t lm_status = LM_STATUS_SUCCESS;
4647 u8_t lm_cli_idx = LM_CLI_IDX_MAX;
4648 u32_t dummy_offset = 0;
4649
4650 // All priorities are mapped by default to zero
4651 mm_mem_zero(pdev->dcbx_info.pri_to_cos, sizeof(pdev->dcbx_info.pri_to_cos));
4652
4653 mm_mem_zero(&(pdev->params.dcbx_port_params), sizeof(pdev->params.dcbx_port_params));
4654
4655 pdev->dcbx_info.dcbx_update_lpme_task_state = DCBX_UPDATE_TASK_STATE_FREE;
4656 pdev->dcbx_info.is_dcbx_neg_received = FALSE;
4657
4658 lm_dcbx_ie_init_params(pdev, b_only_setup);
4659
4660 // Should not be used in MF this is only a pach until MCP will know how to return to default
4661 lm_status = lm_dcbx_read_admin_mib( pdev,
4662 &pdev->dcbx_info.admin_mib_org,
4663 &dummy_offset);
4664
4665 if(LM_STATUS_SUCCESS != lm_status)
4666 {
4667 DbgBreakMsg(" lm_dcbx_admin_mib_updated_init lm_dcbx_read_admin_mib failed ");
4668 return lm_status;
4669 }
4670
4671 if(FALSE == b_only_setup)
4672 {
4673 lm_status = lm_dcbx_get_pfc_fw_cfg_phys_mem(pdev, lm_cli_idx);
4674 if(LM_STATUS_SUCCESS != lm_status )
4675 {
4676 DbgBreakMsg("lm_dcbx_init_params : resource ");
4677 pdev->dcbx_info.dcbx_error |= DCBX_ERROR_RESOURCE;
4678 return lm_status;
4679 }
4680 }
4681
4682
4683 return lm_status;
4684 }
4685
4686 /**
4687 * @description
4688 * Set in a shared port memory place if DCBX completion was
4689 * received. Function is needed for PMF migration in order to
4690 * synchronize the new PMF that DCBX results has ended.
4691 * @param pdev
4692 * @param is_completion_recv
4693 */
4694 void
lm_dcbx_config_drv_flags(IN lm_device_t * pdev,IN const lm_dcbx_drv_flags_cmd_t drv_flags_cmd,IN const u32_t bit_drv_flags)4695 lm_dcbx_config_drv_flags(
4696 IN lm_device_t *pdev,
4697 IN const lm_dcbx_drv_flags_cmd_t drv_flags_cmd,
4698 IN const u32_t bit_drv_flags)
4699 {
4700 const u32_t drv_flags_offset = OFFSETOF(shmem2_region_t,drv_flags);
4701 u32_t drv_flags = 0;
4702 lm_status_t lm_status = LM_STATUS_SUCCESS;
4703 const u8_t port = PORT_ID(pdev);
4704 u32_t port_drv_flags = DRV_FLAGS_FILED_BY_PORT(bit_drv_flags, port);
4705
4706 if(!IS_PMF(pdev))
4707 {
4708 DbgBreakMsg("lm_dcbx_check_drv_flags error only PMF can access this field ");
4709 return;
4710 }
4711
4712 lm_status = lm_hw_lock(pdev, HW_LOCK_RESOURCE_DRV_FLAGS, TRUE);
4713
4714 if(LM_STATUS_SUCCESS != lm_status)
4715 {
4716 DbgBreakMsg("lm_dcbx_set_comp_recv_on_port_bit lm_hw_lock failed ");
4717 return;
4718 }
4719
4720 lm_dcbx_read_shmem2_mcp_fields(pdev,
4721 drv_flags_offset,
4722 &drv_flags);
4723
4724 switch(drv_flags_cmd)
4725 {
4726 case lm_dcbx_drv_flags_set_bit:
4727 SET_FLAGS(drv_flags,port_drv_flags);
4728 break;
4729 case lm_dcbx_drv_flags_reset_bit:
4730 RESET_FLAGS(drv_flags,port_drv_flags);
4731 break;
4732 case lm_dcbx_drv_flags_reset_flags:
4733 port_drv_flags = DRV_FLAGS_GET_PORT_MASK(port);
4734
4735 RESET_FLAGS(drv_flags,port_drv_flags);
4736 break;
4737 default:
4738 DbgBreakMsg("lm_dcbx_set_comp_recv_on_port_bit : illegal drv_flags_cmd ");
4739 return;
4740 };
4741
4742 lm_dcbx_write_shmem2_mcp_fields(pdev,
4743 drv_flags_offset,
4744 drv_flags);
4745
4746 lm_hw_unlock(pdev, HW_LOCK_RESOURCE_DRV_FLAGS);
4747 }
4748 /**
4749 * @description
4750 * Function is needed for PMF migration in order to synchronize
4751 * the new PMF that DCBX results has ended.
4752 * @param pdev
4753 *
4754 * @return u8_t
4755 * This function returns TRUE if DCBX completion received on
4756 * this port
4757 */
4758 u8_t
lm_dcbx_check_drv_flags(IN lm_device_t * pdev,IN const u32_t flags_bits_to_check)4759 lm_dcbx_check_drv_flags(
4760 IN lm_device_t *pdev,
4761 IN const u32_t flags_bits_to_check)
4762 {
4763 const u32_t drv_flags_offset = OFFSETOF(shmem2_region_t,drv_flags);
4764 u32_t drv_flags = 0;
4765 u8_t is_flag_set = FALSE;
4766 const u8_t port = PORT_ID(pdev);
4767 const u32_t port_flags_to_check = DRV_FLAGS_FILED_BY_PORT(flags_bits_to_check, port);
4768
4769 if(!IS_PMF(pdev))
4770 {
4771 DbgBreakMsg("lm_dcbx_check_drv_flags error only PMF can access this field ");
4772 return FALSE;
4773 }
4774
4775 lm_dcbx_read_shmem2_mcp_fields(pdev,
4776 drv_flags_offset,
4777 &drv_flags);
4778
4779 if(GET_FLAGS(drv_flags, port_flags_to_check))
4780 {
4781 is_flag_set = TRUE;
4782 }
4783
4784 return is_flag_set;
4785 }
4786 /**
4787 * @description
4788 * 1. Make sure all the DCBX init parameters for this function
4789 * are correct.
4790 * 2. Register a set DCBX params in order to let the new PMF
4791 * migration function to know the current DCBX settings and that
4792 * the pdev varibales will mach the HW configuration.
4793 * for example in MF when DCBX is configured to static
4794 * configuration ELINK_FEATURE_CONFIG_PFC_ENABLED is set in pdev
4795 * (we get only one interrupt)of only the original
4796 * function.After PMF migration the first link updated will
4797 * cause the PFC state to be incompatible.The function that
4798 * become PMF doesn't have ELINK_FEATURE_CONFIG_PFC_ENABLED set
4799 * @param pdev
4800 */
4801 void
lm_dcbx_pmf_migration(IN struct _lm_device_t * pdev)4802 lm_dcbx_pmf_migration(
4803 IN struct _lm_device_t *pdev)
4804 {
4805 lm_status_t lm_status = LM_STATUS_SUCCESS;
4806 const u8_t is_completion_received_on_port =
4807 lm_dcbx_check_drv_flags(pdev, DRV_FLAGS_DCB_CONFIGURED);
4808
4809 DbgBreakIf(TRUE != IS_DCB_ENABLED(pdev));
4810
4811 // We called lm_dcbx_init_params at the beginning
4812 // verify all the parameters are correct and that there is no error.
4813 DbgBreakIf(FALSE != pdev->dcbx_info.is_dcbx_neg_received);
4814 DbgBreakIf(DCBX_UPDATE_TASK_STATE_FREE != pdev->dcbx_info.dcbx_update_lpme_task_state);
4815 DbgBreakIf(CHK_NULL(pdev->dcbx_info.pfc_fw_cfg_virt));
4816
4817 // for this function the only error possibole is that the pfc_fw_cfg_virt wasn't allocated.
4818 if((DCBX_ERROR_NO_ERROR != pdev->dcbx_info.dcbx_error) ||
4819 (FALSE == IS_MULTI_VNIC(pdev)))
4820 {
4821 DbgBreakMsg("lm_dcbx_init : lm_mcp_cmd_send_recieve failed ");
4822 return;
4823 }
4824
4825 // If we received the DCBX parameters before on this port the new PMF
4826 // will read the current DCBX parameters
4827 if(FALSE == is_completion_received_on_port)
4828 {
4829 // DCBX parameters were not received before
4830 return;
4831 }
4832 // Register a set params in order to let the new PMF migration
4833 // function to know the current DCBX settings.
4834 // A side effect of this function be to set the DCBX parameters again,
4835 // but this is a must because in case of an error(or if we have an
4836 // innterrupt from MCP that eas not handled) the seetings that are
4837 // currently on the chip may not be equale to the local settings.
4838 lm_status = MM_REGISTER_LPME(pdev,
4839 lm_dcbx_init_lpme_set_params,
4840 TRUE,
4841 FALSE);// DCBX sends ramrods
4842
4843 if (LM_STATUS_SUCCESS != lm_status)
4844 {
4845 pdev->dcbx_info.dcbx_error |= DCBX_ERROR_REGISTER_LPME;
4846 // No rollback
4847 // Problem because if DCBX interrupt isn't receive the chip will be
4848 // stuck beacuse QM queues are stopped.
4849 // For release version this will call DCBX start that will restart QM queues.
4850 DbgBreakMsg("lm_dcbx_int : The chip QM queues are stuck until an interrupt from MCP");
4851 }
4852 }
4853 /**
4854 * First check if DCBX is enabled on port.Old MCP that doesn't
4855 * support the field dcbx_en should not be used in 4 port
4856 * because if one port supports DCBX but the other does't,
4857 * driver can't tell the difference according to
4858 * dcbx_lldp_params_offset.(dcbx_lldp_params_offset is valid if
4859 * one port is enabled)
4860 *
4861 * After check that dcbx_lldp_params_offset is valid for
4862 * backward compatibility(until 4 port).
4863 * If dcbx_en isn't zero dcbx_lldp_params_offset must be vaild.
4864 * @param pdev
4865 *
4866 * @return u8_t
4867 */
4868 u8_t
lm_dcbx_port_enable_mcp(IN lm_device_t * pdev)4869 lm_dcbx_port_enable_mcp(IN lm_device_t *pdev)
4870 {
4871 u32_t lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
4872 const u32_t mcp_lldp_params_offset = OFFSETOF(shmem2_region_t,dcbx_lldp_params_offset);
4873 const u8_t port = PORT_ID(pdev);
4874 const u32_t dcbx_en_offset = OFFSETOF(shmem2_region_t,dcbx_en[port]);
4875 u32_t read_dcbx_en = 0;
4876
4877 if(LM_SHMEM2_HAS(pdev, dcbx_en[port]))
4878 {
4879 LM_SHMEM2_READ(pdev, dcbx_en_offset, &read_dcbx_en);
4880
4881 if(0 == read_dcbx_en)
4882 {
4883 return FALSE;
4884 }
4885 }
4886 else
4887 {
4888 DbgMessage(pdev, FATAL, "lm_dcbx_port_enable_mcp: Old MCP a new driver requires"
4889 "a new MFW for knowing if DCBX is enabled in 4 port mode.\n");
4890 }
4891
4892 lm_dcbx_read_shmem2_mcp_fields( pdev,
4893 mcp_lldp_params_offset,
4894 &lldp_params_offset);
4895
4896 DbgBreakIf((0 != read_dcbx_en) &&
4897 (SHMEM_LLDP_DCBX_PARAMS_NONE == lldp_params_offset));
4898
4899 return (SHMEM_LLDP_DCBX_PARAMS_NONE != lldp_params_offset);
4900 }
4901 /*******************************************************************************
4902 * Description:
4903 * The PMF function starts the DCBX negotiation after sending the
4904 * MIB DRV_MSG_LLDP_PMF_MSG with new LLDP/DCBX configurations if available.
4905 * The PMF will call the function dcbx_stop_Hw_TX () that will ensure
4906 * that no traffic can be sent. (The driver will send a ramrod to the
4907 * FW that will stop all the queues in the QM)
4908 * After 1 second (a timer elapsed) if DCBX negotiation didn't end
4909 * (pdev.vars.dcbx_neg_received =0) and link is up a WI lm_dcbx_resume_TX()
4910 * is scheduled .
4911 * In WI read the configuration from local MIB and set DCBX parameters
4912 * to the value in local_MIB.
4913 *
4914 * Return:
4915 ******************************************************************************/
4916 void
lm_dcbx_init(IN struct _lm_device_t * pdev,IN const u8_t b_only_setup)4917 lm_dcbx_init(IN struct _lm_device_t *pdev,
4918 IN const u8_t b_only_setup)
4919 {
4920 u32_t fw_resp = 0 ;
4921 lm_status_t lm_status = LM_STATUS_FAILURE ;
4922 u32_t dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
4923 const u32_t mcp_dcbx_lldp_params_offset = OFFSETOF(shmem2_region_t,dcbx_lldp_params_offset);
4924 u8_t is_mfw_config = FALSE;
4925
4926 DbgBreakIf(FALSE != IS_DCB_ENABLED(pdev));
4927
4928 if(IS_DCB_SUPPORTED(pdev))
4929 {// DCBX is supported on E1H. E2 only in 2 port mode.
4930 if (lm_dcbx_port_enable_mcp(pdev))
4931 {// DCBX supported in MCP
4932
4933 lm_status = lm_dcbx_init_params(pdev, b_only_setup);
4934 if(LM_STATUS_SUCCESS != lm_status)
4935 {// If dcbx pfc_fw_cfg could not be allocated DCBX isn't supported
4936 return;
4937 }
4938
4939 if(IS_PMF_ORIGINAL(pdev))
4940 {//Only the PMF starts and handles
4941 pdev->dcbx_info.is_enabled = TRUE;
4942
4943 lm_dcbx_read_shmem2_mcp_fields( pdev,
4944 mcp_dcbx_lldp_params_offset,
4945 &dcbx_lldp_params_offset);
4946
4947 DbgBreakIf(SHMEM_LLDP_DCBX_PARAMS_NONE == dcbx_lldp_params_offset);
4948
4949 lm_dcbx_init_lldp_updated_params( pdev,
4950 dcbx_lldp_params_offset);
4951
4952 lm_dcbx_admin_mib_updated_init( pdev,
4953 dcbx_lldp_params_offset);
4954
4955 lm_status = lm_mcp_cmd_send_recieve( pdev,
4956 lm_mcp_mb_header,
4957 DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG,
4958 0,
4959 MCP_CMD_DEFAULT_TIMEOUT,
4960 &fw_resp ) ;
4961
4962 if( lm_status != LM_STATUS_SUCCESS )
4963 {
4964 pdev->dcbx_info.dcbx_error |= DCBX_ERROR_MCP_CMD_FAILED;
4965 DbgBreakMsg("lm_dcbx_init : lm_mcp_cmd_send_recieve failed ");
4966 return;
4967 }
4968 is_mfw_config = lm_dcbx_check_drv_flags(pdev, DRV_FLAGS_DCB_MFW_CONFIGURED);
4969
4970 if(TRUE == is_mfw_config)
4971 {
4972 lm_status = MM_REGISTER_LPME(pdev,
4973 lm_dcbx_init_lpme_set_params,
4974 TRUE,
4975 FALSE);// DCBX sends ramrods
4976
4977 if (LM_STATUS_SUCCESS != lm_status)
4978 {
4979 pdev->dcbx_info.dcbx_error |= DCBX_ERROR_REGISTER_LPME;
4980 // No rollback
4981 // Problem because if DCBX interrupt isn't receive the chip will be
4982 // stuck beacuse QM queues are stopped.
4983 // For release version this will call DCBX start that will restart QM queues.
4984 DbgBreakMsg("lm_dcbx_int : The chip QM queues are stuck until an interrupt from MCP");
4985 }
4986 }
4987 }//PMF Original
4988 else
4989 {
4990 pdev->dcbx_info.is_enabled = TRUE;
4991 if(IS_PMF_MIGRATION(pdev))
4992 {
4993 // Send an attention on this Function.
4994 // We create an interrupt on this function to make sure we will wake up another time
4995 // to send the MCP ACK.
4996 LM_GENERAL_ATTN_INTERRUPT_SET(pdev,FUNC_ID(pdev));
4997 }
4998 }
4999 }// DCBX supported in MCP
5000 } //DCBX enabled.
5001 }
5002 /*******************************************************************************
5003 * Description:
5004 *
5005 * Return:
5006 ******************************************************************************/
5007 static void
lm_dcbx_init_set_params_invalid(u32_t * buff_check,u32_t buff_size)5008 lm_dcbx_init_set_params_invalid(u32_t * buff_check,
5009 u32_t buff_size)
5010 {
5011 u32_t i=0;
5012 for (i=0 ; i < buff_size ; i++,buff_check++)
5013 {
5014 *buff_check = DCBX_CONFIG_INV_VALUE;
5015 }
5016 }
5017 /**
5018 * @description
5019 * Init dcbx init default params this function should be called
5020 * once before any other DCBX function is called.
5021 * @param pdev
5022 */
5023 void
lm_dcbx_init_default_params(lm_device_t * pdev)5024 lm_dcbx_init_default_params(lm_device_t *pdev)
5025 {
5026 // Init dcbx and lldp params
5027
5028 lm_dcbx_init_set_params_invalid((u32_t *)(&(pdev->params.lldp_config_params)),
5029 (sizeof(pdev->params.lldp_config_params)/sizeof(u32_t)));
5030
5031 lm_dcbx_init_set_params_invalid((u32_t *)(&(pdev->params.dcbx_config_params)),
5032 (sizeof(pdev->params.dcbx_config_params)/sizeof(u32_t)));
5033
5034 pdev->params.dcbx_config_params.dcb_enable = 1; //DCB by default is disabled
5035 pdev->params.dcbx_config_params.admin_dcbx_enable = 1; //DCBX by default is enabled
5036
5037 if((!(CHIP_IS_E1x(pdev))) &&
5038 IS_PFDEV(pdev))
5039 {
5040 pdev->params.b_dcb_indicate_event = TRUE;
5041 }
5042 }
5043
5044 /**********************end DCBX INIT FUNCTIONS**************************************/
5045
5046 /**********************start DCBX UPDATE FUNCTIONS**************************************/
5047 /*******************************************************************************
5048 * Description:
5049 * Any DCBX update will be treated as a runtime change.
5050 * Runtime changes can take more than 1 second and can't be handled
5051 * from DPC.
5052 * When the PMF detects a DCBX update it will schedule a WI that
5053 * will handle the job.
5054 * This function should be called in PASSIVE IRQL (Currently called from
5055 * DPC) and in mutual exclusion any acces to lm_dcbx_stop_HW_TX
5056 * /lm_dcbx_resume_HW_TX.
5057 *
5058 * Return:
5059 ******************************************************************************/
5060 void
lm_dcbx_update_lpme_set_params(struct _lm_device_t * pdev)5061 lm_dcbx_update_lpme_set_params(struct _lm_device_t *pdev)
5062 {
5063 u32_t offset = 0;
5064 u32_t drv_status = 0;
5065 lm_status_t lm_status = LM_STATUS_SUCCESS;
5066
5067 offset = OFFSETOF(shmem_region_t, func_mb[FUNC_MAILBOX_ID(pdev)].drv_status) ;
5068
5069 // drv_status
5070 LM_SHMEM_READ(pdev,
5071 offset,
5072 &drv_status);
5073
5074 if((IS_PMF(pdev))&&
5075 (GET_FLAGS( drv_status, DRV_STATUS_DCBX_NEGOTIATION_RESULTS))&&
5076 (DCBX_UPDATE_TASK_STATE_SCHEDULE == pdev->dcbx_info.dcbx_update_lpme_task_state))
5077 {
5078 // No lock is needed to be taken because lm_dcbx_set_params is only called from a WI
5079 lm_status = lm_dcbx_set_params_and_read_mib(pdev,
5080 FALSE,
5081 TRUE);
5082
5083 DbgBreakIf(LM_STATUS_SUCCESS != lm_status);
5084
5085 pdev->dcbx_info.dcbx_update_lpme_task_state =
5086 DCBX_UPDATE_TASK_STATE_HANDLED;
5087 // Send an attention on this Function.
5088 // We create an interrupt on this function to make sure we will wake up another time
5089 // to send the MCP ACK.
5090 LM_GENERAL_ATTN_INTERRUPT_SET(pdev,FUNC_ID(pdev));
5091 }
5092 else
5093 {
5094 DbgBreakMsg("lm_dcbx_update_lpme_set_params error");
5095 }
5096 }
5097 /**********************end DCBX UPDATE FUNCTIONS**************************************/
5098
5099 /**
5100 * @description
5101 * Enable indicate event to upper layer
5102 * @param pdev
5103 */
lm_dcbx_ie_update_state(INOUT struct _lm_device_t * pdev,IN const u8_t is_en)5104 void lm_dcbx_ie_update_state(
5105 INOUT struct _lm_device_t * pdev,
5106 IN const u8_t is_en)
5107 {
5108 pdev->dcbx_info.is_indicate_event_en = is_en;
5109 }
5110 /**
5111 * @description
5112 *
5113 * @param pdev
5114 *
5115 * @return u8
5116 */
lm_dcbx_cos_max_num(INOUT const struct _lm_device_t * pdev)5117 u8_t lm_dcbx_cos_max_num(
5118 INOUT const struct _lm_device_t * pdev)
5119 {
5120 u8_t cos_max_num = 0;
5121
5122 if(CHIP_IS_E3B0(pdev))
5123 {
5124 cos_max_num = DCBX_COS_MAX_NUM_E3B0;
5125 }
5126 else
5127 {
5128 cos_max_num = DCBX_COS_MAX_NUM_E2E3A0;
5129 }
5130
5131 return cos_max_num;
5132 }
5133 /**
5134 * @description
5135 * Validate the PFC parameters that were received can be
5136 * configured. The parameters will later be configured in WI.
5137 * @param pdev
5138 * @param pfc_params
5139 * @param dcbx_neg_res_offset - After the offset was read
5140 * correctly from Shmem.
5141 *
5142 * @return STATIC lm_status_t
5143 */
5144 STATIC lm_status_t
lm_dcbx_ie_runtime_params_updated_validate_pfc(INOUT lm_device_t * pdev,IN const dcb_pfc_param_t * pfc_params)5145 lm_dcbx_ie_runtime_params_updated_validate_pfc(
5146 INOUT lm_device_t *pdev,
5147 IN const dcb_pfc_param_t *pfc_params
5148 )
5149 {
5150 lm_status_t lm_status = LM_STATUS_SUCCESS;
5151
5152 if(FALSE == pdev->dcbx_info.is_indicate_event_en)
5153 {
5154 DbgBreakMsg("lm_dcbx_runtime_params_updated_validate_pfc called but is_indicate_event_en is false");
5155 return LM_STATUS_FAILURE;
5156 }
5157
5158 return lm_status;
5159 }
5160 /**
5161 * @description
5162 * Validate the ETS parameters that were received can be
5163 * configured. The parameters will later be configured in WI.
5164 * @param pdev
5165 * @param ets_params
5166 *
5167 * @return STATIC lm_status_t
5168 */
5169 STATIC lm_status_t
lm_dcbx_ie_params_updated_validate_ets(INOUT lm_device_t * pdev,IN const dcb_ets_tsa_param_t * ets_params)5170 lm_dcbx_ie_params_updated_validate_ets(
5171 INOUT lm_device_t *pdev,
5172 IN const dcb_ets_tsa_param_t *ets_params
5173 )
5174 {
5175 lm_status_t lm_status = LM_STATUS_SUCCESS;
5176 const u8_t cos_max_num = lm_dcbx_cos_max_num(pdev);
5177 u8_t i = 0;
5178 u8_t tc_entry = 0;
5179 u8_t tc_entry_bitmap = 0;
5180 u8_t tc_used_bitmap = 0;
5181 u8_t num_of_tc_used = 0;
5182
5183 if(cos_max_num < ets_params->num_traffic_classes )
5184 {
5185 DbgBreakMsg("lm_dcbx_runtime_params_updated_validate_ets num_traffic_classes can't be larger"
5186 "than cos_max_num");
5187 return LM_STATUS_FAILURE;
5188 }
5189
5190 if(LM_DCBX_IE_IS_ETS_DISABLE(ets_params->num_traffic_classes))
5191 {
5192 DbgMessage(pdev, INFORM, "ETS is disabled other ETS paramters not checked \n");
5193
5194 return LM_STATUS_SUCCESS;
5195 }
5196
5197 for(i = 0; i < ARRSIZE(ets_params->priority_assignment_table); i++)
5198 {
5199 //cos_max_num
5200 tc_entry = ets_params->priority_assignment_table[i];
5201 if(tc_entry >= DCBX_MAX_NUM_PG_BW_ENTRIES)
5202 {
5203 DbgBreakMsg("lm_dcbx_runtime_params_updated_validate_ets a tc_entry can't be larger"
5204 "than the number of TC supported");
5205 return LM_STATUS_FAILURE;
5206 }
5207
5208 tc_entry_bitmap = (1 << tc_entry);
5209 // Count the number of TC entries given and fill the appropriate COS entry.
5210 if(0 == (tc_used_bitmap & tc_entry_bitmap))
5211 {
5212 // New TC add it to the bitmask
5213 tc_used_bitmap |= tc_entry_bitmap;
5214 num_of_tc_used++;
5215 DbgBreakIf(cos_max_num < num_of_tc_used);
5216 }
5217
5218
5219 switch(ets_params->tsa_assignment_table[tc_entry])
5220 {
5221 case TSA_ASSIGNMENT_DCB_TSA_STRICT:
5222 case TSA_ASSIGNMENT_DCB_TSA_ETS: //fall through
5223 // Entry can be handled by VBD
5224 break;
5225
5226 case TSA_ASSIGNMENT_DCB_TSA_CBS:
5227 DbgBreakMsg("TSA_ASSIGNMENT_DCB_TSA_CBS value isn't supported by VBD");
5228 return LM_STATUS_INVALID_PARAMETER;
5229 break;
5230 default:
5231 DbgBreakMsg("illegal value for tsa_assignment_table");
5232 break;
5233 }
5234 }
5235
5236 if(ets_params->num_traffic_classes < num_of_tc_used )
5237 {
5238 if(0 == pdev->params.lm_dcb_dont_break_bad_oid)
5239 {
5240 DbgBreakMsg("OS gave more TC than mentioned in num_traffic_classes");
5241 }
5242 return LM_STATUS_INVALID_PARAMETER;
5243 }
5244
5245 return lm_status;
5246 }
5247 /**
5248 * @description
5249 * For classification entries that will be supported are
5250 * returned with the flag DCB_CLASSIF_ENFORCED_BY_VBD set.
5251 *
5252 * Set the flag in classification entries that do not conflict
5253 * with the remote settings and is supported by the miniport,
5254 * and clear the flag in classification entries that do conflict
5255 * with remote settings or is not supported by the miniport.
5256 * @param pdev
5257 * @param classif_params
5258 * @param mcp_dcbx_neg_res_offset
5259 *
5260 * @return STATIC lm_status_t
5261 */
5262 STATIC lm_status_t
lm_dcbx_ie_classif_entries_validate_and_set_enforced(IN struct _lm_device_t * pdev,INOUT dcb_classif_params_t * classif_params)5263 lm_dcbx_ie_classif_entries_validate_and_set_enforced(
5264 IN struct _lm_device_t *pdev,
5265 INOUT dcb_classif_params_t *classif_params)
5266 {
5267 dcb_classif_elem_t *p_classif_elem = classif_params->classif_table;
5268 lm_status_t lm_status = LM_STATUS_SUCCESS;
5269 u8_t i = 0;
5270
5271 if(DCB_CLASSIFI_VER_SIMPLE_ELEM != classif_params->classif_version)
5272 {
5273 DbgBreakMsg("lm_dcbx_runtime_params_updated_en_classif_entries : classif_version not supported ");
5274 return LM_STATUS_FAILURE;
5275 }
5276
5277 for(i = 0; i < classif_params->num_classif_elements; i++,p_classif_elem++)
5278 {
5279
5280 if(NULL == p_classif_elem)
5281 {
5282 DbgBreakMsg("lm_dcbx_runtime_params_updated_en_classif_entries : p_classif_elem is null ");
5283 return LM_STATUS_FAILURE;
5284 }
5285
5286 if(DCB_ACTION_PRIORITY != p_classif_elem->action_selector)
5287 {
5288 // VBD only supports condition_selector that is based on priority
5289 continue;
5290 }
5291 switch(p_classif_elem->condition_selector)
5292 {
5293 case DCB_CONDITION_DEFAULT:
5294 // Must be the first entry
5295 DbgBreakIf(0 != i);
5296 break;
5297
5298 case DCB_CONDITION_TCP_PORT:
5299 case DCB_CONDITION_TCP_OR_UDP_PORT://Fall through
5300 if(TCP_PORT_ISCSI == p_classif_elem->condition_field)
5301 {
5302 SET_FLAGS(p_classif_elem->flags, DCB_CLASSIF_ENFORCED_BY_VBD);
5303 }
5304 break;
5305
5306 case DCB_CONDITION_ETHERTYPE:
5307 if(ETH_TYPE_FCOE == p_classif_elem->condition_field)
5308 {
5309 SET_FLAGS(p_classif_elem->flags, DCB_CLASSIF_ENFORCED_BY_VBD);
5310 }
5311 break;
5312
5313 case DCB_CONDITION_RESERVED:
5314 case DCB_CONDITION_UDP_PORT://Fall through
5315 case DCB_CONDITION_NETDIRECT_PORT://Fall through
5316 //Not supported by VBD
5317 break;
5318 case DCB_CONDITION_MAX:
5319 default:
5320 DbgBreakMsg("lm_dcbx_runtime_params_updated_en_classif_entries: illegal entry ");
5321 break;
5322 }
5323 }
5324 return lm_status;
5325 }
5326 /**
5327 * @description
5328 * The function will allocate room for the calcification entries
5329 * copy the miniport buffer + local MIB.
5330 * The function will also copy all valid entries to the
5331 * beggining classif_params_copy->classif_table
5332 * @param pdev
5333 * @param classif_params
5334 * @param classif_params_copy
5335 * @param lm_cli_idx
5336 *
5337 * @return STATIC lm_status_t
5338 */
5339 STATIC lm_status_t
lm_dcbx_ie_copy_alloc_classif_buffer(INOUT lm_device_t * pdev,IN const dcb_classif_params_t * classif_params,OUT dcb_classif_params_t * classif_params_copy,IN const u8_t lm_cli_idx)5340 lm_dcbx_ie_copy_alloc_classif_buffer(
5341 INOUT lm_device_t *pdev,
5342 IN const dcb_classif_params_t *classif_params,
5343 OUT dcb_classif_params_t *classif_params_copy,
5344 IN const u8_t lm_cli_idx
5345 )
5346 {
5347 dcb_classif_elem_t *p_classif_elem = NULL;
5348 lm_status_t lm_status = LM_STATUS_SUCCESS;
5349 u8_t i = 0;
5350
5351 DbgBreakIf(lm_cli_idx != pdev->dcbx_info.indicate_event.lm_cli_idx);
5352
5353
5354 if(classif_params->num_classif_elements)
5355 {
5356 // The total size allocated
5357 classif_params_copy->classif_table =
5358 mm_rt_alloc_mem(pdev,
5359 LM_DCBX_IE_CLASSIF_ENTRIES_TO_ALOC_SIZE(classif_params->num_classif_elements),
5360 pdev->dcbx_info.indicate_event.lm_cli_idx);
5361
5362 if(CHK_NULL(classif_params_copy->classif_table))
5363 {
5364 DbgBreakMsg(" lm_dcbx_ie_copy_alloc_classif_buffer allocation failure ");
5365 return LM_STATUS_RESOURCE;
5366 }
5367
5368 classif_params_copy->num_classif_elements = classif_params->num_classif_elements;
5369
5370 mm_memcpy(classif_params_copy->classif_table,
5371 classif_params->classif_table,
5372 LM_DCBX_IE_CLASSIF_ENTRIES_TO_ALOC_SIZE(classif_params_copy->num_classif_elements));
5373
5374 p_classif_elem = (dcb_classif_elem_t *)classif_params_copy->classif_table;
5375 //Clear all the DCB_CLASSIF_ENFORCED_BY_VBD from copy entries
5376 for(i = 0; i < classif_params_copy->num_classif_elements; i++,p_classif_elem++)
5377 {
5378 RESET_FLAGS(p_classif_elem->flags, DCB_CLASSIF_ENFORCED_BY_VBD);
5379 }
5380 }
5381
5382 return lm_status;
5383 }
5384 /**
5385 * Copy dcb parameters given by OS.
5386 * @param pdev
5387 * @param dcb_params
5388 * @param dcb_params_copy
5389 * @param lm_cli_idx
5390 *
5391 * @return STATIC lm_status_t
5392 */
5393 STATIC lm_status_t
lm_dcbx_ie_params_updated_copy_dcb_params(INOUT lm_device_t * pdev,IN dcb_indicate_event_params_t * dcb_params,OUT dcb_indicate_event_params_t * dcb_params_copy,IN const u8_t lm_cli_idx)5394 lm_dcbx_ie_params_updated_copy_dcb_params(
5395 INOUT lm_device_t *pdev,
5396 IN dcb_indicate_event_params_t *dcb_params,
5397 OUT dcb_indicate_event_params_t *dcb_params_copy,
5398 IN const u8_t lm_cli_idx)
5399 {
5400 lm_status_t lm_status = LM_STATUS_SUCCESS;
5401
5402 mm_memcpy(dcb_params_copy,
5403 dcb_params,
5404 sizeof(dcb_indicate_event_params_t));
5405
5406 // miniport pointers should not be used we will realloc a struct in lm_dcbx_ie_copy_alloc_classif_buffer
5407 dcb_params_copy->classif_params.classif_table = NULL;
5408 dcb_params_copy->classif_params.num_classif_elements = 0;
5409
5410 lm_status = lm_dcbx_ie_copy_alloc_classif_buffer(pdev,
5411 &dcb_params->classif_params,
5412 &(dcb_params_copy->classif_params),
5413 lm_cli_idx);
5414
5415 if(LM_STATUS_SUCCESS != lm_status)
5416 {
5417 return lm_status;
5418 }
5419
5420 return lm_status;
5421 }
5422 /**
5423 * @description
5424 * Validate the ETS and PFC parameters that were received can be
5425 * configured. The parameters will later be configured in WI.
5426 * For classification entries that will be supported are
5427 * returned with the flag DCB_CLASSIF_ENFORCED_BY_VBD set.
5428 * @param pdev
5429 * @param dcb_params
5430 *
5431 * @return lm_status_t
5432 */
5433 lm_status_t
lm_dcbx_ie_params_updated_validate(INOUT struct _lm_device_t * pdev,OUT dcb_indicate_event_params_t * dcb_params,OUT dcb_indicate_event_params_t * dcb_params_copy,IN const u8_t lm_cli_idx)5434 lm_dcbx_ie_params_updated_validate(
5435 INOUT struct _lm_device_t *pdev,
5436 OUT dcb_indicate_event_params_t *dcb_params,
5437 OUT dcb_indicate_event_params_t *dcb_params_copy,
5438 IN const u8_t lm_cli_idx)
5439 {
5440 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
5441 lm_status_t lm_status = LM_STATUS_SUCCESS;
5442
5443 DbgBreakIf(lm_cli_idx != indicate_event->lm_cli_idx);
5444
5445 if((FALSE == pdev->dcbx_info.is_indicate_event_en) ||
5446 (IS_MULTI_VNIC(pdev)))
5447 {
5448 DbgBreakMsg("lm_dcbx_runtime_params_updated_validate_pfc called but is_indicate_event_en is false");
5449 return LM_STATUS_FAILURE;
5450 }
5451
5452 if(GET_FLAGS(dcb_params->flags, DCB_PARAMS_PFC_ENABLED))
5453 {
5454 lm_status =
5455 lm_dcbx_ie_runtime_params_updated_validate_pfc(pdev,
5456 &dcb_params->pfc_params);
5457
5458 if(LM_STATUS_SUCCESS != lm_status)
5459 {
5460 return lm_status;
5461 }
5462 }
5463
5464 if(GET_FLAGS(dcb_params->flags, DCB_PARAMS_ETS_ENABLED))
5465 {
5466 lm_status =
5467 lm_dcbx_ie_params_updated_validate_ets(pdev,
5468 &dcb_params->ets_params);
5469
5470 if(LM_STATUS_SUCCESS != lm_status)
5471 {
5472 return lm_status;
5473 }
5474 }
5475
5476 if(GET_FLAGS(dcb_params->flags, DCB_PARAMS_CLASSIF_ENABLED))
5477 {
5478 lm_status =
5479 lm_dcbx_ie_classif_entries_validate_and_set_enforced(pdev,
5480 &dcb_params->classif_params);
5481
5482 if(LM_STATUS_SUCCESS != lm_status)
5483 {
5484 return lm_status;
5485 }
5486 }
5487
5488 lm_status = lm_dcbx_ie_params_updated_copy_dcb_params(pdev,
5489 dcb_params,
5490 dcb_params_copy,
5491 indicate_event->lm_cli_idx);
5492 if(LM_STATUS_SUCCESS != lm_status)
5493 {
5494 return lm_status;
5495 }
5496
5497 return lm_status;
5498 }
5499 /**
5500 * @description
5501 * Update the local copy of the configuration parameters free
5502 * the old buffer of the classification.
5503 * @param pdev
5504 * @param dcb_params
5505 * @param lm_cli_idx
5506 *
5507 * @return u8_t
5508 */
5509 STATIC void
lm_dcbx_ie_update_local_params(INOUT struct _lm_device_t * pdev,INOUT dcb_indicate_event_params_t * dcb_params,OUT u8_t * is_local_ets_change,IN const u8_t lm_cli_idx,IN u8_t is_ets_admin_updated)5510 lm_dcbx_ie_update_local_params(
5511 INOUT struct _lm_device_t *pdev,
5512 INOUT dcb_indicate_event_params_t *dcb_params,
5513 OUT u8_t *is_local_ets_change,
5514 IN const u8_t lm_cli_idx,
5515 IN u8_t is_ets_admin_updated
5516 )
5517 {
5518 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
5519 dcb_ets_tsa_param_t ets_params_cmp = {0};
5520 // I do not want to look at changed in this
5521 const u32_t interesting_flags = DCB_PARAMS_WILLING | DCB_PARAMS_ETS_ENABLED |
5522 DCB_PARAMS_PFC_ENABLED | DCB_PARAMS_CLASSIF_ENABLED;
5523
5524 DbgBreakIf(lm_cli_idx != indicate_event->lm_cli_idx);
5525
5526 // Must be reset each OS configuration
5527 indicate_event->is_ets_ieee_params_os_valid = FALSE;
5528
5529 // Copy before overwriting
5530 mm_memcpy(&(ets_params_cmp),
5531 &(indicate_event->ets_ieee_params_os),
5532 sizeof(ets_params_cmp));
5533
5534
5535 if(GET_FLAGS(dcb_params->flags, DCB_PARAMS_ETS_ENABLED))
5536 {
5537 DbgBreakIf(FALSE == is_ets_admin_updated);
5538
5539 mm_memcpy(&(indicate_event->ets_ieee_params_os),
5540 &(dcb_params->ets_params),
5541 sizeof(indicate_event->ets_ieee_params_os));
5542
5543 if(is_ets_admin_updated)
5544 {
5545 indicate_event->is_ets_ieee_params_os_valid = TRUE;
5546 }
5547 }
5548 else
5549 {
5550 mm_mem_zero(&(indicate_event->ets_ieee_params_os),
5551 sizeof(indicate_event->ets_ieee_params_os));
5552 }
5553
5554 if(FALSE == mm_memcmp(&(indicate_event->ets_ieee_params_os),
5555 &(ets_params_cmp),
5556 sizeof(ets_params_cmp)))
5557 {
5558 *is_local_ets_change = TRUE;
5559 }
5560
5561
5562 //A final OID_QOS_PARAMETERS with *only* the NDIS_QOS_PARAMETERS_WILLING flag set is sent to an NDIS QOS capable miniport when:
5563 // 1. DCB feature is uninstalled or the msdcb.sys driver is being stopped by the admin.
5564 // 2. The miniport is being unbound by NDIS for whatever reason.
5565 if(DCB_PARAMS_WILLING == GET_FLAGS(dcb_params->flags, interesting_flags))
5566 {
5567 indicate_event->ets_config_state = lm_dcbx_ets_config_state_cee;
5568 }
5569 else
5570 {
5571 indicate_event->ets_config_state = lm_dcbx_ets_config_state_ieee;
5572 }
5573 }
5574 /**
5575 * For debugging purpose only.
5576 * @param pdev
5577 * @param dcb_params
5578 * @param is_local_ets_change
5579 * @param lm_cli_idx
5580 *
5581 * @return STATIC void
5582 */
5583 STATIC void
lm_dcbx_ie_dbg_copy_dcb_params(INOUT struct _lm_device_t * pdev,INOUT dcb_indicate_event_params_t * dcb_params,IN const u8_t lm_cli_idx)5584 lm_dcbx_ie_dbg_copy_dcb_params(
5585 INOUT struct _lm_device_t *pdev,
5586 INOUT dcb_indicate_event_params_t *dcb_params,
5587 IN const u8_t lm_cli_idx)
5588 {
5589 dcb_indicate_event_params_t *dcb_params_dbg = &pdev->dcbx_info.indicate_event.dcb_params_given_dbg;
5590 const u32_t table_alloc_size_dbg =
5591 min(LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_DBG,
5592 LM_DCBX_IE_CLASSIF_ENTRIES_TO_ALOC_SIZE(dcb_params->classif_params.num_classif_elements));
5593
5594 dcb_params_dbg->flags = dcb_params->flags;
5595
5596 mm_memcpy(&dcb_params_dbg->ets_params,
5597 &dcb_params->ets_params,
5598 sizeof(dcb_params_dbg->ets_params));
5599
5600 mm_memcpy(&dcb_params_dbg->pfc_params,
5601 &dcb_params->pfc_params,
5602 sizeof(dcb_params_dbg->pfc_params));
5603
5604 dcb_params_dbg->classif_params.classif_version =
5605 dcb_params->classif_params.classif_version;
5606
5607 // This can be equal or more than the classification
5608 // entries allocated by dbg and isn't used
5609 dcb_params_dbg->classif_params.num_classif_elements =
5610 dcb_params->classif_params.num_classif_elements;
5611
5612 mm_mem_zero(dcb_params_dbg->classif_params.classif_table,
5613 LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_DBG);
5614
5615 if(NULL != dcb_params_dbg->classif_params.classif_table)
5616 {
5617 mm_memcpy(dcb_params_dbg->classif_params.classif_table,
5618 dcb_params->classif_params.classif_table,
5619 table_alloc_size_dbg);
5620 }
5621 }
5622
5623 /**
5624 * @description
5625 * Creat the IEEE PFC settings from CEE PFC settings.
5626 * @param pdev
5627 * @param cee_pfc
5628 * @param ieee_pfc
5629 * @param flags
5630 *
5631 * @return STATIC void
5632 */
5633 STATIC void
lm_dcbx_ie_pfc_cee_to_ieee_imp(INOUT lm_device_t * pdev,OUT dcb_pfc_param_t * ieee_pfc,OUT u32_t * flags,IN const u8_t is_pfc_en,IN const u8_t pri_en_bitmap)5634 lm_dcbx_ie_pfc_cee_to_ieee_imp(
5635 INOUT lm_device_t *pdev,
5636 OUT dcb_pfc_param_t *ieee_pfc,
5637 OUT u32_t *flags,
5638 IN const u8_t is_pfc_en,
5639 IN const u8_t pri_en_bitmap
5640 )
5641 {
5642 SET_FLAGS(*flags, DCB_PARAMS_PFC_ENABLED);
5643
5644 if(0 == is_pfc_en)
5645 {
5646 return;
5647 }
5648
5649 ieee_pfc->pfc_enable = pri_en_bitmap;
5650 }
5651 /**
5652 * @description
5653 * Creat the IEEE PFC settings from CEE PFC settings.
5654 * @param pdev
5655 * @param cee_pfc
5656 * @param ieee_pfc
5657 * @param flags
5658 *
5659 * @return STATIC void
5660 */
5661 STATIC void
lm_dcbx_ie_pfc_cee_to_ieee(INOUT lm_device_t * pdev,IN const dcbx_pfc_feature_t * cee_pfc,OUT dcb_pfc_param_t * ieee_pfc,OUT u32_t * flags,IN const lm_event_code_t event)5662 lm_dcbx_ie_pfc_cee_to_ieee(
5663 INOUT lm_device_t *pdev,
5664 IN const dcbx_pfc_feature_t *cee_pfc,
5665 OUT dcb_pfc_param_t *ieee_pfc,
5666 OUT u32_t *flags,
5667 IN const lm_event_code_t event
5668 )
5669 {
5670 if( LM_EVENT_CODE_DCBX_OPERA_CHANGE == event)
5671 {
5672 lm_dcbx_ie_pfc_cee_to_ieee_imp(pdev,
5673 ieee_pfc,
5674 flags,
5675 (u8_t)pdev->params.dcbx_port_params.pfc.enabled,
5676 LM_DCBX_PFC_PRI_PAUSE_MASK(pdev));
5677 }
5678 else
5679 {
5680 DbgBreakIf( LM_EVENT_CODE_DCBX_REMOTE_CHANGE != event);
5681
5682 lm_dcbx_ie_pfc_cee_to_ieee_imp(pdev,
5683 ieee_pfc,
5684 flags,
5685 cee_pfc->enabled,
5686 cee_pfc->pri_en_bitmap);
5687 }
5688 }
5689 /**
5690 * @description
5691 * Straight forward parsing.
5692 * The data given from the remote doesn't promise continues
5693 * entries and that for TC_x x is smaller than max TC
5694 * given.
5695 * Strict entry will always be the first TC_0.
5696 * Find an empty cell for strict and count the number of TC
5697 * entries used.
5698 * @param pdev
5699 * @param cee_ets
5700 * @param ieee_ets
5701 * @param flags
5702 * @param event
5703 *
5704 * @return STATIC void
5705 */
5706 STATIC void
lm_dcbx_ie_ets_cee_to_ieee_unparse(INOUT lm_device_t * pdev,IN const dcbx_ets_feature_t * cee_ets,OUT dcb_ets_tsa_param_t * ieee_ets,OUT u32_t * flags)5707 lm_dcbx_ie_ets_cee_to_ieee_unparse(
5708 INOUT lm_device_t *pdev,
5709 IN const dcbx_ets_feature_t *cee_ets,
5710 OUT dcb_ets_tsa_param_t *ieee_ets,
5711 OUT u32_t *flags
5712 )
5713 {
5714 u8_t pri = 0;
5715 u8_t b_found_strict = FALSE;
5716 u8_t tc_entry = 0;
5717 u8_t tc_entry_bitmap = 0;
5718 u8_t tc_used_bitmap_bw = 0;
5719 u8_t num_of_tc_used = 0;
5720 u8_t strict_tc = 0;
5721
5722 ASSERT_STATIC(DCBX_MAX_NUM_PRI_PG_ENTRIES == DCBX_MAX_NUM_PG_BW_ENTRIES);
5723 ASSERT_STATIC(DCBX_MAX_NUM_PRI_PG_ENTRIES == ARRSIZE(ieee_ets->priority_assignment_table));
5724 ASSERT_STATIC(DCBX_MAX_NUM_PG_BW_ENTRIES == ARRSIZE(ieee_ets->tc_bw_assignment_table));
5725 ASSERT_STATIC(DCBX_MAX_NUM_PG_BW_ENTRIES == ARRSIZE(ieee_ets->tsa_assignment_table));
5726
5727 mm_mem_zero(ieee_ets, sizeof(dcb_ets_tsa_param_t));
5728 RESET_FLAGS(*flags, DCB_PARAMS_ETS_ENABLED);
5729
5730 if(FALSE == cee_ets->enabled)
5731 {
5732 return;
5733 }
5734
5735 /************ Find an empty cell for strict and count the number of TC entries used*******/
5736
5737 // Map all BW TC to a bitfield and find if there is a strict TC
5738 for (pri = 0; pri < DCBX_MAX_NUM_PRI_PG_ENTRIES; pri++)
5739 {
5740 tc_entry = DCBX_PRI_PG_GET(cee_ets->pri_pg_tbl, pri);
5741
5742 if(tc_entry < DCBX_MAX_NUM_PG_BW_ENTRIES)
5743 {
5744 // BW
5745 tc_entry_bitmap = (1 << tc_entry);
5746 // Count the number of TC entries given and fill the appropriate COS entry
5747 if (0 == (tc_used_bitmap_bw & tc_entry_bitmap))
5748 {
5749 // New TC add it to the bitmask
5750 tc_used_bitmap_bw |= tc_entry_bitmap;
5751 num_of_tc_used++;
5752 }
5753 }
5754 else if(DCBX_STRICT_PRI_PG == tc_entry)
5755 {
5756 // Strict
5757 b_found_strict = TRUE;
5758 }
5759 else
5760 {
5761 DbgBreakMsg("lm_dcbx_runtime_params_updated_validate_ets a tc_entry can't be larger"
5762 "than the number of TC supported");
5763 return;
5764 }
5765 }
5766
5767 // Find an empty cell for strict
5768 if(TRUE == b_found_strict)
5769 {
5770 if((DCBX_MAX_NUM_PRI_PG_ENTRIES) != num_of_tc_used )
5771 {
5772 // Find a free TC for strict priority
5773 for (tc_entry = 0; tc_entry < DCBX_MAX_NUM_PRI_PG_ENTRIES; tc_entry++)
5774 {
5775 tc_entry_bitmap = (1 << tc_entry);
5776
5777 // Found an unused cell that will be used for strict
5778 if( 0 == (tc_used_bitmap_bw & tc_entry_bitmap))
5779 {
5780 num_of_tc_used++;
5781 strict_tc = tc_entry;
5782 break;
5783 }
5784 }
5785 }
5786 else
5787 {
5788 DbgBreakMsg("lm_dcbx_ie_ets_cee_to_ieee_unparse: this is a bug we cant have 9 TC");
5789 // In case we have 8 used TC and strict The last TC will be shared
5790 // between BW and streict.
5791 strict_tc = DCBX_MAX_NUM_PRI_PG_ENTRIES -1;
5792 }
5793 }
5794
5795 for (pri = 0; pri < DCBX_MAX_NUM_PRI_PG_ENTRIES; pri++)
5796 {
5797 tc_entry = DCBX_PRI_PG_GET(cee_ets->pri_pg_tbl, pri);
5798
5799 if(tc_entry < DCBX_MAX_NUM_PG_BW_ENTRIES)
5800 {
5801 // BW
5802 ieee_ets->priority_assignment_table[pri] = tc_entry;
5803 ieee_ets->tsa_assignment_table[tc_entry] = TSA_ASSIGNMENT_DCB_TSA_ETS;
5804 ieee_ets->tc_bw_assignment_table[tc_entry] = DCBX_PG_BW_GET(cee_ets->pg_bw_tbl,tc_entry);
5805 }
5806 else if(DCBX_STRICT_PRI_PG == tc_entry)
5807 {
5808 // Strict
5809 ieee_ets->priority_assignment_table[pri] = strict_tc;
5810 ieee_ets->tsa_assignment_table[strict_tc] = TSA_ASSIGNMENT_DCB_TSA_STRICT;
5811 ieee_ets->tc_bw_assignment_table[strict_tc] = 0;
5812 }
5813 else
5814 {
5815 DbgBreakMsg("lm_dcbx_runtime_params_updated_validate_ets a tc_entry can't be larger"
5816 "than the number of TC supported");
5817 return;
5818 }
5819 }
5820
5821 ieee_ets->num_traffic_classes = num_of_tc_used;
5822
5823 SET_FLAGS(*flags, DCB_PARAMS_ETS_ENABLED);
5824 }
5825 /**
5826 * @description
5827 * The ETS data is already parse and configured to chip. The use
5828 * of the parse struct is a must because there is an algorithm
5829 * that decide how to configure the chip, and the parsing isn't
5830 * straight forward.
5831 * @param pdev
5832 * @param cee_ets
5833 * @param ieee_ets
5834 * @param flags
5835 * @param event
5836 *
5837 * @return STATIC void
5838 */
5839 STATIC void
lm_dcbx_ie_ets_cee_to_ieee_parsed_data(INOUT lm_device_t * pdev,OUT dcb_ets_tsa_param_t * ieee_ets,OUT u32_t * flags)5840 lm_dcbx_ie_ets_cee_to_ieee_parsed_data(
5841 INOUT lm_device_t *pdev,
5842 OUT dcb_ets_tsa_param_t *ieee_ets,
5843 OUT u32_t *flags
5844 )
5845 {
5846 u8_t i = 0;
5847 u8_t tc_assign = 0;
5848 const u8_t max_tc_sup = lm_dcbx_cos_max_num(pdev) ;
5849 pg_params_t *ets = &(pdev->params.dcbx_port_params.ets);
5850 u16_t pri_bit = 0;
5851
5852 ASSERT_STATIC(DCBX_MAX_NUM_PRI_PG_ENTRIES == DCBX_MAX_NUM_PG_BW_ENTRIES);
5853 ASSERT_STATIC(DCBX_MAX_NUM_PRI_PG_ENTRIES == ARRSIZE(ieee_ets->priority_assignment_table));
5854 ASSERT_STATIC(DCBX_MAX_NUM_PG_BW_ENTRIES == ARRSIZE(ieee_ets->tc_bw_assignment_table));
5855 ASSERT_STATIC(DCBX_MAX_NUM_PG_BW_ENTRIES == ARRSIZE(ieee_ets->tsa_assignment_table));
5856
5857 SET_FLAGS(*flags, DCB_PARAMS_ETS_ENABLED);
5858
5859 if((FALSE == ets->enabled) ||
5860 (max_tc_sup < ets->num_of_cos))
5861 {
5862 DbgBreakIf(max_tc_sup < ets->num_of_cos);
5863 return;
5864 }
5865
5866 ieee_ets->num_traffic_classes = ets->num_of_cos;
5867
5868 for(i = 0; i < ARRSIZE(ieee_ets->priority_assignment_table) ; i++)
5869 {
5870 pri_bit = 1 << i;
5871 for(tc_assign = 0 ; tc_assign < ets->num_of_cos; tc_assign++)
5872 {
5873 if(0 != (pri_bit & ets->cos_params[tc_assign].pri_bitmask))
5874 {
5875 break;
5876 }
5877 }
5878
5879 // If the priority doesn't belong to non of the cos_params then
5880 // assign this priority to zero.
5881 if(ets->num_of_cos == tc_assign)
5882 {
5883 tc_assign = 0;
5884 }
5885
5886 ieee_ets->priority_assignment_table[i] = tc_assign;
5887 }
5888
5889 for(tc_assign = 0 ; tc_assign < ets->num_of_cos; tc_assign++)
5890 {
5891 if(DCBX_S_PRI_INVALID != ets->cos_params[tc_assign].s_pri)
5892 {// COS is SP
5893 // Strict
5894 DbgBreakIf(DCBX_INVALID_COS_BW != ets->cos_params[tc_assign].bw_tbl);
5895
5896 ieee_ets->tsa_assignment_table[tc_assign] = TSA_ASSIGNMENT_DCB_TSA_STRICT;
5897 ieee_ets->tc_bw_assignment_table[tc_assign] = 0;
5898 }
5899 else
5900 {// COS is BW
5901 DbgBreakIf(DCBX_INVALID_COS_BW == ets->cos_params[tc_assign].bw_tbl);
5902
5903 ieee_ets->tsa_assignment_table[tc_assign] = TSA_ASSIGNMENT_DCB_TSA_ETS;
5904 ieee_ets->tc_bw_assignment_table[tc_assign] = (u8_t)ets->cos_params[tc_assign].bw_tbl;
5905 }
5906 }
5907 }
5908 /**
5909 * @description
5910 * Creat the IEEE ETS settings from CEE ETS settings.
5911 * @param pdev
5912 * @param cee_ets
5913 * @param ieee_ets
5914 * @param flags
5915 *
5916 * @return STATIC void
5917 */
5918 STATIC void
lm_dcbx_ie_ets_cee_to_ieee(INOUT lm_device_t * pdev,IN const dcbx_ets_feature_t * cee_ets,OUT dcb_ets_tsa_param_t * ieee_ets,OUT u32_t * flags,IN const lm_event_code_t event)5919 lm_dcbx_ie_ets_cee_to_ieee(
5920 INOUT lm_device_t *pdev,
5921 IN const dcbx_ets_feature_t *cee_ets,
5922 OUT dcb_ets_tsa_param_t *ieee_ets,
5923 OUT u32_t *flags,
5924 IN const lm_event_code_t event
5925 )
5926 {
5927 if( LM_EVENT_CODE_DCBX_OPERA_CHANGE == event)
5928 {
5929 lm_dcbx_ie_ets_cee_to_ieee_parsed_data(pdev, ieee_ets, flags);
5930 }
5931 else
5932 {
5933 DbgBreakIf( LM_EVENT_CODE_DCBX_REMOTE_CHANGE != event);
5934 lm_dcbx_ie_ets_cee_to_ieee_unparse(pdev,
5935 cee_ets,
5936 ieee_ets,
5937 flags);
5938 }
5939 }
5940 /**
5941 * Update the classification entry with the data given.
5942 *
5943 * @param pdev
5944 * @param classif_entry
5945 * @param condition_selector
5946 * @param condition_field
5947 * @param pri
5948 *
5949 * @return STATIC void
5950 */
5951 STATIC void
lm_dcbx_ie_classif_set_entry(IN lm_device_t * pdev,IN dcb_classif_elem_t * classif_entry,IN dcb_condition_selector_t condition_selector,IN u16_t condition_field,IN u16_t pri)5952 lm_dcbx_ie_classif_set_entry(
5953 IN lm_device_t *pdev,
5954 IN dcb_classif_elem_t *classif_entry,
5955 IN dcb_condition_selector_t condition_selector,
5956 IN u16_t condition_field,
5957 IN u16_t pri)
5958 {
5959 classif_entry->flags = 0;
5960 classif_entry->condition_selector = condition_selector;
5961 classif_entry->condition_field = condition_field;
5962 classif_entry->action_selector = DCB_ACTION_PRIORITY;
5963 classif_entry->action_field = pri;
5964 }
5965 /**
5966 * This default entry must be the first one.
5967 * @param pdev
5968 * @param cee_classif
5969 * @param classif_entry
5970 *
5971 * @return STATIC u8_t return the number of entries used by the
5972 * function.
5973 */
5974 STATIC void
lm_dcbx_ie_classif_add_default(INOUT lm_device_t * pdev,IN const dcbx_app_priority_feature_t * cee_classif,IN dcb_classif_elem_t * classif_entry)5975 lm_dcbx_ie_classif_add_default(
5976 INOUT lm_device_t *pdev,
5977 IN const dcbx_app_priority_feature_t *cee_classif,
5978 IN dcb_classif_elem_t *classif_entry)
5979 {
5980 u16_t const default_pri = (cee_classif->default_pri < MAX_PFC_PRIORITIES)? cee_classif->default_pri: 0;
5981
5982 lm_dcbx_ie_classif_set_entry( pdev,
5983 classif_entry,
5984 DCB_CONDITION_DEFAULT,
5985 0,
5986 default_pri);
5987 }
5988 /**
5989 * Parse the CEE entries to indicate event classification
5990 * entries.
5991 * @param pdev
5992 * @param cee_app_pri_tbl
5993 * @param cee_app_pri_tbl_size
5994 * @param classif_table
5995 * @param is_iscsi_cee_rec - There is an ISCSI CEE entry.
5996 * @param event
5997 *
5998 * @return STATIC u8_t return the number of entries used by the
5999 * function.
6000 */
6001 STATIC u8_t
lm_dcbx_ie_classif_parse_cee_arrray(INOUT lm_device_t * pdev,IN const dcbx_app_priority_entry_t * cee_app_pri_tbl,IN const u8_t cee_app_pri_tbl_size,INOUT dcb_classif_elem_t * classif_table,OUT u8_t * is_iscsi_cee_rec)6002 lm_dcbx_ie_classif_parse_cee_arrray(
6003 INOUT lm_device_t *pdev,
6004 IN const dcbx_app_priority_entry_t *cee_app_pri_tbl,
6005 IN const u8_t cee_app_pri_tbl_size,
6006 INOUT dcb_classif_elem_t *classif_table,
6007 OUT u8_t *is_iscsi_cee_rec
6008 )
6009 {
6010 u8_t cee_index = 0;
6011 u32_t pri = 0;
6012 dcb_condition_selector_t condition_selector = 0;
6013 u8_t num_entry_used = 0;
6014 u8_t dummy_flag = FALSE;
6015
6016 if(CHK_NULL(cee_app_pri_tbl))
6017 {
6018 return 0;
6019 }
6020
6021 for( cee_index = 0;
6022 (cee_index < cee_app_pri_tbl_size);
6023 cee_index++)
6024 {
6025 pri = MAX_PFC_PRIORITIES;
6026
6027 if(0 == GET_FLAGS(cee_app_pri_tbl[cee_index].appBitfield, DCBX_APP_ENTRY_VALID))
6028 {
6029 continue;
6030 }
6031
6032 /********************************************************************/
6033 /******** start parse entry to from CEE format to IEEE format********/
6034 if(GET_FLAGS(cee_app_pri_tbl[cee_index].appBitfield, DCBX_APP_SF_ETH_TYPE))
6035 {
6036 condition_selector = DCB_CONDITION_ETHERTYPE;
6037 }
6038 else if(GET_FLAGS(cee_app_pri_tbl[cee_index].appBitfield, DCBX_APP_SF_PORT))
6039 {
6040 condition_selector = DCB_CONDITION_TCP_OR_UDP_PORT;
6041 }
6042 else
6043 {
6044 DbgBreakMsg("lm_dcbx_classif_cee_to_ieee invalid appBitfield ");
6045 continue;
6046 }
6047
6048 lm_dcbx_get_ap_priority(pdev, &pri, cee_app_pri_tbl[cee_index].pri_bitmap, &dummy_flag);
6049
6050 if(MAX_PFC_PRIORITIES == pri)
6051 {
6052 if(0 == cee_app_pri_tbl[cee_index].pri_bitmap)
6053 {
6054 // This is a patch:
6055 // We don't assert as a request from DVT:(CQ64888 and CQ59423).
6056 // A quote from Darshan (DVT) mail "Brocade expects (just like Navasota) that PFC
6057 // be enabled on the iSCSI traffic class (which, I agree, is inappropriate). If the PFC is not set on the iSCSI
6058 // traffic class then it sends the iSCSI App TLV with PRI bit map of zero irrespective of whatever PRI you have
6059 // configured for iSCSI. Once PFC is enabled, it sends the correct App TLV bit map."
6060 #if defined(DBG)
6061 DbgMessage(pdev, FATAL, "lm_dcbx_ie_classif_parse_cee_arrray invalid pri for valid entry ");
6062 #else
6063 DbgBreakMsg("lm_dcbx_ie_classif_parse_cee_arrray invalid pri for valid entry ");
6064 #endif
6065 }
6066 else
6067 {
6068 DbgBreakMsg("lm_dcbx_ie_classif_parse_cee_arrray invalid pri for valid entry ");
6069 }
6070 continue;
6071 }
6072
6073 lm_dcbx_ie_classif_set_entry( pdev,
6074 &(classif_table[num_entry_used]),
6075 condition_selector,
6076 cee_app_pri_tbl[cee_index].app_id,
6077 (u16_t)pri);
6078
6079 num_entry_used++;
6080
6081 // ISCSI is a special case until we will implement IEEE we can send DCB_CONDITION_TCP_PORT.
6082 if((DCB_CONDITION_TCP_OR_UDP_PORT == condition_selector) &&
6083 (TCP_PORT_ISCSI == cee_app_pri_tbl[cee_index].app_id))
6084 {
6085 (*is_iscsi_cee_rec) = TRUE;
6086 }
6087 }
6088
6089 return num_entry_used;
6090 }
6091 /**
6092 * This function is only for verifying that the classification
6093 * Parameters sent to OS are coherent with local classification
6094 * parameters and that the parameters are generally coherent
6095 *
6096 * @param pdev
6097 * @param ieee_classif
6098 * @param event
6099 *
6100 * @return STATIC void
6101 */
6102 STATIC void
lm_dcbx_ie_classif_cee_to_ieee_check_param_dbg(IN const lm_device_t * pdev,IN const dcb_classif_params_t * ieee_classif,IN const lm_event_code_t event)6103 lm_dcbx_ie_classif_cee_to_ieee_check_param_dbg(
6104 IN const lm_device_t *pdev,
6105 IN const dcb_classif_params_t *ieee_classif,
6106 IN const lm_event_code_t event
6107 )
6108 {
6109 dcb_classif_elem_t *p_classif_elem = ieee_classif->classif_table;
6110 u8_t i = 0;
6111 lm_dcbx_ie_classif_dbg_t classif_dbg[MAX_TRAFFIC_TYPE] = {{0}};
6112
6113 for(i = 0; i < ieee_classif->num_classif_elements; i++)
6114 {
6115 if(DCB_ACTION_PRIORITY != p_classif_elem[i].action_selector)
6116 {
6117 // VBD only supports condition_selector that is based on priority
6118 continue;
6119 }
6120
6121 switch(p_classif_elem[i].condition_selector)
6122 {
6123 case DCB_CONDITION_DEFAULT:
6124 // Must be the first entry
6125 DbgBreakIf(0 != i);
6126 break;
6127
6128 case DCB_CONDITION_TCP_PORT:
6129 case DCB_CONDITION_TCP_OR_UDP_PORT://Fall through
6130 if(TCP_PORT_ISCSI == p_classif_elem[i].condition_field)
6131 {
6132 classif_dbg[LLFC_TRAFFIC_TYPE_ISCSI].pri = p_classif_elem[i].action_field;
6133 classif_dbg[LLFC_TRAFFIC_TYPE_ISCSI].num_entries++;
6134 }
6135 break;
6136
6137 case DCB_CONDITION_ETHERTYPE:
6138 if(ETH_TYPE_FCOE == p_classif_elem[i].condition_field)
6139 {
6140 classif_dbg[LLFC_TRAFFIC_TYPE_FCOE].pri = p_classif_elem[i].action_field;
6141 classif_dbg[LLFC_TRAFFIC_TYPE_FCOE].num_entries++;
6142 }
6143 break;
6144
6145 case DCB_CONDITION_RESERVED:
6146 case DCB_CONDITION_UDP_PORT://Fall through
6147 case DCB_CONDITION_NETDIRECT_PORT://Fall through
6148 //Not supported by VBD
6149 break;
6150 case DCB_CONDITION_MAX:
6151 default:
6152 DbgBreakMsg("lm_dcbx_runtime_params_updated_en_classif_entries: illegal entry ");
6153 break;
6154 }
6155 }
6156
6157 // traffic_type_priority and classification DCBX_OPERA parameters are derived both from local MIB
6158 if( LM_EVENT_CODE_DCBX_OPERA_CHANGE == event)
6159 {
6160 for(i = 0; i < MAX_TRAFFIC_TYPE; i++)
6161 {
6162 //num_entries is more interesting if num_entries =< 1 ,otherwise this is a unusually configuration.
6163 if(1 == classif_dbg[i].num_entries)
6164 {
6165 DbgBreakIf(classif_dbg[i].pri !=
6166 pdev->params.dcbx_port_params.app.traffic_type_priority[i]);
6167 }
6168 }
6169 }
6170
6171 }
6172 /**
6173 * @description
6174 * Creat the IEEE settings from CEE settings.
6175 * If there is a given_tabel copy it to the beggining of the
6176 * ieee_classif.
6177 * After search the CEE (local /remote) entries (read from
6178 * chip)an add any valid CEE entry because it has a higher
6179 * priority than given_tabel.
6180 * @param pdev
6181 * @param cee_classif
6182 * @param ieee_classif
6183 * @param ieee_classif_alloc_size
6184 * @param given_tabel
6185 * @param given_tabel_alloc_size
6186 * @param flags
6187 *
6188 * @return STATIC void
6189 */
6190 STATIC lm_status_t
lm_dcbx_ie_classif_cee_to_ieee(INOUT lm_device_t * pdev,IN const dcbx_app_priority_feature_t * cee_classif,IN const dcbx_app_priority_entry_t * cee_app_tbl_ext,IN const u8_t cee_app_tbl_ext_size,OUT dcb_classif_params_t * ieee_classif,IN const u32_t ieee_classif_alloc_size,OUT u32_t * flags,IN const lm_event_code_t event)6191 lm_dcbx_ie_classif_cee_to_ieee(
6192 INOUT lm_device_t *pdev,
6193 IN const dcbx_app_priority_feature_t *cee_classif,
6194 IN const dcbx_app_priority_entry_t *cee_app_tbl_ext,
6195 IN const u8_t cee_app_tbl_ext_size,
6196 OUT dcb_classif_params_t *ieee_classif,
6197 IN const u32_t ieee_classif_alloc_size,
6198 OUT u32_t *flags,
6199 IN const lm_event_code_t event
6200 )
6201 {
6202 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
6203 dcb_classif_elem_t *classif_table = ieee_classif->classif_table;
6204 lm_status_t lm_status = LM_STATUS_SUCCESS;
6205 u16_t num_entry_used = 0;
6206 u8_t is_iscsi_cee_rec = FALSE;
6207
6208 DbgBreakIf(0 != (ieee_classif_alloc_size % sizeof(dcb_classif_elem_t)));
6209
6210 // Check enablement of classification
6211 if( LM_EVENT_CODE_DCBX_OPERA_CHANGE == event)
6212 {
6213 if(0 == pdev->params.dcbx_port_params.app.enabled)
6214 {
6215 return LM_STATUS_SUCCESS;
6216 }
6217 // Default must be the first entry.
6218 lm_dcbx_ie_classif_add_default(pdev,
6219 cee_classif,
6220 classif_table);
6221 num_entry_used++;
6222 }
6223 else
6224 {
6225 DbgBreakIf( LM_EVENT_CODE_DCBX_REMOTE_CHANGE != event);
6226 if(0 == cee_classif->enabled)
6227 {
6228 return LM_STATUS_SUCCESS;
6229 }
6230 }
6231
6232 SET_FLAGS(*flags, DCB_PARAMS_CLASSIF_ENABLED);
6233
6234 num_entry_used += lm_dcbx_ie_classif_parse_cee_arrray(
6235 pdev,
6236 cee_classif->app_pri_tbl,
6237 ARRSIZE(cee_classif->app_pri_tbl),
6238 &(classif_table[num_entry_used]),
6239 &is_iscsi_cee_rec);
6240
6241 num_entry_used += lm_dcbx_ie_classif_parse_cee_arrray(
6242 pdev,
6243 cee_app_tbl_ext,
6244 cee_app_tbl_ext_size,
6245 &(classif_table[num_entry_used]),
6246 &is_iscsi_cee_rec);
6247
6248 // If the operational configuration from MCP contains an entry with 'TCP or UDP port' = 3260 use that entry,
6249 // Else if OS configuration contained an entry with 'TCP port' = 3260 use that entry,
6250 // Else use the default configuration.
6251 if(( LM_EVENT_CODE_DCBX_OPERA_CHANGE == event) &&
6252 ( FALSE == is_iscsi_cee_rec) &&
6253 ( LM_DCBX_ILLEGAL_PRI != indicate_event->iscsi_tcp_pri))
6254 {
6255 DbgBreakIf(pdev->params.dcbx_port_params.app.traffic_type_priority[LLFC_TRAFFIC_TYPE_ISCSI] !=
6256 indicate_event->iscsi_tcp_pri);
6257
6258 lm_dcbx_ie_classif_set_entry( pdev,
6259 &(classif_table[num_entry_used]),
6260 DCB_CONDITION_TCP_PORT,
6261 TCP_PORT_ISCSI,
6262 indicate_event->iscsi_tcp_pri);
6263 num_entry_used++;
6264 }
6265
6266 ieee_classif->num_classif_elements = num_entry_used;
6267
6268 lm_dcbx_ie_classif_cee_to_ieee_check_param_dbg(pdev,
6269 ieee_classif,
6270 event);
6271
6272 return lm_status;
6273 }
6274 /**
6275 * Check if there is a classification parameter update
6276 * @param pdev
6277 * @param params_prev
6278 * @param params_newest
6279 *
6280 * @return STATIC u8_t
6281 */
6282 STATIC u8_t
lm_dcbx_ie_classif_check_if_params_changed(IN const dcb_classif_params_t * params_prev,IN const dcb_classif_params_t * params_newest)6283 lm_dcbx_ie_classif_check_if_params_changed(
6284 IN const dcb_classif_params_t *params_prev,
6285 IN const dcb_classif_params_t *params_newest)
6286 {
6287 dcb_classif_elem_t *p_classif_prev = params_prev->classif_table;
6288 dcb_classif_elem_t *p_classif_newest = params_newest->classif_table;
6289 u16_t index_prev = 0;
6290 u16_t index_newest = 0;
6291 u8_t is_entry_found = 0;
6292
6293 if(params_prev->num_classif_elements != params_newest->num_classif_elements)
6294 {
6295 return TRUE;
6296 }
6297
6298 for(index_prev = 0 ; index_prev < params_prev->num_classif_elements ; index_prev++)
6299 {
6300 is_entry_found = FALSE;
6301 for(index_newest = 0 ; index_newest < params_prev->num_classif_elements ; index_newest++)
6302 {
6303 if(mm_memcmp(&(p_classif_prev[index_prev]),
6304 &(p_classif_newest[index_newest]),
6305 sizeof(p_classif_prev[index_prev])))
6306 {
6307 is_entry_found = TRUE;
6308 break;
6309 }
6310 }
6311
6312 if(FALSE == is_entry_found)
6313 {
6314 return TRUE;
6315 }
6316 }
6317
6318 return FALSE;
6319 }
6320 /**
6321 * @description
6322 * Creat the indicate event struct based on data read from chip.
6323 * If the data has change call upper layer indicate event.
6324 * @param pdev
6325 * @param indicate_params
6326 * @param dcbx_features
6327 * @param event
6328 * @param ieee_classif_alloc_size
6329 * @param given_tabel
6330 * @param given_tabel_alloc_size
6331 * @param ets_given
6332 * @param is_ets_change
6333 * @param is_classif_change
6334 *
6335 * @return STATIC lm_status_t
6336 */
6337 STATIC lm_status_t
lm_dcbx_ie_check_if_param_change_common(INOUT lm_device_t * pdev,INOUT dcb_indicate_event_params_t * indicate_params,IN dcbx_features_t * dcbx_features,IN const dcbx_app_priority_entry_t * cee_app_tbl_ext,IN const u8_t cee_app_tbl_ext_size,IN const lm_event_code_t event,IN const u32_t ieee_classif_alloc_size,IN const lm_dcbx_ie_ets_ieee_config_state ets_ieee_config_state,IN const dcb_ets_tsa_param_t * ets_ieee_config,IN const u8_t is_ets_change)6338 lm_dcbx_ie_check_if_param_change_common(
6339 INOUT lm_device_t *pdev,
6340 INOUT dcb_indicate_event_params_t *indicate_params,
6341 IN dcbx_features_t *dcbx_features,
6342 IN const dcbx_app_priority_entry_t *cee_app_tbl_ext,
6343 IN const u8_t cee_app_tbl_ext_size,
6344 IN const lm_event_code_t event,
6345 IN const u32_t ieee_classif_alloc_size,
6346 IN const lm_dcbx_ie_ets_ieee_config_state ets_ieee_config_state,
6347 IN const dcb_ets_tsa_param_t *ets_ieee_config,
6348 IN const u8_t is_ets_change)
6349 {
6350 dcb_indicate_event_params_t indicate_newest_params = {0};
6351 lm_status_t lm_status = LM_STATUS_SUCCESS;
6352 u8_t is_changed = 0;
6353
6354 // Allocate local buffer that is enough for all entries given and read from chip
6355 indicate_newest_params.classif_params.classif_table =
6356 mm_rt_alloc_mem(pdev, ieee_classif_alloc_size, pdev->dcbx_info.indicate_event.lm_cli_idx);
6357
6358 if(CHK_NULL(indicate_newest_params.classif_params.classif_table))
6359 {
6360 return LM_STATUS_RESOURCE;
6361 }
6362 mm_mem_zero(indicate_newest_params.classif_params.classif_table, ieee_classif_alloc_size);
6363
6364 lm_dcbx_ie_pfc_cee_to_ieee(pdev,
6365 &dcbx_features->pfc,
6366 &indicate_newest_params.pfc_params,
6367 &indicate_newest_params.flags,
6368 event
6369 );
6370
6371 if(FALSE == mm_memcmp(&indicate_params->pfc_params,
6372 &indicate_newest_params.pfc_params ,
6373 sizeof(dcb_pfc_param_t)))
6374 {
6375 is_changed = TRUE;
6376 SET_FLAGS(indicate_newest_params.flags, DCB_PARAMS_PFC_CHANGED);
6377 }
6378
6379 if(lm_dcbx_ets_ieee_config_not_valid == ets_ieee_config_state)
6380 {
6381 lm_dcbx_ie_ets_cee_to_ieee(pdev,
6382 &dcbx_features->ets,
6383 &indicate_newest_params.ets_params,
6384 &indicate_newest_params.flags,
6385 event
6386 );
6387 }
6388 else
6389 {
6390 if(lm_dcbx_ets_ieee_config_en == ets_ieee_config_state)
6391 {
6392 SET_FLAGS(indicate_newest_params.flags, DCB_PARAMS_ETS_ENABLED);
6393 // copy the ets_params that were before (ETS params given from upper module)
6394 mm_memcpy(&indicate_newest_params.ets_params,
6395 ets_ieee_config,
6396 sizeof(dcb_ets_tsa_param_t));
6397 }
6398 else
6399 {
6400 DbgBreakIf(lm_dcbx_ets_ieee_config_di != ets_ieee_config_state);
6401
6402 RESET_FLAGS(indicate_newest_params.flags, DCB_PARAMS_ETS_ENABLED);
6403 mm_mem_zero(&indicate_newest_params.ets_params,
6404 sizeof(dcb_ets_tsa_param_t));
6405 }
6406 }
6407
6408 if((FALSE == mm_memcmp(&indicate_params->ets_params,
6409 &indicate_newest_params.ets_params ,
6410 sizeof(dcb_ets_tsa_param_t))) ||
6411 (TRUE == is_ets_change))
6412 {
6413 is_changed = TRUE;
6414 if(GET_FLAGS(indicate_newest_params.flags, DCB_PARAMS_ETS_ENABLED))
6415 {
6416 SET_FLAGS(indicate_newest_params.flags, DCB_PARAMS_ETS_CHANGED);
6417 }
6418 }
6419
6420 lm_status = lm_dcbx_ie_classif_cee_to_ieee(pdev,
6421 &dcbx_features->app,
6422 cee_app_tbl_ext,
6423 cee_app_tbl_ext_size,
6424 &indicate_newest_params.classif_params,
6425 ieee_classif_alloc_size,
6426 &indicate_newest_params.flags,
6427 event
6428 );
6429
6430 DbgBreakIf(LM_STATUS_SUCCESS != lm_status);
6431
6432 if(TRUE == lm_dcbx_ie_classif_check_if_params_changed(
6433 &indicate_params->classif_params,
6434 &indicate_newest_params.classif_params))
6435 {
6436 is_changed = TRUE;
6437 SET_FLAGS(indicate_newest_params.flags, DCB_PARAMS_CLASSIF_CHANGED);
6438 }
6439
6440 if(TRUE == is_changed)
6441 {
6442
6443 mm_memcpy(&indicate_params->flags,
6444 &indicate_newest_params.flags,
6445 sizeof(indicate_newest_params.flags));
6446
6447 mm_memcpy(&indicate_params->pfc_params,
6448 &indicate_newest_params.pfc_params,
6449 sizeof(indicate_newest_params.pfc_params));
6450
6451 mm_memcpy(&indicate_params->ets_params,
6452 &indicate_newest_params.ets_params,
6453 sizeof(indicate_newest_params.ets_params));
6454
6455 /* Start Update indicate_params with newest temp buffer params */
6456 mm_memcpy(indicate_params->classif_params.classif_table,
6457 indicate_newest_params.classif_params.classif_table,
6458 ieee_classif_alloc_size);
6459
6460 indicate_params->classif_params.num_classif_elements = indicate_newest_params.classif_params.num_classif_elements;
6461
6462
6463 /* End: Update indicate_params with newest temp buffer params */
6464 #ifdef _VBD_CMD_
6465 MM_DCB_INDICATE_EVENT(pdev,event,(u8_t*)indicate_params, sizeof(dcb_indicate_event_params_t));
6466 #endif
6467 #ifdef _VBD_
6468 MM_DCB_INDICATE_EVENT(pdev,event,(u8_t*)indicate_params, sizeof(dcb_indicate_event_params_t));
6469 #endif
6470 }
6471 // Free the local allocated buffer
6472 mm_rt_free_mem(pdev,
6473 indicate_newest_params.classif_params.classif_table,
6474 ieee_classif_alloc_size,
6475 pdev->dcbx_info.indicate_event.lm_cli_idx);
6476 return lm_status;
6477 }
6478 /**
6479 * @description
6480 * Check if local parameter has change , if they have change
6481 * indicate event to upper layer.
6482 * @param pdev
6483 * @param p_local_mib
6484 * @param dcbx_neg_res_offset
6485 * @param is_ets_change
6486 * @param is_classif_change
6487 *
6488 * @return lm_status_t
6489 */
6490 lm_status_t
lm_dcbx_ie_check_if_param_change_local(INOUT lm_device_t * pdev,IN lldp_local_mib_t * p_in_local_mib,IN lldp_local_mib_ext_t * p_in_local_mib_ext,IN const u8_t is_ets_change)6491 lm_dcbx_ie_check_if_param_change_local(
6492 INOUT lm_device_t *pdev,
6493 IN lldp_local_mib_t *p_in_local_mib,
6494 IN lldp_local_mib_ext_t *p_in_local_mib_ext,
6495 IN const u8_t is_ets_change)
6496 {
6497 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
6498 lldp_local_mib_t local_mib = {0};
6499 lldp_local_mib_ext_t local_mib_ext = {0};
6500 lm_status_t lm_status = LM_STATUS_SUCCESS;
6501 lldp_local_mib_t *p_local_mib = p_in_local_mib;
6502 lldp_local_mib_ext_t *p_local_mib_ext = p_in_local_mib_ext;
6503
6504 if(NULL == p_local_mib)
6505 {
6506 // Local MIB was not received read local MIB
6507 lm_status = lm_dcbx_read_local_mib_fields(pdev,
6508 &local_mib,
6509 &local_mib_ext);
6510
6511 if(LM_STATUS_SUCCESS != lm_status)
6512 {
6513 return lm_status;
6514 }
6515
6516 p_local_mib = &local_mib;
6517 p_local_mib_ext = &local_mib_ext;
6518 }
6519
6520 if(CHK_NULL(p_local_mib) || CHK_NULL(p_local_mib_ext))
6521 {
6522 DbgBreakMsg("lm_get_dcbx_drv_param wrong in parameters ");
6523 return lm_status;
6524 }
6525
6526 lm_status = lm_dcbx_ie_check_if_param_change_common(
6527 pdev,
6528 &(indicate_event->local_params),
6529 &p_local_mib->features,
6530 p_local_mib_ext->app_pri_tbl_ext,
6531 ARRSIZE(p_local_mib_ext->app_pri_tbl_ext),
6532 LM_EVENT_CODE_DCBX_OPERA_CHANGE,
6533 LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_LOCAL,
6534 indicate_event->ets_ieee_config_state,
6535 &indicate_event->ets_ieee_params_config,
6536 is_ets_change);
6537
6538 DbgBreakIf(LM_STATUS_SUCCESS != lm_status);
6539
6540 return lm_status;
6541 }
6542 /**
6543 * @description
6544 * Check if Remote parameter has change , if they have change
6545 * indicate event to upper layer.
6546 * @param pdev
6547 * @param dcbx_neg_res_offset
6548 *
6549 * @return lm_status_t
6550 */
6551 lm_status_t
lm_dcbx_ie_check_if_param_change_remote(INOUT lm_device_t * pdev)6552 lm_dcbx_ie_check_if_param_change_remote(
6553 INOUT lm_device_t *pdev)
6554 {
6555 lldp_remote_mib_t remote_mib = {0};
6556 lm_status_t lm_status = LM_STATUS_SUCCESS;
6557
6558 lm_status = lm_dcbx_read_remote_local_mib(pdev,
6559 (u32_t *)&remote_mib,
6560 DCBX_READ_REMOTE_MIB);
6561
6562 if(LM_STATUS_SUCCESS != lm_status)
6563 {
6564 return lm_status;
6565 }
6566
6567
6568 lm_status = lm_dcbx_ie_check_if_param_change_common(
6569 pdev,
6570 &(pdev->dcbx_info.indicate_event.remote_params),
6571 &remote_mib.features,
6572 NULL,
6573 0,
6574 LM_EVENT_CODE_DCBX_REMOTE_CHANGE,
6575 LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_REMOTE,
6576 lm_dcbx_ets_ieee_config_not_valid,
6577 NULL,
6578 FALSE);
6579
6580 DbgBreakIf(LM_STATUS_SUCCESS != lm_status);
6581
6582 return lm_status;
6583 }
6584 /**
6585 * @description
6586 * This function will check if local or remote parameters have
6587 * changed if the parameters have change the function will
6588 * update upper layer.
6589 * Local parameters can be given :
6590 * 1. If we read local parameters to configure the chip we
6591 * should use the same parameter to update upper layer (although
6592 * if there was a change an interrupt is expected) 2.If we are
6593 * from update parameters flow from upper layer ETS and clasif
6594 * settings are not update to chip so if they change we will
6595 * update function.
6596 * @param pdev
6597 * @param p_local_mib
6598 * @param is_ets_change
6599 * @param is_classif_change
6600 *
6601 * @return lm_status_t
6602 */
6603 lm_status_t
lm_dcbx_ie_check_if_param_change(INOUT lm_device_t * pdev,IN lldp_local_mib_t * p_local_mib,IN lldp_local_mib_ext_t * p_local_mib_ext,IN u8_t is_local_ets_change)6604 lm_dcbx_ie_check_if_param_change(
6605 INOUT lm_device_t *pdev,
6606 IN lldp_local_mib_t *p_local_mib,
6607 IN lldp_local_mib_ext_t *p_local_mib_ext,
6608 IN u8_t is_local_ets_change)
6609 {
6610 lm_status_t lm_status = LM_STATUS_SUCCESS;
6611 if(FALSE == pdev->dcbx_info.is_indicate_event_en)
6612 {
6613 DbgBreakMsg("lm_dcbx_runtime_params_updated_validate_pfc called but is_indicate_event_en is false");
6614 return LM_STATUS_FAILURE;
6615 }
6616
6617
6618 lm_status = lm_dcbx_ie_check_if_param_change_local(pdev,
6619 p_local_mib,
6620 p_local_mib_ext,
6621 is_local_ets_change);
6622
6623 DbgBreakIf(LM_STATUS_SUCCESS != lm_status);
6624
6625 lm_status = lm_dcbx_ie_check_if_param_change_remote(pdev);
6626
6627
6628 DbgBreakIf(LM_STATUS_SUCCESS != lm_status);
6629
6630 return lm_status;
6631 }
6632 /**
6633 *
6634 *
6635 * @author shayh (10/9/2011)
6636 *
6637 * @param pdev
6638 */
lm_dcbx_ie_update_bacs_state(INOUT lm_device_t * pdev,IN const u32_t flags)6639 void lm_dcbx_ie_update_bacs_state(
6640 INOUT lm_device_t *pdev,
6641 IN const u32_t flags
6642 )
6643 {
6644 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
6645
6646 SET_FLAGS(indicate_event->dcb_current_oper_state_bitmap, DCB_STATE_CONFIGURED_BY_OS_QOS);
6647
6648 if(GET_FLAGS(flags, DCB_PARAMS_WILLING))
6649 {
6650 SET_FLAGS(indicate_event->dcb_current_oper_state_bitmap,
6651 DCB_STATE_CONFIGURED_BY_OS_QOS_TO_WILLING);
6652 }
6653 else
6654 {
6655 RESET_FLAGS(indicate_event->dcb_current_oper_state_bitmap,
6656 DCB_STATE_CONFIGURED_BY_OS_QOS_TO_WILLING);
6657 }
6658 }
6659 /**
6660 * @description
6661 * 1.Update the local copy of the configuration parameters
6662 * 2.Set data to admin parameters (PFC settings classification
6663 * and PFC as willing ETS as not willing ) update MCP.
6664 * 3. If there are ETS or clasification changes to local
6665 * parameters Update HW/FW because MCP is only awre of PFC
6666 * changes (and will give us an interrupt if there are changes).
6667 * @param pdev
6668 * @param dcb_params
6669 * @param lm_cli_idx
6670 *
6671 * @return lm_status_t
6672 */
6673 lm_status_t
lm_dcbx_ie_runtime_params_updated(INOUT struct _lm_device_t * pdev,INOUT dcb_indicate_event_params_t * dcb_params,IN const u8_t lm_cli_idx)6674 lm_dcbx_ie_runtime_params_updated(
6675 INOUT struct _lm_device_t *pdev,
6676 INOUT dcb_indicate_event_params_t *dcb_params,
6677 IN const u8_t lm_cli_idx)
6678 {
6679 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
6680 lm_status_t lm_status = LM_STATUS_SUCCESS;
6681 u8_t is_local_ets_change = FALSE;
6682 u8_t classif_change_mcp_not_aware = FALSE;
6683 u8_t is_ets_admin_updated = FALSE;
6684
6685 DbgBreakIf(lm_cli_idx != indicate_event->lm_cli_idx);
6686
6687 if(FALSE == pdev->dcbx_info.is_indicate_event_en)
6688 {
6689 DbgBreakMsg("lm_dcbx_runtime_params_updated_validate_pfc called but is_indicate_event_en is false");
6690 return LM_STATUS_FAILURE;
6691 }
6692
6693 /* Update admin MIB*/
6694 lm_status = lm_dcbx_ie_admin_mib_updated_runtime(pdev,
6695 dcb_params,
6696 &classif_change_mcp_not_aware,
6697 &is_ets_admin_updated);
6698
6699 if(LM_STATUS_SUCCESS != lm_status)
6700 {
6701 return lm_status;
6702 }
6703
6704 lm_dcbx_ie_update_local_params(pdev,
6705 dcb_params,
6706 &is_local_ets_change,
6707 indicate_event->lm_cli_idx,
6708 is_ets_admin_updated
6709 );
6710
6711 lm_dcbx_ie_dbg_copy_dcb_params(pdev,
6712 dcb_params,
6713 indicate_event->lm_cli_idx);
6714
6715 lm_dcbx_ie_update_bacs_state(pdev,
6716 dcb_params->flags);
6717
6718 if((TRUE == is_local_ets_change)||
6719 (TRUE == classif_change_mcp_not_aware))
6720 {
6721 // Update HW/FW with new ETS classification configuration.
6722 lm_status = lm_dcbx_set_params_and_read_mib(pdev,
6723 is_local_ets_change,
6724 TRUE);
6725
6726 }
6727
6728 return LM_STATUS_SUCCESS;
6729 }
6730 /**
6731 * @description
6732 * Allocate indicate event bind structs.
6733 * The dcb_local_params->classif_params.classif_table is RT and
6734 * will be changed acording to the amount of entries that are
6735 * given from upper layer.
6736 * @param lm_cli_idx
6737 *
6738 * @return lm_status_t
6739 */
6740 lm_status_t
lm_dcbx_ie_initialize(INOUT struct _lm_device_t * pdev,IN const u8_t lm_cli_idx)6741 lm_dcbx_ie_initialize(
6742 INOUT struct _lm_device_t *pdev,
6743 IN const u8_t lm_cli_idx)
6744 {
6745 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
6746 const u32_t classif_table_aloc_size_local = LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_LOCAL;
6747 const u32_t classif_table_aloc_size_remote = LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_REMOTE;
6748
6749 DbgBreakIf(LM_CLI_IDX_MAX != indicate_event->lm_cli_idx);
6750 DbgBreakIf ((0 == pdev->params.b_dcb_indicate_event));
6751
6752 DbgBreakIf((NULL != indicate_event->remote_params.classif_params.classif_table) ||
6753 (NULL != indicate_event->local_params.classif_params.classif_table) ||
6754 (NULL != indicate_event->dcb_params_given_dbg.classif_params.classif_table));
6755
6756 indicate_event->lm_cli_idx = lm_cli_idx;
6757
6758 // Allocate dcb_remote_params
6759 indicate_event->remote_params.classif_params.classif_table =
6760 mm_alloc_mem(pdev, classif_table_aloc_size_remote, indicate_event->lm_cli_idx);
6761
6762 if(CHK_NULL(indicate_event->remote_params.classif_params.classif_table))
6763 {
6764 DbgBreakMsg("lm_dcbx_ie_alloc_bind_structs allocation failed remote ");
6765 return LM_STATUS_RESOURCE;
6766 }
6767
6768 // Allocate dcb_local_params
6769 //The only RT memory is the local table that can include upper layer classification entries
6770 indicate_event->local_params.classif_params.classif_table =
6771 mm_alloc_mem(pdev, classif_table_aloc_size_local, indicate_event->lm_cli_idx);
6772
6773 if(CHK_NULL(indicate_event->local_params.classif_params.classif_table))
6774 {
6775 DbgBreakMsg("lm_dcbx_ie_alloc_bind_structs allocation failed local ");
6776 return LM_STATUS_RESOURCE;
6777 }
6778
6779 indicate_event->dcb_params_given_dbg.classif_params.classif_table =
6780 mm_alloc_mem(pdev, LM_DCBX_IE_CLASSIF_TABLE_ALOC_SIZE_DBG, indicate_event->lm_cli_idx);
6781
6782 if(CHK_NULL(indicate_event->dcb_params_given_dbg.classif_params.classif_table))
6783 {
6784 DbgBreakMsg("lm_dcbx_ie_alloc_bind_structs allocation failed given DBG");
6785 return LM_STATUS_RESOURCE;
6786 }
6787
6788 return LM_STATUS_SUCCESS;
6789 }
6790 /**
6791 * @description
6792 * Free indicate event structs that were allocated by RT.
6793 * This code must be done from LPME while is_indicate_event_en
6794 * is still valid to avoid a race.
6795 * @param lm_cli_idx
6796 *
6797 * @return void
6798 */
6799 void
lm_dcbx_ie_deinitialize(INOUT struct _lm_device_t * pdev,IN const u8_t lm_cli_idx)6800 lm_dcbx_ie_deinitialize(
6801 INOUT struct _lm_device_t *pdev,
6802 IN const u8_t lm_cli_idx)
6803 {
6804 lm_dcbx_indicate_event_t *indicate_event = &pdev->dcbx_info.indicate_event;
6805
6806 DbgBreakIf(lm_cli_idx != indicate_event->lm_cli_idx);
6807
6808 DbgBreakIf(NULL == indicate_event->local_params.classif_params.classif_table);
6809 DbgBreakIf(NULL == indicate_event->remote_params.classif_params.classif_table);
6810 DbgBreakIf(NULL == indicate_event->dcb_params_given_dbg.classif_params.classif_table);
6811
6812 lm_dcbx_ie_init_params(pdev, FALSE);
6813 }
6814