net/sfc/base: provide APIs to configure and reset vPort
[dpdk.git] / drivers / net / sfc / base / ef10_evb.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2018-2019 Solarflare Communications Inc.
4  * All rights reserved.
5  */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10 #if EFSYS_OPT_EVB
11
12 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
13
14         __checkReturn   efx_rc_t
15 ef10_evb_init(
16         __in            efx_nic_t *enp)
17 {
18         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
19                 enp->en_family == EFX_FAMILY_MEDFORD ||
20                 enp->en_family == EFX_FAMILY_MEDFORD2);
21
22         return (0);
23 }
24
25         void
26 ef10_evb_fini(
27         __in            efx_nic_t *enp)
28 {
29         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
30                 enp->en_family == EFX_FAMILY_MEDFORD ||
31                 enp->en_family == EFX_FAMILY_MEDFORD2);
32 }
33
34         __checkReturn   efx_rc_t
35 efx_mcdi_vswitch_alloc(
36         __in            efx_nic_t *enp,
37         __in            efx_vport_id_t vport_id,
38         __in            efx_vswitch_type_t vswitch_type)
39 {
40         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VSWITCH_ALLOC_IN_LEN,
41                 MC_CMD_VSWITCH_ALLOC_OUT_LEN);
42         efx_mcdi_req_t req;
43         efx_rc_t rc;
44         uint8_t ntags;
45
46         /* Ensure EFX and MCDI use same values for vswitch types */
47         EFX_STATIC_ASSERT(EFX_VSWITCH_TYPE_VLAN ==
48                 MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_VLAN);
49         EFX_STATIC_ASSERT(EFX_VSWITCH_TYPE_VEB ==
50                 MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_VEB);
51         EFX_STATIC_ASSERT(EFX_VSWITCH_TYPE_MUX ==
52                 MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_MUX);
53
54         /* First try with maximum number of VLAN tags FW supports */
55         ntags = 2;
56 retry:
57         req.emr_cmd = MC_CMD_VSWITCH_ALLOC;
58         req.emr_in_buf = payload;
59         req.emr_in_length = MC_CMD_VSWITCH_ALLOC_IN_LEN;
60         req.emr_out_buf = payload;
61         req.emr_out_length = MC_CMD_VSWITCH_ALLOC_OUT_LEN;
62
63         MCDI_IN_SET_DWORD(req, VSWITCH_ALLOC_IN_UPSTREAM_PORT_ID, vport_id);
64         MCDI_IN_SET_DWORD(req, VSWITCH_ALLOC_IN_TYPE, vswitch_type);
65         MCDI_IN_SET_DWORD(req, VSWITCH_ALLOC_IN_NUM_VLAN_TAGS, ntags);
66         MCDI_IN_POPULATE_DWORD_1(req, VSWITCH_ALLOC_IN_FLAGS,
67                 VSWITCH_ALLOC_IN_FLAG_AUTO_PORT, 0);
68
69         efx_mcdi_execute(enp, &req);
70
71         if (req.emr_rc != 0) {
72                 rc = req.emr_rc;
73                 /*
74                  * efx_rc_t error codes in libefx are translated from MCDI
75                  * error codes in efx_mcdi_request_errcode. As this conversion
76                  * is not a 1:1, here we check the specific MCDI error code.
77                  */
78                 if (req.emr_err_code == MC_CMD_ERR_VLAN_LIMIT) {
79                         /* Too many VLAN tags, retry with fewer */
80                         EFSYS_PROBE(vlan_limit);
81                         ntags--;
82                         if (ntags > 0) {
83                                 /*
84                                  * Zero the buffer before reusing it
85                                  * for another request
86                                  */
87                                 memset(payload, 0, sizeof (payload));
88                                 goto retry;
89                         }
90                         goto fail1;
91                 }
92         }
93
94         return (0);
95
96 fail1:
97         EFSYS_PROBE1(fail1, efx_rc_t, rc);
98         return (rc);
99 }
100
101         __checkReturn   efx_rc_t
102 efx_mcdi_vswitch_free(
103         __in            efx_nic_t *enp)
104 {
105         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VSWITCH_FREE_IN_LEN,
106                 MC_CMD_VSWITCH_FREE_OUT_LEN);
107         efx_mcdi_req_t req;
108         efx_rc_t rc;
109
110         req.emr_cmd = MC_CMD_VSWITCH_FREE;
111         req.emr_in_buf = payload;
112         req.emr_in_length = MC_CMD_VSWITCH_FREE_IN_LEN;
113         req.emr_out_buf = payload;
114         req.emr_out_length = MC_CMD_VSWITCH_FREE_OUT_LEN;
115
116         MCDI_IN_SET_DWORD(req, VSWITCH_FREE_IN_UPSTREAM_PORT_ID,
117                 EVB_PORT_ID_ASSIGNED);
118         efx_mcdi_execute(enp, &req);
119
120         if (req.emr_rc != 0) {
121                 rc = req.emr_rc;
122                 goto fail1;
123         }
124
125         return (0);
126
127 fail1:
128         EFSYS_PROBE1(fail1, efx_rc_t, rc);
129         return (rc);
130 }
131
132         __checkReturn   efx_rc_t
133 efx_mcdi_vport_alloc(
134         __in            efx_nic_t *enp,
135         __in            efx_vport_type_t vport_type,
136         __in            uint16_t vid,
137         __in            boolean_t vlan_restrict,
138         __out           efx_vport_id_t *vport_idp)
139 {
140         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_ALLOC_IN_LEN,
141                 MC_CMD_VPORT_ALLOC_OUT_LEN);
142         efx_mcdi_req_t req;
143         efx_rc_t rc;
144
145         /* Ensure EFX and MCDI use same values for vport types */
146         EFX_STATIC_ASSERT(EFX_VPORT_TYPE_NORMAL ==
147                 MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL);
148         EFX_STATIC_ASSERT(EFX_VPORT_TYPE_EXPANSION ==
149                 MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_EXPANSION);
150         EFX_STATIC_ASSERT(EFX_VPORT_TYPE_TEST ==
151                 MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_TEST);
152
153         req.emr_cmd = MC_CMD_VPORT_ALLOC;
154         req.emr_in_buf = payload;
155         req.emr_in_length = MC_CMD_VPORT_ALLOC_IN_LEN;
156         req.emr_out_buf = payload;
157         req.emr_out_length = MC_CMD_VPORT_ALLOC_OUT_LEN;
158
159         MCDI_IN_SET_DWORD(req, VPORT_ALLOC_IN_UPSTREAM_PORT_ID,
160                 EVB_PORT_ID_ASSIGNED);
161         MCDI_IN_SET_DWORD(req, VPORT_ALLOC_IN_TYPE, vport_type);
162         MCDI_IN_SET_DWORD(req, VPORT_ALLOC_IN_NUM_VLAN_TAGS,
163                 (vid != EFX_FILTER_VID_UNSPEC));
164
165         MCDI_IN_POPULATE_DWORD_2(req, VPORT_ALLOC_IN_FLAGS,
166                 VPORT_ALLOC_IN_FLAG_AUTO_PORT, 0,
167                 VPORT_ALLOC_IN_FLAG_VLAN_RESTRICT, vlan_restrict);
168
169         if (vid != EFX_FILTER_VID_UNSPEC)
170                 MCDI_IN_POPULATE_DWORD_1(req, VPORT_ALLOC_IN_VLAN_TAGS,
171                         VPORT_ALLOC_IN_VLAN_TAG_0, vid);
172
173         efx_mcdi_execute(enp, &req);
174
175         if (req.emr_rc != 0) {
176                 rc = req.emr_rc;
177                 goto fail1;
178         }
179
180         if (req.emr_out_length_used < MC_CMD_VPORT_ALLOC_OUT_LEN) {
181                 rc = EMSGSIZE;
182                 goto fail2;
183         }
184
185         *vport_idp = *MCDI_OUT2(req, uint32_t, VPORT_ALLOC_OUT_VPORT_ID);
186         return (0);
187
188 fail2:
189         EFSYS_PROBE(fail2);
190 fail1:
191         EFSYS_PROBE1(fail1, efx_rc_t, rc);
192         return (rc);
193 }
194
195         __checkReturn   efx_rc_t
196 efx_mcdi_vport_free(
197         __in            efx_nic_t *enp,
198         __in            efx_vport_id_t vport_id)
199 {
200         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_FREE_IN_LEN,
201                 MC_CMD_VPORT_FREE_OUT_LEN);
202         efx_mcdi_req_t req;
203         efx_rc_t rc;
204
205         req.emr_cmd = MC_CMD_VPORT_FREE;
206         req.emr_in_buf = payload;
207         req.emr_in_length = MC_CMD_VPORT_FREE_IN_LEN;
208         req.emr_out_buf = payload;
209         req.emr_out_length = MC_CMD_VPORT_FREE_OUT_LEN;
210
211         MCDI_IN_SET_DWORD(req, VPORT_FREE_IN_VPORT_ID, vport_id);
212         efx_mcdi_execute(enp, &req);
213
214         if (req.emr_rc != 0) {
215                 rc = req.emr_rc;
216                 goto fail1;
217         }
218
219         return (0);
220
221 fail1:
222         EFSYS_PROBE1(fail1, efx_rc_t, rc);
223         return (rc);
224 }
225
226         __checkReturn                   efx_rc_t
227 efx_mcdi_vport_mac_addr_add(
228         __in                            efx_nic_t *enp,
229         __in                            efx_vport_id_t vport_id,
230         __in_bcount(EFX_MAC_ADDR_LEN)   uint8_t *addrp)
231 {
232         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN,
233                 MC_CMD_VPORT_ADD_MAC_ADDRESS_OUT_LEN);
234         efx_mcdi_req_t req;
235         efx_rc_t rc;
236
237         req.emr_cmd = MC_CMD_VPORT_ADD_MAC_ADDRESS;
238         req.emr_in_buf = payload;
239         req.emr_in_length = MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN;
240         req.emr_out_buf = payload;
241         req.emr_out_length = MC_CMD_VPORT_ADD_MAC_ADDRESS_OUT_LEN;
242
243         MCDI_IN_SET_DWORD(req, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, vport_id);
244         EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t,
245                                 VPORT_ADD_MAC_ADDRESS_IN_MACADDR), addrp);
246
247         efx_mcdi_execute(enp, &req);
248
249         if (req.emr_rc != 0) {
250                 rc = req.emr_rc;
251                 goto fail1;
252         }
253
254         return (0);
255
256 fail1:
257         EFSYS_PROBE1(fail1, efx_rc_t, rc);
258         return (rc);
259 }
260
261         __checkReturn                   efx_rc_t
262 efx_mcdi_vport_mac_addr_del(
263         __in                            efx_nic_t *enp,
264         __in                            efx_vport_id_t vport_id,
265         __in_bcount(EFX_MAC_ADDR_LEN)   uint8_t *addrp)
266 {
267         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN,
268                 MC_CMD_VPORT_DEL_MAC_ADDRESS_OUT_LEN);
269         efx_mcdi_req_t req;
270         efx_rc_t rc;
271
272         req.emr_cmd = MC_CMD_VPORT_DEL_MAC_ADDRESS;
273         req.emr_in_buf = payload;
274         req.emr_in_length = MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN;
275         req.emr_out_buf = payload;
276         req.emr_out_length = MC_CMD_VPORT_DEL_MAC_ADDRESS_OUT_LEN;
277
278         MCDI_IN_SET_DWORD(req, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, vport_id);
279         EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t,
280                                 VPORT_DEL_MAC_ADDRESS_IN_MACADDR), addrp);
281
282         efx_mcdi_execute(enp, &req);
283
284         if (req.emr_rc != 0) {
285                 rc = req.emr_rc;
286                 goto fail1;
287         }
288
289         return (0);
290
291 fail1:
292         EFSYS_PROBE1(fail1, efx_rc_t, rc);
293         return (rc);
294 }
295
296         __checkReturn   efx_rc_t
297 efx_mcdi_port_assign(
298         __in            efx_nic_t *enp,
299         __in            efx_vport_id_t vport_id,
300         __in            uint32_t vf_index)
301 {
302         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_EVB_PORT_ASSIGN_IN_LEN,
303                 MC_CMD_EVB_PORT_ASSIGN_OUT_LEN);
304         efx_mcdi_req_t req;
305         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
306         efx_rc_t rc;
307
308         req.emr_cmd = MC_CMD_EVB_PORT_ASSIGN;
309         req.emr_in_buf = payload;
310         req.emr_in_length = MC_CMD_EVB_PORT_ASSIGN_IN_LEN;
311         req.emr_out_buf = payload;
312         req.emr_out_length = MC_CMD_EVB_PORT_ASSIGN_OUT_LEN;
313
314         MCDI_IN_SET_DWORD(req, EVB_PORT_ASSIGN_IN_PORT_ID, vport_id);
315         MCDI_IN_POPULATE_DWORD_2(req, EVB_PORT_ASSIGN_IN_FUNCTION,
316                 EVB_PORT_ASSIGN_IN_PF, encp->enc_pf,
317                 EVB_PORT_ASSIGN_IN_VF, vf_index);
318
319         efx_mcdi_execute(enp, &req);
320
321         if (req.emr_rc != 0) {
322                 rc = req.emr_rc;
323                 goto fail1;
324         }
325
326         return (0);
327
328 fail1:
329         EFSYS_PROBE1(fail1, efx_rc_t, rc);
330         return (rc);
331 }
332
333         __checkReturn                           efx_rc_t
334 efx_mcdi_vport_reconfigure(
335         __in                                    efx_nic_t *enp,
336         __in                                    efx_vport_id_t vport_id,
337         __in_opt                                uint16_t *vidp,
338         __in_bcount_opt(EFX_MAC_ADDR_LEN)       uint8_t *addrp,
339         __out_opt                               boolean_t *fn_resetp)
340 {
341         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_RECONFIGURE_IN_LEN,
342                 MC_CMD_VPORT_RECONFIGURE_OUT_LEN);
343         efx_mcdi_req_t req;
344         efx_rc_t rc;
345         uint32_t reset_flag = 0;
346
347         req.emr_cmd = MC_CMD_VPORT_RECONFIGURE;
348         req.emr_in_buf = payload;
349         req.emr_in_length = MC_CMD_VPORT_RECONFIGURE_IN_LEN;
350         req.emr_out_buf = payload;
351         req.emr_out_length = MC_CMD_VPORT_RECONFIGURE_OUT_LEN;
352
353         MCDI_IN_SET_DWORD(req, VPORT_RECONFIGURE_IN_VPORT_ID, vport_id);
354
355         if (vidp != NULL) {
356                 MCDI_IN_POPULATE_DWORD_1(req, VPORT_RECONFIGURE_IN_FLAGS,
357                         VPORT_RECONFIGURE_IN_REPLACE_VLAN_TAGS, 1);
358                 if (*vidp != EFX_FILTER_VID_UNSPEC) {
359                         MCDI_IN_SET_DWORD(req,
360                                 VPORT_RECONFIGURE_IN_NUM_VLAN_TAGS, 1);
361                         MCDI_IN_POPULATE_DWORD_1(req,
362                                 VPORT_RECONFIGURE_IN_VLAN_TAGS,
363                                 VPORT_RECONFIGURE_IN_VLAN_TAG_0, *vidp);
364                 }
365         }
366
367         if ((addrp != NULL) && (efx_is_zero_eth_addr(addrp) == B_FALSE)) {
368                 MCDI_IN_POPULATE_DWORD_1(req, VPORT_RECONFIGURE_IN_FLAGS,
369                          VPORT_RECONFIGURE_IN_REPLACE_MACADDRS, 1);
370                 MCDI_IN_SET_DWORD(req, VPORT_RECONFIGURE_IN_NUM_MACADDRS, 1);
371                 EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t,
372                                         VPORT_RECONFIGURE_IN_MACADDRS), addrp);
373         }
374
375         efx_mcdi_execute(enp, &req);
376         if (req.emr_rc != 0) {
377                 rc = req.emr_rc;
378                 goto fail1;
379         }
380
381         if (req.emr_out_length_used < MC_CMD_VPORT_RECONFIGURE_OUT_LEN) {
382                 rc = EMSGSIZE;
383                 goto fail2;
384         }
385
386         reset_flag = MCDI_OUT_DWORD_FIELD(req, VPORT_RECONFIGURE_OUT_FLAGS,
387                                             VPORT_RECONFIGURE_OUT_RESET_DONE);
388
389         if (fn_resetp != NULL)
390                 *fn_resetp = (reset_flag != 0);
391
392         return (0);
393
394 fail2:
395         EFSYS_PROBE(fail2);
396 fail1:
397         EFSYS_PROBE1(fail1, efx_rc_t, rc);
398         return (rc);
399 }
400
401         __checkReturn   efx_rc_t
402 ef10_evb_vswitch_alloc(
403         __in            efx_nic_t *enp,
404         __out           efx_vswitch_id_t *vswitch_idp)
405 {
406         efx_rc_t rc;
407         if (vswitch_idp == NULL) {
408                 rc = EINVAL;
409                 goto fail1;
410         }
411
412         if ((rc = efx_mcdi_vswitch_alloc(enp, EVB_PORT_ID_ASSIGNED,
413                         EFX_VSWITCH_TYPE_VEB)) != 0) {
414                 goto fail2;
415         }
416
417         *vswitch_idp = EFX_DEFAULT_VSWITCH_ID;
418         return (0);
419
420 fail2:
421         EFSYS_PROBE(fail2);
422 fail1:
423         EFSYS_PROBE1(fail1, efx_rc_t, rc);
424         return (rc);
425 }
426
427         __checkReturn   efx_rc_t
428 ef10_evb_vswitch_free(
429         __in            efx_nic_t *enp,
430         __in            efx_vswitch_id_t vswitch_id)
431 {
432         _NOTE(ARGUNUSED(vswitch_id))
433
434         return (efx_mcdi_vswitch_free(enp));
435 }
436
437         __checkReturn   efx_rc_t
438 ef10_evb_vport_alloc(
439         __in            efx_nic_t *enp,
440         __in            efx_vswitch_id_t vswitch_id,
441         __in            efx_vport_type_t vport_type,
442         __in            uint16_t vid,
443         __in            boolean_t vlan_restrict,
444         __out           efx_vport_id_t *vport_idp)
445 {
446         _NOTE(ARGUNUSED(vswitch_id))
447
448         return (efx_mcdi_vport_alloc(enp,
449                         vport_type, vid,
450                         vlan_restrict, vport_idp));
451 }
452
453         __checkReturn   efx_rc_t
454 ef10_evb_vport_free(
455         __in            efx_nic_t *enp,
456         __in            efx_vswitch_id_t vswitch_id,
457         __in            efx_vport_id_t vport_id)
458 {
459         _NOTE(ARGUNUSED(vswitch_id))
460
461         return (efx_mcdi_vport_free(enp, vport_id));
462 }
463
464         __checkReturn                   efx_rc_t
465 ef10_evb_vport_mac_addr_add(
466         __in                            efx_nic_t *enp,
467         __in                            efx_vswitch_id_t vswitch_id,
468         __in                            efx_vport_id_t vport_id,
469         __in_bcount(EFX_MAC_ADDR_LEN)   uint8_t *addrp)
470 {
471         _NOTE(ARGUNUSED(vswitch_id))
472         EFSYS_ASSERT(addrp != NULL);
473
474         return (efx_mcdi_vport_mac_addr_add(enp, vport_id, addrp));
475 }
476
477         __checkReturn                   efx_rc_t
478 ef10_evb_vport_mac_addr_del(
479         __in                            efx_nic_t *enp,
480         __in                            efx_vswitch_id_t vswitch_id,
481         __in                            efx_vport_id_t vport_id,
482         __in_bcount(EFX_MAC_ADDR_LEN)   uint8_t *addrp)
483 {
484         _NOTE(ARGUNUSED(vswitch_id))
485         EFSYS_ASSERT(addrp != NULL);
486
487         return (efx_mcdi_vport_mac_addr_del(enp, vport_id, addrp));
488 }
489
490         __checkReturn   efx_rc_t
491 ef10_evb_vadaptor_alloc(
492         __in            efx_nic_t *enp,
493         __in            efx_vswitch_id_t vswitch_id,
494         __in            efx_vport_id_t vport_id)
495 {
496         _NOTE(ARGUNUSED(vswitch_id))
497
498         return (efx_mcdi_vadaptor_alloc(enp, vport_id));
499 }
500
501         __checkReturn   efx_rc_t
502 ef10_evb_vadaptor_free(
503         __in            efx_nic_t *enp,
504         __in            efx_vswitch_id_t vswitch_id,
505         __in            efx_vport_id_t vport_id)
506 {
507         _NOTE(ARGUNUSED(vswitch_id))
508
509         return (efx_mcdi_vadaptor_free(enp, vport_id));
510 }
511
512         __checkReturn   efx_rc_t
513 ef10_evb_vport_assign(
514         __in            efx_nic_t *enp,
515         __in            efx_vswitch_id_t vswitch_id,
516         __in            efx_vport_id_t vport_id,
517         __in    uint32_t vf_index)
518 {
519         _NOTE(ARGUNUSED(vswitch_id))
520
521         return (efx_mcdi_port_assign(enp, vport_id, vf_index));
522 }
523
524         __checkReturn                           efx_rc_t
525 ef10_evb_vport_reconfigure(
526         __in                                    efx_nic_t *enp,
527         __in                                    efx_vswitch_id_t vswitch_id,
528         __in                                    efx_vport_id_t vport_id,
529         __in_opt                                uint16_t *vidp,
530         __in_bcount_opt(EFX_MAC_ADDR_LEN)       uint8_t *addrp,
531         __out_opt                               boolean_t *fn_resetp)
532 {
533         _NOTE(ARGUNUSED(vswitch_id))
534
535         return (efx_mcdi_vport_reconfigure(enp, vport_id, vidp,
536                         addrp, fn_resetp));
537 }
538
539 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
540 #endif /* EFSYS_OPT_EVB */