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