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