]>
Commit | Line | Data |
---|---|---|
d71d8381 JS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // Copyright (c) 2016-2017 Hisilicon Limited. | |
cacde272 YL |
3 | |
4 | #include "hclge_main.h" | |
a61432d4 | 5 | #include "hclge_dcb.h" |
cacde272 YL |
6 | #include "hclge_tm.h" |
7 | #include "hnae3.h" | |
8 | ||
9 | #define BW_PERCENT 100 | |
10 | ||
11 | static int hclge_ieee_ets_to_tm_info(struct hclge_dev *hdev, | |
12 | struct ieee_ets *ets) | |
13 | { | |
14 | u8 i; | |
15 | ||
16 | for (i = 0; i < HNAE3_MAX_TC; i++) { | |
17 | switch (ets->tc_tsa[i]) { | |
18 | case IEEE_8021QAZ_TSA_STRICT: | |
19 | hdev->tm_info.tc_info[i].tc_sch_mode = | |
20 | HCLGE_SCH_MODE_SP; | |
21 | hdev->tm_info.pg_info[0].tc_dwrr[i] = 0; | |
22 | break; | |
23 | case IEEE_8021QAZ_TSA_ETS: | |
24 | hdev->tm_info.tc_info[i].tc_sch_mode = | |
25 | HCLGE_SCH_MODE_DWRR; | |
26 | hdev->tm_info.pg_info[0].tc_dwrr[i] = | |
27 | ets->tc_tx_bw[i]; | |
28 | break; | |
29 | default: | |
30 | /* Hardware only supports SP (strict priority) | |
31 | * or ETS (enhanced transmission selection) | |
32 | * algorithms, if we receive some other value | |
33 | * from dcbnl, then throw an error. | |
34 | */ | |
35 | return -EINVAL; | |
36 | } | |
37 | } | |
38 | ||
e432abfb YL |
39 | hclge_tm_prio_tc_info_update(hdev, ets->prio_tc); |
40 | ||
41 | return 0; | |
cacde272 YL |
42 | } |
43 | ||
44 | static void hclge_tm_info_to_ieee_ets(struct hclge_dev *hdev, | |
45 | struct ieee_ets *ets) | |
46 | { | |
47 | u32 i; | |
48 | ||
49 | memset(ets, 0, sizeof(*ets)); | |
50 | ets->willing = 1; | |
51 | ets->ets_cap = hdev->tc_max; | |
52 | ||
53 | for (i = 0; i < HNAE3_MAX_TC; i++) { | |
54 | ets->prio_tc[i] = hdev->tm_info.prio_tc[i]; | |
55 | ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i]; | |
56 | ||
57 | if (hdev->tm_info.tc_info[i].tc_sch_mode == | |
58 | HCLGE_SCH_MODE_SP) | |
59 | ets->tc_tsa[i] = IEEE_8021QAZ_TSA_STRICT; | |
60 | else | |
61 | ets->tc_tsa[i] = IEEE_8021QAZ_TSA_ETS; | |
62 | } | |
63 | } | |
64 | ||
65 | /* IEEE std */ | |
66 | static int hclge_ieee_getets(struct hnae3_handle *h, struct ieee_ets *ets) | |
67 | { | |
68 | struct hclge_vport *vport = hclge_get_vport(h); | |
69 | struct hclge_dev *hdev = vport->back; | |
70 | ||
71 | hclge_tm_info_to_ieee_ets(hdev, ets); | |
72 | ||
73 | return 0; | |
74 | } | |
75 | ||
e432abfb YL |
76 | static int hclge_dcb_common_validate(struct hclge_dev *hdev, u8 num_tc, |
77 | u8 *prio_tc) | |
78 | { | |
79 | int i; | |
80 | ||
81 | if (num_tc > hdev->tc_max) { | |
82 | dev_err(&hdev->pdev->dev, | |
83 | "tc num checking failed, %u > tc_max(%u)\n", | |
84 | num_tc, hdev->tc_max); | |
85 | return -EINVAL; | |
86 | } | |
87 | ||
88 | for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) { | |
89 | if (prio_tc[i] >= num_tc) { | |
90 | dev_err(&hdev->pdev->dev, | |
adcf738b | 91 | "prio_tc[%d] checking failed, %u >= num_tc(%u)\n", |
e432abfb YL |
92 | i, prio_tc[i], num_tc); |
93 | return -EINVAL; | |
94 | } | |
95 | } | |
96 | ||
de67a690 YL |
97 | if (num_tc > hdev->vport[0].alloc_tqps) { |
98 | dev_err(&hdev->pdev->dev, | |
99 | "allocated tqp checking failed, %u > tqp(%u)\n", | |
100 | num_tc, hdev->vport[0].alloc_tqps); | |
101 | return -EINVAL; | |
e432abfb YL |
102 | } |
103 | ||
104 | return 0; | |
105 | } | |
106 | ||
161ad669 GH |
107 | static u8 hclge_ets_tc_changed(struct hclge_dev *hdev, struct ieee_ets *ets, |
108 | bool *changed) | |
cacde272 | 109 | { |
161ad669 | 110 | u8 max_tc_id = 0; |
cacde272 YL |
111 | u8 i; |
112 | ||
e432abfb | 113 | for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) { |
cacde272 YL |
114 | if (ets->prio_tc[i] != hdev->tm_info.prio_tc[i]) |
115 | *changed = true; | |
116 | ||
161ad669 GH |
117 | if (ets->prio_tc[i] > max_tc_id) |
118 | max_tc_id = ets->prio_tc[i]; | |
e432abfb | 119 | } |
cacde272 | 120 | |
161ad669 GH |
121 | /* return max tc number, max tc id need to plus 1 */ |
122 | return max_tc_id + 1; | |
123 | } | |
124 | ||
125 | static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev, | |
126 | struct ieee_ets *ets, bool *changed) | |
127 | { | |
128 | bool has_ets_tc = false; | |
129 | u32 total_ets_bw = 0; | |
130 | u8 i; | |
e432abfb | 131 | |
c2d56897 | 132 | for (i = 0; i < hdev->tc_max; i++) { |
cacde272 YL |
133 | switch (ets->tc_tsa[i]) { |
134 | case IEEE_8021QAZ_TSA_STRICT: | |
135 | if (hdev->tm_info.tc_info[i].tc_sch_mode != | |
136 | HCLGE_SCH_MODE_SP) | |
137 | *changed = true; | |
138 | break; | |
139 | case IEEE_8021QAZ_TSA_ETS: | |
731797fd GH |
140 | /* The hardware will switch to sp mode if bandwidth is |
141 | * 0, so limit ets bandwidth must be greater than 0. | |
142 | */ | |
143 | if (!ets->tc_tx_bw[i]) { | |
144 | dev_err(&hdev->pdev->dev, | |
145 | "tc%u ets bw cannot be 0\n", i); | |
146 | return -EINVAL; | |
147 | } | |
148 | ||
cacde272 YL |
149 | if (hdev->tm_info.tc_info[i].tc_sch_mode != |
150 | HCLGE_SCH_MODE_DWRR) | |
151 | *changed = true; | |
152 | ||
153 | total_ets_bw += ets->tc_tx_bw[i]; | |
adefc0a2 JS |
154 | has_ets_tc = true; |
155 | break; | |
cacde272 YL |
156 | default: |
157 | return -EINVAL; | |
158 | } | |
159 | } | |
160 | ||
adefc0a2 | 161 | if (has_ets_tc && total_ets_bw != BW_PERCENT) |
cacde272 YL |
162 | return -EINVAL; |
163 | ||
161ad669 GH |
164 | return 0; |
165 | } | |
166 | ||
167 | static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets, | |
168 | u8 *tc, bool *changed) | |
169 | { | |
170 | u8 tc_num; | |
171 | int ret; | |
172 | ||
173 | tc_num = hclge_ets_tc_changed(hdev, ets, changed); | |
174 | ||
175 | ret = hclge_dcb_common_validate(hdev, tc_num, ets->prio_tc); | |
176 | if (ret) | |
177 | return ret; | |
178 | ||
179 | ret = hclge_ets_sch_mode_validate(hdev, ets, changed); | |
180 | if (ret) | |
181 | return ret; | |
182 | ||
183 | *tc = tc_num; | |
cacde272 YL |
184 | if (*tc != hdev->tm_info.num_tc) |
185 | *changed = true; | |
186 | ||
187 | return 0; | |
188 | } | |
189 | ||
a1ef124e | 190 | static int hclge_map_update(struct hclge_dev *hdev) |
cacde272 | 191 | { |
cacde272 YL |
192 | int ret; |
193 | ||
9e5157ba | 194 | ret = hclge_tm_schd_setup_hw(hdev); |
cacde272 YL |
195 | if (ret) |
196 | return ret; | |
197 | ||
44e59e37 | 198 | ret = hclge_pause_setup_hw(hdev, false); |
cacde272 YL |
199 | if (ret) |
200 | return ret; | |
201 | ||
202 | ret = hclge_buffer_alloc(hdev); | |
203 | if (ret) | |
204 | return ret; | |
205 | ||
268f5dfa YL |
206 | hclge_rss_indir_init_cfg(hdev); |
207 | ||
cacde272 YL |
208 | return hclge_rss_init_hw(hdev); |
209 | } | |
210 | ||
199d2dd4 YL |
211 | static int hclge_notify_down_uinit(struct hclge_dev *hdev) |
212 | { | |
213 | int ret; | |
214 | ||
215 | ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); | |
216 | if (ret) | |
217 | return ret; | |
218 | ||
219 | return hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT); | |
220 | } | |
221 | ||
222 | static int hclge_notify_init_up(struct hclge_dev *hdev) | |
223 | { | |
224 | int ret; | |
225 | ||
226 | ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); | |
227 | if (ret) | |
228 | return ret; | |
229 | ||
230 | return hclge_notify_client(hdev, HNAE3_UP_CLIENT); | |
231 | } | |
232 | ||
cacde272 YL |
233 | static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) |
234 | { | |
235 | struct hclge_vport *vport = hclge_get_vport(h); | |
1c822948 | 236 | struct net_device *netdev = h->kinfo.netdev; |
cacde272 YL |
237 | struct hclge_dev *hdev = vport->back; |
238 | bool map_changed = false; | |
239 | u8 num_tc = 0; | |
240 | int ret; | |
241 | ||
30d240df YL |
242 | if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || |
243 | hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE) | |
cacde272 YL |
244 | return -EINVAL; |
245 | ||
246 | ret = hclge_ets_validate(hdev, ets, &num_tc, &map_changed); | |
247 | if (ret) | |
248 | return ret; | |
249 | ||
af013903 | 250 | if (map_changed) { |
1c822948 YL |
251 | netif_dbg(h, drv, netdev, "set ets\n"); |
252 | ||
199d2dd4 | 253 | ret = hclge_notify_down_uinit(hdev); |
af013903 HT |
254 | if (ret) |
255 | return ret; | |
256 | } | |
257 | ||
e432abfb | 258 | hclge_tm_schd_info_update(hdev, num_tc); |
0472e95f JS |
259 | if (num_tc > 1) |
260 | hdev->flag |= HCLGE_FLAG_DCB_ENABLE; | |
261 | else | |
262 | hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; | |
cacde272 YL |
263 | |
264 | ret = hclge_ieee_ets_to_tm_info(hdev, ets); | |
265 | if (ret) | |
1821dce9 | 266 | goto err_out; |
cacde272 YL |
267 | |
268 | if (map_changed) { | |
a1ef124e YL |
269 | ret = hclge_map_update(hdev); |
270 | if (ret) | |
271 | goto err_out; | |
272 | ||
7f2f8cf6 | 273 | return hclge_notify_init_up(hdev); |
cacde272 YL |
274 | } |
275 | ||
276 | return hclge_tm_dwrr_cfg(hdev); | |
1821dce9 YL |
277 | |
278 | err_out: | |
279 | if (!map_changed) | |
280 | return ret; | |
281 | ||
199d2dd4 | 282 | hclge_notify_init_up(hdev); |
1821dce9 | 283 | |
1821dce9 | 284 | return ret; |
cacde272 YL |
285 | } |
286 | ||
287 | static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) | |
288 | { | |
64fd2300 | 289 | u64 requests[HNAE3_MAX_TC], indications[HNAE3_MAX_TC]; |
cacde272 YL |
290 | struct hclge_vport *vport = hclge_get_vport(h); |
291 | struct hclge_dev *hdev = vport->back; | |
64fd2300 | 292 | int ret; |
8c1671e0 | 293 | u8 i; |
cacde272 YL |
294 | |
295 | memset(pfc, 0, sizeof(*pfc)); | |
296 | pfc->pfc_cap = hdev->pfc_max; | |
8c1671e0 | 297 | pfc->pfc_en = hdev->tm_info.pfc_en; |
cacde272 | 298 | |
64fd2300 PL |
299 | ret = hclge_pfc_tx_stats_get(hdev, requests); |
300 | if (ret) | |
301 | return ret; | |
302 | ||
303 | ret = hclge_pfc_rx_stats_get(hdev, indications); | |
304 | if (ret) | |
305 | return ret; | |
306 | ||
307 | for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { | |
308 | pfc->requests[i] = requests[i]; | |
309 | pfc->indications[i] = indications[i]; | |
310 | } | |
cacde272 YL |
311 | return 0; |
312 | } | |
313 | ||
314 | static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) | |
315 | { | |
316 | struct hclge_vport *vport = hclge_get_vport(h); | |
1c822948 | 317 | struct net_device *netdev = h->kinfo.netdev; |
cacde272 YL |
318 | struct hclge_dev *hdev = vport->back; |
319 | u8 i, j, pfc_map, *prio_tc; | |
aea8cfb3 | 320 | int ret; |
cacde272 | 321 | |
0472e95f | 322 | if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) |
cacde272 YL |
323 | return -EINVAL; |
324 | ||
d3ad430a YL |
325 | if (pfc->pfc_en == hdev->tm_info.pfc_en) |
326 | return 0; | |
327 | ||
cacde272 YL |
328 | prio_tc = hdev->tm_info.prio_tc; |
329 | pfc_map = 0; | |
330 | ||
331 | for (i = 0; i < hdev->tm_info.num_tc; i++) { | |
332 | for (j = 0; j < HNAE3_MAX_USER_PRIO; j++) { | |
333 | if ((prio_tc[j] == i) && (pfc->pfc_en & BIT(j))) { | |
334 | pfc_map |= BIT(i); | |
335 | break; | |
336 | } | |
337 | } | |
338 | } | |
339 | ||
cacde272 | 340 | hdev->tm_info.hw_pfc_map = pfc_map; |
d3ad430a | 341 | hdev->tm_info.pfc_en = pfc->pfc_en; |
cacde272 | 342 | |
1c822948 | 343 | netif_dbg(h, drv, netdev, |
96e65abb | 344 | "set pfc: pfc_en=%x, pfc_map=%x, num_tc=%u\n", |
1c822948 YL |
345 | pfc->pfc_en, pfc_map, hdev->tm_info.num_tc); |
346 | ||
ae179b2f YL |
347 | hclge_tm_pfc_info_update(hdev); |
348 | ||
aea8cfb3 YL |
349 | ret = hclge_pause_setup_hw(hdev, false); |
350 | if (ret) | |
351 | return ret; | |
352 | ||
353 | ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); | |
354 | if (ret) | |
355 | return ret; | |
356 | ||
357 | ret = hclge_buffer_alloc(hdev); | |
358 | if (ret) { | |
359 | hclge_notify_client(hdev, HNAE3_UP_CLIENT); | |
360 | return ret; | |
361 | } | |
362 | ||
363 | return hclge_notify_client(hdev, HNAE3_UP_CLIENT); | |
cacde272 YL |
364 | } |
365 | ||
366 | /* DCBX configuration */ | |
367 | static u8 hclge_getdcbx(struct hnae3_handle *h) | |
368 | { | |
369 | struct hclge_vport *vport = hclge_get_vport(h); | |
370 | struct hclge_dev *hdev = vport->back; | |
371 | ||
30d240df YL |
372 | if (hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE) |
373 | return 0; | |
374 | ||
cacde272 YL |
375 | return hdev->dcbx_cap; |
376 | } | |
377 | ||
378 | static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode) | |
379 | { | |
380 | struct hclge_vport *vport = hclge_get_vport(h); | |
1c822948 | 381 | struct net_device *netdev = h->kinfo.netdev; |
cacde272 YL |
382 | struct hclge_dev *hdev = vport->back; |
383 | ||
1c822948 YL |
384 | netif_dbg(h, drv, netdev, "set dcbx: mode=%u\n", mode); |
385 | ||
cacde272 YL |
386 | /* No support for LLD_MANAGED modes or CEE */ |
387 | if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || | |
388 | (mode & DCB_CAP_DCBX_VER_CEE) || | |
389 | !(mode & DCB_CAP_DCBX_HOST)) | |
390 | return 1; | |
391 | ||
392 | hdev->dcbx_cap = mode; | |
393 | ||
394 | return 0; | |
395 | } | |
396 | ||
5a5c9091 JS |
397 | static int hclge_mqprio_qopt_check(struct hclge_dev *hdev, |
398 | struct tc_mqprio_qopt_offload *mqprio_qopt) | |
399 | { | |
400 | u16 queue_sum = 0; | |
401 | int ret; | |
402 | int i; | |
403 | ||
404 | if (!mqprio_qopt->qopt.num_tc) { | |
405 | mqprio_qopt->qopt.num_tc = 1; | |
406 | return 0; | |
407 | } | |
408 | ||
409 | ret = hclge_dcb_common_validate(hdev, mqprio_qopt->qopt.num_tc, | |
410 | mqprio_qopt->qopt.prio_tc_map); | |
411 | if (ret) | |
412 | return ret; | |
413 | ||
414 | for (i = 0; i < mqprio_qopt->qopt.num_tc; i++) { | |
415 | if (!is_power_of_2(mqprio_qopt->qopt.count[i])) { | |
416 | dev_err(&hdev->pdev->dev, | |
417 | "qopt queue count must be power of 2\n"); | |
418 | return -EINVAL; | |
419 | } | |
420 | ||
f1c2e66d | 421 | if (mqprio_qopt->qopt.count[i] > hdev->pf_rss_size_max) { |
5a5c9091 JS |
422 | dev_err(&hdev->pdev->dev, |
423 | "qopt queue count should be no more than %u\n", | |
f1c2e66d | 424 | hdev->pf_rss_size_max); |
5a5c9091 JS |
425 | return -EINVAL; |
426 | } | |
427 | ||
428 | if (mqprio_qopt->qopt.offset[i] != queue_sum) { | |
429 | dev_err(&hdev->pdev->dev, | |
430 | "qopt queue offset must start from 0, and being continuous\n"); | |
431 | return -EINVAL; | |
432 | } | |
433 | ||
434 | if (mqprio_qopt->min_rate[i] || mqprio_qopt->max_rate[i]) { | |
435 | dev_err(&hdev->pdev->dev, | |
436 | "qopt tx_rate is not supported\n"); | |
437 | return -EOPNOTSUPP; | |
438 | } | |
439 | ||
440 | queue_sum = mqprio_qopt->qopt.offset[i]; | |
441 | queue_sum += mqprio_qopt->qopt.count[i]; | |
442 | } | |
443 | if (hdev->vport[0].alloc_tqps < queue_sum) { | |
444 | dev_err(&hdev->pdev->dev, | |
445 | "qopt queue count sum should be less than %u\n", | |
446 | hdev->vport[0].alloc_tqps); | |
447 | return -EINVAL; | |
448 | } | |
449 | ||
450 | return 0; | |
451 | } | |
452 | ||
453 | static void hclge_sync_mqprio_qopt(struct hnae3_tc_info *tc_info, | |
454 | struct tc_mqprio_qopt_offload *mqprio_qopt) | |
455 | { | |
5a5c9091 JS |
456 | memset(tc_info, 0, sizeof(*tc_info)); |
457 | tc_info->num_tc = mqprio_qopt->qopt.num_tc; | |
458 | memcpy(tc_info->prio_tc, mqprio_qopt->qopt.prio_tc_map, | |
459 | sizeof_field(struct hnae3_tc_info, prio_tc)); | |
460 | memcpy(tc_info->tqp_count, mqprio_qopt->qopt.count, | |
461 | sizeof_field(struct hnae3_tc_info, tqp_count)); | |
462 | memcpy(tc_info->tqp_offset, mqprio_qopt->qopt.offset, | |
463 | sizeof_field(struct hnae3_tc_info, tqp_offset)); | |
5a5c9091 JS |
464 | } |
465 | ||
466 | static int hclge_config_tc(struct hclge_dev *hdev, | |
467 | struct hnae3_tc_info *tc_info) | |
468 | { | |
469 | int i; | |
470 | ||
471 | hclge_tm_schd_info_update(hdev, tc_info->num_tc); | |
472 | for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) | |
473 | hdev->tm_info.prio_tc[i] = tc_info->prio_tc[i]; | |
474 | ||
475 | return hclge_map_update(hdev); | |
476 | } | |
477 | ||
30d240df | 478 | /* Set up TC for hardware offloaded mqprio in channel mode */ |
5a5c9091 JS |
479 | static int hclge_setup_tc(struct hnae3_handle *h, |
480 | struct tc_mqprio_qopt_offload *mqprio_qopt) | |
30d240df YL |
481 | { |
482 | struct hclge_vport *vport = hclge_get_vport(h); | |
5a5c9091 | 483 | struct hnae3_knic_private_info *kinfo; |
30d240df | 484 | struct hclge_dev *hdev = vport->back; |
5a5c9091 JS |
485 | struct hnae3_tc_info old_tc_info; |
486 | u8 tc = mqprio_qopt->qopt.num_tc; | |
30d240df YL |
487 | int ret; |
488 | ||
5a5c9091 JS |
489 | /* if client unregistered, it's not allowed to change |
490 | * mqprio configuration, which may cause uninit ring | |
491 | * fail. | |
492 | */ | |
493 | if (!test_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state)) | |
494 | return -EBUSY; | |
495 | ||
30d240df YL |
496 | if (hdev->flag & HCLGE_FLAG_DCB_ENABLE) |
497 | return -EINVAL; | |
498 | ||
5a5c9091 JS |
499 | ret = hclge_mqprio_qopt_check(hdev, mqprio_qopt); |
500 | if (ret) { | |
501 | dev_err(&hdev->pdev->dev, | |
502 | "failed to check mqprio qopt params, ret = %d\n", ret); | |
503 | return ret; | |
504 | } | |
30d240df | 505 | |
199d2dd4 | 506 | ret = hclge_notify_down_uinit(hdev); |
c2a39d98 YL |
507 | if (ret) |
508 | return ret; | |
509 | ||
5a5c9091 JS |
510 | kinfo = &vport->nic.kinfo; |
511 | memcpy(&old_tc_info, &kinfo->tc_info, sizeof(old_tc_info)); | |
512 | hclge_sync_mqprio_qopt(&kinfo->tc_info, mqprio_qopt); | |
513 | kinfo->tc_info.mqprio_active = tc > 0; | |
c2a39d98 | 514 | |
5a5c9091 | 515 | ret = hclge_config_tc(hdev, &kinfo->tc_info); |
1cce5eb6 YL |
516 | if (ret) |
517 | goto err_out; | |
30d240df YL |
518 | |
519 | hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; | |
520 | ||
521 | if (tc > 1) | |
522 | hdev->flag |= HCLGE_FLAG_MQPRIO_ENABLE; | |
523 | else | |
524 | hdev->flag &= ~HCLGE_FLAG_MQPRIO_ENABLE; | |
525 | ||
199d2dd4 | 526 | return hclge_notify_init_up(hdev); |
1cce5eb6 YL |
527 | |
528 | err_out: | |
d82650be JS |
529 | if (!tc) { |
530 | dev_warn(&hdev->pdev->dev, | |
531 | "failed to destroy mqprio, will active after reset, ret = %d\n", | |
532 | ret); | |
533 | } else { | |
534 | /* roll-back */ | |
535 | memcpy(&kinfo->tc_info, &old_tc_info, sizeof(old_tc_info)); | |
536 | if (hclge_config_tc(hdev, &kinfo->tc_info)) | |
537 | dev_err(&hdev->pdev->dev, | |
538 | "failed to roll back tc configuration\n"); | |
539 | } | |
199d2dd4 | 540 | hclge_notify_init_up(hdev); |
1cce5eb6 | 541 | |
1cce5eb6 | 542 | return ret; |
30d240df YL |
543 | } |
544 | ||
cacde272 YL |
545 | static const struct hnae3_dcb_ops hns3_dcb_ops = { |
546 | .ieee_getets = hclge_ieee_getets, | |
547 | .ieee_setets = hclge_ieee_setets, | |
548 | .ieee_getpfc = hclge_ieee_getpfc, | |
549 | .ieee_setpfc = hclge_ieee_setpfc, | |
550 | .getdcbx = hclge_getdcbx, | |
551 | .setdcbx = hclge_setdcbx, | |
30d240df | 552 | .setup_tc = hclge_setup_tc, |
cacde272 YL |
553 | }; |
554 | ||
555 | void hclge_dcb_ops_set(struct hclge_dev *hdev) | |
556 | { | |
557 | struct hclge_vport *vport = hdev->vport; | |
558 | struct hnae3_knic_private_info *kinfo; | |
559 | ||
560 | /* Hdev does not support DCB or vport is | |
561 | * not a pf, then dcb_ops is not set. | |
562 | */ | |
563 | if (!hnae3_dev_dcb_supported(hdev) || | |
564 | vport->vport_id != 0) | |
565 | return; | |
566 | ||
567 | kinfo = &vport->nic.kinfo; | |
568 | kinfo->dcb_ops = &hns3_dcb_ops; | |
569 | hdev->dcbx_cap = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_HOST; | |
570 | } |