net/sfc/base: support data path with EVB module
[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 ef10_evb_vswitch_alloc(
335         __in            efx_nic_t *enp,
336         __out           efx_vswitch_id_t *vswitch_idp)
337 {
338         efx_rc_t rc;
339         if (vswitch_idp == NULL) {
340                 rc = EINVAL;
341                 goto fail1;
342         }
343
344         if ((rc = efx_mcdi_vswitch_alloc(enp, EVB_PORT_ID_ASSIGNED,
345                         EFX_VSWITCH_TYPE_VEB)) != 0) {
346                 goto fail2;
347         }
348
349         *vswitch_idp = EFX_DEFAULT_VSWITCH_ID;
350         return (0);
351
352 fail2:
353         EFSYS_PROBE(fail2);
354 fail1:
355         EFSYS_PROBE1(fail1, efx_rc_t, rc);
356         return (rc);
357 }
358
359         __checkReturn   efx_rc_t
360 ef10_evb_vswitch_free(
361         __in            efx_nic_t *enp,
362         __in            efx_vswitch_id_t vswitch_id)
363 {
364         _NOTE(ARGUNUSED(vswitch_id))
365
366         return (efx_mcdi_vswitch_free(enp));
367 }
368
369         __checkReturn   efx_rc_t
370 ef10_evb_vport_alloc(
371         __in            efx_nic_t *enp,
372         __in            efx_vswitch_id_t vswitch_id,
373         __in            efx_vport_type_t vport_type,
374         __in            uint16_t vid,
375         __in            boolean_t vlan_restrict,
376         __out           efx_vport_id_t *vport_idp)
377 {
378         _NOTE(ARGUNUSED(vswitch_id))
379
380         return (efx_mcdi_vport_alloc(enp,
381                         vport_type, vid,
382                         vlan_restrict, vport_idp));
383 }
384
385         __checkReturn   efx_rc_t
386 ef10_evb_vport_free(
387         __in            efx_nic_t *enp,
388         __in            efx_vswitch_id_t vswitch_id,
389         __in            efx_vport_id_t vport_id)
390 {
391         _NOTE(ARGUNUSED(vswitch_id))
392
393         return (efx_mcdi_vport_free(enp, vport_id));
394 }
395
396         __checkReturn                   efx_rc_t
397 ef10_evb_vport_mac_addr_add(
398         __in                            efx_nic_t *enp,
399         __in                            efx_vswitch_id_t vswitch_id,
400         __in                            efx_vport_id_t vport_id,
401         __in_bcount(EFX_MAC_ADDR_LEN)   uint8_t *addrp)
402 {
403         _NOTE(ARGUNUSED(vswitch_id))
404         EFSYS_ASSERT(addrp != NULL);
405
406         return (efx_mcdi_vport_mac_addr_add(enp, vport_id, addrp));
407 }
408
409         __checkReturn                   efx_rc_t
410 ef10_evb_vport_mac_addr_del(
411         __in                            efx_nic_t *enp,
412         __in                            efx_vswitch_id_t vswitch_id,
413         __in                            efx_vport_id_t vport_id,
414         __in_bcount(EFX_MAC_ADDR_LEN)   uint8_t *addrp)
415 {
416         _NOTE(ARGUNUSED(vswitch_id))
417         EFSYS_ASSERT(addrp != NULL);
418
419         return (efx_mcdi_vport_mac_addr_del(enp, vport_id, addrp));
420 }
421
422         __checkReturn   efx_rc_t
423 ef10_evb_vadaptor_alloc(
424         __in            efx_nic_t *enp,
425         __in            efx_vswitch_id_t vswitch_id,
426         __in            efx_vport_id_t vport_id)
427 {
428         _NOTE(ARGUNUSED(vswitch_id))
429
430         return (efx_mcdi_vadaptor_alloc(enp, vport_id));
431 }
432
433         __checkReturn   efx_rc_t
434 ef10_evb_vadaptor_free(
435         __in            efx_nic_t *enp,
436         __in            efx_vswitch_id_t vswitch_id,
437         __in            efx_vport_id_t vport_id)
438 {
439         _NOTE(ARGUNUSED(vswitch_id))
440
441         return (efx_mcdi_vadaptor_free(enp, vport_id));
442 }
443
444         __checkReturn   efx_rc_t
445 ef10_evb_vport_assign(
446         __in            efx_nic_t *enp,
447         __in            efx_vswitch_id_t vswitch_id,
448         __in            efx_vport_id_t vport_id,
449         __in    uint32_t vf_index)
450 {
451         _NOTE(ARGUNUSED(vswitch_id))
452
453         return (efx_mcdi_port_assign(enp, vport_id, vf_index));
454 }
455
456 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
457 #endif /* EFSYS_OPT_EVB */