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