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
ef10_proxy_auth_init(__in efx_nic_t * enp)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
ef10_proxy_auth_fini(__in efx_nic_t * enp)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
efx_mcdi_proxy_configure(__in efx_nic_t * enp,__in boolean_t disable_proxy,__in uint64_t req_buffer_addr,__in uint64_t resp_buffer_addr,__in uint64_t stat_buffer_addr,__in size_t req_size,__in size_t resp_size,__in uint32_t block_cnt,__in uint8_t * op_maskp,__in size_t op_mask_size)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
efx_mcdi_privilege_modify(__in efx_nic_t * enp,__in uint32_t fn_group,__in uint32_t pf_index,__in uint32_t vf_index,__in uint32_t add_privileges_mask,__in uint32_t remove_privileges_mask)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
efx_proxy_auth_fill_op_mask(__in_ecount (op_count)uint32_t * op_listp,__in size_t op_count,__out_ecount (op_mask_size)uint32_t * op_maskp,__in size_t op_mask_size)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
ef10_proxy_auth_mc_config(__in efx_nic_t * enp,__in_ecount (block_cnt)efsys_mem_t * request_bufferp,__in_ecount (block_cnt)efsys_mem_t * response_bufferp,__in_ecount (block_cnt)efsys_mem_t * status_bufferp,__in uint32_t block_cnt,__in_ecount (op_count)uint32_t * op_listp,__in size_t op_count)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
ef10_proxy_auth_disable(__in efx_nic_t * enp)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
ef10_proxy_auth_privilege_modify(__in efx_nic_t * enp,__in uint32_t fn_group,__in uint32_t pf_index,__in uint32_t vf_index,__in uint32_t add_privileges_mask,__in uint32_t remove_privileges_mask)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
efx_mcdi_privilege_mask_set(__in efx_nic_t * enp,__in uint32_t vf_index,__in uint32_t mask,__in uint32_t value)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
ef10_proxy_auth_set_privilege_mask(__in efx_nic_t * enp,__in uint32_t vf_index,__in uint32_t mask,__in uint32_t value)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
efx_mcdi_proxy_complete(__in efx_nic_t * enp,__in uint32_t fn_index,__in uint32_t proxy_result,__in uint32_t handle)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
ef10_proxy_auth_complete_request(__in efx_nic_t * enp,__in uint32_t fn_index,__in uint32_t proxy_result,__in uint32_t handle)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
efx_mcdi_proxy_cmd(__in efx_nic_t * enp,__in uint32_t pf_index,__in uint32_t vf_index,__in_bcount (request_size)uint8_t * request_bufferp,__in size_t request_size,__out_bcount (response_size)uint8_t * response_bufferp,__in size_t response_size,__out_opt size_t * response_size_actualp)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
ef10_proxy_auth_get_privilege_mask(__in efx_nic_t * enp,__in uint32_t pf_index,__in uint32_t vf_index,__out uint32_t * maskp)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
ef10_proxy_auth_exec_cmd(__in efx_nic_t * enp,__inout efx_proxy_cmd_params_t * paramsp)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 */
471