1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 1999 - 2024 Intel Corporation. */
3
4 #include "ixgbe.h"
5 #include <linux/dcbnl.h>
6 #include "ixgbe_dcb_82598.h"
7 #include "ixgbe_dcb_82599.h"
8 #include "ixgbe_sriov.h"
9
10 /* Callbacks for DCB netlink in the kernel */
11 #define BIT_PFC 0x02
12 #define BIT_PG_RX 0x04
13 #define BIT_PG_TX 0x08
14 #define BIT_APP_UPCHG 0x10
15
16 /* Responses for the DCB_C_SET_ALL command */
17 #define DCB_HW_CHG_RST 0 /* DCB configuration changed with reset */
18 #define DCB_NO_HW_CHG 1 /* DCB configuration did not change */
19 #define DCB_HW_CHG 2 /* DCB configuration changed, no reset */
20
ixgbe_copy_dcb_cfg(struct ixgbe_adapter * adapter,int tc_max)21 static int ixgbe_copy_dcb_cfg(struct ixgbe_adapter *adapter, int tc_max)
22 {
23 struct ixgbe_dcb_config *scfg = &adapter->temp_dcb_cfg;
24 struct ixgbe_dcb_config *dcfg = &adapter->dcb_cfg;
25 struct tc_configuration *src = NULL;
26 struct tc_configuration *dst = NULL;
27 int i, j;
28 int tx = DCB_TX_CONFIG;
29 int rx = DCB_RX_CONFIG;
30 int changes = 0;
31 #ifdef IXGBE_FCOE
32 struct dcb_app app = {
33 .selector = DCB_APP_IDTYPE_ETHTYPE,
34 .protocol = ETH_P_FCOE,
35 };
36 u8 up = dcb_getapp(adapter->netdev, &app);
37
38 if (up && !(up & BIT(adapter->fcoe.up)))
39 changes |= BIT_APP_UPCHG;
40 #endif
41
42 for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) {
43 src = &scfg->tc_config[i - DCB_PG_ATTR_TC_0];
44 dst = &dcfg->tc_config[i - DCB_PG_ATTR_TC_0];
45
46 if (dst->path[tx].prio_type != src->path[tx].prio_type) {
47 dst->path[tx].prio_type = src->path[tx].prio_type;
48 changes |= BIT_PG_TX;
49 }
50
51 if (dst->path[tx].bwg_id != src->path[tx].bwg_id) {
52 dst->path[tx].bwg_id = src->path[tx].bwg_id;
53 changes |= BIT_PG_TX;
54 }
55
56 if (dst->path[tx].bwg_percent != src->path[tx].bwg_percent) {
57 dst->path[tx].bwg_percent = src->path[tx].bwg_percent;
58 changes |= BIT_PG_TX;
59 }
60
61 if (dst->path[tx].up_to_tc_bitmap !=
62 src->path[tx].up_to_tc_bitmap) {
63 dst->path[tx].up_to_tc_bitmap =
64 src->path[tx].up_to_tc_bitmap;
65 changes |= (BIT_PG_TX | BIT_PFC | BIT_APP_UPCHG);
66 }
67
68 if (dst->path[rx].prio_type != src->path[rx].prio_type) {
69 dst->path[rx].prio_type = src->path[rx].prio_type;
70 changes |= BIT_PG_RX;
71 }
72
73 if (dst->path[rx].bwg_id != src->path[rx].bwg_id) {
74 dst->path[rx].bwg_id = src->path[rx].bwg_id;
75 changes |= BIT_PG_RX;
76 }
77
78 if (dst->path[rx].bwg_percent != src->path[rx].bwg_percent) {
79 dst->path[rx].bwg_percent = src->path[rx].bwg_percent;
80 changes |= BIT_PG_RX;
81 }
82
83 if (dst->path[rx].up_to_tc_bitmap !=
84 src->path[rx].up_to_tc_bitmap) {
85 dst->path[rx].up_to_tc_bitmap =
86 src->path[rx].up_to_tc_bitmap;
87 changes |= (BIT_PG_RX | BIT_PFC | BIT_APP_UPCHG);
88 }
89 }
90
91 for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) {
92 j = i - DCB_PG_ATTR_BW_ID_0;
93 if (dcfg->bw_percentage[tx][j] != scfg->bw_percentage[tx][j]) {
94 dcfg->bw_percentage[tx][j] = scfg->bw_percentage[tx][j];
95 changes |= BIT_PG_TX;
96 }
97 if (dcfg->bw_percentage[rx][j] != scfg->bw_percentage[rx][j]) {
98 dcfg->bw_percentage[rx][j] = scfg->bw_percentage[rx][j];
99 changes |= BIT_PG_RX;
100 }
101 }
102
103 for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) {
104 j = i - DCB_PFC_UP_ATTR_0;
105 if (dcfg->tc_config[j].dcb_pfc != scfg->tc_config[j].dcb_pfc) {
106 dcfg->tc_config[j].dcb_pfc = scfg->tc_config[j].dcb_pfc;
107 changes |= BIT_PFC;
108 }
109 }
110
111 if (dcfg->pfc_mode_enable != scfg->pfc_mode_enable) {
112 dcfg->pfc_mode_enable = scfg->pfc_mode_enable;
113 changes |= BIT_PFC;
114 }
115
116 return changes;
117 }
118
ixgbe_dcbnl_get_state(struct net_device * netdev)119 static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
120 {
121 struct ixgbe_adapter *adapter = netdev_priv(netdev);
122
123 return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
124 }
125
ixgbe_dcbnl_set_state(struct net_device * netdev,u8 state)126 static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
127 {
128 struct ixgbe_adapter *adapter = netdev_priv(netdev);
129
130 /* Fail command if not in CEE mode */
131 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
132 return 1;
133
134 /* verify there is something to do, if not then exit */
135 if (!state == !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
136 return 0;
137
138 return !!ixgbe_setup_tc(netdev,
139 state ? adapter->dcb_cfg.num_tcs.pg_tcs : 0);
140 }
141
ixgbe_dcbnl_get_perm_hw_addr(struct net_device * netdev,u8 * perm_addr)142 static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
143 u8 *perm_addr)
144 {
145 struct ixgbe_adapter *adapter = netdev_priv(netdev);
146 int i, j;
147
148 memset(perm_addr, 0xff, MAX_ADDR_LEN);
149
150 for (i = 0; i < netdev->addr_len; i++)
151 perm_addr[i] = adapter->hw.mac.perm_addr[i];
152
153 switch (adapter->hw.mac.type) {
154 case ixgbe_mac_82599EB:
155 case ixgbe_mac_X540:
156 case ixgbe_mac_X550:
157 case ixgbe_mac_e610:
158 for (j = 0; j < netdev->addr_len; j++, i++)
159 perm_addr[i] = adapter->hw.mac.san_addr[j];
160 break;
161 default:
162 break;
163 }
164 }
165
ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device * netdev,int tc,u8 prio,u8 bwg_id,u8 bw_pct,u8 up_map)166 static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
167 u8 prio, u8 bwg_id, u8 bw_pct,
168 u8 up_map)
169 {
170 struct ixgbe_adapter *adapter = netdev_priv(netdev);
171
172 if (prio != DCB_ATTR_VALUE_UNDEFINED)
173 adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio;
174 if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
175 adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id = bwg_id;
176 if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
177 adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent =
178 bw_pct;
179 if (up_map != DCB_ATTR_VALUE_UNDEFINED)
180 adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap =
181 up_map;
182 }
183
ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device * netdev,int bwg_id,u8 bw_pct)184 static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
185 u8 bw_pct)
186 {
187 struct ixgbe_adapter *adapter = netdev_priv(netdev);
188
189 adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
190 }
191
ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device * netdev,int tc,u8 prio,u8 bwg_id,u8 bw_pct,u8 up_map)192 static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
193 u8 prio, u8 bwg_id, u8 bw_pct,
194 u8 up_map)
195 {
196 struct ixgbe_adapter *adapter = netdev_priv(netdev);
197
198 if (prio != DCB_ATTR_VALUE_UNDEFINED)
199 adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio;
200 if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
201 adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id = bwg_id;
202 if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
203 adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent =
204 bw_pct;
205 if (up_map != DCB_ATTR_VALUE_UNDEFINED)
206 adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap =
207 up_map;
208 }
209
ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device * netdev,int bwg_id,u8 bw_pct)210 static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
211 u8 bw_pct)
212 {
213 struct ixgbe_adapter *adapter = netdev_priv(netdev);
214
215 adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
216 }
217
ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device * netdev,int tc,u8 * prio,u8 * bwg_id,u8 * bw_pct,u8 * up_map)218 static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
219 u8 *prio, u8 *bwg_id, u8 *bw_pct,
220 u8 *up_map)
221 {
222 struct ixgbe_adapter *adapter = netdev_priv(netdev);
223
224 *prio = adapter->dcb_cfg.tc_config[tc].path[0].prio_type;
225 *bwg_id = adapter->dcb_cfg.tc_config[tc].path[0].bwg_id;
226 *bw_pct = adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent;
227 *up_map = adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap;
228 }
229
ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device * netdev,int bwg_id,u8 * bw_pct)230 static void ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
231 u8 *bw_pct)
232 {
233 struct ixgbe_adapter *adapter = netdev_priv(netdev);
234
235 *bw_pct = adapter->dcb_cfg.bw_percentage[0][bwg_id];
236 }
237
ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device * netdev,int tc,u8 * prio,u8 * bwg_id,u8 * bw_pct,u8 * up_map)238 static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc,
239 u8 *prio, u8 *bwg_id, u8 *bw_pct,
240 u8 *up_map)
241 {
242 struct ixgbe_adapter *adapter = netdev_priv(netdev);
243
244 *prio = adapter->dcb_cfg.tc_config[tc].path[1].prio_type;
245 *bwg_id = adapter->dcb_cfg.tc_config[tc].path[1].bwg_id;
246 *bw_pct = adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent;
247 *up_map = adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap;
248 }
249
ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device * netdev,int bwg_id,u8 * bw_pct)250 static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
251 u8 *bw_pct)
252 {
253 struct ixgbe_adapter *adapter = netdev_priv(netdev);
254
255 *bw_pct = adapter->dcb_cfg.bw_percentage[1][bwg_id];
256 }
257
ixgbe_dcbnl_set_pfc_cfg(struct net_device * netdev,int priority,u8 setting)258 static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
259 u8 setting)
260 {
261 struct ixgbe_adapter *adapter = netdev_priv(netdev);
262
263 adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
264 if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
265 adapter->dcb_cfg.tc_config[priority].dcb_pfc)
266 adapter->temp_dcb_cfg.pfc_mode_enable = true;
267 }
268
ixgbe_dcbnl_get_pfc_cfg(struct net_device * netdev,int priority,u8 * setting)269 static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
270 u8 *setting)
271 {
272 struct ixgbe_adapter *adapter = netdev_priv(netdev);
273
274 *setting = adapter->dcb_cfg.tc_config[priority].dcb_pfc;
275 }
276
ixgbe_dcbnl_devreset(struct net_device * dev)277 static void ixgbe_dcbnl_devreset(struct net_device *dev)
278 {
279 struct ixgbe_adapter *adapter = netdev_priv(dev);
280
281 while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
282 usleep_range(1000, 2000);
283
284 if (netif_running(dev))
285 dev->netdev_ops->ndo_stop(dev);
286
287 ixgbe_clear_interrupt_scheme(adapter);
288 ixgbe_init_interrupt_scheme(adapter);
289
290 if (netif_running(dev))
291 dev->netdev_ops->ndo_open(dev);
292
293 clear_bit(__IXGBE_RESETTING, &adapter->state);
294 }
295
ixgbe_dcbnl_set_all(struct net_device * netdev)296 static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
297 {
298 struct ixgbe_adapter *adapter = netdev_priv(netdev);
299 struct ixgbe_dcb_config *dcb_cfg = &adapter->dcb_cfg;
300 struct ixgbe_hw *hw = &adapter->hw;
301 int ret = DCB_NO_HW_CHG;
302 int i;
303
304 /* Fail command if not in CEE mode */
305 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
306 return DCB_NO_HW_CHG;
307
308 adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(adapter,
309 MAX_TRAFFIC_CLASS);
310 if (!adapter->dcb_set_bitmap)
311 return DCB_NO_HW_CHG;
312
313 if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) {
314 u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS];
315 u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS];
316 /* Priority to TC mapping in CEE case default to 1:1 */
317 u8 prio_tc[MAX_USER_PRIORITY];
318 int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
319
320 #ifdef IXGBE_FCOE
321 if (adapter->netdev->fcoe_mtu)
322 max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
323 #endif
324
325 ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame,
326 DCB_TX_CONFIG);
327 ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame,
328 DCB_RX_CONFIG);
329
330 ixgbe_dcb_unpack_refill(dcb_cfg, DCB_TX_CONFIG, refill);
331 ixgbe_dcb_unpack_max(dcb_cfg, max);
332 ixgbe_dcb_unpack_bwgid(dcb_cfg, DCB_TX_CONFIG, bwg_id);
333 ixgbe_dcb_unpack_prio(dcb_cfg, DCB_TX_CONFIG, prio_type);
334 ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc);
335
336 ixgbe_dcb_hw_ets_config(hw, refill, max, bwg_id,
337 prio_type, prio_tc);
338
339 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
340 netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
341
342 ret = DCB_HW_CHG_RST;
343 }
344
345 if (adapter->dcb_set_bitmap & BIT_PFC) {
346 if (dcb_cfg->pfc_mode_enable) {
347 u8 pfc_en;
348 u8 prio_tc[MAX_USER_PRIORITY];
349
350 ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc);
351 ixgbe_dcb_unpack_pfc(dcb_cfg, &pfc_en);
352 ixgbe_dcb_hw_pfc_config(hw, pfc_en, prio_tc);
353 } else {
354 hw->mac.ops.fc_enable(hw);
355 }
356
357 ixgbe_set_rx_drop_en(adapter);
358
359 ret = DCB_HW_CHG;
360 }
361
362 #ifdef IXGBE_FCOE
363 /* Reprogram FCoE hardware offloads when the traffic class
364 * FCoE is using changes. This happens if the APP info
365 * changes or the up2tc mapping is updated.
366 */
367 if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
368 struct dcb_app app = {
369 .selector = DCB_APP_IDTYPE_ETHTYPE,
370 .protocol = ETH_P_FCOE,
371 };
372 u8 up = dcb_getapp(netdev, &app);
373
374 adapter->fcoe.up = ffs(up) - 1;
375 ixgbe_dcbnl_devreset(netdev);
376 ret = DCB_HW_CHG_RST;
377 }
378 #endif
379
380 adapter->dcb_set_bitmap = 0x00;
381 return ret;
382 }
383
ixgbe_dcbnl_getcap(struct net_device * netdev,int capid,u8 * cap)384 static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
385 {
386 struct ixgbe_adapter *adapter = netdev_priv(netdev);
387
388 switch (capid) {
389 case DCB_CAP_ATTR_PG:
390 *cap = true;
391 break;
392 case DCB_CAP_ATTR_PFC:
393 *cap = true;
394 break;
395 case DCB_CAP_ATTR_UP2TC:
396 *cap = false;
397 break;
398 case DCB_CAP_ATTR_PG_TCS:
399 *cap = 0x80;
400 break;
401 case DCB_CAP_ATTR_PFC_TCS:
402 *cap = 0x80;
403 break;
404 case DCB_CAP_ATTR_GSP:
405 *cap = true;
406 break;
407 case DCB_CAP_ATTR_BCN:
408 *cap = false;
409 break;
410 case DCB_CAP_ATTR_DCBX:
411 *cap = adapter->dcbx_cap;
412 break;
413 default:
414 *cap = false;
415 break;
416 }
417
418 return 0;
419 }
420
ixgbe_dcbnl_getnumtcs(struct net_device * netdev,int tcid,u8 * num)421 static int ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
422 {
423 struct ixgbe_adapter *adapter = netdev_priv(netdev);
424
425 if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
426 switch (tcid) {
427 case DCB_NUMTCS_ATTR_PG:
428 *num = adapter->dcb_cfg.num_tcs.pg_tcs;
429 break;
430 case DCB_NUMTCS_ATTR_PFC:
431 *num = adapter->dcb_cfg.num_tcs.pfc_tcs;
432 break;
433 default:
434 return -EINVAL;
435 }
436 } else {
437 return -EINVAL;
438 }
439
440 return 0;
441 }
442
ixgbe_dcbnl_setnumtcs(struct net_device * netdev,int tcid,u8 num)443 static int ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num)
444 {
445 return -EINVAL;
446 }
447
ixgbe_dcbnl_getpfcstate(struct net_device * netdev)448 static u8 ixgbe_dcbnl_getpfcstate(struct net_device *netdev)
449 {
450 struct ixgbe_adapter *adapter = netdev_priv(netdev);
451
452 return adapter->dcb_cfg.pfc_mode_enable;
453 }
454
ixgbe_dcbnl_setpfcstate(struct net_device * netdev,u8 state)455 static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
456 {
457 struct ixgbe_adapter *adapter = netdev_priv(netdev);
458
459 adapter->temp_dcb_cfg.pfc_mode_enable = state;
460 }
461
462 /**
463 * ixgbe_dcbnl_getapp - retrieve the DCBX application user priority
464 * @netdev : the corresponding netdev
465 * @idtype : identifies the id as ether type or TCP/UDP port number
466 * @id: id is either ether type or TCP/UDP port number
467 *
468 * Returns : on success, returns a non-zero 802.1p user priority bitmap
469 * otherwise returns -EINVAL as the invalid user priority bitmap to indicate an
470 * error.
471 */
ixgbe_dcbnl_getapp(struct net_device * netdev,u8 idtype,u16 id)472 static int ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
473 {
474 struct ixgbe_adapter *adapter = netdev_priv(netdev);
475 struct dcb_app app = {
476 .selector = idtype,
477 .protocol = id,
478 };
479
480 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
481 return -EINVAL;
482
483 return dcb_getapp(netdev, &app);
484 }
485
ixgbe_dcbnl_ieee_getets(struct net_device * dev,struct ieee_ets * ets)486 static int ixgbe_dcbnl_ieee_getets(struct net_device *dev,
487 struct ieee_ets *ets)
488 {
489 struct ixgbe_adapter *adapter = netdev_priv(dev);
490 struct ieee_ets *my_ets = adapter->ixgbe_ieee_ets;
491
492 ets->ets_cap = adapter->dcb_cfg.num_tcs.pg_tcs;
493
494 /* No IEEE PFC settings available */
495 if (!my_ets)
496 return 0;
497
498 ets->cbs = my_ets->cbs;
499 memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
500 memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
501 memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
502 memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
503 return 0;
504 }
505
ixgbe_dcbnl_ieee_setets(struct net_device * dev,struct ieee_ets * ets)506 static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
507 struct ieee_ets *ets)
508 {
509 struct ixgbe_adapter *adapter = netdev_priv(dev);
510 int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
511 int i, err;
512 __u8 max_tc = 0;
513 __u8 map_chg = 0;
514
515 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
516 return -EINVAL;
517
518 if (!adapter->ixgbe_ieee_ets) {
519 adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets),
520 GFP_KERNEL);
521 if (!adapter->ixgbe_ieee_ets)
522 return -ENOMEM;
523
524 /* initialize UP2TC mappings to invalid value */
525 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
526 adapter->ixgbe_ieee_ets->prio_tc[i] =
527 IEEE_8021QAZ_MAX_TCS;
528 /* if possible update UP2TC mappings from HW */
529 ixgbe_dcb_read_rtrup2tc(&adapter->hw,
530 adapter->ixgbe_ieee_ets->prio_tc);
531 }
532
533 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
534 if (ets->prio_tc[i] > max_tc)
535 max_tc = ets->prio_tc[i];
536 if (ets->prio_tc[i] != adapter->ixgbe_ieee_ets->prio_tc[i])
537 map_chg = 1;
538 }
539
540 memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets));
541
542 if (max_tc)
543 max_tc++;
544
545 if (max_tc > adapter->dcb_cfg.num_tcs.pg_tcs)
546 return -EINVAL;
547
548 if (max_tc != adapter->hw_tcs) {
549 err = ixgbe_setup_tc(dev, max_tc);
550 if (err)
551 return err;
552 } else if (map_chg) {
553 ixgbe_dcbnl_devreset(dev);
554 }
555
556 return ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
557 }
558
ixgbe_dcbnl_ieee_getpfc(struct net_device * dev,struct ieee_pfc * pfc)559 static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
560 struct ieee_pfc *pfc)
561 {
562 struct ixgbe_adapter *adapter = netdev_priv(dev);
563 struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc;
564 int i;
565
566 pfc->pfc_cap = adapter->dcb_cfg.num_tcs.pfc_tcs;
567
568 /* No IEEE PFC settings available */
569 if (!my_pfc)
570 return 0;
571
572 pfc->pfc_en = my_pfc->pfc_en;
573 pfc->mbc = my_pfc->mbc;
574 pfc->delay = my_pfc->delay;
575
576 for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
577 pfc->requests[i] = adapter->stats.pxoffrxc[i];
578 pfc->indications[i] = adapter->stats.pxofftxc[i];
579 }
580
581 return 0;
582 }
583
ixgbe_dcbnl_ieee_setpfc(struct net_device * dev,struct ieee_pfc * pfc)584 static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
585 struct ieee_pfc *pfc)
586 {
587 struct ixgbe_adapter *adapter = netdev_priv(dev);
588 struct ixgbe_hw *hw = &adapter->hw;
589 u8 *prio_tc;
590 int err;
591
592 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
593 return -EINVAL;
594
595 if (!adapter->ixgbe_ieee_pfc) {
596 adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc),
597 GFP_KERNEL);
598 if (!adapter->ixgbe_ieee_pfc)
599 return -ENOMEM;
600 }
601
602 prio_tc = adapter->ixgbe_ieee_ets->prio_tc;
603 memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc));
604
605 /* Enable link flow control parameters if PFC is disabled */
606 if (pfc->pfc_en)
607 err = ixgbe_dcb_hw_pfc_config(hw, pfc->pfc_en, prio_tc);
608 else
609 err = hw->mac.ops.fc_enable(hw);
610
611 ixgbe_set_rx_drop_en(adapter);
612
613 return err;
614 }
615
ixgbe_dcbnl_ieee_setapp(struct net_device * dev,struct dcb_app * app)616 static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
617 struct dcb_app *app)
618 {
619 struct ixgbe_adapter *adapter = netdev_priv(dev);
620 int err;
621
622 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
623 return -EINVAL;
624
625 err = dcb_ieee_setapp(dev, app);
626 if (err)
627 return err;
628
629 #ifdef IXGBE_FCOE
630 if (app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
631 app->protocol == ETH_P_FCOE) {
632 u8 app_mask = dcb_ieee_getapp_mask(dev, app);
633
634 if (app_mask & BIT(adapter->fcoe.up))
635 return 0;
636
637 adapter->fcoe.up = app->priority;
638 ixgbe_dcbnl_devreset(dev);
639 }
640 #endif
641
642 /* VF devices should use default UP when available */
643 if (app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
644 app->protocol == 0) {
645 int vf;
646
647 adapter->default_up = app->priority;
648
649 for (vf = 0; vf < adapter->num_vfs; vf++) {
650 struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
651
652 if (!vfinfo->pf_qos)
653 ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
654 app->priority, vf);
655 }
656 }
657
658 return 0;
659 }
660
ixgbe_dcbnl_ieee_delapp(struct net_device * dev,struct dcb_app * app)661 static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev,
662 struct dcb_app *app)
663 {
664 struct ixgbe_adapter *adapter = netdev_priv(dev);
665 int err;
666
667 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
668 return -EINVAL;
669
670 err = dcb_ieee_delapp(dev, app);
671
672 #ifdef IXGBE_FCOE
673 if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
674 app->protocol == ETH_P_FCOE) {
675 u8 app_mask = dcb_ieee_getapp_mask(dev, app);
676
677 if (app_mask & BIT(adapter->fcoe.up))
678 return 0;
679
680 adapter->fcoe.up = app_mask ?
681 ffs(app_mask) - 1 : IXGBE_FCOE_DEFTC;
682 ixgbe_dcbnl_devreset(dev);
683 }
684 #endif
685 /* IF default priority is being removed clear VF default UP */
686 if (app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
687 app->protocol == 0 && adapter->default_up == app->priority) {
688 int vf;
689 long unsigned int app_mask = dcb_ieee_getapp_mask(dev, app);
690 int qos = app_mask ? find_first_bit(&app_mask, 8) : 0;
691
692 adapter->default_up = qos;
693
694 for (vf = 0; vf < adapter->num_vfs; vf++) {
695 struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
696
697 if (!vfinfo->pf_qos)
698 ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
699 qos, vf);
700 }
701 }
702
703 return err;
704 }
705
ixgbe_dcbnl_getdcbx(struct net_device * dev)706 static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
707 {
708 struct ixgbe_adapter *adapter = netdev_priv(dev);
709 return adapter->dcbx_cap;
710 }
711
ixgbe_dcbnl_setdcbx(struct net_device * dev,u8 mode)712 static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode)
713 {
714 struct ixgbe_adapter *adapter = netdev_priv(dev);
715 struct ieee_ets ets = {0};
716 struct ieee_pfc pfc = {0};
717 int err = 0;
718
719 /* no support for LLD_MANAGED modes or CEE+IEEE */
720 if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
721 ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) ||
722 !(mode & DCB_CAP_DCBX_HOST))
723 return 1;
724
725 if (mode == adapter->dcbx_cap)
726 return 0;
727
728 adapter->dcbx_cap = mode;
729
730 /* ETS and PFC defaults */
731 ets.ets_cap = 8;
732 pfc.pfc_cap = 8;
733
734 if (mode & DCB_CAP_DCBX_VER_IEEE) {
735 ixgbe_dcbnl_ieee_setets(dev, &ets);
736 ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
737 } else if (mode & DCB_CAP_DCBX_VER_CEE) {
738 u8 mask = BIT_PFC | BIT_PG_TX | BIT_PG_RX | BIT_APP_UPCHG;
739
740 adapter->dcb_set_bitmap |= mask;
741 ixgbe_dcbnl_set_all(dev);
742 } else {
743 /* Drop into single TC mode strict priority as this
744 * indicates CEE and IEEE versions are disabled
745 */
746 ixgbe_dcbnl_ieee_setets(dev, &ets);
747 ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
748 err = ixgbe_setup_tc(dev, 0);
749 }
750
751 return err ? 1 : 0;
752 }
753
754 const struct dcbnl_rtnl_ops ixgbe_dcbnl_ops = {
755 .ieee_getets = ixgbe_dcbnl_ieee_getets,
756 .ieee_setets = ixgbe_dcbnl_ieee_setets,
757 .ieee_getpfc = ixgbe_dcbnl_ieee_getpfc,
758 .ieee_setpfc = ixgbe_dcbnl_ieee_setpfc,
759 .ieee_setapp = ixgbe_dcbnl_ieee_setapp,
760 .ieee_delapp = ixgbe_dcbnl_ieee_delapp,
761 .getstate = ixgbe_dcbnl_get_state,
762 .setstate = ixgbe_dcbnl_set_state,
763 .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr,
764 .setpgtccfgtx = ixgbe_dcbnl_set_pg_tc_cfg_tx,
765 .setpgbwgcfgtx = ixgbe_dcbnl_set_pg_bwg_cfg_tx,
766 .setpgtccfgrx = ixgbe_dcbnl_set_pg_tc_cfg_rx,
767 .setpgbwgcfgrx = ixgbe_dcbnl_set_pg_bwg_cfg_rx,
768 .getpgtccfgtx = ixgbe_dcbnl_get_pg_tc_cfg_tx,
769 .getpgbwgcfgtx = ixgbe_dcbnl_get_pg_bwg_cfg_tx,
770 .getpgtccfgrx = ixgbe_dcbnl_get_pg_tc_cfg_rx,
771 .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx,
772 .setpfccfg = ixgbe_dcbnl_set_pfc_cfg,
773 .getpfccfg = ixgbe_dcbnl_get_pfc_cfg,
774 .setall = ixgbe_dcbnl_set_all,
775 .getcap = ixgbe_dcbnl_getcap,
776 .getnumtcs = ixgbe_dcbnl_getnumtcs,
777 .setnumtcs = ixgbe_dcbnl_setnumtcs,
778 .getpfcstate = ixgbe_dcbnl_getpfcstate,
779 .setpfcstate = ixgbe_dcbnl_setpfcstate,
780 .getapp = ixgbe_dcbnl_getapp,
781 .getdcbx = ixgbe_dcbnl_getdcbx,
782 .setdcbx = ixgbe_dcbnl_setdcbx,
783 };
784