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 */ 471