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