efx_nvram.c revision 294080
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 294080 2016-01-15 06:28:58Z 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_get_version, /* envo_get_version */ 46 falcon_nvram_read_chunk, /* envo_read_chunk */ 47 falcon_nvram_erase, /* envo_erase */ 48 falcon_nvram_write_chunk, /* envo_write_chunk */ 49 falcon_nvram_rw_finish, /* envo_rw_finish */ 50 falcon_nvram_set_version, /* envo_set_version */ 51 falcon_nvram_type_to_partn, /* envo_type_to_partn */ 52 falcon_nvram_partn_size, /* envo_partn_size */ 53 falcon_nvram_partn_rw_start, /* envo_partn_rw_start */ 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_get_version, /* envo_get_version */ 65 siena_nvram_read_chunk, /* envo_read_chunk */ 66 siena_nvram_erase, /* envo_erase */ 67 siena_nvram_write_chunk, /* envo_write_chunk */ 68 siena_nvram_rw_finish, /* envo_rw_finish */ 69 siena_nvram_set_version, /* envo_set_version */ 70 siena_nvram_type_to_partn, /* envo_type_to_partn */ 71 siena_nvram_partn_size, /* envo_partn_size */ 72 siena_nvram_partn_rw_start, /* envo_partn_rw_start */ 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_get_version, /* envo_get_version */ 84 ef10_nvram_read_chunk, /* envo_read_chunk */ 85 ef10_nvram_erase, /* envo_erase */ 86 ef10_nvram_write_chunk, /* envo_write_chunk */ 87 ef10_nvram_rw_finish, /* envo_rw_finish */ 88 ef10_nvram_set_version, /* envo_set_version */ 89 ef10_nvram_type_to_partn, /* envo_type_to_partn */ 90 ef10_nvram_partn_size, /* envo_partn_size */ 91 ef10_nvram_partn_rw_start, /* envo_partn_rw_start */ 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 efx_rc_t rc; 215 216 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 217 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 218 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 219 220 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 221 222 if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0) 223 goto fail1; 224 225 return (0); 226 227fail1: 228 EFSYS_PROBE1(fail1, efx_rc_t, rc); 229 230 return (rc); 231} 232 233 __checkReturn efx_rc_t 234efx_nvram_rw_start( 235 __in efx_nic_t *enp, 236 __in efx_nvram_type_t type, 237 __out_opt size_t *chunk_sizep) 238{ 239 efx_nvram_ops_t *envop = enp->en_envop; 240 uint32_t partn; 241 efx_rc_t rc; 242 243 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 244 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 245 246 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 247 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 248 249 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 250 251 if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 252 goto fail1; 253 254 if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0) 255 goto fail2; 256 257 enp->en_nvram_locked = type; 258 259 return (0); 260 261fail2: 262 EFSYS_PROBE(fail2); 263fail1: 264 EFSYS_PROBE1(fail1, efx_rc_t, rc); 265 266 return (rc); 267} 268 269 __checkReturn efx_rc_t 270efx_nvram_read_chunk( 271 __in efx_nic_t *enp, 272 __in efx_nvram_type_t type, 273 __in unsigned int offset, 274 __out_bcount(size) caddr_t data, 275 __in size_t size) 276{ 277 efx_nvram_ops_t *envop = enp->en_envop; 278 efx_rc_t rc; 279 280 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 281 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 282 283 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 284 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 285 286 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 287 288 if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0) 289 goto fail1; 290 291 return (0); 292 293fail1: 294 EFSYS_PROBE1(fail1, efx_rc_t, rc); 295 296 return (rc); 297} 298 299 __checkReturn efx_rc_t 300efx_nvram_erase( 301 __in efx_nic_t *enp, 302 __in efx_nvram_type_t type) 303{ 304 efx_nvram_ops_t *envop = enp->en_envop; 305 efx_rc_t rc; 306 307 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 308 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 309 310 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 311 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 312 313 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 314 315 if ((rc = envop->envo_erase(enp, type)) != 0) 316 goto fail1; 317 318 return (0); 319 320fail1: 321 EFSYS_PROBE1(fail1, efx_rc_t, rc); 322 323 return (rc); 324} 325 326 __checkReturn efx_rc_t 327efx_nvram_write_chunk( 328 __in efx_nic_t *enp, 329 __in efx_nvram_type_t type, 330 __in unsigned int offset, 331 __in_bcount(size) caddr_t data, 332 __in size_t size) 333{ 334 efx_nvram_ops_t *envop = enp->en_envop; 335 efx_rc_t rc; 336 337 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 338 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 339 340 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 341 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 342 343 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 344 345 if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0) 346 goto fail1; 347 348 return (0); 349 350fail1: 351 EFSYS_PROBE1(fail1, efx_rc_t, rc); 352 353 return (rc); 354} 355 356 void 357efx_nvram_rw_finish( 358 __in efx_nic_t *enp, 359 __in efx_nvram_type_t type) 360{ 361 efx_nvram_ops_t *envop = enp->en_envop; 362 363 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 364 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 365 366 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 367 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 368 369 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 370 371 envop->envo_rw_finish(enp, type); 372 373 enp->en_nvram_locked = EFX_NVRAM_INVALID; 374} 375 376 __checkReturn efx_rc_t 377efx_nvram_set_version( 378 __in efx_nic_t *enp, 379 __in efx_nvram_type_t type, 380 __in_ecount(4) uint16_t version[4]) 381{ 382 efx_nvram_ops_t *envop = enp->en_envop; 383 efx_rc_t rc; 384 385 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 386 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 387 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 388 389 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 390 391 /* 392 * The Siena implementation of envo_set_version() will attempt to 393 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector. 394 * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 395 */ 396 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 397 398 if ((rc = envop->envo_set_version(enp, type, version)) != 0) 399 goto fail1; 400 401 return (0); 402 403fail1: 404 EFSYS_PROBE1(fail1, efx_rc_t, rc); 405 406 return (rc); 407} 408 409void 410efx_nvram_fini( 411 __in efx_nic_t *enp) 412{ 413 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 414 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 415 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 416 417 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 418 419 enp->en_envop = NULL; 420 enp->en_mod_flags &= ~EFX_MOD_NVRAM; 421} 422 423#endif /* EFSYS_OPT_NVRAM */ 424 425#if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD 426 427/* 428 * Internal MCDI request handling 429 */ 430 431 __checkReturn efx_rc_t 432efx_mcdi_nvram_partitions( 433 __in efx_nic_t *enp, 434 __out_bcount(size) caddr_t data, 435 __in size_t size, 436 __out unsigned int *npartnp) 437{ 438 efx_mcdi_req_t req; 439 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN, 440 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)]; 441 unsigned int npartn; 442 efx_rc_t rc; 443 444 (void) memset(payload, 0, sizeof (payload)); 445 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS; 446 req.emr_in_buf = payload; 447 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN; 448 req.emr_out_buf = payload; 449 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX; 450 451 efx_mcdi_execute(enp, &req); 452 453 if (req.emr_rc != 0) { 454 rc = req.emr_rc; 455 goto fail1; 456 } 457 458 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) { 459 rc = EMSGSIZE; 460 goto fail2; 461 } 462 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); 463 464 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) { 465 rc = ENOENT; 466 goto fail3; 467 } 468 469 if (size < npartn * sizeof (uint32_t)) { 470 rc = ENOSPC; 471 goto fail3; 472 } 473 474 *npartnp = npartn; 475 476 memcpy(data, 477 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID), 478 (npartn * sizeof (uint32_t))); 479 480 return (0); 481 482fail3: 483 EFSYS_PROBE(fail3); 484fail2: 485 EFSYS_PROBE(fail2); 486fail1: 487 EFSYS_PROBE1(fail1, efx_rc_t, rc); 488 489 return (rc); 490} 491 492 __checkReturn efx_rc_t 493efx_mcdi_nvram_metadata( 494 __in efx_nic_t *enp, 495 __in uint32_t partn, 496 __out uint32_t *subtypep, 497 __out_ecount(4) uint16_t version[4], 498 __out_bcount_opt(size) char *descp, 499 __in size_t size) 500{ 501 efx_mcdi_req_t req; 502 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN, 503 MC_CMD_NVRAM_METADATA_OUT_LENMAX)]; 504 efx_rc_t rc; 505 506 (void) memset(payload, 0, sizeof (payload)); 507 req.emr_cmd = MC_CMD_NVRAM_METADATA; 508 req.emr_in_buf = payload; 509 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN; 510 req.emr_out_buf = payload; 511 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX; 512 513 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); 514 515 efx_mcdi_execute(enp, &req); 516 517 if (req.emr_rc != 0) { 518 rc = req.emr_rc; 519 goto fail1; 520 } 521 522 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) { 523 rc = EMSGSIZE; 524 goto fail2; 525 } 526 527 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 528 NVRAM_METADATA_OUT_SUBTYPE_VALID)) { 529 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE); 530 } else { 531 *subtypep = 0; 532 } 533 534 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 535 NVRAM_METADATA_OUT_VERSION_VALID)) { 536 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W); 537 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X); 538 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y); 539 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z); 540 } else { 541 version[0] = version[1] = version[2] = version[3] = 0; 542 } 543 544 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 545 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) { 546 /* Return optional descrition string */ 547 if ((descp != NULL) && (size > 0)) { 548 size_t desclen; 549 550 descp[0] = '\0'; 551 desclen = (req.emr_out_length_used 552 - MC_CMD_NVRAM_METADATA_OUT_LEN(0)); 553 554 EFSYS_ASSERT3U(desclen, <=, 555 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM); 556 557 if (size < desclen) { 558 rc = ENOSPC; 559 goto fail3; 560 } 561 562 memcpy(descp, MCDI_OUT2(req, char, 563 NVRAM_METADATA_OUT_DESCRIPTION), 564 desclen); 565 566 /* Ensure string is NUL terminated */ 567 descp[desclen] = '\0'; 568 } 569 } 570 571 return (0); 572 573fail3: 574 EFSYS_PROBE(fail3); 575fail2: 576 EFSYS_PROBE(fail2); 577fail1: 578 EFSYS_PROBE1(fail1, efx_rc_t, rc); 579 580 return (rc); 581} 582 583 __checkReturn efx_rc_t 584efx_mcdi_nvram_info( 585 __in efx_nic_t *enp, 586 __in uint32_t partn, 587 __out_opt size_t *sizep, 588 __out_opt uint32_t *addressp, 589 __out_opt uint32_t *erase_sizep, 590 __out_opt uint32_t *write_sizep) 591{ 592 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN, 593 MC_CMD_NVRAM_INFO_V2_OUT_LEN)]; 594 efx_mcdi_req_t req; 595 efx_rc_t rc; 596 597 (void) memset(payload, 0, sizeof (payload)); 598 req.emr_cmd = MC_CMD_NVRAM_INFO; 599 req.emr_in_buf = payload; 600 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN; 601 req.emr_out_buf = payload; 602 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN; 603 604 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn); 605 606 efx_mcdi_execute_quiet(enp, &req); 607 608 if (req.emr_rc != 0) { 609 rc = req.emr_rc; 610 goto fail1; 611 } 612 613 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) { 614 rc = EMSGSIZE; 615 goto fail2; 616 } 617 618 if (sizep) 619 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE); 620 621 if (addressp) 622 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR); 623 624 if (erase_sizep) 625 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE); 626 627 if (write_sizep) { 628 *write_sizep = 629 (req.emr_out_length_used < 630 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ? 631 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE); 632 } 633 634 return (0); 635 636fail2: 637 EFSYS_PROBE(fail2); 638fail1: 639 EFSYS_PROBE1(fail1, efx_rc_t, rc); 640 641 return (rc); 642} 643 644 __checkReturn efx_rc_t 645efx_mcdi_nvram_update_start( 646 __in efx_nic_t *enp, 647 __in uint32_t partn) 648{ 649 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_IN_LEN, 650 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)]; 651 efx_mcdi_req_t req; 652 efx_rc_t rc; 653 654 (void) memset(payload, 0, sizeof (payload)); 655 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; 656 req.emr_in_buf = payload; 657 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN; 658 req.emr_out_buf = payload; 659 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN; 660 661 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn); 662 663 efx_mcdi_execute(enp, &req); 664 665 if (req.emr_rc != 0) { 666 rc = req.emr_rc; 667 goto fail1; 668 } 669 670 return (0); 671 672fail1: 673 EFSYS_PROBE1(fail1, efx_rc_t, rc); 674 675 return (rc); 676} 677 678 __checkReturn efx_rc_t 679efx_mcdi_nvram_read( 680 __in efx_nic_t *enp, 681 __in uint32_t partn, 682 __in uint32_t offset, 683 __out_bcount(size) caddr_t data, 684 __in size_t size) 685{ 686 efx_mcdi_req_t req; 687 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_LEN, 688 MC_CMD_NVRAM_READ_OUT_LENMAX)]; 689 efx_rc_t rc; 690 691 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) { 692 rc = EINVAL; 693 goto fail1; 694 } 695 696 (void) memset(payload, 0, sizeof (payload)); 697 req.emr_cmd = MC_CMD_NVRAM_READ; 698 req.emr_in_buf = payload; 699 req.emr_in_length = MC_CMD_NVRAM_READ_IN_LEN; 700 req.emr_out_buf = payload; 701 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX; 702 703 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_TYPE, partn); 704 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_OFFSET, offset); 705 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_LENGTH, size); 706 707 efx_mcdi_execute(enp, &req); 708 709 if (req.emr_rc != 0) { 710 rc = req.emr_rc; 711 goto fail1; 712 } 713 714 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) { 715 rc = EMSGSIZE; 716 goto fail2; 717 } 718 719 memcpy(data, 720 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER), 721 size); 722 723 return (0); 724 725fail2: 726 EFSYS_PROBE(fail2); 727fail1: 728 EFSYS_PROBE1(fail1, efx_rc_t, rc); 729 730 return (rc); 731} 732 733 __checkReturn efx_rc_t 734efx_mcdi_nvram_erase( 735 __in efx_nic_t *enp, 736 __in uint32_t partn, 737 __in uint32_t offset, 738 __in size_t size) 739{ 740 efx_mcdi_req_t req; 741 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN, 742 MC_CMD_NVRAM_ERASE_OUT_LEN)]; 743 efx_rc_t rc; 744 745 (void) memset(payload, 0, sizeof (payload)); 746 req.emr_cmd = MC_CMD_NVRAM_ERASE; 747 req.emr_in_buf = payload; 748 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; 749 req.emr_out_buf = payload; 750 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN; 751 752 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); 753 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); 754 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); 755 756 efx_mcdi_execute(enp, &req); 757 758 if (req.emr_rc != 0) { 759 rc = req.emr_rc; 760 goto fail1; 761 } 762 763 return (0); 764 765fail1: 766 EFSYS_PROBE1(fail1, efx_rc_t, rc); 767 768 return (rc); 769} 770 771/* 772 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both 773 * Sienna and EF10 based boards. However EF10 based boards support the use 774 * of this command with payloads up to the maximum MCDI V2 payload length. 775 */ 776 __checkReturn efx_rc_t 777efx_mcdi_nvram_write( 778 __in efx_nic_t *enp, 779 __in uint32_t partn, 780 __in uint32_t offset, 781 __out_bcount(size) caddr_t data, 782 __in size_t size) 783{ 784 efx_mcdi_req_t req; 785 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1, 786 MCDI_CTL_SDU_LEN_MAX_V2)]; 787 efx_rc_t rc; 788 size_t max_data_size; 789 790 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length 791 - MC_CMD_NVRAM_WRITE_IN_LEN(0); 792 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0); 793 EFSYS_ASSERT3U(max_data_size, <, 794 enp->en_nic_cfg.enc_mcdi_max_payload_length); 795 796 if (size > max_data_size) { 797 rc = EINVAL; 798 goto fail1; 799 } 800 801 (void) memset(payload, 0, sizeof (payload)); 802 req.emr_cmd = MC_CMD_NVRAM_WRITE; 803 req.emr_in_buf = payload; 804 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size); 805 req.emr_out_buf = payload; 806 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN; 807 808 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); 809 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); 810 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size); 811 812 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), 813 data, size); 814 815 efx_mcdi_execute(enp, &req); 816 817 if (req.emr_rc != 0) { 818 rc = req.emr_rc; 819 goto fail2; 820 } 821 822 return (0); 823 824fail2: 825 EFSYS_PROBE(fail2); 826fail1: 827 EFSYS_PROBE1(fail1, efx_rc_t, rc); 828 829 return (rc); 830} 831 832 __checkReturn efx_rc_t 833efx_mcdi_nvram_update_finish( 834 __in efx_nic_t *enp, 835 __in uint32_t partn, 836 __in boolean_t reboot) 837{ 838 efx_mcdi_req_t req; 839 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN, 840 MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN)]; 841 efx_rc_t rc; 842 843 (void) memset(payload, 0, sizeof (payload)); 844 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH; 845 req.emr_in_buf = payload; 846 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN; 847 req.emr_out_buf = payload; 848 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN; 849 850 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn); 851 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot); 852 853 efx_mcdi_execute(enp, &req); 854 855 if (req.emr_rc != 0) { 856 rc = req.emr_rc; 857 goto fail1; 858 } 859 860 return (0); 861 862fail1: 863 EFSYS_PROBE1(fail1, efx_rc_t, rc); 864 865 return (rc); 866} 867 868#if EFSYS_OPT_DIAG 869 870 __checkReturn efx_rc_t 871efx_mcdi_nvram_test( 872 __in efx_nic_t *enp, 873 __in uint32_t partn) 874{ 875 efx_mcdi_req_t req; 876 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN, 877 MC_CMD_NVRAM_TEST_OUT_LEN)]; 878 int result; 879 efx_rc_t rc; 880 881 (void) memset(payload, 0, sizeof (payload)); 882 req.emr_cmd = MC_CMD_NVRAM_TEST; 883 req.emr_in_buf = payload; 884 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; 885 req.emr_out_buf = payload; 886 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; 887 888 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn); 889 890 efx_mcdi_execute(enp, &req); 891 892 if (req.emr_rc != 0) { 893 rc = req.emr_rc; 894 goto fail1; 895 } 896 897 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { 898 rc = EMSGSIZE; 899 goto fail2; 900 } 901 902 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); 903 if (result == MC_CMD_NVRAM_TEST_FAIL) { 904 905 EFSYS_PROBE1(nvram_test_failure, int, partn); 906 907 rc = (EINVAL); 908 goto fail3; 909 } 910 911 return (0); 912 913fail3: 914 EFSYS_PROBE(fail3); 915fail2: 916 EFSYS_PROBE(fail2); 917fail1: 918 EFSYS_PROBE1(fail1, efx_rc_t, rc); 919 920 return (rc); 921} 922 923#endif /* EFSYS_OPT_DIAG */ 924 925 926#endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ 927