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