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