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