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