net/sfc/base: add MCDI wrappers for vPort and vSwitch in EVB
[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_ecount(6)  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_ecount(6)  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 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
334 #endif /* EFSYS_OPT_EVB */