efx_nvram.c revision 294250
1217309Snwhitehorn/*- 2217309Snwhitehorn * Copyright (c) 2009-2015 Solarflare Communications Inc. 3217309Snwhitehorn * All rights reserved. 4217309Snwhitehorn * 5217309Snwhitehorn * Redistribution and use in source and binary forms, with or without 6217309Snwhitehorn * modification, are permitted provided that the following conditions are met: 7217309Snwhitehorn * 8217309Snwhitehorn * 1. Redistributions of source code must retain the above copyright notice, 9217309Snwhitehorn * this list of conditions and the following disclaimer. 10217309Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright notice, 11217309Snwhitehorn * this list of conditions and the following disclaimer in the documentation 12217309Snwhitehorn * and/or other materials provided with the distribution. 13217309Snwhitehorn * 14217309Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15217309Snwhitehorn * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16217309Snwhitehorn * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17217309Snwhitehorn * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18217309Snwhitehorn * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19217309Snwhitehorn * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20217309Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21217309Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22217309Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23217309Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24217309Snwhitehorn * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25217309Snwhitehorn * 26217309Snwhitehorn * The views and conclusions contained in the software and documentation are 27217309Snwhitehorn * those of the authors and should not be interpreted as representing official 28217309Snwhitehorn * policies, either expressed or implied, of the FreeBSD Project. 29217309Snwhitehorn */ 30217309Snwhitehorn 31217309Snwhitehorn#include <sys/cdefs.h> 32217309Snwhitehorn__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_nvram.c 294250 2016-01-18 06:14:43Z arybchik $"); 33217309Snwhitehorn 34217309Snwhitehorn#include "efx.h" 35217309Snwhitehorn#include "efx_impl.h" 36217309Snwhitehorn 37217309Snwhitehorn#if EFSYS_OPT_NVRAM 38217309Snwhitehorn 39217309Snwhitehorn#if EFSYS_OPT_FALCON 40217309Snwhitehorn 41217309Snwhitehornstatic efx_nvram_ops_t __efx_nvram_falcon_ops = { 42217309Snwhitehorn#if EFSYS_OPT_DIAG 43217309Snwhitehorn falcon_nvram_test, /* envo_test */ 44217309Snwhitehorn#endif /* EFSYS_OPT_DIAG */ 45217309Snwhitehorn falcon_nvram_get_version, /* envo_get_version */ 46217309Snwhitehorn falcon_nvram_set_version, /* envo_set_version */ 47217309Snwhitehorn falcon_nvram_type_to_partn, /* envo_type_to_partn */ 48217309Snwhitehorn falcon_nvram_partn_size, /* envo_partn_size */ 49217309Snwhitehorn falcon_nvram_partn_rw_start, /* envo_partn_rw_start */ 50217309Snwhitehorn falcon_nvram_partn_read, /* envo_partn_read */ 51217309Snwhitehorn falcon_nvram_partn_erase, /* envo_partn_erase */ 52217309Snwhitehorn falcon_nvram_partn_write, /* envo_partn_write */ 53217309Snwhitehorn falcon_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 54217309Snwhitehorn}; 55217309Snwhitehorn 56217309Snwhitehorn#endif /* EFSYS_OPT_FALCON */ 57217309Snwhitehorn 58217309Snwhitehorn#if EFSYS_OPT_SIENA 59217309Snwhitehorn 60217309Snwhitehornstatic efx_nvram_ops_t __efx_nvram_siena_ops = { 61217309Snwhitehorn#if EFSYS_OPT_DIAG 62217309Snwhitehorn siena_nvram_test, /* envo_test */ 63217309Snwhitehorn#endif /* EFSYS_OPT_DIAG */ 64217309Snwhitehorn siena_nvram_get_version, /* envo_get_version */ 65217309Snwhitehorn siena_nvram_set_version, /* envo_set_version */ 66217309Snwhitehorn siena_nvram_type_to_partn, /* envo_type_to_partn */ 67217309Snwhitehorn siena_nvram_partn_size, /* envo_partn_size */ 68217309Snwhitehorn siena_nvram_partn_rw_start, /* envo_partn_rw_start */ 69217309Snwhitehorn siena_nvram_partn_read, /* envo_partn_read */ 70217309Snwhitehorn siena_nvram_partn_erase, /* envo_partn_erase */ 71217309Snwhitehorn siena_nvram_partn_write, /* envo_partn_write */ 72217309Snwhitehorn siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 73217309Snwhitehorn}; 74217309Snwhitehorn 75217309Snwhitehorn#endif /* EFSYS_OPT_SIENA */ 76217309Snwhitehorn 77217309Snwhitehorn#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 78217309Snwhitehorn 79217309Snwhitehornstatic efx_nvram_ops_t __efx_nvram_ef10_ops = { 80217309Snwhitehorn#if EFSYS_OPT_DIAG 81217309Snwhitehorn ef10_nvram_test, /* envo_test */ 82217309Snwhitehorn#endif /* EFSYS_OPT_DIAG */ 83217309Snwhitehorn ef10_nvram_get_version, /* envo_get_version */ 84217309Snwhitehorn ef10_nvram_set_version, /* envo_set_version */ 85217309Snwhitehorn ef10_nvram_type_to_partn, /* envo_type_to_partn */ 86217309Snwhitehorn ef10_nvram_partn_size, /* envo_partn_size */ 87217309Snwhitehorn ef10_nvram_partn_rw_start, /* envo_partn_rw_start */ 88217309Snwhitehorn ef10_nvram_partn_read, /* envo_partn_read */ 89217309Snwhitehorn ef10_nvram_partn_erase, /* envo_partn_erase */ 90217309Snwhitehorn ef10_nvram_partn_write, /* envo_partn_write */ 91217309Snwhitehorn ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 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 uint32_t partn; 388 389 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 390 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 391 392 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 393 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 394 395 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 396 397 if (envop->envo_type_to_partn(enp, type, &partn) == 0) 398 envop->envo_partn_rw_finish(enp, partn); 399 400 enp->en_nvram_locked = EFX_NVRAM_INVALID; 401} 402 403 __checkReturn efx_rc_t 404efx_nvram_set_version( 405 __in efx_nic_t *enp, 406 __in efx_nvram_type_t type, 407 __in_ecount(4) uint16_t version[4]) 408{ 409 efx_nvram_ops_t *envop = enp->en_envop; 410 efx_rc_t rc; 411 412 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 413 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 414 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 415 416 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 417 418 /* 419 * The Siena implementation of envo_set_version() will attempt to 420 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector. 421 * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 422 */ 423 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 424 425 if ((rc = envop->envo_set_version(enp, type, version)) != 0) 426 goto fail1; 427 428 return (0); 429 430fail1: 431 EFSYS_PROBE1(fail1, efx_rc_t, rc); 432 433 return (rc); 434} 435 436void 437efx_nvram_fini( 438 __in efx_nic_t *enp) 439{ 440 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 441 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 442 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 443 444 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 445 446 enp->en_envop = NULL; 447 enp->en_mod_flags &= ~EFX_MOD_NVRAM; 448} 449 450#endif /* EFSYS_OPT_NVRAM */ 451 452#if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD 453 454/* 455 * Internal MCDI request handling 456 */ 457 458 __checkReturn efx_rc_t 459efx_mcdi_nvram_partitions( 460 __in efx_nic_t *enp, 461 __out_bcount(size) caddr_t data, 462 __in size_t size, 463 __out unsigned int *npartnp) 464{ 465 efx_mcdi_req_t req; 466 uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN, 467 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)]; 468 unsigned int npartn; 469 efx_rc_t rc; 470 471 (void) memset(payload, 0, sizeof (payload)); 472 req.emr_cmd = MC_CMD_NVRAM_PARTITIONS; 473 req.emr_in_buf = payload; 474 req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN; 475 req.emr_out_buf = payload; 476 req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX; 477 478 efx_mcdi_execute(enp, &req); 479 480 if (req.emr_rc != 0) { 481 rc = req.emr_rc; 482 goto fail1; 483 } 484 485 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) { 486 rc = EMSGSIZE; 487 goto fail2; 488 } 489 npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); 490 491 if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) { 492 rc = ENOENT; 493 goto fail3; 494 } 495 496 if (size < npartn * sizeof (uint32_t)) { 497 rc = ENOSPC; 498 goto fail3; 499 } 500 501 *npartnp = npartn; 502 503 memcpy(data, 504 MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID), 505 (npartn * sizeof (uint32_t))); 506 507 return (0); 508 509fail3: 510 EFSYS_PROBE(fail3); 511fail2: 512 EFSYS_PROBE(fail2); 513fail1: 514 EFSYS_PROBE1(fail1, efx_rc_t, rc); 515 516 return (rc); 517} 518 519 __checkReturn efx_rc_t 520efx_mcdi_nvram_metadata( 521 __in efx_nic_t *enp, 522 __in uint32_t partn, 523 __out uint32_t *subtypep, 524 __out_ecount(4) uint16_t version[4], 525 __out_bcount_opt(size) char *descp, 526 __in size_t size) 527{ 528 efx_mcdi_req_t req; 529 uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN, 530 MC_CMD_NVRAM_METADATA_OUT_LENMAX)]; 531 efx_rc_t rc; 532 533 (void) memset(payload, 0, sizeof (payload)); 534 req.emr_cmd = MC_CMD_NVRAM_METADATA; 535 req.emr_in_buf = payload; 536 req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN; 537 req.emr_out_buf = payload; 538 req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX; 539 540 MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); 541 542 efx_mcdi_execute(enp, &req); 543 544 if (req.emr_rc != 0) { 545 rc = req.emr_rc; 546 goto fail1; 547 } 548 549 if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) { 550 rc = EMSGSIZE; 551 goto fail2; 552 } 553 554 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 555 NVRAM_METADATA_OUT_SUBTYPE_VALID)) { 556 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE); 557 } else { 558 *subtypep = 0; 559 } 560 561 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 562 NVRAM_METADATA_OUT_VERSION_VALID)) { 563 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W); 564 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X); 565 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y); 566 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z); 567 } else { 568 version[0] = version[1] = version[2] = version[3] = 0; 569 } 570 571 if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 572 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) { 573 /* Return optional descrition string */ 574 if ((descp != NULL) && (size > 0)) { 575 size_t desclen; 576 577 descp[0] = '\0'; 578 desclen = (req.emr_out_length_used 579 - MC_CMD_NVRAM_METADATA_OUT_LEN(0)); 580 581 EFSYS_ASSERT3U(desclen, <=, 582 MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM); 583 584 if (size < desclen) { 585 rc = ENOSPC; 586 goto fail3; 587 } 588 589 memcpy(descp, MCDI_OUT2(req, char, 590 NVRAM_METADATA_OUT_DESCRIPTION), 591 desclen); 592 593 /* Ensure string is NUL terminated */ 594 descp[desclen] = '\0'; 595 } 596 } 597 598 return (0); 599 600fail3: 601 EFSYS_PROBE(fail3); 602fail2: 603 EFSYS_PROBE(fail2); 604fail1: 605 EFSYS_PROBE1(fail1, efx_rc_t, rc); 606 607 return (rc); 608} 609 610 __checkReturn efx_rc_t 611efx_mcdi_nvram_info( 612 __in efx_nic_t *enp, 613 __in uint32_t partn, 614 __out_opt size_t *sizep, 615 __out_opt uint32_t *addressp, 616 __out_opt uint32_t *erase_sizep, 617 __out_opt uint32_t *write_sizep) 618{ 619 uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN, 620 MC_CMD_NVRAM_INFO_V2_OUT_LEN)]; 621 efx_mcdi_req_t req; 622 efx_rc_t rc; 623 624 (void) memset(payload, 0, sizeof (payload)); 625 req.emr_cmd = MC_CMD_NVRAM_INFO; 626 req.emr_in_buf = payload; 627 req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN; 628 req.emr_out_buf = payload; 629 req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN; 630 631 MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn); 632 633 efx_mcdi_execute_quiet(enp, &req); 634 635 if (req.emr_rc != 0) { 636 rc = req.emr_rc; 637 goto fail1; 638 } 639 640 if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) { 641 rc = EMSGSIZE; 642 goto fail2; 643 } 644 645 if (sizep) 646 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE); 647 648 if (addressp) 649 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR); 650 651 if (erase_sizep) 652 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE); 653 654 if (write_sizep) { 655 *write_sizep = 656 (req.emr_out_length_used < 657 MC_CMD_NVRAM_INFO_V2_OUT_LEN) ? 658 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE); 659 } 660 661 return (0); 662 663fail2: 664 EFSYS_PROBE(fail2); 665fail1: 666 EFSYS_PROBE1(fail1, efx_rc_t, rc); 667 668 return (rc); 669} 670 671 __checkReturn efx_rc_t 672efx_mcdi_nvram_update_start( 673 __in efx_nic_t *enp, 674 __in uint32_t partn) 675{ 676 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_IN_LEN, 677 MC_CMD_NVRAM_UPDATE_START_OUT_LEN)]; 678 efx_mcdi_req_t req; 679 efx_rc_t rc; 680 681 (void) memset(payload, 0, sizeof (payload)); 682 req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; 683 req.emr_in_buf = payload; 684 req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN; 685 req.emr_out_buf = payload; 686 req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN; 687 688 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn); 689 690 efx_mcdi_execute(enp, &req); 691 692 if (req.emr_rc != 0) { 693 rc = req.emr_rc; 694 goto fail1; 695 } 696 697 return (0); 698 699fail1: 700 EFSYS_PROBE1(fail1, efx_rc_t, rc); 701 702 return (rc); 703} 704 705 __checkReturn efx_rc_t 706efx_mcdi_nvram_read( 707 __in efx_nic_t *enp, 708 __in uint32_t partn, 709 __in uint32_t offset, 710 __out_bcount(size) caddr_t data, 711 __in size_t size) 712{ 713 efx_mcdi_req_t req; 714 uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_LEN, 715 MC_CMD_NVRAM_READ_OUT_LENMAX)]; 716 efx_rc_t rc; 717 718 if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) { 719 rc = EINVAL; 720 goto fail1; 721 } 722 723 (void) memset(payload, 0, sizeof (payload)); 724 req.emr_cmd = MC_CMD_NVRAM_READ; 725 req.emr_in_buf = payload; 726 req.emr_in_length = MC_CMD_NVRAM_READ_IN_LEN; 727 req.emr_out_buf = payload; 728 req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX; 729 730 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_TYPE, partn); 731 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_OFFSET, offset); 732 MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_LENGTH, size); 733 734 efx_mcdi_execute(enp, &req); 735 736 if (req.emr_rc != 0) { 737 rc = req.emr_rc; 738 goto fail1; 739 } 740 741 if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) { 742 rc = EMSGSIZE; 743 goto fail2; 744 } 745 746 memcpy(data, 747 MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER), 748 size); 749 750 return (0); 751 752fail2: 753 EFSYS_PROBE(fail2); 754fail1: 755 EFSYS_PROBE1(fail1, efx_rc_t, rc); 756 757 return (rc); 758} 759 760 __checkReturn efx_rc_t 761efx_mcdi_nvram_erase( 762 __in efx_nic_t *enp, 763 __in uint32_t partn, 764 __in uint32_t offset, 765 __in size_t size) 766{ 767 efx_mcdi_req_t req; 768 uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN, 769 MC_CMD_NVRAM_ERASE_OUT_LEN)]; 770 efx_rc_t rc; 771 772 (void) memset(payload, 0, sizeof (payload)); 773 req.emr_cmd = MC_CMD_NVRAM_ERASE; 774 req.emr_in_buf = payload; 775 req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; 776 req.emr_out_buf = payload; 777 req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN; 778 779 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); 780 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); 781 MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); 782 783 efx_mcdi_execute(enp, &req); 784 785 if (req.emr_rc != 0) { 786 rc = req.emr_rc; 787 goto fail1; 788 } 789 790 return (0); 791 792fail1: 793 EFSYS_PROBE1(fail1, efx_rc_t, rc); 794 795 return (rc); 796} 797 798/* 799 * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both 800 * Sienna and EF10 based boards. However EF10 based boards support the use 801 * of this command with payloads up to the maximum MCDI V2 payload length. 802 */ 803 __checkReturn efx_rc_t 804efx_mcdi_nvram_write( 805 __in efx_nic_t *enp, 806 __in uint32_t partn, 807 __in uint32_t offset, 808 __out_bcount(size) caddr_t data, 809 __in size_t size) 810{ 811 efx_mcdi_req_t req; 812 uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1, 813 MCDI_CTL_SDU_LEN_MAX_V2)]; 814 efx_rc_t rc; 815 size_t max_data_size; 816 817 max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length 818 - MC_CMD_NVRAM_WRITE_IN_LEN(0); 819 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0); 820 EFSYS_ASSERT3U(max_data_size, <, 821 enp->en_nic_cfg.enc_mcdi_max_payload_length); 822 823 if (size > max_data_size) { 824 rc = EINVAL; 825 goto fail1; 826 } 827 828 (void) memset(payload, 0, sizeof (payload)); 829 req.emr_cmd = MC_CMD_NVRAM_WRITE; 830 req.emr_in_buf = payload; 831 req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size); 832 req.emr_out_buf = payload; 833 req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN; 834 835 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); 836 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); 837 MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size); 838 839 memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), 840 data, size); 841 842 efx_mcdi_execute(enp, &req); 843 844 if (req.emr_rc != 0) { 845 rc = req.emr_rc; 846 goto fail2; 847 } 848 849 return (0); 850 851fail2: 852 EFSYS_PROBE(fail2); 853fail1: 854 EFSYS_PROBE1(fail1, efx_rc_t, rc); 855 856 return (rc); 857} 858 859 __checkReturn efx_rc_t 860efx_mcdi_nvram_update_finish( 861 __in efx_nic_t *enp, 862 __in uint32_t partn, 863 __in boolean_t reboot) 864{ 865 efx_mcdi_req_t req; 866 uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN, 867 MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN)]; 868 efx_rc_t rc; 869 870 (void) memset(payload, 0, sizeof (payload)); 871 req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH; 872 req.emr_in_buf = payload; 873 req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN; 874 req.emr_out_buf = payload; 875 req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN; 876 877 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn); 878 MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot); 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 return (0); 888 889fail1: 890 EFSYS_PROBE1(fail1, efx_rc_t, rc); 891 892 return (rc); 893} 894 895#if EFSYS_OPT_DIAG 896 897 __checkReturn efx_rc_t 898efx_mcdi_nvram_test( 899 __in efx_nic_t *enp, 900 __in uint32_t partn) 901{ 902 efx_mcdi_req_t req; 903 uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN, 904 MC_CMD_NVRAM_TEST_OUT_LEN)]; 905 int result; 906 efx_rc_t rc; 907 908 (void) memset(payload, 0, sizeof (payload)); 909 req.emr_cmd = MC_CMD_NVRAM_TEST; 910 req.emr_in_buf = payload; 911 req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; 912 req.emr_out_buf = payload; 913 req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; 914 915 MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn); 916 917 efx_mcdi_execute(enp, &req); 918 919 if (req.emr_rc != 0) { 920 rc = req.emr_rc; 921 goto fail1; 922 } 923 924 if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { 925 rc = EMSGSIZE; 926 goto fail2; 927 } 928 929 result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); 930 if (result == MC_CMD_NVRAM_TEST_FAIL) { 931 932 EFSYS_PROBE1(nvram_test_failure, int, partn); 933 934 rc = (EINVAL); 935 goto fail3; 936 } 937 938 return (0); 939 940fail3: 941 EFSYS_PROBE(fail3); 942fail2: 943 EFSYS_PROBE(fail2); 944fail1: 945 EFSYS_PROBE1(fail1, efx_rc_t, rc); 946 947 return (rc); 948} 949 950#endif /* EFSYS_OPT_DIAG */ 951 952 953#endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ 954