efx_nvram.c revision 294251
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: head/sys/dev/sfxge/common/efx_nvram.c 294251 2016-01-18 06:16:51Z arybchik $"); 33 34#include "efx.h" 35#include "efx_impl.h" 36 37#if EFSYS_OPT_NVRAM 38 39#if EFSYS_OPT_FALCON 40 41static efx_nvram_ops_t __efx_nvram_falcon_ops = { 42#if EFSYS_OPT_DIAG 43 falcon_nvram_test, /* envo_test */ 44#endif /* EFSYS_OPT_DIAG */ 45 falcon_nvram_set_version, /* envo_set_version */ 46 falcon_nvram_type_to_partn, /* envo_type_to_partn */ 47 falcon_nvram_partn_size, /* envo_partn_size */ 48 falcon_nvram_partn_rw_start, /* envo_partn_rw_start */ 49 falcon_nvram_partn_read, /* envo_partn_read */ 50 falcon_nvram_partn_erase, /* envo_partn_erase */ 51 falcon_nvram_partn_write, /* envo_partn_write */ 52 falcon_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 53 falcon_nvram_partn_get_version, /* envo_partn_get_version */ 54}; 55 56#endif /* EFSYS_OPT_FALCON */ 57 58#if EFSYS_OPT_SIENA 59 60static efx_nvram_ops_t __efx_nvram_siena_ops = { 61#if EFSYS_OPT_DIAG 62 siena_nvram_test, /* envo_test */ 63#endif /* EFSYS_OPT_DIAG */ 64 siena_nvram_set_version, /* envo_set_version */ 65 siena_nvram_type_to_partn, /* envo_type_to_partn */ 66 siena_nvram_partn_size, /* envo_partn_size */ 67 siena_nvram_partn_rw_start, /* envo_partn_rw_start */ 68 siena_nvram_partn_read, /* envo_partn_read */ 69 siena_nvram_partn_erase, /* envo_partn_erase */ 70 siena_nvram_partn_write, /* envo_partn_write */ 71 siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 72 siena_nvram_partn_get_version, /* envo_partn_get_version */ 73}; 74 75#endif /* EFSYS_OPT_SIENA */ 76 77#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 78 79static efx_nvram_ops_t __efx_nvram_ef10_ops = { 80#if EFSYS_OPT_DIAG 81 ef10_nvram_test, /* envo_test */ 82#endif /* EFSYS_OPT_DIAG */ 83 ef10_nvram_set_version, /* envo_set_version */ 84 ef10_nvram_type_to_partn, /* envo_type_to_partn */ 85 ef10_nvram_partn_size, /* envo_partn_size */ 86 ef10_nvram_partn_rw_start, /* envo_partn_rw_start */ 87 ef10_nvram_partn_read, /* envo_partn_read */ 88 ef10_nvram_partn_erase, /* envo_partn_erase */ 89 ef10_nvram_partn_write, /* envo_partn_write */ 90 ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 91 ef10_nvram_partn_get_version, /* envo_partn_get_version */ 92}; 93 94#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 95 96 __checkReturn efx_rc_t 97efx_nvram_init( 98 __in efx_nic_t *enp) 99{ 100 efx_nvram_ops_t *envop; 101 efx_rc_t rc; 102 103 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 104 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 105 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM)); 106 107 switch (enp->en_family) { 108#if EFSYS_OPT_FALCON 109 case EFX_FAMILY_FALCON: 110 envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops; 111 break; 112#endif /* EFSYS_OPT_FALCON */ 113 114#if EFSYS_OPT_SIENA 115 case EFX_FAMILY_SIENA: 116 envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops; 117 break; 118#endif /* EFSYS_OPT_SIENA */ 119 120#if EFSYS_OPT_HUNTINGTON 121 case EFX_FAMILY_HUNTINGTON: 122 envop = (efx_nvram_ops_t *)&__efx_nvram_ef10_ops; 123 break; 124#endif /* EFSYS_OPT_HUNTINGTON */ 125 126#if EFSYS_OPT_MEDFORD 127 case EFX_FAMILY_MEDFORD: 128 envop = (efx_nvram_ops_t *)&__efx_nvram_ef10_ops; 129 break; 130#endif /* EFSYS_OPT_MEDFORD */ 131 132 default: 133 EFSYS_ASSERT(0); 134 rc = ENOTSUP; 135 goto fail1; 136 } 137 138 enp->en_envop = envop; 139 enp->en_mod_flags |= EFX_MOD_NVRAM; 140 141 return (0); 142 143fail1: 144 EFSYS_PROBE1(fail1, efx_rc_t, rc); 145 146 return (rc); 147} 148 149#if EFSYS_OPT_DIAG 150 151 __checkReturn efx_rc_t 152efx_nvram_test( 153 __in efx_nic_t *enp) 154{ 155 efx_nvram_ops_t *envop = enp->en_envop; 156 efx_rc_t rc; 157 158 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 159 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 160 161 if ((rc = envop->envo_test(enp)) != 0) 162 goto fail1; 163 164 return (0); 165 166fail1: 167 EFSYS_PROBE1(fail1, efx_rc_t, rc); 168 169 return (rc); 170} 171 172#endif /* EFSYS_OPT_DIAG */ 173 174 __checkReturn efx_rc_t 175efx_nvram_size( 176 __in efx_nic_t *enp, 177 __in efx_nvram_type_t type, 178 __out size_t *sizep) 179{ 180 efx_nvram_ops_t *envop = enp->en_envop; 181 uint32_t partn; 182 efx_rc_t rc; 183 184 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 185 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 186 187 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 188 189 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 190 goto fail1; 191 192 if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0) 193 goto fail2; 194 195 return (0); 196 197fail2: 198 EFSYS_PROBE(fail2); 199fail1: 200 EFSYS_PROBE1(fail1, efx_rc_t, rc); 201 *sizep = 0; 202 203 return (rc); 204} 205 206 __checkReturn efx_rc_t 207efx_nvram_get_version( 208 __in efx_nic_t *enp, 209 __in efx_nvram_type_t type, 210 __out uint32_t *subtypep, 211 __out_ecount(4) uint16_t version[4]) 212{ 213 efx_nvram_ops_t *envop = enp->en_envop; 214 uint32_t partn; 215 efx_rc_t rc; 216 217 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 218 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 219 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 220 221 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 222 223 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 224 goto fail1; 225 226 if ((rc = envop->envo_partn_get_version(enp, partn, 227 subtypep, version)) != 0) 228 goto fail2; 229 230 return (0); 231 232fail2: 233 EFSYS_PROBE(fail2); 234fail1: 235 EFSYS_PROBE1(fail1, efx_rc_t, rc); 236 237 return (rc); 238} 239 240 __checkReturn efx_rc_t 241efx_nvram_rw_start( 242 __in efx_nic_t *enp, 243 __in efx_nvram_type_t type, 244 __out_opt size_t *chunk_sizep) 245{ 246 efx_nvram_ops_t *envop = enp->en_envop; 247 uint32_t partn; 248 efx_rc_t rc; 249 250 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 251 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 252 253 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 254 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 255 256 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 257 258 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 259 goto fail1; 260 261 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0) 262 goto fail2; 263 264 enp->en_nvram_locked = type; 265 266 return (0); 267 268fail2: 269 EFSYS_PROBE(fail2); 270fail1: 271 EFSYS_PROBE1(fail1, efx_rc_t, rc); 272 273 return (rc); 274} 275 276 __checkReturn efx_rc_t 277efx_nvram_read_chunk( 278 __in efx_nic_t *enp, 279 __in efx_nvram_type_t type, 280 __in unsigned int offset, 281 __out_bcount(size) caddr_t data, 282 __in size_t size) 283{ 284 efx_nvram_ops_t *envop = enp->en_envop; 285 uint32_t partn; 286 efx_rc_t rc; 287 288 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 289 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 290 291 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 292 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 293 294 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 295 296 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 297 goto fail1; 298 299 if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0) 300 goto fail2; 301 302 return (0); 303 304fail2: 305 EFSYS_PROBE(fail2); 306fail1: 307 EFSYS_PROBE1(fail1, efx_rc_t, rc); 308 309 return (rc); 310} 311 312 __checkReturn efx_rc_t 313efx_nvram_erase( 314 __in efx_nic_t *enp, 315 __in efx_nvram_type_t type) 316{ 317 efx_nvram_ops_t *envop = enp->en_envop; 318 unsigned int offset = 0; 319 size_t size = 0; 320 uint32_t partn; 321 efx_rc_t rc; 322 323 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 324 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 325 326 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 327 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 328 329 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 330 331 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 332 goto fail1; 333 334 if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0) 335 goto fail2; 336 337 if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0) 338 goto fail3; 339 340 return (0); 341 342fail3: 343 EFSYS_PROBE(fail3); 344fail2: 345 EFSYS_PROBE(fail2); 346fail1: 347 EFSYS_PROBE1(fail1, efx_rc_t, rc); 348 349 return (rc); 350} 351 352 __checkReturn efx_rc_t 353efx_nvram_write_chunk( 354 __in efx_nic_t *enp, 355 __in efx_nvram_type_t type, 356 __in unsigned int offset, 357 __in_bcount(size) caddr_t data, 358 __in size_t size) 359{ 360 efx_nvram_ops_t *envop = enp->en_envop; 361 uint32_t partn; 362 efx_rc_t rc; 363 364 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 365 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 366 367 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 368 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 369 370 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 371 372 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 373 goto fail1; 374 375 if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0) 376 goto fail2; 377 378 return (0); 379 380fail2: 381 EFSYS_PROBE(fail2); 382fail1: 383 EFSYS_PROBE1(fail1, efx_rc_t, rc); 384 385 return (rc); 386} 387 388 void 389efx_nvram_rw_finish( 390 __in efx_nic_t *enp, 391 __in efx_nvram_type_t type) 392{ 393 efx_nvram_ops_t *envop = enp->en_envop; 394 uint32_t partn; 395 396 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 397 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 398 399 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 400 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 401 402 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 403 404 if (envop->envo_type_to_partn(enp, type, &partn) == 0) 405 envop->envo_partn_rw_finish(enp, partn); 406 407 enp->en_nvram_locked = EFX_NVRAM_INVALID; 408} 409 410 __checkReturn efx_rc_t 411efx_nvram_set_version( 412 __in efx_nic_t *enp, 413 __in efx_nvram_type_t type, 414 __in_ecount(4) uint16_t version[4]) 415{ 416 efx_nvram_ops_t *envop = enp->en_envop; 417 efx_rc_t rc; 418 419 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 420 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 421 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 422 423 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 424 425 /* 426 * The Siena implementation of envo_set_version() will attempt to 427 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector. 428 * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 429 */ 430 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 431 432 if ((rc = envop->envo_set_version(enp, type, version)) != 0) 433 goto fail1; 434 435 return (0); 436 437fail1: 438 EFSYS_PROBE1(fail1, efx_rc_t, rc); 439 440 return (rc); 441} 442 443void 444efx_nvram_fini( 445 __in efx_nic_t *enp) 446{ 447 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 448 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 449 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 450 451 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 452 453 enp->en_envop = NULL; 454 enp->en_mod_flags &= ~EFX_MOD_NVRAM; 455} 456 457#endif /* EFSYS_OPT_NVRAM */ 458 459#if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD 460 461/* 462 * Internal MCDI request handling 463 */ 464 465 __checkReturn efx_rc_t 466efx_mcdi_nvram_partitions( 467 __in efx_nic_t *enp, 468 __out_bcount(size) caddr_t data, 469 __in size_t size, 470 __out unsigned int *npartnp) 471{ 472 efx_mcdi_req_t req; 473 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN, 474 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)]; 475 unsigned int npartn; 476 efx_rc_t rc; 477 478 (void) memset(payload, 0, sizeof (payload)); 479 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS; 480 req.emr_in_buf = payload; 481 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN; 482 req.emr_out_buf = payload; 483 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX; 484 485 efx_mcdi_execute(enp, &req); 486 487 if (req.emr_rc != 0) { 488 rc = req.emr_rc; 489 goto fail1; 490 } 491 492 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) { 493 rc = EMSGSIZE; 494 goto fail2; 495 } 496 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); 497 498 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) { 499 rc = ENOENT; 500 goto fail3; 501 } 502 503 if (size < npartn * sizeof (uint32_t)) { 504 rc = ENOSPC; 505 goto fail3; 506 } 507 508 *npartnp = npartn; 509 510 memcpy(data, 511 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID), 512 (npartn * sizeof (uint32_t))); 513 514 return (0); 515 516fail3: 517 EFSYS_PROBE(fail3); 518fail2: 519 EFSYS_PROBE(fail2); 520fail1: 521 EFSYS_PROBE1(fail1, efx_rc_t, rc); 522 523 return (rc); 524} 525 526 __checkReturn efx_rc_t 527efx_mcdi_nvram_metadata( 528 __in efx_nic_t *enp, 529 __in uint32_t partn, 530 __out uint32_t *subtypep, 531 __out_ecount(4) uint16_t version[4], 532 __out_bcount_opt(size) char *descp, 533 __in size_t size) 534{ 535 efx_mcdi_req_t req; 536 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN, 537 MC_CMD_NVRAM_METADATA_OUT_LENMAX)]; 538 efx_rc_t rc; 539 540 (void) memset(payload, 0, sizeof (payload)); 541 req.emr_cmd = MC_CMD_NVRAM_METADATA; 542 req.emr_in_buf = payload; 543 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN; 544 req.emr_out_buf = payload; 545 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX; 546 547 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); 548 549 efx_mcdi_execute(enp, &req); 550 551 if (req.emr_rc != 0) { 552 rc = req.emr_rc; 553 goto fail1; 554 } 555 556 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) { 557 rc = EMSGSIZE; 558 goto fail2; 559 } 560 561 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 562 NVRAM_METADATA_OUT_SUBTYPE_VALID)) { 563 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE); 564 } else { 565 *subtypep = 0; 566 } 567 568 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 569 NVRAM_METADATA_OUT_VERSION_VALID)) { 570 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W); 571 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X); 572 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y); 573 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z); 574 } else { 575 version[0] = version[1] = version[2] = version[3] = 0; 576 } 577 578 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 579 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) { 580 /* Return optional descrition string */ 581 if ((descp != NULL) && (size > 0)) { 582 size_t desclen; 583 584 descp[0] = '\0'; 585 desclen = (req.emr_out_length_used 586 - MC_CMD_NVRAM_METADATA_OUT_LEN(0)); 587 588 EFSYS_ASSERT3U(desclen, <=, 589 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM); 590 591 if (size < desclen) { 592 rc = ENOSPC; 593 goto fail3; 594 } 595 596 memcpy(descp, MCDI_OUT2(req, char, 597 NVRAM_METADATA_OUT_DESCRIPTION), 598 desclen); 599 600 /* Ensure string is NUL terminated */ 601 descp[desclen] = '\0'; 602 } 603 } 604 605 return (0); 606 607fail3: 608 EFSYS_PROBE(fail3); 609fail2: 610 EFSYS_PROBE(fail2); 611fail1: 612 EFSYS_PROBE1(fail1, efx_rc_t, rc); 613 614 return (rc); 615} 616 617 __checkReturn efx_rc_t 618efx_mcdi_nvram_info( 619 __in efx_nic_t *enp, 620 __in uint32_t partn, 621 __out_opt size_t *sizep, 622 __out_opt uint32_t *addressp, 623 __out_opt uint32_t *erase_sizep, 624 __out_opt uint32_t *write_sizep) 625{ 626 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN, 627 MC_CMD_NVRAM_INFO_V2_OUT_LEN)]; 628 efx_mcdi_req_t req; 629 efx_rc_t rc; 630 631 (void) memset(payload, 0, sizeof (payload)); 632 req.emr_cmd = MC_CMD_NVRAM_INFO; 633 req.emr_in_buf = payload; 634 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN; 635 req.emr_out_buf = payload; 636 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN; 637 638 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn); 639 640 efx_mcdi_execute_quiet(enp, &req); 641 642 if (req.emr_rc != 0) { 643 rc = req.emr_rc; 644 goto fail1; 645 } 646 647 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) { 648 rc = EMSGSIZE; 649 goto fail2; 650 } 651 652 if (sizep) 653 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE); 654 655 if (addressp) 656 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR); 657 658 if (erase_sizep) 659 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE); 660 661 if (write_sizep) { 662 *write_sizep = 663 (req.emr_out_length_used < 664 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ? 665 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE); 666 } 667 668 return (0); 669 670fail2: 671 EFSYS_PROBE(fail2); 672fail1: 673 EFSYS_PROBE1(fail1, efx_rc_t, rc); 674 675 return (rc); 676} 677 678 __checkReturn efx_rc_t 679efx_mcdi_nvram_update_start( 680 __in efx_nic_t *enp, 681 __in uint32_t partn) 682{ 683 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_IN_LEN, 684 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)]; 685 efx_mcdi_req_t req; 686 efx_rc_t rc; 687 688 (void) memset(payload, 0, sizeof (payload)); 689 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; 690 req.emr_in_buf = payload; 691 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN; 692 req.emr_out_buf = payload; 693 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN; 694 695 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn); 696 697 efx_mcdi_execute(enp, &req); 698 699 if (req.emr_rc != 0) { 700 rc = req.emr_rc; 701 goto fail1; 702 } 703 704 return (0); 705 706fail1: 707 EFSYS_PROBE1(fail1, efx_rc_t, rc); 708 709 return (rc); 710} 711 712 __checkReturn efx_rc_t 713efx_mcdi_nvram_read( 714 __in efx_nic_t *enp, 715 __in uint32_t partn, 716 __in uint32_t offset, 717 __out_bcount(size) caddr_t data, 718 __in size_t size) 719{ 720 efx_mcdi_req_t req; 721 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_LEN, 722 MC_CMD_NVRAM_READ_OUT_LENMAX)]; 723 efx_rc_t rc; 724 725 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) { 726 rc = EINVAL; 727 goto fail1; 728 } 729 730 (void) memset(payload, 0, sizeof (payload)); 731 req.emr_cmd = MC_CMD_NVRAM_READ; 732 req.emr_in_buf = payload; 733 req.emr_in_length = MC_CMD_NVRAM_READ_IN_LEN; 734 req.emr_out_buf = payload; 735 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX; 736 737 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_TYPE, partn); 738 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_OFFSET, offset); 739 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_LENGTH, size); 740 741 efx_mcdi_execute(enp, &req); 742 743 if (req.emr_rc != 0) { 744 rc = req.emr_rc; 745 goto fail1; 746 } 747 748 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) { 749 rc = EMSGSIZE; 750 goto fail2; 751 } 752 753 memcpy(data, 754 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER), 755 size); 756 757 return (0); 758 759fail2: 760 EFSYS_PROBE(fail2); 761fail1: 762 EFSYS_PROBE1(fail1, efx_rc_t, rc); 763 764 return (rc); 765} 766 767 __checkReturn efx_rc_t 768efx_mcdi_nvram_erase( 769 __in efx_nic_t *enp, 770 __in uint32_t partn, 771 __in uint32_t offset, 772 __in size_t size) 773{ 774 efx_mcdi_req_t req; 775 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN, 776 MC_CMD_NVRAM_ERASE_OUT_LEN)]; 777 efx_rc_t rc; 778 779 (void) memset(payload, 0, sizeof (payload)); 780 req.emr_cmd = MC_CMD_NVRAM_ERASE; 781 req.emr_in_buf = payload; 782 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; 783 req.emr_out_buf = payload; 784 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN; 785 786 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); 787 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); 788 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); 789 790 efx_mcdi_execute(enp, &req); 791 792 if (req.emr_rc != 0) { 793 rc = req.emr_rc; 794 goto fail1; 795 } 796 797 return (0); 798 799fail1: 800 EFSYS_PROBE1(fail1, efx_rc_t, rc); 801 802 return (rc); 803} 804 805/* 806 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both 807 * Sienna and EF10 based boards. However EF10 based boards support the use 808 * of this command with payloads up to the maximum MCDI V2 payload length. 809 */ 810 __checkReturn efx_rc_t 811efx_mcdi_nvram_write( 812 __in efx_nic_t *enp, 813 __in uint32_t partn, 814 __in uint32_t offset, 815 __out_bcount(size) caddr_t data, 816 __in size_t size) 817{ 818 efx_mcdi_req_t req; 819 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1, 820 MCDI_CTL_SDU_LEN_MAX_V2)]; 821 efx_rc_t rc; 822 size_t max_data_size; 823 824 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length 825 - MC_CMD_NVRAM_WRITE_IN_LEN(0); 826 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0); 827 EFSYS_ASSERT3U(max_data_size, <, 828 enp->en_nic_cfg.enc_mcdi_max_payload_length); 829 830 if (size > max_data_size) { 831 rc = EINVAL; 832 goto fail1; 833 } 834 835 (void) memset(payload, 0, sizeof (payload)); 836 req.emr_cmd = MC_CMD_NVRAM_WRITE; 837 req.emr_in_buf = payload; 838 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size); 839 req.emr_out_buf = payload; 840 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN; 841 842 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); 843 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); 844 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size); 845 846 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), 847 data, size); 848 849 efx_mcdi_execute(enp, &req); 850 851 if (req.emr_rc != 0) { 852 rc = req.emr_rc; 853 goto fail2; 854 } 855 856 return (0); 857 858fail2: 859 EFSYS_PROBE(fail2); 860fail1: 861 EFSYS_PROBE1(fail1, efx_rc_t, rc); 862 863 return (rc); 864} 865 866 __checkReturn efx_rc_t 867efx_mcdi_nvram_update_finish( 868 __in efx_nic_t *enp, 869 __in uint32_t partn, 870 __in boolean_t reboot) 871{ 872 efx_mcdi_req_t req; 873 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN, 874 MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN)]; 875 efx_rc_t rc; 876 877 (void) memset(payload, 0, sizeof (payload)); 878 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH; 879 req.emr_in_buf = payload; 880 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN; 881 req.emr_out_buf = payload; 882 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN; 883 884 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn); 885 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot); 886 887 efx_mcdi_execute(enp, &req); 888 889 if (req.emr_rc != 0) { 890 rc = req.emr_rc; 891 goto fail1; 892 } 893 894 return (0); 895 896fail1: 897 EFSYS_PROBE1(fail1, efx_rc_t, rc); 898 899 return (rc); 900} 901 902#if EFSYS_OPT_DIAG 903 904 __checkReturn efx_rc_t 905efx_mcdi_nvram_test( 906 __in efx_nic_t *enp, 907 __in uint32_t partn) 908{ 909 efx_mcdi_req_t req; 910 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN, 911 MC_CMD_NVRAM_TEST_OUT_LEN)]; 912 int result; 913 efx_rc_t rc; 914 915 (void) memset(payload, 0, sizeof (payload)); 916 req.emr_cmd = MC_CMD_NVRAM_TEST; 917 req.emr_in_buf = payload; 918 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; 919 req.emr_out_buf = payload; 920 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; 921 922 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn); 923 924 efx_mcdi_execute(enp, &req); 925 926 if (req.emr_rc != 0) { 927 rc = req.emr_rc; 928 goto fail1; 929 } 930 931 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { 932 rc = EMSGSIZE; 933 goto fail2; 934 } 935 936 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); 937 if (result == MC_CMD_NVRAM_TEST_FAIL) { 938 939 EFSYS_PROBE1(nvram_test_failure, int, partn); 940 941 rc = (EINVAL); 942 goto fail3; 943 } 944 945 return (0); 946 947fail3: 948 EFSYS_PROBE(fail3); 949fail2: 950 EFSYS_PROBE(fail2); 951fail1: 952 EFSYS_PROBE1(fail1, efx_rc_t, rc); 953 954 return (rc); 955} 956 957#endif /* EFSYS_OPT_DIAG */ 958 959 960#endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ 961