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