1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2021 Xilinx, Inc. 4 * Copyright(c) 2009-2019 Solarflare Communications Inc. 5 */ 6 7 #include "efx.h" 8 #include "efx_impl.h" 9 10 #if EFSYS_OPT_VPD 11 12 #if EFSYS_OPT_SIENA 13 14 static __checkReturn efx_rc_t 15 siena_vpd_get_static( 16 __in efx_nic_t *enp, 17 __in uint32_t partn, 18 __deref_out_bcount_opt(*sizep) caddr_t *svpdp, 19 __out size_t *sizep) 20 { 21 siena_mc_static_config_hdr_t *scfg; 22 caddr_t svpd; 23 size_t size; 24 uint8_t cksum; 25 unsigned int vpd_offset; 26 unsigned int vpd_length; 27 unsigned int hdr_length; 28 unsigned int pos; 29 unsigned int region; 30 efx_rc_t rc; 31 32 EFSYS_ASSERT(partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 || 33 partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1); 34 35 /* Allocate sufficient memory for the entire static cfg area */ 36 if ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0) 37 goto fail1; 38 39 if (size < SIENA_NVRAM_CHUNK) { 40 rc = EINVAL; 41 goto fail2; 42 } 43 44 EFSYS_KMEM_ALLOC(enp->en_esip, size, scfg); 45 if (scfg == NULL) { 46 rc = ENOMEM; 47 goto fail3; 48 } 49 50 if ((rc = siena_nvram_partn_read(enp, partn, 0, 51 (caddr_t)scfg, SIENA_NVRAM_CHUNK)) != 0) 52 goto fail4; 53 54 /* Verify the magic number */ 55 if (EFX_DWORD_FIELD(scfg->magic, EFX_DWORD_0) != 56 SIENA_MC_STATIC_CONFIG_MAGIC) { 57 rc = EINVAL; 58 goto fail5; 59 } 60 61 /* All future versions of the structure must be backwards compatible */ 62 EFX_STATIC_ASSERT(SIENA_MC_STATIC_CONFIG_VERSION == 0); 63 64 hdr_length = EFX_WORD_FIELD(scfg->length, EFX_WORD_0); 65 vpd_offset = EFX_DWORD_FIELD(scfg->static_vpd_offset, EFX_DWORD_0); 66 vpd_length = EFX_DWORD_FIELD(scfg->static_vpd_length, EFX_DWORD_0); 67 68 /* Verify the hdr doesn't overflow the sector size */ 69 if (hdr_length > size || vpd_offset > size || vpd_length > size || 70 vpd_length + vpd_offset > size) { 71 rc = EINVAL; 72 goto fail6; 73 } 74 75 /* Read the remainder of scfg + static vpd */ 76 region = vpd_offset + vpd_length; 77 if (region > SIENA_NVRAM_CHUNK) { 78 if ((rc = siena_nvram_partn_read(enp, partn, SIENA_NVRAM_CHUNK, 79 (caddr_t)scfg + SIENA_NVRAM_CHUNK, 80 region - SIENA_NVRAM_CHUNK)) != 0) 81 goto fail7; 82 } 83 84 /* Verify checksum */ 85 cksum = 0; 86 for (pos = 0; pos < hdr_length; pos++) 87 cksum += ((uint8_t *)scfg)[pos]; 88 if (cksum != 0) { 89 rc = EINVAL; 90 goto fail8; 91 } 92 93 if (vpd_length == 0) 94 svpd = NULL; 95 else { 96 /* Copy the vpd data out */ 97 EFSYS_KMEM_ALLOC(enp->en_esip, vpd_length, svpd); 98 if (svpd == NULL) { 99 rc = ENOMEM; 100 goto fail9; 101 } 102 memcpy(svpd, (caddr_t)scfg + vpd_offset, vpd_length); 103 } 104 105 EFSYS_KMEM_FREE(enp->en_esip, size, scfg); 106 107 *svpdp = svpd; 108 *sizep = vpd_length; 109 110 return (0); 111 112 fail9: 113 EFSYS_PROBE(fail9); 114 fail8: 115 EFSYS_PROBE(fail8); 116 fail7: 117 EFSYS_PROBE(fail7); 118 fail6: 119 EFSYS_PROBE(fail6); 120 fail5: 121 EFSYS_PROBE(fail5); 122 fail4: 123 EFSYS_PROBE(fail4); 124 125 EFSYS_KMEM_FREE(enp->en_esip, size, scfg); 126 127 fail3: 128 EFSYS_PROBE(fail3); 129 fail2: 130 EFSYS_PROBE(fail2); 131 fail1: 132 EFSYS_PROBE1(fail1, efx_rc_t, rc); 133 134 return (rc); 135 } 136 137 __checkReturn efx_rc_t 138 siena_vpd_init( 139 __in efx_nic_t *enp) 140 { 141 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 142 caddr_t svpd = NULL; 143 unsigned int partn; 144 size_t size = 0; 145 efx_rc_t rc; 146 147 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 148 149 partn = (emip->emi_port == 1) 150 ? MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 151 : MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1; 152 153 /* 154 * We need the static VPD sector to present a unified static+dynamic 155 * VPD, that is, basically on every read, write, verify cycle. Since 156 * it should *never* change we can just cache it here. 157 */ 158 if ((rc = siena_vpd_get_static(enp, partn, &svpd, &size)) != 0) 159 goto fail1; 160 161 if (svpd != NULL && size > 0) { 162 if ((rc = efx_vpd_hunk_verify(svpd, size, NULL)) != 0) 163 goto fail2; 164 } 165 166 enp->en_u.siena.enu_svpd = svpd; 167 enp->en_u.siena.enu_svpd_length = size; 168 169 return (0); 170 171 fail2: 172 EFSYS_PROBE(fail2); 173 174 EFSYS_KMEM_FREE(enp->en_esip, size, svpd); 175 fail1: 176 EFSYS_PROBE1(fail1, efx_rc_t, rc); 177 178 return (rc); 179 } 180 181 __checkReturn efx_rc_t 182 siena_vpd_size( 183 __in efx_nic_t *enp, 184 __out size_t *sizep) 185 { 186 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 187 uint32_t partn; 188 efx_rc_t rc; 189 190 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 191 192 /* 193 * This function returns the total size the user should allocate 194 * for all VPD operations. We've already cached the static vpd, 195 * so we just need to return an upper bound on the dynamic vpd. 196 * Since the dynamic_config structure can change under our feet, 197 * (as version numbers are inserted), just be safe and return the 198 * total size of the dynamic_config *sector* 199 */ 200 partn = (emip->emi_port == 1) 201 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 202 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1; 203 204 if ((rc = siena_nvram_partn_size(enp, partn, sizep)) != 0) 205 goto fail1; 206 207 return (0); 208 209 fail1: 210 EFSYS_PROBE1(fail1, efx_rc_t, rc); 211 212 return (rc); 213 } 214 215 __checkReturn efx_rc_t 216 siena_vpd_read( 217 __in efx_nic_t *enp, 218 __out_bcount(size) caddr_t data, 219 __in size_t size) 220 { 221 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 222 siena_mc_dynamic_config_hdr_t *dcfg = NULL; 223 unsigned int vpd_length; 224 unsigned int vpd_offset; 225 unsigned int dcfg_partn; 226 size_t dcfg_size; 227 efx_rc_t rc; 228 229 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 230 231 dcfg_partn = (emip->emi_port == 1) 232 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 233 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1; 234 235 if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn, 236 B_TRUE, &dcfg, &dcfg_size)) != 0) 237 goto fail1; 238 239 vpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0); 240 vpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0); 241 242 if (vpd_length > size) { 243 rc = EFAULT; /* Invalid dcfg: header bigger than sector */ 244 goto fail2; 245 } 246 247 EFSYS_ASSERT3U(vpd_length, <=, size); 248 memcpy(data, (caddr_t)dcfg + vpd_offset, vpd_length); 249 250 /* Pad data with all-1s, consistent with update operations */ 251 memset(data + vpd_length, 0xff, size - vpd_length); 252 253 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg); 254 255 return (0); 256 257 fail2: 258 EFSYS_PROBE(fail2); 259 260 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg); 261 fail1: 262 EFSYS_PROBE1(fail1, efx_rc_t, rc); 263 264 return (rc); 265 } 266 267 __checkReturn efx_rc_t 268 siena_vpd_verify( 269 __in efx_nic_t *enp, 270 __in_bcount(size) caddr_t data, 271 __in size_t size) 272 { 273 efx_vpd_tag_t stag; 274 efx_vpd_tag_t dtag; 275 efx_vpd_keyword_t skey; 276 efx_vpd_keyword_t dkey; 277 unsigned int scont; 278 unsigned int dcont; 279 280 efx_rc_t rc; 281 282 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 283 284 /* 285 * Strictly you could take the view that dynamic vpd is optional. 286 * Instead, to conform more closely to the read/verify/reinit() 287 * paradigm, we require dynamic vpd. siena_vpd_reinit() will 288 * reinitialize it as required. 289 */ 290 if ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0) 291 goto fail1; 292 293 /* 294 * Verify that there is no duplication between the static and 295 * dynamic cfg sectors. 296 */ 297 if (enp->en_u.siena.enu_svpd_length == 0) 298 goto done; 299 300 dcont = 0; 301 _NOTE(CONSTANTCONDITION) 302 while (1) { 303 if ((rc = efx_vpd_hunk_next(data, size, &dtag, 304 &dkey, NULL, NULL, &dcont)) != 0) 305 goto fail2; 306 if (dcont == 0) 307 break; 308 309 /* 310 * Skip the RV keyword. It should be present in both the static 311 * and dynamic cfg sectors. 312 */ 313 if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V')) 314 continue; 315 316 scont = 0; 317 _NOTE(CONSTANTCONDITION) 318 while (1) { 319 if ((rc = efx_vpd_hunk_next( 320 enp->en_u.siena.enu_svpd, 321 enp->en_u.siena.enu_svpd_length, &stag, &skey, 322 NULL, NULL, &scont)) != 0) 323 goto fail3; 324 if (scont == 0) 325 break; 326 327 if (stag == dtag && skey == dkey) { 328 rc = EEXIST; 329 goto fail4; 330 } 331 } 332 } 333 334 done: 335 return (0); 336 337 fail4: 338 EFSYS_PROBE(fail4); 339 fail3: 340 EFSYS_PROBE(fail3); 341 fail2: 342 EFSYS_PROBE(fail2); 343 fail1: 344 EFSYS_PROBE1(fail1, efx_rc_t, rc); 345 346 return (rc); 347 } 348 349 __checkReturn efx_rc_t 350 siena_vpd_reinit( 351 __in efx_nic_t *enp, 352 __in_bcount(size) caddr_t data, 353 __in size_t size) 354 { 355 boolean_t wantpid; 356 efx_rc_t rc; 357 358 /* 359 * Only create a PID if the dynamic cfg doesn't have one 360 */ 361 if (enp->en_u.siena.enu_svpd_length == 0) 362 wantpid = B_TRUE; 363 else { 364 unsigned int offset; 365 uint8_t length; 366 367 rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd, 368 enp->en_u.siena.enu_svpd_length, 369 EFX_VPD_ID, 0, &offset, &length); 370 if (rc == 0) 371 wantpid = B_FALSE; 372 else if (rc == ENOENT) 373 wantpid = B_TRUE; 374 else 375 goto fail1; 376 } 377 378 if ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0) 379 goto fail2; 380 381 return (0); 382 383 fail2: 384 EFSYS_PROBE(fail2); 385 fail1: 386 EFSYS_PROBE1(fail1, efx_rc_t, rc); 387 388 return (rc); 389 } 390 391 __checkReturn efx_rc_t 392 siena_vpd_get( 393 __in efx_nic_t *enp, 394 __in_bcount(size) caddr_t data, 395 __in size_t size, 396 __inout efx_vpd_value_t *evvp) 397 { 398 unsigned int offset; 399 uint8_t length; 400 efx_rc_t rc; 401 402 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 403 404 /* Attempt to satisfy the request from svpd first */ 405 if (enp->en_u.siena.enu_svpd_length > 0) { 406 if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd, 407 enp->en_u.siena.enu_svpd_length, evvp->evv_tag, 408 evvp->evv_keyword, &offset, &length)) == 0) { 409 evvp->evv_length = length; 410 memcpy(evvp->evv_value, 411 enp->en_u.siena.enu_svpd + offset, length); 412 return (0); 413 } else if (rc != ENOENT) 414 goto fail1; 415 } 416 417 /* And then from the provided data buffer */ 418 if ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag, 419 evvp->evv_keyword, &offset, &length)) != 0) { 420 if (rc == ENOENT) 421 return (rc); 422 423 goto fail2; 424 } 425 426 evvp->evv_length = length; 427 memcpy(evvp->evv_value, data + offset, length); 428 429 return (0); 430 431 fail2: 432 EFSYS_PROBE(fail2); 433 fail1: 434 EFSYS_PROBE1(fail1, efx_rc_t, rc); 435 436 return (rc); 437 } 438 439 __checkReturn efx_rc_t 440 siena_vpd_set( 441 __in efx_nic_t *enp, 442 __in_bcount(size) caddr_t data, 443 __in size_t size, 444 __in efx_vpd_value_t *evvp) 445 { 446 efx_rc_t rc; 447 448 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 449 450 /* If the provided (tag,keyword) exists in svpd, then it is readonly */ 451 if (enp->en_u.siena.enu_svpd_length > 0) { 452 unsigned int offset; 453 uint8_t length; 454 455 if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd, 456 enp->en_u.siena.enu_svpd_length, evvp->evv_tag, 457 evvp->evv_keyword, &offset, &length)) == 0) { 458 rc = EACCES; 459 goto fail1; 460 } 461 } 462 463 if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0) 464 goto fail2; 465 466 return (0); 467 468 fail2: 469 EFSYS_PROBE(fail2); 470 fail1: 471 EFSYS_PROBE1(fail1, efx_rc_t, rc); 472 473 return (rc); 474 } 475 476 __checkReturn efx_rc_t 477 siena_vpd_next( 478 __in efx_nic_t *enp, 479 __in_bcount(size) caddr_t data, 480 __in size_t size, 481 __out efx_vpd_value_t *evvp, 482 __inout unsigned int *contp) 483 { 484 _NOTE(ARGUNUSED(enp, data, size, evvp, contp)) 485 486 return (ENOTSUP); 487 } 488 489 __checkReturn efx_rc_t 490 siena_vpd_write( 491 __in efx_nic_t *enp, 492 __in_bcount(size) caddr_t data, 493 __in size_t size) 494 { 495 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 496 siena_mc_dynamic_config_hdr_t *dcfg = NULL; 497 unsigned int vpd_offset; 498 unsigned int dcfg_partn; 499 unsigned int hdr_length; 500 unsigned int pos; 501 uint8_t cksum; 502 size_t partn_size, dcfg_size; 503 size_t vpd_length; 504 efx_rc_t rc; 505 506 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 507 508 /* Determine total length of all tags */ 509 if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0) 510 goto fail1; 511 512 /* Lock dynamic config sector for write, and read structure only */ 513 dcfg_partn = (emip->emi_port == 1) 514 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 515 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1; 516 517 if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &partn_size)) != 0) 518 goto fail2; 519 520 if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0) 521 goto fail3; 522 523 if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn, 524 B_FALSE, &dcfg, &dcfg_size)) != 0) 525 goto fail4; 526 527 hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0); 528 529 /* Allocated memory should have room for the new VPD */ 530 if (hdr_length + vpd_length > dcfg_size) { 531 rc = ENOSPC; 532 goto fail5; 533 } 534 535 /* Copy in new vpd and update header */ 536 vpd_offset = dcfg_size - vpd_length; 537 EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset, EFX_DWORD_0, vpd_offset); 538 memcpy((caddr_t)dcfg + vpd_offset, data, vpd_length); 539 EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_length, EFX_DWORD_0, vpd_length); 540 541 /* Update the checksum */ 542 cksum = 0; 543 for (pos = 0; pos < hdr_length; pos++) 544 cksum += ((uint8_t *)dcfg)[pos]; 545 dcfg->csum.eb_u8[0] -= cksum; 546 547 /* Erase and write the new sector */ 548 if ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, partn_size)) != 0) 549 goto fail6; 550 551 /* Write out the new structure to nvram */ 552 if ((rc = siena_nvram_partn_write(enp, dcfg_partn, 0, (caddr_t)dcfg, 553 vpd_offset + vpd_length)) != 0) 554 goto fail7; 555 556 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg); 557 558 siena_nvram_partn_unlock(enp, dcfg_partn, NULL); 559 560 return (0); 561 562 fail7: 563 EFSYS_PROBE(fail7); 564 fail6: 565 EFSYS_PROBE(fail6); 566 fail5: 567 EFSYS_PROBE(fail5); 568 569 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg); 570 fail4: 571 EFSYS_PROBE(fail4); 572 573 siena_nvram_partn_unlock(enp, dcfg_partn, NULL); 574 fail3: 575 EFSYS_PROBE(fail3); 576 fail2: 577 EFSYS_PROBE(fail2); 578 fail1: 579 EFSYS_PROBE1(fail1, efx_rc_t, rc); 580 581 return (rc); 582 } 583 584 void 585 siena_vpd_fini( 586 __in efx_nic_t *enp) 587 { 588 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 589 590 if (enp->en_u.siena.enu_svpd_length > 0) { 591 EFSYS_KMEM_FREE(enp->en_esip, enp->en_u.siena.enu_svpd_length, 592 enp->en_u.siena.enu_svpd); 593 594 enp->en_u.siena.enu_svpd = NULL; 595 enp->en_u.siena.enu_svpd_length = 0; 596 } 597 } 598 599 #endif /* EFSYS_OPT_SIENA */ 600 601 #endif /* EFSYS_OPT_VPD */ 602