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