xref: /titanic_52/usr/src/uts/common/io/bnxe/577xx/drivers/common/lm/device/lm_dcbx.c (revision d14abf155341d55053c76eeec58b787a456b753b)
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
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
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
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
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  ******************************************************************************/
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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(&params->ets_params, sizeof(params->ets_params));
4574 
4575     mm_mem_zero(&params->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
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
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
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
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
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
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
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
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
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
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  */
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  */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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  */
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
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
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
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