common/sfc_efx: update copyright year
[dpdk.git] / drivers / common / sfc_efx / base / ef10_proxy.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2021 Xilinx, Inc.
4  * Copyright(c) 2018-2019 Solarflare Communications Inc.
5  */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
11
12         __checkReturn   efx_rc_t
13 ef10_proxy_auth_init(
14         __in            efx_nic_t *enp)
15 {
16         EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
17
18         return (0);
19 }
20
21                         void
22 ef10_proxy_auth_fini(
23         __in            efx_nic_t *enp)
24 {
25         EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
26 }
27
28 static  __checkReturn   efx_rc_t
29 efx_mcdi_proxy_configure(
30         __in            efx_nic_t *enp,
31         __in            boolean_t disable_proxy,
32         __in            uint64_t req_buffer_addr,
33         __in            uint64_t resp_buffer_addr,
34         __in            uint64_t stat_buffer_addr,
35         __in            size_t req_size,
36         __in            size_t resp_size,
37         __in            uint32_t block_cnt,
38         __in            uint8_t *op_maskp,
39         __in            size_t op_mask_size)
40 {
41         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PROXY_CONFIGURE_EXT_IN_LEN,
42                 MC_CMD_PROXY_CONFIGURE_OUT_LEN);
43         efx_mcdi_req_t req;
44         efx_rc_t rc;
45
46         req.emr_cmd = MC_CMD_PROXY_CONFIGURE;
47         req.emr_in_buf = payload;
48         req.emr_in_length = MC_CMD_PROXY_CONFIGURE_EXT_IN_LEN;
49         req.emr_out_buf = payload;
50         req.emr_out_length = MC_CMD_PROXY_CONFIGURE_OUT_LEN;
51
52         if (!disable_proxy) {
53                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_FLAGS, 1);
54                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BUFF_ADDR_LO,
55                         req_buffer_addr & 0xffffffff);
56                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BUFF_ADDR_HI,
57                         req_buffer_addr >> 32);
58                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BUFF_ADDR_LO,
59                         resp_buffer_addr & 0xffffffff);
60                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BUFF_ADDR_HI,
61                         resp_buffer_addr >> 32);
62                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BUFF_ADDR_LO,
63                         stat_buffer_addr & 0xffffffff);
64                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BUFF_ADDR_HI,
65                         stat_buffer_addr >> 32);
66                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REQUEST_BLOCK_SIZE,
67                         req_size);
68                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_REPLY_BLOCK_SIZE,
69                         resp_size);
70                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_STATUS_BLOCK_SIZE,
71                         MC_PROXY_STATUS_BUFFER_LEN);
72                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_IN_NUM_BLOCKS,
73                         block_cnt);
74                 memcpy(MCDI_IN2(req, efx_byte_t,
75                                 PROXY_CONFIGURE_IN_ALLOWED_MCDI_MASK),
76                         op_maskp, op_mask_size);
77                 MCDI_IN_SET_DWORD(req, PROXY_CONFIGURE_EXT_IN_RESERVED,
78                         EFX_PROXY_CONFIGURE_MAGIC);
79         }
80
81         efx_mcdi_execute(enp, &req);
82
83         if (req.emr_rc != 0) {
84                 rc = req.emr_rc;
85                 goto fail1;
86         }
87
88         return (0);
89
90 fail1:
91         EFSYS_PROBE1(fail1, efx_rc_t, rc);
92         return (rc);
93 }
94
95 static  __checkReturn   efx_rc_t
96 efx_mcdi_privilege_modify(
97         __in            efx_nic_t *enp,
98         __in            uint32_t fn_group,
99         __in            uint32_t pf_index,
100         __in            uint32_t vf_index,
101         __in            uint32_t add_privileges_mask,
102         __in            uint32_t remove_privileges_mask)
103 {
104         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MODIFY_IN_LEN,
105                 MC_CMD_PRIVILEGE_MODIFY_OUT_LEN);
106         efx_mcdi_req_t req;
107         efx_rc_t rc;
108
109         req.emr_cmd = MC_CMD_PRIVILEGE_MODIFY;
110         req.emr_in_buf = payload;
111         req.emr_in_length = MC_CMD_PRIVILEGE_MODIFY_IN_LEN;
112         req.emr_out_buf = payload;
113         req.emr_out_length = MC_CMD_PRIVILEGE_MODIFY_OUT_LEN;
114
115         EFSYS_ASSERT(fn_group <= MC_CMD_PRIVILEGE_MODIFY_IN_ONE);
116
117         MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_FN_GROUP, fn_group);
118
119         if ((fn_group == MC_CMD_PRIVILEGE_MODIFY_IN_ONE) ||
120             (fn_group == MC_CMD_PRIVILEGE_MODIFY_IN_VFS_OF_PF)) {
121                 MCDI_IN_POPULATE_DWORD_2(req,
122                     PRIVILEGE_MODIFY_IN_FUNCTION,
123                     PRIVILEGE_MODIFY_IN_FUNCTION_PF, pf_index,
124                     PRIVILEGE_MODIFY_IN_FUNCTION_VF, vf_index);
125         }
126
127         MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_ADD_MASK,
128                 add_privileges_mask);
129         MCDI_IN_SET_DWORD(req, PRIVILEGE_MODIFY_IN_REMOVE_MASK,
130                 remove_privileges_mask);
131
132         efx_mcdi_execute(enp, &req);
133
134         if (req.emr_rc != 0) {
135                 rc = req.emr_rc;
136                 goto fail1;
137         }
138
139         return (0);
140
141 fail1:
142         EFSYS_PROBE1(fail1, efx_rc_t, rc);
143         return (rc);
144 }
145
146 static  __checkReturn                   efx_rc_t
147 efx_proxy_auth_fill_op_mask(
148         __in_ecount(op_count)           uint32_t *op_listp,
149         __in                            size_t op_count,
150         __out_ecount(op_mask_size)      uint32_t *op_maskp,
151         __in                            size_t op_mask_size)
152 {
153         efx_rc_t rc;
154         uint32_t op;
155
156         if ((op_listp == NULL) || (op_maskp == NULL)) {
157                 rc = EINVAL;
158                 goto fail1;
159         }
160
161         while (op_count--) {
162                 op = *op_listp++;
163                 if (op > op_mask_size * 32) {
164                         rc = EINVAL;
165                         goto fail2;
166                 }
167                 op_maskp[op / 32] |= 1u << (op & 31);
168         }
169
170         return (0);
171
172 fail2:
173         EFSYS_PROBE(fail2);
174 fail1:
175         EFSYS_PROBE1(fail1, efx_rc_t, rc);
176         return (rc);
177 }
178
179         __checkReturn           efx_rc_t
180 ef10_proxy_auth_mc_config(
181         __in                    efx_nic_t *enp,
182         __in_ecount(block_cnt)  efsys_mem_t *request_bufferp,
183         __in_ecount(block_cnt)  efsys_mem_t *response_bufferp,
184         __in_ecount(block_cnt)  efsys_mem_t *status_bufferp,
185         __in                    uint32_t block_cnt,
186         __in_ecount(op_count)   uint32_t *op_listp,
187         __in                    size_t op_count)
188 {
189 #define PROXY_OPS_MASK_SIZE                                             \
190         (EFX_DIV_ROUND_UP(                                              \
191             MC_CMD_PROXY_CONFIGURE_IN_ALLOWED_MCDI_MASK_LEN,            \
192             sizeof (uint32_t)))
193
194         efx_rc_t rc;
195         uint32_t op_mask[PROXY_OPS_MASK_SIZE] = {0};
196
197         /* Prepare the operation mask from operation list array */
198         if ((rc = efx_proxy_auth_fill_op_mask(op_listp, op_count,
199                         op_mask, PROXY_OPS_MASK_SIZE) != 0))
200                 goto fail1;
201
202         if ((rc = efx_mcdi_proxy_configure(enp, B_FALSE,
203                         EFSYS_MEM_ADDR(request_bufferp),
204                         EFSYS_MEM_ADDR(response_bufferp),
205                         EFSYS_MEM_ADDR(status_bufferp),
206                         EFSYS_MEM_SIZE(request_bufferp) / block_cnt,
207                         EFSYS_MEM_SIZE(response_bufferp) / block_cnt,
208                         block_cnt, (uint8_t *)&op_mask,
209                         sizeof (op_mask))) != 0)
210                 goto fail2;
211
212         return (0);
213
214 fail2:
215         EFSYS_PROBE(fail2);
216
217 fail1:
218         EFSYS_PROBE1(fail1, efx_rc_t, rc);
219         return (rc);
220 }
221
222         __checkReturn   efx_rc_t
223 ef10_proxy_auth_disable(
224         __in            efx_nic_t *enp)
225 {
226         efx_rc_t rc;
227
228         if ((rc = efx_mcdi_proxy_configure(enp, B_TRUE,
229                         0, 0, 0, 0, 0, 0, NULL, 0) != 0))
230                 goto fail1;
231
232         return (0);
233
234 fail1:
235         EFSYS_PROBE1(fail1, efx_rc_t, rc);
236         return (rc);
237 }
238
239         __checkReturn   efx_rc_t
240 ef10_proxy_auth_privilege_modify(
241         __in            efx_nic_t *enp,
242         __in            uint32_t fn_group,
243         __in            uint32_t pf_index,
244         __in            uint32_t vf_index,
245         __in            uint32_t add_privileges_mask,
246         __in            uint32_t remove_privileges_mask)
247 {
248         return (efx_mcdi_privilege_modify(enp, fn_group, pf_index, vf_index,
249                         add_privileges_mask, remove_privileges_mask));
250 }
251
252 static  __checkReturn   efx_rc_t
253 efx_mcdi_privilege_mask_set(
254         __in            efx_nic_t *enp,
255         __in            uint32_t vf_index,
256         __in            uint32_t mask,
257         __in            uint32_t value)
258 {
259         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MASK_IN_LEN,
260                 MC_CMD_PRIVILEGE_MASK_OUT_LEN);
261         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
262         efx_mcdi_req_t req;
263         efx_rc_t rc;
264         uint32_t old_mask = 0;
265         uint32_t new_mask = 0;
266
267         EFSYS_ASSERT((value & ~mask) == 0);
268
269         req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
270         req.emr_in_buf = payload;
271         req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
272         req.emr_out_buf = payload;
273         req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
274
275         /* Get privilege mask */
276         MCDI_IN_POPULATE_DWORD_2(req, PRIVILEGE_MASK_IN_FUNCTION,
277                 PRIVILEGE_MASK_IN_FUNCTION_PF, encp->enc_pf,
278                 PRIVILEGE_MASK_IN_FUNCTION_VF, vf_index);
279
280         efx_mcdi_execute(enp, &req);
281
282         if (req.emr_rc != 0) {
283                 rc = req.emr_rc;
284                 goto fail1;
285         }
286
287         if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
288                 rc = EMSGSIZE;
289                 goto fail2;
290         }
291
292         old_mask = *MCDI_OUT2(req, uint32_t, PRIVILEGE_MASK_OUT_OLD_MASK);
293         new_mask = old_mask & ~mask;
294         new_mask |= (value & mask);
295
296         if (new_mask == old_mask)
297                 return (0);
298
299         new_mask |= MC_CMD_PRIVILEGE_MASK_IN_DO_CHANGE;
300         memset(payload, 0, sizeof (payload));
301
302         req.emr_cmd = MC_CMD_PRIVILEGE_MASK;
303         req.emr_in_buf = payload;
304         req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN;
305         req.emr_out_buf = payload;
306         req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN;
307
308         /* Set privilege mask */
309         MCDI_IN_SET_DWORD(req, PRIVILEGE_MASK_IN_NEW_MASK, new_mask);
310
311         efx_mcdi_execute(enp, &req);
312         if (req.emr_rc != 0) {
313                 rc = req.emr_rc;
314                 goto fail3;
315         }
316
317         if (req.emr_out_length_used != MC_CMD_PRIVILEGE_MASK_OUT_LEN) {
318                 rc = EMSGSIZE;
319                 goto fail4;
320         }
321
322         return (0);
323
324 fail4:
325         EFSYS_PROBE(fail4);
326 fail3:
327         EFSYS_PROBE(fail3);
328 fail2:
329         EFSYS_PROBE(fail2);
330 fail1:
331         EFSYS_PROBE1(fail1, efx_rc_t, rc);
332         return (rc);
333 }
334
335         __checkReturn   efx_rc_t
336 ef10_proxy_auth_set_privilege_mask(
337         __in            efx_nic_t *enp,
338         __in            uint32_t vf_index,
339         __in            uint32_t mask,
340         __in            uint32_t value)
341 {
342         return (efx_mcdi_privilege_mask_set(enp, vf_index,
343                         mask, value));
344 }
345
346 static  __checkReturn   efx_rc_t
347 efx_mcdi_proxy_complete(
348         __in            efx_nic_t *enp,
349         __in            uint32_t fn_index,
350         __in            uint32_t proxy_result,
351         __in            uint32_t handle)
352 {
353         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PROXY_COMPLETE_IN_LEN,
354                 MC_CMD_PROXY_COMPLETE_OUT_LEN);
355         efx_mcdi_req_t req;
356         efx_rc_t rc;
357
358         req.emr_cmd = MC_CMD_PROXY_COMPLETE;
359         req.emr_in_buf = payload;
360         req.emr_in_length = MC_CMD_PROXY_COMPLETE_IN_LEN;
361         req.emr_out_buf = payload;
362         req.emr_out_length = MC_CMD_PROXY_COMPLETE_OUT_LEN;
363
364         MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_BLOCK_INDEX, fn_index);
365         MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_STATUS, proxy_result);
366         MCDI_IN_SET_DWORD(req, PROXY_COMPLETE_IN_HANDLE, handle);
367
368         efx_mcdi_execute(enp, &req);
369
370         if (req.emr_rc != 0) {
371                 rc = req.emr_rc;
372                 goto fail1;
373         }
374
375         return (0);
376
377 fail1:
378         EFSYS_PROBE1(fail1, efx_rc_t, rc);
379         return (rc);
380 }
381
382         __checkReturn   efx_rc_t
383 ef10_proxy_auth_complete_request(
384         __in            efx_nic_t *enp,
385         __in            uint32_t fn_index,
386         __in            uint32_t proxy_result,
387         __in            uint32_t handle)
388 {
389         return (efx_mcdi_proxy_complete(enp, fn_index,
390                         proxy_result, handle));
391 }
392
393 static  __checkReturn                   efx_rc_t
394 efx_mcdi_proxy_cmd(
395         __in                            efx_nic_t *enp,
396         __in                            uint32_t pf_index,
397         __in                            uint32_t vf_index,
398         __in_bcount(request_size)       uint8_t *request_bufferp,
399         __in                            size_t request_size,
400         __out_bcount(response_size)     uint8_t *response_bufferp,
401         __in                            size_t response_size,
402         __out_opt                       size_t *response_size_actualp)
403 {
404         efx_dword_t *inbufp;
405         efx_mcdi_req_t req;
406         efx_rc_t rc;
407
408         if (request_size % sizeof (*inbufp) != 0) {
409                 rc = EINVAL;
410                 goto fail1;
411         }
412
413         EFSYS_KMEM_ALLOC(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
414
415         req.emr_cmd = MC_CMD_PROXY_CMD;
416         req.emr_in_buf = (uint8_t *) inbufp;
417         req.emr_in_length = MC_CMD_PROXY_CMD_IN_LEN + request_size;
418         req.emr_out_buf = response_bufferp;
419         req.emr_out_length = response_size;
420
421         MCDI_IN_POPULATE_DWORD_2(req, PROXY_CMD_IN_TARGET,
422                  PROXY_CMD_IN_TARGET_PF, pf_index,
423                  PROXY_CMD_IN_TARGET_VF, vf_index);
424
425         /* Proxied command should be located just after PROXY_CMD */
426         memcpy(&inbufp[MC_CMD_PROXY_CMD_IN_LEN / sizeof (*inbufp)],
427                 request_bufferp, request_size);
428
429         efx_mcdi_execute(enp, &req);
430
431         EFSYS_KMEM_FREE(enp, (MC_CMD_PROXY_CMD_IN_LEN + request_size), inbufp);
432         if (req.emr_rc != 0) {
433                 rc = req.emr_rc;
434                 goto fail2;
435         }
436
437         if (response_size_actualp != NULL)
438                 *response_size_actualp = req.emr_out_length_used;
439
440         return (0);
441
442 fail2:
443         EFSYS_PROBE(fail2);
444 fail1:
445         EFSYS_PROBE1(fail1, efx_rc_t, rc);
446         return (rc);
447 }
448
449         __checkReturn   efx_rc_t
450 ef10_proxy_auth_get_privilege_mask(
451         __in            efx_nic_t *enp,
452         __in            uint32_t pf_index,
453         __in            uint32_t vf_index,
454         __out           uint32_t *maskp)
455 {
456         return (efx_mcdi_privilege_mask(enp, pf_index, vf_index, maskp));
457 }
458
459
460         __checkReturn   efx_rc_t
461 ef10_proxy_auth_exec_cmd(
462         __in            efx_nic_t *enp,
463         __inout         efx_proxy_cmd_params_t *paramsp)
464 {
465         return (efx_mcdi_proxy_cmd(enp, paramsp->pf_index, paramsp->vf_index,
466                         paramsp->request_bufferp, paramsp->request_size,
467                         paramsp->response_bufferp, paramsp->response_size,
468                         paramsp->response_size_actualp));
469 }
470 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */