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