1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
4 #include <linux/netdevice.h>
5 #include <linux/string.h>
6 #include <linux/bitops.h>
12 static u8
mlxsw_sp_dcbnl_getdcbx(struct net_device __always_unused
*dev
)
14 return DCB_CAP_DCBX_HOST
| DCB_CAP_DCBX_VER_IEEE
;
17 static u8
mlxsw_sp_dcbnl_setdcbx(struct net_device __always_unused
*dev
,
20 return (mode
!= (DCB_CAP_DCBX_HOST
| DCB_CAP_DCBX_VER_IEEE
)) ? 1 : 0;
23 static int mlxsw_sp_dcbnl_ieee_getets(struct net_device
*dev
,
26 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(dev
);
28 memcpy(ets
, mlxsw_sp_port
->dcb
.ets
, sizeof(*ets
));
33 static int mlxsw_sp_port_ets_validate(struct mlxsw_sp_port
*mlxsw_sp_port
,
36 struct net_device
*dev
= mlxsw_sp_port
->dev
;
37 bool has_ets_tc
= false;
40 for (i
= 0; i
< IEEE_8021QAZ_MAX_TCS
; i
++) {
41 switch (ets
->tc_tsa
[i
]) {
42 case IEEE_8021QAZ_TSA_STRICT
:
44 case IEEE_8021QAZ_TSA_ETS
:
46 tx_bw_sum
+= ets
->tc_tx_bw
[i
];
49 netdev_err(dev
, "Only strict priority and ETS are supported\n");
53 if (ets
->prio_tc
[i
] >= IEEE_8021QAZ_MAX_TCS
) {
54 netdev_err(dev
, "Invalid TC\n");
59 if (has_ets_tc
&& tx_bw_sum
!= 100) {
60 netdev_err(dev
, "Total ETS bandwidth should equal 100\n");
67 static int mlxsw_sp_port_headroom_ets_set(struct mlxsw_sp_port
*mlxsw_sp_port
,
70 struct net_device
*dev
= mlxsw_sp_port
->dev
;
71 struct mlxsw_sp_hdroom hdroom
;
75 hdroom
= *mlxsw_sp_port
->hdroom
;
76 for (prio
= 0; prio
< IEEE_8021QAZ_MAX_TCS
; prio
++)
77 hdroom
.prios
.prio
[prio
].ets_buf_idx
= ets
->prio_tc
[prio
];
78 mlxsw_sp_hdroom_prios_reset_buf_idx(&hdroom
);
79 mlxsw_sp_hdroom_bufs_reset_lossiness(&hdroom
);
80 mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port
, &hdroom
);
82 err
= mlxsw_sp_hdroom_configure(mlxsw_sp_port
, &hdroom
);
84 netdev_err(dev
, "Failed to configure port's headroom\n");
91 static int __mlxsw_sp_dcbnl_ieee_setets(struct mlxsw_sp_port
*mlxsw_sp_port
,
94 struct ieee_ets
*my_ets
= mlxsw_sp_port
->dcb
.ets
;
95 struct net_device
*dev
= mlxsw_sp_port
->dev
;
98 /* Egress configuration. */
99 for (i
= 0; i
< IEEE_8021QAZ_MAX_TCS
; i
++) {
100 bool dwrr
= ets
->tc_tsa
[i
] == IEEE_8021QAZ_TSA_ETS
;
101 u8 weight
= ets
->tc_tx_bw
[i
];
103 err
= mlxsw_sp_port_ets_set(mlxsw_sp_port
,
104 MLXSW_REG_QEEC_HR_SUBGROUP
, i
,
107 netdev_err(dev
, "Failed to link subgroup ETS element %d to group\n",
109 goto err_port_ets_set
;
113 for (i
= 0; i
< IEEE_8021QAZ_MAX_TCS
; i
++) {
114 err
= mlxsw_sp_port_prio_tc_set(mlxsw_sp_port
, i
,
117 netdev_err(dev
, "Failed to map prio %d to TC %d\n", i
,
119 goto err_port_prio_tc_set
;
123 /* Ingress configuration. */
124 err
= mlxsw_sp_port_headroom_ets_set(mlxsw_sp_port
, ets
);
126 goto err_port_headroom_set
;
130 err_port_headroom_set
:
131 i
= IEEE_8021QAZ_MAX_TCS
;
132 err_port_prio_tc_set
:
133 for (i
--; i
>= 0; i
--)
134 mlxsw_sp_port_prio_tc_set(mlxsw_sp_port
, i
, my_ets
->prio_tc
[i
]);
135 i
= IEEE_8021QAZ_MAX_TCS
;
137 for (i
--; i
>= 0; i
--) {
138 bool dwrr
= my_ets
->tc_tsa
[i
] == IEEE_8021QAZ_TSA_ETS
;
139 u8 weight
= my_ets
->tc_tx_bw
[i
];
141 err
= mlxsw_sp_port_ets_set(mlxsw_sp_port
,
142 MLXSW_REG_QEEC_HR_SUBGROUP
, i
,
148 static int mlxsw_sp_dcbnl_ieee_setets(struct net_device
*dev
,
149 struct ieee_ets
*ets
)
151 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(dev
);
154 err
= mlxsw_sp_port_ets_validate(mlxsw_sp_port
, ets
);
158 err
= __mlxsw_sp_dcbnl_ieee_setets(mlxsw_sp_port
, ets
);
162 memcpy(mlxsw_sp_port
->dcb
.ets
, ets
, sizeof(*ets
));
163 mlxsw_sp_port
->dcb
.ets
->ets_cap
= IEEE_8021QAZ_MAX_TCS
;
168 static int mlxsw_sp_dcbnl_app_validate(struct net_device
*dev
,
173 if (app
->priority
>= IEEE_8021QAZ_MAX_TCS
) {
174 netdev_err(dev
, "APP entry with priority value %u is invalid\n",
179 switch (app
->selector
) {
180 case IEEE_8021QAZ_APP_SEL_DSCP
:
181 if (app
->protocol
>= 64) {
182 netdev_err(dev
, "DSCP APP entry with protocol value %u is invalid\n",
187 /* Warn about any DSCP APP entries with the same PID. */
188 prio
= fls(dcb_ieee_getapp_mask(dev
, app
));
190 if (prio
< app
->priority
)
191 netdev_warn(dev
, "Choosing priority %d for DSCP %d in favor of previously-active value of %d\n",
192 app
->priority
, app
->protocol
, prio
);
193 else if (prio
> app
->priority
)
194 netdev_warn(dev
, "Ignoring new priority %d for DSCP %d in favor of current value of %d\n",
195 app
->priority
, app
->protocol
, prio
);
199 case IEEE_8021QAZ_APP_SEL_ETHERTYPE
:
201 netdev_err(dev
, "EtherType APP entries with protocol value != 0 not supported\n");
207 netdev_err(dev
, "APP entries with selector %u not supported\n",
216 mlxsw_sp_port_dcb_app_default_prio(struct mlxsw_sp_port
*mlxsw_sp_port
)
220 prio_mask
= dcb_ieee_getapp_default_prio_mask(mlxsw_sp_port
->dev
);
222 /* Take the highest configured priority. */
223 return fls(prio_mask
) - 1;
229 mlxsw_sp_port_dcb_app_dscp_prio_map(struct mlxsw_sp_port
*mlxsw_sp_port
,
231 struct dcb_ieee_app_dscp_map
*map
)
235 dcb_ieee_getapp_dscp_prio_mask_map(mlxsw_sp_port
->dev
, map
);
236 for (i
= 0; i
< ARRAY_SIZE(map
->map
); ++i
) {
238 map
->map
[i
] = fls(map
->map
[i
]) - 1;
240 map
->map
[i
] = default_prio
;
245 mlxsw_sp_port_dcb_app_prio_dscp_map(struct mlxsw_sp_port
*mlxsw_sp_port
,
246 struct dcb_ieee_app_prio_map
*map
)
248 bool have_dscp
= false;
251 dcb_ieee_getapp_prio_dscp_mask_map(mlxsw_sp_port
->dev
, map
);
252 for (i
= 0; i
< ARRAY_SIZE(map
->map
); ++i
) {
254 map
->map
[i
] = fls64(map
->map
[i
]) - 1;
263 mlxsw_sp_port_dcb_app_update_qpts(struct mlxsw_sp_port
*mlxsw_sp_port
,
264 enum mlxsw_reg_qpts_trust_state ts
)
266 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
267 char qpts_pl
[MLXSW_REG_QPTS_LEN
];
269 mlxsw_reg_qpts_pack(qpts_pl
, mlxsw_sp_port
->local_port
, ts
);
270 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(qpts
), qpts_pl
);
274 mlxsw_sp_port_dcb_app_update_qrwe(struct mlxsw_sp_port
*mlxsw_sp_port
,
277 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
278 char qrwe_pl
[MLXSW_REG_QRWE_LEN
];
280 mlxsw_reg_qrwe_pack(qrwe_pl
, mlxsw_sp_port
->local_port
,
281 false, rewrite_dscp
);
282 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(qrwe
), qrwe_pl
);
286 mlxsw_sp_port_dcb_toggle_trust(struct mlxsw_sp_port
*mlxsw_sp_port
,
287 enum mlxsw_reg_qpts_trust_state ts
)
289 bool rewrite_dscp
= ts
== MLXSW_REG_QPTS_TRUST_STATE_DSCP
;
292 if (mlxsw_sp_port
->dcb
.trust_state
== ts
)
295 err
= mlxsw_sp_port_dcb_app_update_qpts(mlxsw_sp_port
, ts
);
299 err
= mlxsw_sp_port_dcb_app_update_qrwe(mlxsw_sp_port
, rewrite_dscp
);
301 goto err_update_qrwe
;
303 mlxsw_sp_port
->dcb
.trust_state
= ts
;
307 mlxsw_sp_port_dcb_app_update_qpts(mlxsw_sp_port
,
308 mlxsw_sp_port
->dcb
.trust_state
);
313 mlxsw_sp_port_dcb_app_update_qpdp(struct mlxsw_sp_port
*mlxsw_sp_port
,
316 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
317 char qpdp_pl
[MLXSW_REG_QPDP_LEN
];
319 mlxsw_reg_qpdp_pack(qpdp_pl
, mlxsw_sp_port
->local_port
, default_prio
);
320 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(qpdp
), qpdp_pl
);
324 mlxsw_sp_port_dcb_app_update_qpdpm(struct mlxsw_sp_port
*mlxsw_sp_port
,
325 struct dcb_ieee_app_dscp_map
*map
)
327 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
328 char qpdpm_pl
[MLXSW_REG_QPDPM_LEN
];
331 mlxsw_reg_qpdpm_pack(qpdpm_pl
, mlxsw_sp_port
->local_port
);
332 for (i
= 0; i
< ARRAY_SIZE(map
->map
); ++i
)
333 mlxsw_reg_qpdpm_dscp_pack(qpdpm_pl
, i
, map
->map
[i
]);
334 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(qpdpm
), qpdpm_pl
);
338 mlxsw_sp_port_dcb_app_update_qpdsm(struct mlxsw_sp_port
*mlxsw_sp_port
,
339 struct dcb_ieee_app_prio_map
*map
)
341 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
342 char qpdsm_pl
[MLXSW_REG_QPDSM_LEN
];
345 mlxsw_reg_qpdsm_pack(qpdsm_pl
, mlxsw_sp_port
->local_port
);
346 for (i
= 0; i
< ARRAY_SIZE(map
->map
); ++i
)
347 mlxsw_reg_qpdsm_prio_pack(qpdsm_pl
, i
, map
->map
[i
]);
348 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(qpdsm
), qpdsm_pl
);
351 static int mlxsw_sp_port_dcb_app_update(struct mlxsw_sp_port
*mlxsw_sp_port
)
353 struct dcb_ieee_app_prio_map prio_map
;
354 struct dcb_ieee_app_dscp_map dscp_map
;
359 default_prio
= mlxsw_sp_port_dcb_app_default_prio(mlxsw_sp_port
);
360 err
= mlxsw_sp_port_dcb_app_update_qpdp(mlxsw_sp_port
, default_prio
);
362 netdev_err(mlxsw_sp_port
->dev
, "Couldn't configure port default priority\n");
366 have_dscp
= mlxsw_sp_port_dcb_app_prio_dscp_map(mlxsw_sp_port
,
369 mlxsw_sp_port_dcb_app_dscp_prio_map(mlxsw_sp_port
, default_prio
,
371 err
= mlxsw_sp_port_dcb_app_update_qpdpm(mlxsw_sp_port
,
374 netdev_err(mlxsw_sp_port
->dev
, "Couldn't configure priority map\n");
378 err
= mlxsw_sp_port_dcb_app_update_qpdsm(mlxsw_sp_port
,
381 netdev_err(mlxsw_sp_port
->dev
, "Couldn't configure DSCP rewrite map\n");
386 err
= mlxsw_sp_port_dcb_toggle_trust(mlxsw_sp_port
,
387 MLXSW_REG_QPTS_TRUST_STATE_PCP
);
389 netdev_err(mlxsw_sp_port
->dev
, "Couldn't switch to trust L2\n");
393 err
= mlxsw_sp_port_dcb_toggle_trust(mlxsw_sp_port
,
394 MLXSW_REG_QPTS_TRUST_STATE_DSCP
);
396 /* A failure to set trust DSCP means that the QPDPM and QPDSM
397 * maps installed above are not in effect. And since we are here
398 * attempting to set trust DSCP, we couldn't have attempted to
399 * switch trust to PCP. Thus no cleanup is necessary.
401 netdev_err(mlxsw_sp_port
->dev
, "Couldn't switch to trust L3\n");
408 static int mlxsw_sp_dcbnl_ieee_setapp(struct net_device
*dev
,
411 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(dev
);
414 err
= mlxsw_sp_dcbnl_app_validate(dev
, app
);
418 err
= dcb_ieee_setapp(dev
, app
);
422 err
= mlxsw_sp_port_dcb_app_update(mlxsw_sp_port
);
429 dcb_ieee_delapp(dev
, app
);
433 static int mlxsw_sp_dcbnl_ieee_delapp(struct net_device
*dev
,
436 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(dev
);
439 err
= dcb_ieee_delapp(dev
, app
);
443 err
= mlxsw_sp_port_dcb_app_update(mlxsw_sp_port
);
445 netdev_err(dev
, "Failed to update DCB APP configuration\n");
449 static int mlxsw_sp_dcbnl_ieee_getmaxrate(struct net_device
*dev
,
450 struct ieee_maxrate
*maxrate
)
452 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(dev
);
454 memcpy(maxrate
, mlxsw_sp_port
->dcb
.maxrate
, sizeof(*maxrate
));
459 static int mlxsw_sp_dcbnl_ieee_setmaxrate(struct net_device
*dev
,
460 struct ieee_maxrate
*maxrate
)
462 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(dev
);
463 struct ieee_maxrate
*my_maxrate
= mlxsw_sp_port
->dcb
.maxrate
;
466 for (i
= 0; i
< IEEE_8021QAZ_MAX_TCS
; i
++) {
467 err
= mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port
,
468 MLXSW_REG_QEEC_HR_SUBGROUP
,
470 maxrate
->tc_maxrate
[i
], 0);
472 netdev_err(dev
, "Failed to set maxrate for TC %d\n", i
);
473 goto err_port_ets_maxrate_set
;
477 memcpy(mlxsw_sp_port
->dcb
.maxrate
, maxrate
, sizeof(*maxrate
));
481 err_port_ets_maxrate_set
:
482 for (i
--; i
>= 0; i
--)
483 mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port
,
484 MLXSW_REG_QEEC_HR_SUBGROUP
,
486 my_maxrate
->tc_maxrate
[i
], 0);
490 static int mlxsw_sp_port_pfc_cnt_get(struct mlxsw_sp_port
*mlxsw_sp_port
,
493 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
494 struct ieee_pfc
*my_pfc
= mlxsw_sp_port
->dcb
.pfc
;
495 char ppcnt_pl
[MLXSW_REG_PPCNT_LEN
];
498 mlxsw_reg_ppcnt_pack(ppcnt_pl
, mlxsw_sp_port
->local_port
,
499 MLXSW_REG_PPCNT_PRIO_CNT
, prio
);
500 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ppcnt
), ppcnt_pl
);
504 my_pfc
->requests
[prio
] = mlxsw_reg_ppcnt_tx_pause_get(ppcnt_pl
);
505 my_pfc
->indications
[prio
] = mlxsw_reg_ppcnt_rx_pause_get(ppcnt_pl
);
510 static int mlxsw_sp_dcbnl_ieee_getpfc(struct net_device
*dev
,
511 struct ieee_pfc
*pfc
)
513 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(dev
);
516 for (i
= 0; i
< IEEE_8021QAZ_MAX_TCS
; i
++) {
517 err
= mlxsw_sp_port_pfc_cnt_get(mlxsw_sp_port
, i
);
519 netdev_err(dev
, "Failed to get PFC count for priority %d\n",
525 memcpy(pfc
, mlxsw_sp_port
->dcb
.pfc
, sizeof(*pfc
));
530 static int mlxsw_sp_port_pfc_set(struct mlxsw_sp_port
*mlxsw_sp_port
,
531 struct ieee_pfc
*pfc
)
533 char pfcc_pl
[MLXSW_REG_PFCC_LEN
];
535 mlxsw_reg_pfcc_pack(pfcc_pl
, mlxsw_sp_port
->local_port
);
536 mlxsw_reg_pfcc_pprx_set(pfcc_pl
, mlxsw_sp_port
->link
.rx_pause
);
537 mlxsw_reg_pfcc_pptx_set(pfcc_pl
, mlxsw_sp_port
->link
.tx_pause
);
538 mlxsw_reg_pfcc_prio_pack(pfcc_pl
, pfc
->pfc_en
);
540 return mlxsw_reg_write(mlxsw_sp_port
->mlxsw_sp
->core
, MLXSW_REG(pfcc
),
544 static int mlxsw_sp_dcbnl_ieee_setpfc(struct net_device
*dev
,
545 struct ieee_pfc
*pfc
)
547 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(dev
);
548 bool pause_en
= mlxsw_sp_port_is_pause_en(mlxsw_sp_port
);
549 struct mlxsw_sp_hdroom orig_hdroom
;
550 struct mlxsw_sp_hdroom hdroom
;
554 if (pause_en
&& pfc
->pfc_en
) {
555 netdev_err(dev
, "PAUSE frames already enabled on port\n");
559 orig_hdroom
= *mlxsw_sp_port
->hdroom
;
561 hdroom
= orig_hdroom
;
563 hdroom
.delay_bytes
= DIV_ROUND_UP(pfc
->delay
, BITS_PER_BYTE
);
565 hdroom
.delay_bytes
= 0;
567 for (prio
= 0; prio
< IEEE_8021QAZ_MAX_TCS
; prio
++)
568 hdroom
.prios
.prio
[prio
].lossy
= !(pfc
->pfc_en
& BIT(prio
));
570 mlxsw_sp_hdroom_bufs_reset_lossiness(&hdroom
);
571 mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port
, &hdroom
);
573 err
= mlxsw_sp_hdroom_configure(mlxsw_sp_port
, &hdroom
);
575 netdev_err(dev
, "Failed to configure port's headroom for PFC\n");
579 err
= mlxsw_sp_port_pfc_set(mlxsw_sp_port
, pfc
);
581 netdev_err(dev
, "Failed to configure PFC\n");
582 goto err_port_pfc_set
;
585 memcpy(mlxsw_sp_port
->dcb
.pfc
, pfc
, sizeof(*pfc
));
586 mlxsw_sp_port
->dcb
.pfc
->pfc_cap
= IEEE_8021QAZ_MAX_TCS
;
591 mlxsw_sp_hdroom_configure(mlxsw_sp_port
, &orig_hdroom
);
595 static const struct dcbnl_rtnl_ops mlxsw_sp_dcbnl_ops
= {
596 .ieee_getets
= mlxsw_sp_dcbnl_ieee_getets
,
597 .ieee_setets
= mlxsw_sp_dcbnl_ieee_setets
,
598 .ieee_getmaxrate
= mlxsw_sp_dcbnl_ieee_getmaxrate
,
599 .ieee_setmaxrate
= mlxsw_sp_dcbnl_ieee_setmaxrate
,
600 .ieee_getpfc
= mlxsw_sp_dcbnl_ieee_getpfc
,
601 .ieee_setpfc
= mlxsw_sp_dcbnl_ieee_setpfc
,
602 .ieee_setapp
= mlxsw_sp_dcbnl_ieee_setapp
,
603 .ieee_delapp
= mlxsw_sp_dcbnl_ieee_delapp
,
605 .getdcbx
= mlxsw_sp_dcbnl_getdcbx
,
606 .setdcbx
= mlxsw_sp_dcbnl_setdcbx
,
609 static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port
*mlxsw_sp_port
)
611 mlxsw_sp_port
->dcb
.ets
= kzalloc(sizeof(*mlxsw_sp_port
->dcb
.ets
),
613 if (!mlxsw_sp_port
->dcb
.ets
)
616 mlxsw_sp_port
->dcb
.ets
->ets_cap
= IEEE_8021QAZ_MAX_TCS
;
621 static void mlxsw_sp_port_ets_fini(struct mlxsw_sp_port
*mlxsw_sp_port
)
623 kfree(mlxsw_sp_port
->dcb
.ets
);
626 static int mlxsw_sp_port_maxrate_init(struct mlxsw_sp_port
*mlxsw_sp_port
)
630 mlxsw_sp_port
->dcb
.maxrate
= kmalloc(sizeof(*mlxsw_sp_port
->dcb
.maxrate
),
632 if (!mlxsw_sp_port
->dcb
.maxrate
)
635 for (i
= 0; i
< IEEE_8021QAZ_MAX_TCS
; i
++)
636 mlxsw_sp_port
->dcb
.maxrate
->tc_maxrate
[i
] = MLXSW_REG_QEEC_MAS_DIS
;
641 static void mlxsw_sp_port_maxrate_fini(struct mlxsw_sp_port
*mlxsw_sp_port
)
643 kfree(mlxsw_sp_port
->dcb
.maxrate
);
646 static int mlxsw_sp_port_pfc_init(struct mlxsw_sp_port
*mlxsw_sp_port
)
648 mlxsw_sp_port
->dcb
.pfc
= kzalloc(sizeof(*mlxsw_sp_port
->dcb
.pfc
),
650 if (!mlxsw_sp_port
->dcb
.pfc
)
653 mlxsw_sp_port
->dcb
.pfc
->pfc_cap
= IEEE_8021QAZ_MAX_TCS
;
658 static void mlxsw_sp_port_pfc_fini(struct mlxsw_sp_port
*mlxsw_sp_port
)
660 kfree(mlxsw_sp_port
->dcb
.pfc
);
663 int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port
*mlxsw_sp_port
)
667 err
= mlxsw_sp_port_ets_init(mlxsw_sp_port
);
670 err
= mlxsw_sp_port_maxrate_init(mlxsw_sp_port
);
672 goto err_port_maxrate_init
;
673 err
= mlxsw_sp_port_pfc_init(mlxsw_sp_port
);
675 goto err_port_pfc_init
;
677 mlxsw_sp_port
->dcb
.trust_state
= MLXSW_REG_QPTS_TRUST_STATE_PCP
;
678 mlxsw_sp_port
->dev
->dcbnl_ops
= &mlxsw_sp_dcbnl_ops
;
683 mlxsw_sp_port_maxrate_fini(mlxsw_sp_port
);
684 err_port_maxrate_init
:
685 mlxsw_sp_port_ets_fini(mlxsw_sp_port
);
689 void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port
*mlxsw_sp_port
)
691 mlxsw_sp_port_pfc_fini(mlxsw_sp_port
);
692 mlxsw_sp_port_maxrate_fini(mlxsw_sp_port
);
693 mlxsw_sp_port_ets_fini(mlxsw_sp_port
);