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 <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 compatable */ 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 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 scont = 0; 330 _NOTE(CONSTANTCONDITION) 331 while (1) { 332 if ((rc = efx_vpd_hunk_next( 333 enp->en_u.siena.enu_svpd, 334 enp->en_u.siena.enu_svpd_length, &stag, &skey, 335 NULL, NULL, &scont)) != 0) 336 goto fail3; 337 if (scont == 0) 338 break; 339 340 if (stag == dtag && skey == dkey) { 341 rc = EEXIST; 342 goto fail4; 343 } 344 } 345 } 346 347 done: 348 return (0); 349 350 fail4: 351 EFSYS_PROBE(fail4); 352 fail3: 353 EFSYS_PROBE(fail3); 354 fail2: 355 EFSYS_PROBE(fail2); 356 fail1: 357 EFSYS_PROBE1(fail1, efx_rc_t, rc); 358 359 return (rc); 360 } 361 362 __checkReturn efx_rc_t 363 siena_vpd_reinit( 364 __in efx_nic_t *enp, 365 __in_bcount(size) caddr_t data, 366 __in size_t size) 367 { 368 boolean_t wantpid; 369 efx_rc_t rc; 370 371 /* 372 * Only create a PID if the dynamic cfg doesn't have one 373 */ 374 if (enp->en_u.siena.enu_svpd_length == 0) 375 wantpid = B_TRUE; 376 else { 377 unsigned int offset; 378 uint8_t length; 379 380 rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd, 381 enp->en_u.siena.enu_svpd_length, 382 EFX_VPD_ID, 0, &offset, &length); 383 if (rc == 0) 384 wantpid = B_FALSE; 385 else if (rc == ENOENT) 386 wantpid = B_TRUE; 387 else 388 goto fail1; 389 } 390 391 if ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0) 392 goto fail2; 393 394 return (0); 395 396 fail2: 397 EFSYS_PROBE(fail2); 398 fail1: 399 EFSYS_PROBE1(fail1, efx_rc_t, rc); 400 401 return (rc); 402 } 403 404 __checkReturn efx_rc_t 405 siena_vpd_get( 406 __in efx_nic_t *enp, 407 __in_bcount(size) caddr_t data, 408 __in size_t size, 409 __inout efx_vpd_value_t *evvp) 410 { 411 unsigned int offset; 412 uint8_t length; 413 efx_rc_t rc; 414 415 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 416 417 /* Attempt to satisfy the request from svpd first */ 418 if (enp->en_u.siena.enu_svpd_length > 0) { 419 if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd, 420 enp->en_u.siena.enu_svpd_length, evvp->evv_tag, 421 evvp->evv_keyword, &offset, &length)) == 0) { 422 evvp->evv_length = length; 423 memcpy(evvp->evv_value, 424 enp->en_u.siena.enu_svpd + offset, length); 425 return (0); 426 } else if (rc != ENOENT) 427 goto fail1; 428 } 429 430 /* And then from the provided data buffer */ 431 if ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag, 432 evvp->evv_keyword, &offset, &length)) != 0) 433 goto fail2; 434 435 evvp->evv_length = length; 436 memcpy(evvp->evv_value, data + offset, length); 437 438 return (0); 439 440 fail2: 441 EFSYS_PROBE(fail2); 442 fail1: 443 EFSYS_PROBE1(fail1, efx_rc_t, rc); 444 445 return (rc); 446 } 447 448 __checkReturn efx_rc_t 449 siena_vpd_set( 450 __in efx_nic_t *enp, 451 __in_bcount(size) caddr_t data, 452 __in size_t size, 453 __in efx_vpd_value_t *evvp) 454 { 455 efx_rc_t rc; 456 457 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 458 459 /* If the provided (tag,keyword) exists in svpd, then it is readonly */ 460 if (enp->en_u.siena.enu_svpd_length > 0) { 461 unsigned int offset; 462 uint8_t length; 463 464 if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd, 465 enp->en_u.siena.enu_svpd_length, evvp->evv_tag, 466 evvp->evv_keyword, &offset, &length)) == 0) { 467 rc = EACCES; 468 goto fail1; 469 } 470 } 471 472 if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0) 473 goto fail2; 474 475 return (0); 476 477 fail2: 478 EFSYS_PROBE(fail2); 479 fail1: 480 EFSYS_PROBE1(fail1, efx_rc_t, rc); 481 482 return (rc); 483 } 484 485 __checkReturn efx_rc_t 486 siena_vpd_next( 487 __in efx_nic_t *enp, 488 __in_bcount(size) caddr_t data, 489 __in size_t size, 490 __out efx_vpd_value_t *evvp, 491 __inout unsigned int *contp) 492 { 493 _NOTE(ARGUNUSED(enp, data, size, evvp, contp)) 494 495 return (ENOTSUP); 496 } 497 498 __checkReturn efx_rc_t 499 siena_vpd_write( 500 __in efx_nic_t *enp, 501 __in_bcount(size) caddr_t data, 502 __in size_t size) 503 { 504 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 505 siena_mc_dynamic_config_hdr_t *dcfg = NULL; 506 unsigned int vpd_offset; 507 unsigned int dcfg_partn; 508 unsigned int hdr_length; 509 unsigned int pos; 510 uint8_t cksum; 511 size_t partn_size, dcfg_size; 512 size_t vpd_length; 513 efx_rc_t rc; 514 515 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 516 517 /* Determine total length of all tags */ 518 if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0) 519 goto fail1; 520 521 /* Lock dynamic config sector for write, and read structure only */ 522 dcfg_partn = (emip->emi_port == 1) 523 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 524 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1; 525 526 if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &partn_size)) != 0) 527 goto fail2; 528 529 if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0) 530 goto fail3; 531 532 if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn, 533 B_FALSE, &dcfg, &dcfg_size)) != 0) 534 goto fail4; 535 536 hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0); 537 538 /* Allocated memory should have room for the new VPD */ 539 if (hdr_length + vpd_length > dcfg_size) { 540 rc = ENOSPC; 541 goto fail5; 542 } 543 544 /* Copy in new vpd and update header */ 545 vpd_offset = dcfg_size - vpd_length; 546 EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset, EFX_DWORD_0, vpd_offset); 547 memcpy((caddr_t)dcfg + vpd_offset, data, vpd_length); 548 EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_length, EFX_DWORD_0, vpd_length); 549 550 /* Update the checksum */ 551 cksum = 0; 552 for (pos = 0; pos < hdr_length; pos++) 553 cksum += ((uint8_t *)dcfg)[pos]; 554 dcfg->csum.eb_u8[0] -= cksum; 555 556 /* Erase and write the new sector */ 557 if ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, partn_size)) != 0) 558 goto fail6; 559 560 /* Write out the new structure to nvram */ 561 if ((rc = siena_nvram_partn_write(enp, dcfg_partn, 0, (caddr_t)dcfg, 562 vpd_offset + vpd_length)) != 0) 563 goto fail7; 564 565 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg); 566 567 siena_nvram_partn_unlock(enp, dcfg_partn); 568 569 return (0); 570 571 fail7: 572 EFSYS_PROBE(fail7); 573 fail6: 574 EFSYS_PROBE(fail6); 575 fail5: 576 EFSYS_PROBE(fail5); 577 578 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg); 579 fail4: 580 EFSYS_PROBE(fail4); 581 582 siena_nvram_partn_unlock(enp, dcfg_partn); 583 fail3: 584 EFSYS_PROBE(fail3); 585 fail2: 586 EFSYS_PROBE(fail2); 587 fail1: 588 EFSYS_PROBE1(fail1, efx_rc_t, rc); 589 590 return (rc); 591 } 592 593 void 594 siena_vpd_fini( 595 __in efx_nic_t *enp) 596 { 597 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 598 599 if (enp->en_u.siena.enu_svpd_length > 0) { 600 EFSYS_KMEM_FREE(enp->en_esip, enp->en_u.siena.enu_svpd_length, 601 enp->en_u.siena.enu_svpd); 602 603 enp->en_u.siena.enu_svpd = NULL; 604 enp->en_u.siena.enu_svpd_length = 0; 605 } 606 } 607 608 #endif /* EFSYS_OPT_SIENA */ 609 610 #endif /* EFSYS_OPT_VPD */ 611