1227569Sphilip/*- 2300607Sarybchik * Copyright (c) 2009-2016 Solarflare Communications Inc. 3283514Sarybchik * All rights reserved. 4227569Sphilip * 5227569Sphilip * Redistribution and use in source and binary forms, with or without 6283514Sarybchik * modification, are permitted provided that the following conditions are met: 7227569Sphilip * 8283514Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 9283514Sarybchik * this list of conditions and the following disclaimer. 10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 11283514Sarybchik * this list of conditions and the following disclaimer in the documentation 12283514Sarybchik * and/or other materials provided with the distribution. 13283514Sarybchik * 14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15283514Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16283514Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17283514Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18283514Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19283514Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20283514Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21283514Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22283514Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23283514Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24283514Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25283514Sarybchik * 26283514Sarybchik * The views and conclusions contained in the software and documentation are 27283514Sarybchik * those of the authors and should not be interpreted as representing official 28283514Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 29227569Sphilip */ 30227569Sphilip 31228078Sphilip#include <sys/cdefs.h> 32228078Sphilip__FBSDID("$FreeBSD: stable/11/sys/dev/sfxge/common/efx_vpd.c 342428 2018-12-25 07:03:01Z arybchik $"); 33228078Sphilip 34227569Sphilip#include "efx.h" 35227569Sphilip#include "efx_impl.h" 36227569Sphilip 37227569Sphilip#if EFSYS_OPT_VPD 38227569Sphilip 39227569Sphilip#define TAG_TYPE_LBN 7 40227569Sphilip#define TAG_TYPE_WIDTH 1 41227569Sphilip#define TAG_TYPE_LARGE_ITEM_DECODE 1 42227569Sphilip#define TAG_TYPE_SMALL_ITEM_DECODE 0 43227569Sphilip 44227569Sphilip#define TAG_SMALL_ITEM_NAME_LBN 3 45227569Sphilip#define TAG_SMALL_ITEM_NAME_WIDTH 4 46227569Sphilip#define TAG_SMALL_ITEM_SIZE_LBN 0 47227569Sphilip#define TAG_SMALL_ITEM_SIZE_WIDTH 3 48227569Sphilip 49227569Sphilip#define TAG_LARGE_ITEM_NAME_LBN 0 50227569Sphilip#define TAG_LARGE_ITEM_NAME_WIDTH 7 51227569Sphilip 52227569Sphilip#define TAG_NAME_END_DECODE 0x0f 53227569Sphilip#define TAG_NAME_ID_STRING_DECODE 0x02 54227569Sphilip#define TAG_NAME_VPD_R_DECODE 0x10 55227569Sphilip#define TAG_NAME_VPD_W_DECODE 0x11 56227569Sphilip 57227569Sphilip#if EFSYS_OPT_SIENA 58227569Sphilip 59299517Sarybchikstatic const efx_vpd_ops_t __efx_vpd_siena_ops = { 60227569Sphilip siena_vpd_init, /* evpdo_init */ 61227569Sphilip siena_vpd_size, /* evpdo_size */ 62227569Sphilip siena_vpd_read, /* evpdo_read */ 63227569Sphilip siena_vpd_verify, /* evpdo_verify */ 64227569Sphilip siena_vpd_reinit, /* evpdo_reinit */ 65227569Sphilip siena_vpd_get, /* evpdo_get */ 66227569Sphilip siena_vpd_set, /* evpdo_set */ 67227569Sphilip siena_vpd_next, /* evpdo_next */ 68227569Sphilip siena_vpd_write, /* evpdo_write */ 69227569Sphilip siena_vpd_fini, /* evpdo_fini */ 70227569Sphilip}; 71227569Sphilip 72227569Sphilip#endif /* EFSYS_OPT_SIENA */ 73227569Sphilip 74293755Sarybchik#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 75283514Sarybchik 76299517Sarybchikstatic const efx_vpd_ops_t __efx_vpd_ef10_ops = { 77293755Sarybchik ef10_vpd_init, /* evpdo_init */ 78293755Sarybchik ef10_vpd_size, /* evpdo_size */ 79293755Sarybchik ef10_vpd_read, /* evpdo_read */ 80293755Sarybchik ef10_vpd_verify, /* evpdo_verify */ 81293755Sarybchik ef10_vpd_reinit, /* evpdo_reinit */ 82293755Sarybchik ef10_vpd_get, /* evpdo_get */ 83293755Sarybchik ef10_vpd_set, /* evpdo_set */ 84293755Sarybchik ef10_vpd_next, /* evpdo_next */ 85293755Sarybchik ef10_vpd_write, /* evpdo_write */ 86293755Sarybchik ef10_vpd_fini, /* evpdo_fini */ 87283514Sarybchik}; 88283514Sarybchik 89293755Sarybchik#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 90283514Sarybchik 91291436Sarybchik __checkReturn efx_rc_t 92227569Sphilipefx_vpd_init( 93227569Sphilip __in efx_nic_t *enp) 94227569Sphilip{ 95299517Sarybchik const efx_vpd_ops_t *evpdop; 96291436Sarybchik efx_rc_t rc; 97227569Sphilip 98227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 99227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 100227569Sphilip EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_VPD)); 101227569Sphilip 102227569Sphilip switch (enp->en_family) { 103227569Sphilip#if EFSYS_OPT_SIENA 104227569Sphilip case EFX_FAMILY_SIENA: 105299517Sarybchik evpdop = &__efx_vpd_siena_ops; 106227569Sphilip break; 107227569Sphilip#endif /* EFSYS_OPT_SIENA */ 108227569Sphilip 109283514Sarybchik#if EFSYS_OPT_HUNTINGTON 110283514Sarybchik case EFX_FAMILY_HUNTINGTON: 111299517Sarybchik evpdop = &__efx_vpd_ef10_ops; 112283514Sarybchik break; 113283514Sarybchik#endif /* EFSYS_OPT_HUNTINGTON */ 114283514Sarybchik 115293755Sarybchik#if EFSYS_OPT_MEDFORD 116293755Sarybchik case EFX_FAMILY_MEDFORD: 117299517Sarybchik evpdop = &__efx_vpd_ef10_ops; 118293755Sarybchik break; 119293755Sarybchik#endif /* EFSYS_OPT_MEDFORD */ 120293755Sarybchik 121227569Sphilip default: 122227569Sphilip EFSYS_ASSERT(0); 123227569Sphilip rc = ENOTSUP; 124227569Sphilip goto fail1; 125227569Sphilip } 126227569Sphilip 127227569Sphilip if (evpdop->evpdo_init != NULL) { 128227569Sphilip if ((rc = evpdop->evpdo_init(enp)) != 0) 129227569Sphilip goto fail2; 130227569Sphilip } 131227569Sphilip 132227569Sphilip enp->en_evpdop = evpdop; 133227569Sphilip enp->en_mod_flags |= EFX_MOD_VPD; 134227569Sphilip 135227569Sphilip return (0); 136227569Sphilip 137227569Sphilipfail2: 138227569Sphilip EFSYS_PROBE(fail2); 139227569Sphilipfail1: 140291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 141227569Sphilip 142227569Sphilip return (rc); 143227569Sphilip} 144227569Sphilip 145291436Sarybchik __checkReturn efx_rc_t 146227569Sphilipefx_vpd_size( 147227569Sphilip __in efx_nic_t *enp, 148227569Sphilip __out size_t *sizep) 149227569Sphilip{ 150299517Sarybchik const efx_vpd_ops_t *evpdop = enp->en_evpdop; 151291436Sarybchik efx_rc_t rc; 152227569Sphilip 153227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 154227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD); 155227569Sphilip 156227569Sphilip if ((rc = evpdop->evpdo_size(enp, sizep)) != 0) 157227569Sphilip goto fail1; 158227569Sphilip 159227569Sphilip return (0); 160227569Sphilip 161227569Sphilipfail1: 162291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 163227569Sphilip 164227569Sphilip return (rc); 165227569Sphilip} 166227569Sphilip 167291436Sarybchik __checkReturn efx_rc_t 168227569Sphilipefx_vpd_read( 169227569Sphilip __in efx_nic_t *enp, 170227569Sphilip __out_bcount(size) caddr_t data, 171227569Sphilip __in size_t size) 172227569Sphilip{ 173299517Sarybchik const efx_vpd_ops_t *evpdop = enp->en_evpdop; 174291436Sarybchik efx_rc_t rc; 175227569Sphilip 176227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 177227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD); 178227569Sphilip 179227569Sphilip if ((rc = evpdop->evpdo_read(enp, data, size)) != 0) 180227569Sphilip goto fail1; 181227569Sphilip 182227569Sphilip return (0); 183227569Sphilip 184227569Sphilipfail1: 185291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 186227569Sphilip 187227569Sphilip return (rc); 188227569Sphilip} 189227569Sphilip 190291436Sarybchik __checkReturn efx_rc_t 191227569Sphilipefx_vpd_verify( 192227569Sphilip __in efx_nic_t *enp, 193227569Sphilip __in_bcount(size) caddr_t data, 194227569Sphilip __in size_t size) 195227569Sphilip{ 196299517Sarybchik const efx_vpd_ops_t *evpdop = enp->en_evpdop; 197291436Sarybchik efx_rc_t rc; 198227569Sphilip 199227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 200227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD); 201227569Sphilip 202227569Sphilip if ((rc = evpdop->evpdo_verify(enp, data, size)) != 0) 203227569Sphilip goto fail1; 204227569Sphilip 205227569Sphilip return (0); 206227569Sphilip 207227569Sphilipfail1: 208291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 209227569Sphilip 210227569Sphilip return (rc); 211227569Sphilip} 212227569Sphilip 213291436Sarybchik __checkReturn efx_rc_t 214227569Sphilipefx_vpd_reinit( 215227569Sphilip __in efx_nic_t *enp, 216227569Sphilip __in_bcount(size) caddr_t data, 217227569Sphilip __in size_t size) 218227569Sphilip{ 219299517Sarybchik const efx_vpd_ops_t *evpdop = enp->en_evpdop; 220291436Sarybchik efx_rc_t rc; 221227569Sphilip 222227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 223227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD); 224227569Sphilip 225227569Sphilip if (evpdop->evpdo_reinit == NULL) { 226227569Sphilip rc = ENOTSUP; 227227569Sphilip goto fail1; 228227569Sphilip } 229227569Sphilip 230227569Sphilip if ((rc = evpdop->evpdo_reinit(enp, data, size)) != 0) 231227569Sphilip goto fail2; 232227569Sphilip 233227569Sphilip return (0); 234227569Sphilip 235227569Sphilipfail2: 236227569Sphilip EFSYS_PROBE(fail2); 237227569Sphilipfail1: 238291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 239227569Sphilip 240227569Sphilip return (rc); 241227569Sphilip} 242227569Sphilip 243291436Sarybchik __checkReturn efx_rc_t 244227569Sphilipefx_vpd_get( 245227569Sphilip __in efx_nic_t *enp, 246227569Sphilip __in_bcount(size) caddr_t data, 247227569Sphilip __in size_t size, 248227569Sphilip __inout efx_vpd_value_t *evvp) 249227569Sphilip{ 250299517Sarybchik const efx_vpd_ops_t *evpdop = enp->en_evpdop; 251291436Sarybchik efx_rc_t rc; 252227569Sphilip 253227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 254227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD); 255227569Sphilip 256299901Sarybchik if ((rc = evpdop->evpdo_get(enp, data, size, evvp)) != 0) { 257299901Sarybchik if (rc == ENOENT) 258299901Sarybchik return (rc); 259299901Sarybchik 260227569Sphilip goto fail1; 261299901Sarybchik } 262227569Sphilip 263227569Sphilip return (0); 264227569Sphilip 265227569Sphilipfail1: 266291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 267227569Sphilip 268227569Sphilip return (rc); 269227569Sphilip} 270227569Sphilip 271291436Sarybchik __checkReturn efx_rc_t 272227569Sphilipefx_vpd_set( 273227569Sphilip __in efx_nic_t *enp, 274227569Sphilip __inout_bcount(size) caddr_t data, 275227569Sphilip __in size_t size, 276227569Sphilip __in efx_vpd_value_t *evvp) 277227569Sphilip{ 278299517Sarybchik const efx_vpd_ops_t *evpdop = enp->en_evpdop; 279291436Sarybchik efx_rc_t rc; 280227569Sphilip 281227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 282227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD); 283227569Sphilip 284227569Sphilip if ((rc = evpdop->evpdo_set(enp, data, size, evvp)) != 0) 285227569Sphilip goto fail1; 286227569Sphilip 287227569Sphilip return (0); 288227569Sphilip 289227569Sphilipfail1: 290291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 291227569Sphilip 292227569Sphilip return (rc); 293227569Sphilip} 294227569Sphilip 295291436Sarybchik __checkReturn efx_rc_t 296227569Sphilipefx_vpd_next( 297227569Sphilip __in efx_nic_t *enp, 298227569Sphilip __inout_bcount(size) caddr_t data, 299227569Sphilip __in size_t size, 300227569Sphilip __out efx_vpd_value_t *evvp, 301227569Sphilip __inout unsigned int *contp) 302227569Sphilip{ 303299517Sarybchik const efx_vpd_ops_t *evpdop = enp->en_evpdop; 304291436Sarybchik efx_rc_t rc; 305227569Sphilip 306227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 307227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD); 308227569Sphilip 309227569Sphilip if ((rc = evpdop->evpdo_next(enp, data, size, evvp, contp)) != 0) 310227569Sphilip goto fail1; 311227569Sphilip 312227569Sphilip return (0); 313227569Sphilip 314227569Sphilipfail1: 315291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 316227569Sphilip 317227569Sphilip return (rc); 318227569Sphilip} 319227569Sphilip 320291436Sarybchik __checkReturn efx_rc_t 321227569Sphilipefx_vpd_write( 322227569Sphilip __in efx_nic_t *enp, 323227569Sphilip __in_bcount(size) caddr_t data, 324227569Sphilip __in size_t size) 325227569Sphilip{ 326299517Sarybchik const efx_vpd_ops_t *evpdop = enp->en_evpdop; 327291436Sarybchik efx_rc_t rc; 328227569Sphilip 329227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 330227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD); 331227569Sphilip 332227569Sphilip if ((rc = evpdop->evpdo_write(enp, data, size)) != 0) 333227569Sphilip goto fail1; 334227569Sphilip 335227569Sphilip return (0); 336227569Sphilip 337227569Sphilipfail1: 338291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 339227569Sphilip 340227569Sphilip return (rc); 341227569Sphilip} 342227569Sphilip 343291436Sarybchikstatic __checkReturn efx_rc_t 344227569Sphilipefx_vpd_next_tag( 345227569Sphilip __in caddr_t data, 346227569Sphilip __in size_t size, 347227569Sphilip __inout unsigned int *offsetp, 348227569Sphilip __out efx_vpd_tag_t *tagp, 349227569Sphilip __out uint16_t *lengthp) 350227569Sphilip{ 351227569Sphilip efx_byte_t byte; 352227569Sphilip efx_word_t word; 353227569Sphilip uint8_t name; 354227569Sphilip uint16_t length; 355227569Sphilip size_t headlen; 356291436Sarybchik efx_rc_t rc; 357227569Sphilip 358227569Sphilip if (*offsetp >= size) { 359227569Sphilip rc = EFAULT; 360227569Sphilip goto fail1; 361227569Sphilip } 362227569Sphilip 363227569Sphilip EFX_POPULATE_BYTE_1(byte, EFX_BYTE_0, data[*offsetp]); 364227569Sphilip 365227569Sphilip switch (EFX_BYTE_FIELD(byte, TAG_TYPE)) { 366227569Sphilip case TAG_TYPE_SMALL_ITEM_DECODE: 367227569Sphilip headlen = 1; 368227569Sphilip 369227569Sphilip name = EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_NAME); 370227569Sphilip length = (uint16_t)EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_SIZE); 371227569Sphilip 372227569Sphilip break; 373227569Sphilip 374227569Sphilip case TAG_TYPE_LARGE_ITEM_DECODE: 375227569Sphilip headlen = 3; 376227569Sphilip 377227569Sphilip if (*offsetp + headlen > size) { 378227569Sphilip rc = EFAULT; 379227569Sphilip goto fail2; 380227569Sphilip } 381227569Sphilip 382227569Sphilip name = EFX_BYTE_FIELD(byte, TAG_LARGE_ITEM_NAME); 383227569Sphilip EFX_POPULATE_WORD_2(word, 384227569Sphilip EFX_BYTE_0, data[*offsetp + 1], 385227569Sphilip EFX_BYTE_1, data[*offsetp + 2]); 386227569Sphilip length = EFX_WORD_FIELD(word, EFX_WORD_0); 387227569Sphilip 388227569Sphilip break; 389227569Sphilip 390227569Sphilip default: 391227569Sphilip rc = EFAULT; 392227569Sphilip goto fail2; 393227569Sphilip } 394227569Sphilip 395227569Sphilip if (*offsetp + headlen + length > size) { 396227569Sphilip rc = EFAULT; 397227569Sphilip goto fail3; 398227569Sphilip } 399227569Sphilip 400227569Sphilip EFX_STATIC_ASSERT(TAG_NAME_END_DECODE == EFX_VPD_END); 401227569Sphilip EFX_STATIC_ASSERT(TAG_NAME_ID_STRING_DECODE == EFX_VPD_ID); 402227569Sphilip EFX_STATIC_ASSERT(TAG_NAME_VPD_R_DECODE == EFX_VPD_RO); 403227569Sphilip EFX_STATIC_ASSERT(TAG_NAME_VPD_W_DECODE == EFX_VPD_RW); 404227569Sphilip if (name != EFX_VPD_END && name != EFX_VPD_ID && 405227569Sphilip name != EFX_VPD_RO) { 406227569Sphilip rc = EFAULT; 407227569Sphilip goto fail4; 408227569Sphilip } 409227569Sphilip 410227569Sphilip *tagp = name; 411227569Sphilip *lengthp = length; 412227569Sphilip *offsetp += headlen; 413227569Sphilip 414227569Sphilip return (0); 415227569Sphilip 416227569Sphilipfail4: 417227569Sphilip EFSYS_PROBE(fail4); 418227569Sphilipfail3: 419227569Sphilip EFSYS_PROBE(fail3); 420227569Sphilipfail2: 421227569Sphilip EFSYS_PROBE(fail2); 422227569Sphilipfail1: 423291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 424227569Sphilip 425227569Sphilip return (rc); 426227569Sphilip} 427227569Sphilip 428291436Sarybchikstatic __checkReturn efx_rc_t 429227569Sphilipefx_vpd_next_keyword( 430227569Sphilip __in_bcount(size) caddr_t tag, 431227569Sphilip __in size_t size, 432227569Sphilip __in unsigned int pos, 433227569Sphilip __out efx_vpd_keyword_t *keywordp, 434227569Sphilip __out uint8_t *lengthp) 435227569Sphilip{ 436227569Sphilip efx_vpd_keyword_t keyword; 437227569Sphilip uint8_t length; 438291436Sarybchik efx_rc_t rc; 439227569Sphilip 440227569Sphilip if (pos + 3U > size) { 441227569Sphilip rc = EFAULT; 442227569Sphilip goto fail1; 443227569Sphilip } 444227569Sphilip 445227569Sphilip keyword = EFX_VPD_KEYWORD(tag[pos], tag[pos + 1]); 446227569Sphilip length = tag[pos + 2]; 447227569Sphilip 448227569Sphilip if (length == 0 || pos + 3U + length > size) { 449227569Sphilip rc = EFAULT; 450227569Sphilip goto fail2; 451227569Sphilip } 452227569Sphilip 453227569Sphilip *keywordp = keyword; 454227569Sphilip *lengthp = length; 455227569Sphilip 456227569Sphilip return (0); 457227569Sphilip 458227569Sphilipfail2: 459227569Sphilip EFSYS_PROBE(fail2); 460227569Sphilipfail1: 461291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 462227569Sphilip 463227569Sphilip return (rc); 464227569Sphilip} 465227569Sphilip 466291436Sarybchik __checkReturn efx_rc_t 467227569Sphilipefx_vpd_hunk_length( 468227569Sphilip __in_bcount(size) caddr_t data, 469227569Sphilip __in size_t size, 470227569Sphilip __out size_t *lengthp) 471227569Sphilip{ 472227569Sphilip efx_vpd_tag_t tag; 473227569Sphilip unsigned int offset; 474227569Sphilip uint16_t taglen; 475291436Sarybchik efx_rc_t rc; 476227569Sphilip 477227569Sphilip offset = 0; 478227569Sphilip _NOTE(CONSTANTCONDITION) 479227569Sphilip while (1) { 480227569Sphilip if ((rc = efx_vpd_next_tag(data, size, &offset, 481227569Sphilip &tag, &taglen)) != 0) 482227569Sphilip goto fail1; 483227569Sphilip offset += taglen; 484227569Sphilip if (tag == EFX_VPD_END) 485227569Sphilip break; 486227569Sphilip } 487227569Sphilip 488227569Sphilip *lengthp = offset; 489227569Sphilip 490227569Sphilip return (0); 491227569Sphilip 492227569Sphilipfail1: 493291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 494227569Sphilip 495227569Sphilip return (rc); 496227569Sphilip} 497227569Sphilip 498291436Sarybchik __checkReturn efx_rc_t 499227569Sphilipefx_vpd_hunk_verify( 500227569Sphilip __in_bcount(size) caddr_t data, 501227569Sphilip __in size_t size, 502227569Sphilip __out_opt boolean_t *cksummedp) 503227569Sphilip{ 504227569Sphilip efx_vpd_tag_t tag; 505227569Sphilip efx_vpd_keyword_t keyword; 506227569Sphilip unsigned int offset; 507227569Sphilip unsigned int pos; 508227569Sphilip unsigned int i; 509227569Sphilip uint16_t taglen; 510227569Sphilip uint8_t keylen; 511227569Sphilip uint8_t cksum; 512227569Sphilip boolean_t cksummed = B_FALSE; 513291436Sarybchik efx_rc_t rc; 514227569Sphilip 515227569Sphilip /* 516227569Sphilip * Parse every tag,keyword in the existing VPD. If the csum is present, 517227569Sphilip * the assert it is correct, and is the final keyword in the RO block. 518227569Sphilip */ 519227569Sphilip offset = 0; 520227569Sphilip _NOTE(CONSTANTCONDITION) 521227569Sphilip while (1) { 522227569Sphilip if ((rc = efx_vpd_next_tag(data, size, &offset, 523227569Sphilip &tag, &taglen)) != 0) 524227569Sphilip goto fail1; 525227569Sphilip if (tag == EFX_VPD_END) 526227569Sphilip break; 527227569Sphilip else if (tag == EFX_VPD_ID) 528227569Sphilip goto done; 529227569Sphilip 530227569Sphilip for (pos = 0; pos != taglen; pos += 3 + keylen) { 531227569Sphilip /* RV keyword must be the last in the block */ 532291398Sarybchik if (cksummed) { 533291398Sarybchik rc = EFAULT; 534227569Sphilip goto fail2; 535291398Sarybchik } 536227569Sphilip 537227569Sphilip if ((rc = efx_vpd_next_keyword(data + offset, 538227569Sphilip taglen, pos, &keyword, &keylen)) != 0) 539227569Sphilip goto fail3; 540227569Sphilip 541227569Sphilip if (keyword == EFX_VPD_KEYWORD('R', 'V')) { 542227569Sphilip cksum = 0; 543227569Sphilip for (i = 0; i < offset + pos + 4; i++) 544227569Sphilip cksum += data[i]; 545227569Sphilip 546227569Sphilip if (cksum != 0) { 547227569Sphilip rc = EFAULT; 548227569Sphilip goto fail4; 549227569Sphilip } 550227569Sphilip 551227569Sphilip cksummed = B_TRUE; 552227569Sphilip } 553227569Sphilip } 554227569Sphilip 555227569Sphilip done: 556227569Sphilip offset += taglen; 557227569Sphilip } 558227569Sphilip 559227569Sphilip if (!cksummed) { 560227569Sphilip rc = EFAULT; 561227569Sphilip goto fail5; 562227569Sphilip } 563227569Sphilip 564227569Sphilip if (cksummedp != NULL) 565227569Sphilip *cksummedp = cksummed; 566227569Sphilip 567227569Sphilip return (0); 568227569Sphilip 569227569Sphilipfail5: 570227569Sphilip EFSYS_PROBE(fail5); 571227569Sphilipfail4: 572227569Sphilip EFSYS_PROBE(fail4); 573227569Sphilipfail3: 574227569Sphilip EFSYS_PROBE(fail3); 575227569Sphilipfail2: 576227569Sphilip EFSYS_PROBE(fail2); 577227569Sphilipfail1: 578291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 579227569Sphilip 580227569Sphilip return (rc); 581227569Sphilip} 582227569Sphilip 583283514Sarybchikstatic uint8_t __efx_vpd_blank_pid[] = { 584227569Sphilip /* Large resource type ID length 1 */ 585227569Sphilip 0x82, 0x01, 0x00, 586227569Sphilip /* Product name ' ' */ 587227569Sphilip 0x32, 588227569Sphilip}; 589227569Sphilip 590283514Sarybchikstatic uint8_t __efx_vpd_blank_r[] = { 591227569Sphilip /* Large resource type VPD-R length 4 */ 592227569Sphilip 0x90, 0x04, 0x00, 593227569Sphilip /* RV keyword length 1 */ 594227569Sphilip 'R', 'V', 0x01, 595227569Sphilip /* RV payload checksum */ 596227569Sphilip 0x00, 597227569Sphilip}; 598227569Sphilip 599291436Sarybchik __checkReturn efx_rc_t 600227569Sphilipefx_vpd_hunk_reinit( 601283514Sarybchik __in_bcount(size) caddr_t data, 602227569Sphilip __in size_t size, 603227569Sphilip __in boolean_t wantpid) 604227569Sphilip{ 605227569Sphilip unsigned int offset = 0; 606227569Sphilip unsigned int pos; 607227569Sphilip efx_byte_t byte; 608227569Sphilip uint8_t cksum; 609291436Sarybchik efx_rc_t rc; 610227569Sphilip 611227569Sphilip if (size < 0x100) { 612227569Sphilip rc = ENOSPC; 613227569Sphilip goto fail1; 614227569Sphilip } 615227569Sphilip 616227569Sphilip if (wantpid) { 617227569Sphilip memcpy(data + offset, __efx_vpd_blank_pid, 618227569Sphilip sizeof (__efx_vpd_blank_pid)); 619227569Sphilip offset += sizeof (__efx_vpd_blank_pid); 620227569Sphilip } 621227569Sphilip 622227569Sphilip memcpy(data + offset, __efx_vpd_blank_r, sizeof (__efx_vpd_blank_r)); 623227569Sphilip offset += sizeof (__efx_vpd_blank_r); 624227569Sphilip 625227569Sphilip /* Update checksum */ 626227569Sphilip cksum = 0; 627227569Sphilip for (pos = 0; pos < offset; pos++) 628227569Sphilip cksum += data[pos]; 629227569Sphilip data[offset - 1] -= cksum; 630227569Sphilip 631227569Sphilip /* Append trailing tag */ 632227569Sphilip EFX_POPULATE_BYTE_3(byte, 633227569Sphilip TAG_TYPE, TAG_TYPE_SMALL_ITEM_DECODE, 634227569Sphilip TAG_SMALL_ITEM_NAME, TAG_NAME_END_DECODE, 635227569Sphilip TAG_SMALL_ITEM_SIZE, 0); 636227569Sphilip data[offset] = EFX_BYTE_FIELD(byte, EFX_BYTE_0); 637227569Sphilip offset++; 638227569Sphilip 639227569Sphilip return (0); 640227569Sphilip 641227569Sphilipfail1: 642291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 643227569Sphilip 644227569Sphilip return (rc); 645227569Sphilip} 646227569Sphilip 647291436Sarybchik __checkReturn efx_rc_t 648227569Sphilipefx_vpd_hunk_next( 649227569Sphilip __in_bcount(size) caddr_t data, 650227569Sphilip __in size_t size, 651227569Sphilip __out efx_vpd_tag_t *tagp, 652227569Sphilip __out efx_vpd_keyword_t *keywordp, 653293895Sarybchik __out_opt unsigned int *payloadp, 654227569Sphilip __out_opt uint8_t *paylenp, 655227569Sphilip __inout unsigned int *contp) 656227569Sphilip{ 657227569Sphilip efx_vpd_tag_t tag; 658227569Sphilip efx_vpd_keyword_t keyword = 0; 659227569Sphilip unsigned int offset; 660227569Sphilip unsigned int pos; 661227569Sphilip unsigned int index; 662227569Sphilip uint16_t taglen; 663227569Sphilip uint8_t keylen; 664227569Sphilip uint8_t paylen; 665291436Sarybchik efx_rc_t rc; 666227569Sphilip 667227569Sphilip offset = index = 0; 668227569Sphilip _NOTE(CONSTANTCONDITION) 669227569Sphilip while (1) { 670227569Sphilip if ((rc = efx_vpd_next_tag(data, size, &offset, 671227569Sphilip &tag, &taglen)) != 0) 672227569Sphilip goto fail1; 673293895Sarybchik 674293895Sarybchik if (tag == EFX_VPD_END) { 675293895Sarybchik keyword = 0; 676293895Sarybchik paylen = 0; 677293895Sarybchik index = 0; 678227569Sphilip break; 679293895Sarybchik } 680227569Sphilip 681227569Sphilip if (tag == EFX_VPD_ID) { 682293895Sarybchik if (index++ == *contp) { 683227569Sphilip EFSYS_ASSERT3U(taglen, <, 0x100); 684293895Sarybchik keyword = 0; 685227569Sphilip paylen = (uint8_t)MIN(taglen, 0xff); 686227569Sphilip 687227569Sphilip goto done; 688227569Sphilip } 689227569Sphilip } else { 690227569Sphilip for (pos = 0; pos != taglen; pos += 3 + keylen) { 691227569Sphilip if ((rc = efx_vpd_next_keyword(data + offset, 692227569Sphilip taglen, pos, &keyword, &keylen)) != 0) 693227569Sphilip goto fail2; 694227569Sphilip 695293895Sarybchik if (index++ == *contp) { 696227569Sphilip offset += pos + 3; 697227569Sphilip paylen = keylen; 698227569Sphilip 699227569Sphilip goto done; 700227569Sphilip } 701227569Sphilip } 702227569Sphilip } 703227569Sphilip 704227569Sphilip offset += taglen; 705227569Sphilip } 706227569Sphilip 707227569Sphilipdone: 708227569Sphilip *tagp = tag; 709227569Sphilip *keywordp = keyword; 710227569Sphilip if (payloadp != NULL) 711227569Sphilip *payloadp = offset; 712227569Sphilip if (paylenp != NULL) 713227569Sphilip *paylenp = paylen; 714227569Sphilip 715293895Sarybchik *contp = index; 716227569Sphilip return (0); 717227569Sphilip 718227569Sphilipfail2: 719227569Sphilip EFSYS_PROBE(fail2); 720227569Sphilipfail1: 721291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 722227569Sphilip 723227569Sphilip return (rc); 724227569Sphilip} 725227569Sphilip 726291436Sarybchik __checkReturn efx_rc_t 727227569Sphilipefx_vpd_hunk_get( 728227569Sphilip __in_bcount(size) caddr_t data, 729227569Sphilip __in size_t size, 730227569Sphilip __in efx_vpd_tag_t tag, 731227569Sphilip __in efx_vpd_keyword_t keyword, 732227569Sphilip __out unsigned int *payloadp, 733227569Sphilip __out uint8_t *paylenp) 734227569Sphilip{ 735227569Sphilip efx_vpd_tag_t itag; 736227569Sphilip efx_vpd_keyword_t ikeyword; 737227569Sphilip unsigned int offset; 738227569Sphilip unsigned int pos; 739227569Sphilip uint16_t taglen; 740227569Sphilip uint8_t keylen; 741291436Sarybchik efx_rc_t rc; 742227569Sphilip 743227569Sphilip offset = 0; 744227569Sphilip _NOTE(CONSTANTCONDITION) 745227569Sphilip while (1) { 746227569Sphilip if ((rc = efx_vpd_next_tag(data, size, &offset, 747227569Sphilip &itag, &taglen)) != 0) 748227569Sphilip goto fail1; 749227569Sphilip if (itag == EFX_VPD_END) 750227569Sphilip break; 751227569Sphilip 752227569Sphilip if (itag == tag) { 753227569Sphilip if (itag == EFX_VPD_ID) { 754227569Sphilip EFSYS_ASSERT3U(taglen, <, 0x100); 755227569Sphilip 756227569Sphilip *paylenp = (uint8_t)MIN(taglen, 0xff); 757227569Sphilip *payloadp = offset; 758227569Sphilip return (0); 759227569Sphilip } 760227569Sphilip 761227569Sphilip for (pos = 0; pos != taglen; pos += 3 + keylen) { 762227569Sphilip if ((rc = efx_vpd_next_keyword(data + offset, 763227569Sphilip taglen, pos, &ikeyword, &keylen)) != 0) 764227569Sphilip goto fail2; 765227569Sphilip 766227569Sphilip if (ikeyword == keyword) { 767227569Sphilip *paylenp = keylen; 768227569Sphilip *payloadp = offset + pos + 3; 769227569Sphilip return (0); 770227569Sphilip } 771227569Sphilip } 772227569Sphilip } 773227569Sphilip 774227569Sphilip offset += taglen; 775227569Sphilip } 776227569Sphilip 777227569Sphilip /* Not an error */ 778227569Sphilip return (ENOENT); 779227569Sphilip 780227569Sphilipfail2: 781227569Sphilip EFSYS_PROBE(fail2); 782227569Sphilipfail1: 783291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 784227569Sphilip 785227569Sphilip return (rc); 786227569Sphilip} 787227569Sphilip 788291436Sarybchik __checkReturn efx_rc_t 789227569Sphilipefx_vpd_hunk_set( 790227569Sphilip __in_bcount(size) caddr_t data, 791227569Sphilip __in size_t size, 792227569Sphilip __in efx_vpd_value_t *evvp) 793227569Sphilip{ 794227569Sphilip efx_word_t word; 795227569Sphilip efx_vpd_tag_t tag; 796227569Sphilip efx_vpd_keyword_t keyword; 797227569Sphilip unsigned int offset; 798227569Sphilip unsigned int pos; 799227569Sphilip unsigned int taghead; 800227569Sphilip unsigned int source; 801227569Sphilip unsigned int dest; 802227569Sphilip unsigned int i; 803227569Sphilip uint16_t taglen; 804227569Sphilip uint8_t keylen; 805227569Sphilip uint8_t cksum; 806227569Sphilip size_t used; 807291436Sarybchik efx_rc_t rc; 808227569Sphilip 809227569Sphilip switch (evvp->evv_tag) { 810227569Sphilip case EFX_VPD_ID: 811227569Sphilip if (evvp->evv_keyword != 0) { 812227569Sphilip rc = EINVAL; 813227569Sphilip goto fail1; 814227569Sphilip } 815227569Sphilip 816227569Sphilip /* Can't delete the ID keyword */ 817227569Sphilip if (evvp->evv_length == 0) { 818227569Sphilip rc = EINVAL; 819227569Sphilip goto fail1; 820227569Sphilip } 821227569Sphilip break; 822227569Sphilip 823227569Sphilip case EFX_VPD_RO: 824227569Sphilip if (evvp->evv_keyword == EFX_VPD_KEYWORD('R', 'V')) { 825227569Sphilip rc = EINVAL; 826227569Sphilip goto fail1; 827227569Sphilip } 828227569Sphilip break; 829227569Sphilip 830227569Sphilip default: 831227569Sphilip rc = EINVAL; 832227569Sphilip goto fail1; 833227569Sphilip } 834227569Sphilip 835227569Sphilip /* Determine total size of all current tags */ 836227569Sphilip if ((rc = efx_vpd_hunk_length(data, size, &used)) != 0) 837227569Sphilip goto fail2; 838227569Sphilip 839227569Sphilip offset = 0; 840227569Sphilip _NOTE(CONSTANTCONDITION) 841227569Sphilip while (1) { 842227569Sphilip taghead = offset; 843227569Sphilip if ((rc = efx_vpd_next_tag(data, size, &offset, 844227569Sphilip &tag, &taglen)) != 0) 845227569Sphilip goto fail3; 846227569Sphilip if (tag == EFX_VPD_END) 847227569Sphilip break; 848227569Sphilip else if (tag != evvp->evv_tag) { 849227569Sphilip offset += taglen; 850227569Sphilip continue; 851227569Sphilip } 852227569Sphilip 853227569Sphilip /* We only support modifying large resource tags */ 854227569Sphilip if (offset - taghead != 3) { 855227569Sphilip rc = EINVAL; 856227569Sphilip goto fail4; 857227569Sphilip } 858227569Sphilip 859227569Sphilip /* 860227569Sphilip * Work out the offset of the byte immediately after the 861227569Sphilip * old (=source) and new (=dest) new keyword/tag 862227569Sphilip */ 863227569Sphilip pos = 0; 864227569Sphilip if (tag == EFX_VPD_ID) { 865227569Sphilip source = offset + taglen; 866227569Sphilip dest = offset + evvp->evv_length; 867227569Sphilip goto check_space; 868227569Sphilip } 869227569Sphilip 870227569Sphilip EFSYS_ASSERT3U(tag, ==, EFX_VPD_RO); 871227569Sphilip source = dest = 0; 872227569Sphilip for (pos = 0; pos != taglen; pos += 3 + keylen) { 873227569Sphilip if ((rc = efx_vpd_next_keyword(data + offset, 874227569Sphilip taglen, pos, &keyword, &keylen)) != 0) 875227569Sphilip goto fail5; 876227569Sphilip 877227569Sphilip if (keyword == evvp->evv_keyword && 878227569Sphilip evvp->evv_length == 0) { 879227569Sphilip /* Deleting this keyword */ 880227569Sphilip source = offset + pos + 3 + keylen; 881227569Sphilip dest = offset + pos; 882227569Sphilip break; 883227569Sphilip 884227569Sphilip } else if (keyword == evvp->evv_keyword) { 885227569Sphilip /* Adjusting this keyword */ 886227569Sphilip source = offset + pos + 3 + keylen; 887227569Sphilip dest = offset + pos + 3 + evvp->evv_length; 888227569Sphilip break; 889227569Sphilip 890227569Sphilip } else if (keyword == EFX_VPD_KEYWORD('R', 'V')) { 891227569Sphilip /* The RV keyword must be at the end */ 892227569Sphilip EFSYS_ASSERT3U(pos + 3 + keylen, ==, taglen); 893227569Sphilip 894227569Sphilip /* 895227569Sphilip * The keyword doesn't already exist. If the 896227569Sphilip * user deleting a non-existant keyword then 897227569Sphilip * this is a no-op. 898227569Sphilip */ 899227569Sphilip if (evvp->evv_length == 0) 900227569Sphilip return (0); 901227569Sphilip 902227569Sphilip /* Insert this keyword before the RV keyword */ 903227569Sphilip source = offset + pos; 904227569Sphilip dest = offset + pos + 3 + evvp->evv_length; 905227569Sphilip break; 906227569Sphilip } 907227569Sphilip } 908227569Sphilip 909227569Sphilip check_space: 910227569Sphilip if (used + dest > size + source) { 911227569Sphilip rc = ENOSPC; 912227569Sphilip goto fail6; 913227569Sphilip } 914227569Sphilip 915227569Sphilip /* Move trailing data */ 916227569Sphilip (void) memmove(data + dest, data + source, used - source); 917227569Sphilip 918227569Sphilip /* Copy contents */ 919227569Sphilip memcpy(data + dest - evvp->evv_length, evvp->evv_value, 920227569Sphilip evvp->evv_length); 921227569Sphilip 922227569Sphilip /* Insert new keyword header if required */ 923227569Sphilip if (tag != EFX_VPD_ID && evvp->evv_length > 0) { 924227569Sphilip EFX_POPULATE_WORD_1(word, EFX_WORD_0, 925227569Sphilip evvp->evv_keyword); 926227569Sphilip data[offset + pos + 0] = 927227569Sphilip EFX_WORD_FIELD(word, EFX_BYTE_0); 928227569Sphilip data[offset + pos + 1] = 929227569Sphilip EFX_WORD_FIELD(word, EFX_BYTE_1); 930227569Sphilip data[offset + pos + 2] = evvp->evv_length; 931227569Sphilip } 932227569Sphilip 933227569Sphilip /* Modify tag length (large resource type) */ 934342428Sarybchik taglen += (uint16_t)(dest - source); 935227569Sphilip EFX_POPULATE_WORD_1(word, EFX_WORD_0, taglen); 936227569Sphilip data[offset - 2] = EFX_WORD_FIELD(word, EFX_BYTE_0); 937227569Sphilip data[offset - 1] = EFX_WORD_FIELD(word, EFX_BYTE_1); 938227569Sphilip 939227569Sphilip goto checksum; 940227569Sphilip } 941227569Sphilip 942227569Sphilip /* Unable to find the matching tag */ 943227569Sphilip rc = ENOENT; 944227569Sphilip goto fail7; 945227569Sphilip 946227569Sphilipchecksum: 947227569Sphilip /* Find the RV tag, and update the checksum */ 948227569Sphilip offset = 0; 949227569Sphilip _NOTE(CONSTANTCONDITION) 950227569Sphilip while (1) { 951227569Sphilip if ((rc = efx_vpd_next_tag(data, size, &offset, 952227569Sphilip &tag, &taglen)) != 0) 953227569Sphilip goto fail8; 954227569Sphilip if (tag == EFX_VPD_END) 955227569Sphilip break; 956227569Sphilip if (tag == EFX_VPD_RO) { 957227569Sphilip for (pos = 0; pos != taglen; pos += 3 + keylen) { 958227569Sphilip if ((rc = efx_vpd_next_keyword(data + offset, 959227569Sphilip taglen, pos, &keyword, &keylen)) != 0) 960227569Sphilip goto fail9; 961227569Sphilip 962227569Sphilip if (keyword == EFX_VPD_KEYWORD('R', 'V')) { 963227569Sphilip cksum = 0; 964227569Sphilip for (i = 0; i < offset + pos + 3; i++) 965227569Sphilip cksum += data[i]; 966227569Sphilip data[i] = -cksum; 967227569Sphilip break; 968227569Sphilip } 969227569Sphilip } 970227569Sphilip } 971227569Sphilip 972227569Sphilip offset += taglen; 973227569Sphilip } 974227569Sphilip 975227569Sphilip /* Zero out the unused portion */ 976227569Sphilip (void) memset(data + offset + taglen, 0xff, size - offset - taglen); 977227569Sphilip 978227569Sphilip return (0); 979227569Sphilip 980227569Sphilipfail9: 981227569Sphilip EFSYS_PROBE(fail9); 982227569Sphilipfail8: 983227569Sphilip EFSYS_PROBE(fail8); 984227569Sphilipfail7: 985227569Sphilip EFSYS_PROBE(fail7); 986227569Sphilipfail6: 987227569Sphilip EFSYS_PROBE(fail6); 988227569Sphilipfail5: 989227569Sphilip EFSYS_PROBE(fail5); 990227569Sphilipfail4: 991227569Sphilip EFSYS_PROBE(fail4); 992227569Sphilipfail3: 993227569Sphilip EFSYS_PROBE(fail3); 994227569Sphilipfail2: 995227569Sphilip EFSYS_PROBE(fail2); 996227569Sphilipfail1: 997291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 998227569Sphilip 999227569Sphilip return (rc); 1000227569Sphilip} 1001227569Sphilip 1002227569Sphilip void 1003227569Sphilipefx_vpd_fini( 1004227569Sphilip __in efx_nic_t *enp) 1005227569Sphilip{ 1006299517Sarybchik const efx_vpd_ops_t *evpdop = enp->en_evpdop; 1007227569Sphilip 1008227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1009227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 1010227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD); 1011227569Sphilip 1012227569Sphilip if (evpdop->evpdo_fini != NULL) 1013227569Sphilip evpdop->evpdo_fini(enp); 1014227569Sphilip 1015227569Sphilip enp->en_evpdop = NULL; 1016227569Sphilip enp->en_mod_flags &= ~EFX_MOD_VPD; 1017227569Sphilip} 1018227569Sphilip 1019227569Sphilip#endif /* EFSYS_OPT_VPD */ 1020