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