xref: /dpdk/drivers/common/sfc_efx/base/efx_vpd.c (revision 672386c1e9e1f64f7aa3b1360ad22dc737ea8d72)
15e111ed8SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
25e111ed8SAndrew Rybchenko  *
3*672386c1SAndrew Rybchenko  * Copyright(c) 2019-2021 Xilinx, Inc.
45e111ed8SAndrew Rybchenko  * Copyright(c) 2009-2019 Solarflare Communications Inc.
55e111ed8SAndrew Rybchenko  */
65e111ed8SAndrew Rybchenko 
75e111ed8SAndrew Rybchenko #include "efx.h"
85e111ed8SAndrew Rybchenko #include "efx_impl.h"
95e111ed8SAndrew Rybchenko 
105e111ed8SAndrew Rybchenko #if EFSYS_OPT_VPD
115e111ed8SAndrew Rybchenko 
125e111ed8SAndrew Rybchenko #define	TAG_TYPE_LBN 7
135e111ed8SAndrew Rybchenko #define	TAG_TYPE_WIDTH 1
145e111ed8SAndrew Rybchenko #define	TAG_TYPE_LARGE_ITEM_DECODE 1
155e111ed8SAndrew Rybchenko #define	TAG_TYPE_SMALL_ITEM_DECODE 0
165e111ed8SAndrew Rybchenko 
175e111ed8SAndrew Rybchenko #define	TAG_SMALL_ITEM_NAME_LBN 3
185e111ed8SAndrew Rybchenko #define	TAG_SMALL_ITEM_NAME_WIDTH 4
195e111ed8SAndrew Rybchenko #define	TAG_SMALL_ITEM_SIZE_LBN 0
205e111ed8SAndrew Rybchenko #define	TAG_SMALL_ITEM_SIZE_WIDTH 3
215e111ed8SAndrew Rybchenko 
225e111ed8SAndrew Rybchenko #define	TAG_LARGE_ITEM_NAME_LBN 0
235e111ed8SAndrew Rybchenko #define	TAG_LARGE_ITEM_NAME_WIDTH 7
245e111ed8SAndrew Rybchenko 
255e111ed8SAndrew Rybchenko #define	TAG_NAME_END_DECODE 0x0f
265e111ed8SAndrew Rybchenko #define	TAG_NAME_ID_STRING_DECODE 0x02
275e111ed8SAndrew Rybchenko #define	TAG_NAME_VPD_R_DECODE 0x10
285e111ed8SAndrew Rybchenko #define	TAG_NAME_VPD_W_DECODE 0x11
295e111ed8SAndrew Rybchenko 
305e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
315e111ed8SAndrew Rybchenko 
325e111ed8SAndrew Rybchenko static const efx_vpd_ops_t	__efx_vpd_siena_ops = {
335e111ed8SAndrew Rybchenko 	siena_vpd_init,		/* evpdo_init */
345e111ed8SAndrew Rybchenko 	siena_vpd_size,		/* evpdo_size */
355e111ed8SAndrew Rybchenko 	siena_vpd_read,		/* evpdo_read */
365e111ed8SAndrew Rybchenko 	siena_vpd_verify,	/* evpdo_verify */
375e111ed8SAndrew Rybchenko 	siena_vpd_reinit,	/* evpdo_reinit */
385e111ed8SAndrew Rybchenko 	siena_vpd_get,		/* evpdo_get */
395e111ed8SAndrew Rybchenko 	siena_vpd_set,		/* evpdo_set */
405e111ed8SAndrew Rybchenko 	siena_vpd_next,		/* evpdo_next */
415e111ed8SAndrew Rybchenko 	siena_vpd_write,	/* evpdo_write */
425e111ed8SAndrew Rybchenko 	siena_vpd_fini,		/* evpdo_fini */
435e111ed8SAndrew Rybchenko };
445e111ed8SAndrew Rybchenko 
455e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_SIENA */
465e111ed8SAndrew Rybchenko 
475e111ed8SAndrew Rybchenko #if EFX_OPTS_EF10()
485e111ed8SAndrew Rybchenko 
495e111ed8SAndrew Rybchenko static const efx_vpd_ops_t	__efx_vpd_ef10_ops = {
505e111ed8SAndrew Rybchenko 	ef10_vpd_init,		/* evpdo_init */
515e111ed8SAndrew Rybchenko 	ef10_vpd_size,		/* evpdo_size */
525e111ed8SAndrew Rybchenko 	ef10_vpd_read,		/* evpdo_read */
535e111ed8SAndrew Rybchenko 	ef10_vpd_verify,	/* evpdo_verify */
545e111ed8SAndrew Rybchenko 	ef10_vpd_reinit,	/* evpdo_reinit */
555e111ed8SAndrew Rybchenko 	ef10_vpd_get,		/* evpdo_get */
565e111ed8SAndrew Rybchenko 	ef10_vpd_set,		/* evpdo_set */
575e111ed8SAndrew Rybchenko 	ef10_vpd_next,		/* evpdo_next */
585e111ed8SAndrew Rybchenko 	ef10_vpd_write,		/* evpdo_write */
595e111ed8SAndrew Rybchenko 	ef10_vpd_fini,		/* evpdo_fini */
605e111ed8SAndrew Rybchenko };
615e111ed8SAndrew Rybchenko 
625e111ed8SAndrew Rybchenko #endif	/* EFX_OPTS_EF10() */
635e111ed8SAndrew Rybchenko 
645e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_init(__in efx_nic_t * enp)655e111ed8SAndrew Rybchenko efx_vpd_init(
665e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp)
675e111ed8SAndrew Rybchenko {
685e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop;
695e111ed8SAndrew Rybchenko 	efx_rc_t rc;
705e111ed8SAndrew Rybchenko 
715e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
725e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
735e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_VPD));
745e111ed8SAndrew Rybchenko 
755e111ed8SAndrew Rybchenko 	switch (enp->en_family) {
765e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
775e111ed8SAndrew Rybchenko 	case EFX_FAMILY_SIENA:
785e111ed8SAndrew Rybchenko 		evpdop = &__efx_vpd_siena_ops;
795e111ed8SAndrew Rybchenko 		break;
805e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_SIENA */
815e111ed8SAndrew Rybchenko 
825e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
835e111ed8SAndrew Rybchenko 	case EFX_FAMILY_HUNTINGTON:
845e111ed8SAndrew Rybchenko 		evpdop = &__efx_vpd_ef10_ops;
855e111ed8SAndrew Rybchenko 		break;
865e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_HUNTINGTON */
875e111ed8SAndrew Rybchenko 
885e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
895e111ed8SAndrew Rybchenko 	case EFX_FAMILY_MEDFORD:
905e111ed8SAndrew Rybchenko 		evpdop = &__efx_vpd_ef10_ops;
915e111ed8SAndrew Rybchenko 		break;
925e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MEDFORD */
935e111ed8SAndrew Rybchenko 
945e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
955e111ed8SAndrew Rybchenko 	case EFX_FAMILY_MEDFORD2:
965e111ed8SAndrew Rybchenko 		evpdop = &__efx_vpd_ef10_ops;
975e111ed8SAndrew Rybchenko 		break;
985e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MEDFORD2 */
995e111ed8SAndrew Rybchenko 
1005e111ed8SAndrew Rybchenko 	default:
1015e111ed8SAndrew Rybchenko 		EFSYS_ASSERT(0);
1025e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
1035e111ed8SAndrew Rybchenko 		goto fail1;
1045e111ed8SAndrew Rybchenko 	}
1055e111ed8SAndrew Rybchenko 
1065e111ed8SAndrew Rybchenko 	if (evpdop->evpdo_init != NULL) {
1075e111ed8SAndrew Rybchenko 		if ((rc = evpdop->evpdo_init(enp)) != 0)
1085e111ed8SAndrew Rybchenko 			goto fail2;
1095e111ed8SAndrew Rybchenko 	}
1105e111ed8SAndrew Rybchenko 
1115e111ed8SAndrew Rybchenko 	enp->en_evpdop = evpdop;
1125e111ed8SAndrew Rybchenko 	enp->en_mod_flags |= EFX_MOD_VPD;
1135e111ed8SAndrew Rybchenko 
1145e111ed8SAndrew Rybchenko 	return (0);
1155e111ed8SAndrew Rybchenko 
1165e111ed8SAndrew Rybchenko fail2:
1175e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1185e111ed8SAndrew Rybchenko fail1:
1195e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1205e111ed8SAndrew Rybchenko 
1215e111ed8SAndrew Rybchenko 	return (rc);
1225e111ed8SAndrew Rybchenko }
1235e111ed8SAndrew Rybchenko 
1245e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_size(__in efx_nic_t * enp,__out size_t * sizep)1255e111ed8SAndrew Rybchenko efx_vpd_size(
1265e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
1275e111ed8SAndrew Rybchenko 	__out			size_t *sizep)
1285e111ed8SAndrew Rybchenko {
1295e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop = enp->en_evpdop;
1305e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1315e111ed8SAndrew Rybchenko 
1325e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1335e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
1345e111ed8SAndrew Rybchenko 
1355e111ed8SAndrew Rybchenko 	if ((rc = evpdop->evpdo_size(enp, sizep)) != 0)
1365e111ed8SAndrew Rybchenko 		goto fail1;
1375e111ed8SAndrew Rybchenko 
1385e111ed8SAndrew Rybchenko 	return (0);
1395e111ed8SAndrew Rybchenko 
1405e111ed8SAndrew Rybchenko fail1:
1415e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1425e111ed8SAndrew Rybchenko 
1435e111ed8SAndrew Rybchenko 	return (rc);
1445e111ed8SAndrew Rybchenko }
1455e111ed8SAndrew Rybchenko 
1465e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_read(__in efx_nic_t * enp,__out_bcount (size)caddr_t data,__in size_t size)1475e111ed8SAndrew Rybchenko efx_vpd_read(
1485e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
1495e111ed8SAndrew Rybchenko 	__out_bcount(size)	caddr_t data,
1505e111ed8SAndrew Rybchenko 	__in			size_t size)
1515e111ed8SAndrew Rybchenko {
1525e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop = enp->en_evpdop;
1535e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1545e111ed8SAndrew Rybchenko 
1555e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1565e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
1575e111ed8SAndrew Rybchenko 
1585e111ed8SAndrew Rybchenko 	if ((rc = evpdop->evpdo_read(enp, data, size)) != 0)
1595e111ed8SAndrew Rybchenko 		goto fail1;
1605e111ed8SAndrew Rybchenko 
1615e111ed8SAndrew Rybchenko 	return (0);
1625e111ed8SAndrew Rybchenko 
1635e111ed8SAndrew Rybchenko fail1:
1645e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1655e111ed8SAndrew Rybchenko 
1665e111ed8SAndrew Rybchenko 	return (rc);
1675e111ed8SAndrew Rybchenko }
1685e111ed8SAndrew Rybchenko 
1695e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_verify(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)1705e111ed8SAndrew Rybchenko efx_vpd_verify(
1715e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
1725e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
1735e111ed8SAndrew Rybchenko 	__in			size_t size)
1745e111ed8SAndrew Rybchenko {
1755e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop = enp->en_evpdop;
1765e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1775e111ed8SAndrew Rybchenko 
1785e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1795e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
1805e111ed8SAndrew Rybchenko 
1815e111ed8SAndrew Rybchenko 	if ((rc = evpdop->evpdo_verify(enp, data, size)) != 0)
1825e111ed8SAndrew Rybchenko 		goto fail1;
1835e111ed8SAndrew Rybchenko 
1845e111ed8SAndrew Rybchenko 	return (0);
1855e111ed8SAndrew Rybchenko 
1865e111ed8SAndrew Rybchenko fail1:
1875e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1885e111ed8SAndrew Rybchenko 
1895e111ed8SAndrew Rybchenko 	return (rc);
1905e111ed8SAndrew Rybchenko }
1915e111ed8SAndrew Rybchenko 
1925e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_reinit(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)1935e111ed8SAndrew Rybchenko efx_vpd_reinit(
1945e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
1955e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
1965e111ed8SAndrew Rybchenko 	__in			size_t size)
1975e111ed8SAndrew Rybchenko {
1985e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop = enp->en_evpdop;
1995e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2005e111ed8SAndrew Rybchenko 
2015e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2025e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
2035e111ed8SAndrew Rybchenko 
2045e111ed8SAndrew Rybchenko 	if (evpdop->evpdo_reinit == NULL) {
2055e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
2065e111ed8SAndrew Rybchenko 		goto fail1;
2075e111ed8SAndrew Rybchenko 	}
2085e111ed8SAndrew Rybchenko 
2095e111ed8SAndrew Rybchenko 	if ((rc = evpdop->evpdo_reinit(enp, data, size)) != 0)
2105e111ed8SAndrew Rybchenko 		goto fail2;
2115e111ed8SAndrew Rybchenko 
2125e111ed8SAndrew Rybchenko 	return (0);
2135e111ed8SAndrew Rybchenko 
2145e111ed8SAndrew Rybchenko fail2:
2155e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
2165e111ed8SAndrew Rybchenko fail1:
2175e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2185e111ed8SAndrew Rybchenko 
2195e111ed8SAndrew Rybchenko 	return (rc);
2205e111ed8SAndrew Rybchenko }
2215e111ed8SAndrew Rybchenko 
2225e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_get(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size,__inout efx_vpd_value_t * evvp)2235e111ed8SAndrew Rybchenko efx_vpd_get(
2245e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
2255e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
2265e111ed8SAndrew Rybchenko 	__in			size_t size,
2275e111ed8SAndrew Rybchenko 	__inout			efx_vpd_value_t *evvp)
2285e111ed8SAndrew Rybchenko {
2295e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop = enp->en_evpdop;
2305e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2315e111ed8SAndrew Rybchenko 
2325e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2335e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
2345e111ed8SAndrew Rybchenko 
2355e111ed8SAndrew Rybchenko 	if ((rc = evpdop->evpdo_get(enp, data, size, evvp)) != 0) {
2365e111ed8SAndrew Rybchenko 		if (rc == ENOENT)
2375e111ed8SAndrew Rybchenko 			return (rc);
2385e111ed8SAndrew Rybchenko 
2395e111ed8SAndrew Rybchenko 		goto fail1;
2405e111ed8SAndrew Rybchenko 	}
2415e111ed8SAndrew Rybchenko 
2425e111ed8SAndrew Rybchenko 	return (0);
2435e111ed8SAndrew Rybchenko 
2445e111ed8SAndrew Rybchenko fail1:
2455e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2465e111ed8SAndrew Rybchenko 
2475e111ed8SAndrew Rybchenko 	return (rc);
2485e111ed8SAndrew Rybchenko }
2495e111ed8SAndrew Rybchenko 
2505e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_set(__in efx_nic_t * enp,__inout_bcount (size)caddr_t data,__in size_t size,__in efx_vpd_value_t * evvp)2515e111ed8SAndrew Rybchenko efx_vpd_set(
2525e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
2535e111ed8SAndrew Rybchenko 	__inout_bcount(size)	caddr_t data,
2545e111ed8SAndrew Rybchenko 	__in			size_t size,
2555e111ed8SAndrew Rybchenko 	__in			efx_vpd_value_t *evvp)
2565e111ed8SAndrew Rybchenko {
2575e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop = enp->en_evpdop;
2585e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2595e111ed8SAndrew Rybchenko 
2605e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2615e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
2625e111ed8SAndrew Rybchenko 
2635e111ed8SAndrew Rybchenko 	if ((rc = evpdop->evpdo_set(enp, data, size, evvp)) != 0)
2645e111ed8SAndrew Rybchenko 		goto fail1;
2655e111ed8SAndrew Rybchenko 
2665e111ed8SAndrew Rybchenko 	return (0);
2675e111ed8SAndrew Rybchenko 
2685e111ed8SAndrew Rybchenko fail1:
2695e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2705e111ed8SAndrew Rybchenko 
2715e111ed8SAndrew Rybchenko 	return (rc);
2725e111ed8SAndrew Rybchenko }
2735e111ed8SAndrew Rybchenko 
2745e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_next(__in efx_nic_t * enp,__inout_bcount (size)caddr_t data,__in size_t size,__out efx_vpd_value_t * evvp,__inout unsigned int * contp)2755e111ed8SAndrew Rybchenko efx_vpd_next(
2765e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
2775e111ed8SAndrew Rybchenko 	__inout_bcount(size)	caddr_t data,
2785e111ed8SAndrew Rybchenko 	__in			size_t size,
2795e111ed8SAndrew Rybchenko 	__out			efx_vpd_value_t *evvp,
2805e111ed8SAndrew Rybchenko 	__inout			unsigned int *contp)
2815e111ed8SAndrew Rybchenko {
2825e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop = enp->en_evpdop;
2835e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2845e111ed8SAndrew Rybchenko 
2855e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2865e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
2875e111ed8SAndrew Rybchenko 
2885e111ed8SAndrew Rybchenko 	if ((rc = evpdop->evpdo_next(enp, data, size, evvp, contp)) != 0)
2895e111ed8SAndrew Rybchenko 		goto fail1;
2905e111ed8SAndrew Rybchenko 
2915e111ed8SAndrew Rybchenko 	return (0);
2925e111ed8SAndrew Rybchenko 
2935e111ed8SAndrew Rybchenko fail1:
2945e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2955e111ed8SAndrew Rybchenko 
2965e111ed8SAndrew Rybchenko 	return (rc);
2975e111ed8SAndrew Rybchenko }
2985e111ed8SAndrew Rybchenko 
2995e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_write(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)3005e111ed8SAndrew Rybchenko efx_vpd_write(
3015e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
3025e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
3035e111ed8SAndrew Rybchenko 	__in			size_t size)
3045e111ed8SAndrew Rybchenko {
3055e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop = enp->en_evpdop;
3065e111ed8SAndrew Rybchenko 	efx_rc_t rc;
3075e111ed8SAndrew Rybchenko 
3085e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3095e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
3105e111ed8SAndrew Rybchenko 
3115e111ed8SAndrew Rybchenko 	if ((rc = evpdop->evpdo_write(enp, data, size)) != 0)
3125e111ed8SAndrew Rybchenko 		goto fail1;
3135e111ed8SAndrew Rybchenko 
3145e111ed8SAndrew Rybchenko 	return (0);
3155e111ed8SAndrew Rybchenko 
3165e111ed8SAndrew Rybchenko fail1:
3175e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3185e111ed8SAndrew Rybchenko 
3195e111ed8SAndrew Rybchenko 	return (rc);
3205e111ed8SAndrew Rybchenko }
3215e111ed8SAndrew Rybchenko 
3225e111ed8SAndrew Rybchenko static	__checkReturn		efx_rc_t
efx_vpd_next_tag(__in caddr_t data,__in size_t size,__inout unsigned int * offsetp,__out efx_vpd_tag_t * tagp,__out uint16_t * lengthp)3235e111ed8SAndrew Rybchenko efx_vpd_next_tag(
3245e111ed8SAndrew Rybchenko 	__in			caddr_t data,
3255e111ed8SAndrew Rybchenko 	__in			size_t size,
3265e111ed8SAndrew Rybchenko 	__inout			unsigned int *offsetp,
3275e111ed8SAndrew Rybchenko 	__out			efx_vpd_tag_t *tagp,
3285e111ed8SAndrew Rybchenko 	__out			uint16_t *lengthp)
3295e111ed8SAndrew Rybchenko {
3305e111ed8SAndrew Rybchenko 	efx_byte_t byte;
3315e111ed8SAndrew Rybchenko 	efx_word_t word;
3325e111ed8SAndrew Rybchenko 	uint8_t name;
3335e111ed8SAndrew Rybchenko 	uint16_t length;
3345e111ed8SAndrew Rybchenko 	size_t headlen;
3355e111ed8SAndrew Rybchenko 	efx_rc_t rc;
3365e111ed8SAndrew Rybchenko 
3375e111ed8SAndrew Rybchenko 	if (*offsetp >= size) {
3385e111ed8SAndrew Rybchenko 		rc = EFAULT;
3395e111ed8SAndrew Rybchenko 		goto fail1;
3405e111ed8SAndrew Rybchenko 	}
3415e111ed8SAndrew Rybchenko 
3425e111ed8SAndrew Rybchenko 	EFX_POPULATE_BYTE_1(byte, EFX_BYTE_0, data[*offsetp]);
3435e111ed8SAndrew Rybchenko 
3445e111ed8SAndrew Rybchenko 	switch (EFX_BYTE_FIELD(byte, TAG_TYPE)) {
3455e111ed8SAndrew Rybchenko 	case TAG_TYPE_SMALL_ITEM_DECODE:
3465e111ed8SAndrew Rybchenko 		headlen = 1;
3475e111ed8SAndrew Rybchenko 
3485e111ed8SAndrew Rybchenko 		name = EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_NAME);
3495e111ed8SAndrew Rybchenko 		length = (uint16_t)EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_SIZE);
3505e111ed8SAndrew Rybchenko 
3515e111ed8SAndrew Rybchenko 		break;
3525e111ed8SAndrew Rybchenko 
3535e111ed8SAndrew Rybchenko 	case TAG_TYPE_LARGE_ITEM_DECODE:
3545e111ed8SAndrew Rybchenko 		headlen = 3;
3555e111ed8SAndrew Rybchenko 
3565e111ed8SAndrew Rybchenko 		if (*offsetp + headlen > size) {
3575e111ed8SAndrew Rybchenko 			rc = EFAULT;
3585e111ed8SAndrew Rybchenko 			goto fail2;
3595e111ed8SAndrew Rybchenko 		}
3605e111ed8SAndrew Rybchenko 
3615e111ed8SAndrew Rybchenko 		name = EFX_BYTE_FIELD(byte, TAG_LARGE_ITEM_NAME);
3625e111ed8SAndrew Rybchenko 		EFX_POPULATE_WORD_2(word,
3635e111ed8SAndrew Rybchenko 				    EFX_BYTE_0, data[*offsetp + 1],
3645e111ed8SAndrew Rybchenko 				    EFX_BYTE_1, data[*offsetp + 2]);
3655e111ed8SAndrew Rybchenko 		length = EFX_WORD_FIELD(word, EFX_WORD_0);
3665e111ed8SAndrew Rybchenko 
3675e111ed8SAndrew Rybchenko 		break;
3685e111ed8SAndrew Rybchenko 
3695e111ed8SAndrew Rybchenko 	default:
3705e111ed8SAndrew Rybchenko 		rc = EFAULT;
3715e111ed8SAndrew Rybchenko 		goto fail2;
3725e111ed8SAndrew Rybchenko 	}
3735e111ed8SAndrew Rybchenko 
3745e111ed8SAndrew Rybchenko 	if (*offsetp + headlen + length > size) {
3755e111ed8SAndrew Rybchenko 		rc = EFAULT;
3765e111ed8SAndrew Rybchenko 		goto fail3;
3775e111ed8SAndrew Rybchenko 	}
3785e111ed8SAndrew Rybchenko 
3795e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(TAG_NAME_END_DECODE == EFX_VPD_END);
3805e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(TAG_NAME_ID_STRING_DECODE == EFX_VPD_ID);
3815e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(TAG_NAME_VPD_R_DECODE == EFX_VPD_RO);
3825e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(TAG_NAME_VPD_W_DECODE == EFX_VPD_RW);
3835e111ed8SAndrew Rybchenko 	if (name != EFX_VPD_END && name != EFX_VPD_ID &&
3845e111ed8SAndrew Rybchenko 	    name != EFX_VPD_RO) {
3855e111ed8SAndrew Rybchenko 		rc = EFAULT;
3865e111ed8SAndrew Rybchenko 		goto fail4;
3875e111ed8SAndrew Rybchenko 	}
3885e111ed8SAndrew Rybchenko 
3895e111ed8SAndrew Rybchenko 	*tagp = name;
3905e111ed8SAndrew Rybchenko 	*lengthp = length;
3915e111ed8SAndrew Rybchenko 	*offsetp += headlen;
3925e111ed8SAndrew Rybchenko 
3935e111ed8SAndrew Rybchenko 	return (0);
3945e111ed8SAndrew Rybchenko 
3955e111ed8SAndrew Rybchenko fail4:
3965e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail4);
3975e111ed8SAndrew Rybchenko fail3:
3985e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
3995e111ed8SAndrew Rybchenko fail2:
4005e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
4015e111ed8SAndrew Rybchenko fail1:
4025e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4035e111ed8SAndrew Rybchenko 
4045e111ed8SAndrew Rybchenko 	return (rc);
4055e111ed8SAndrew Rybchenko }
4065e111ed8SAndrew Rybchenko 
4075e111ed8SAndrew Rybchenko static	__checkReturn		efx_rc_t
efx_vpd_next_keyword(__in_bcount (size)caddr_t tag,__in size_t size,__in unsigned int pos,__out efx_vpd_keyword_t * keywordp,__out uint8_t * lengthp)4085e111ed8SAndrew Rybchenko efx_vpd_next_keyword(
4095e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t tag,
4105e111ed8SAndrew Rybchenko 	__in			size_t size,
4115e111ed8SAndrew Rybchenko 	__in			unsigned int pos,
4125e111ed8SAndrew Rybchenko 	__out			efx_vpd_keyword_t *keywordp,
4135e111ed8SAndrew Rybchenko 	__out			uint8_t *lengthp)
4145e111ed8SAndrew Rybchenko {
4155e111ed8SAndrew Rybchenko 	efx_vpd_keyword_t keyword;
4165e111ed8SAndrew Rybchenko 	uint8_t length;
4175e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4185e111ed8SAndrew Rybchenko 
4195e111ed8SAndrew Rybchenko 	if (pos + 3U > size) {
4205e111ed8SAndrew Rybchenko 		rc = EFAULT;
4215e111ed8SAndrew Rybchenko 		goto fail1;
4225e111ed8SAndrew Rybchenko 	}
4235e111ed8SAndrew Rybchenko 
4245e111ed8SAndrew Rybchenko 	keyword = EFX_VPD_KEYWORD(tag[pos], tag[pos + 1]);
4255e111ed8SAndrew Rybchenko 	length = tag[pos + 2];
4265e111ed8SAndrew Rybchenko 
4275e111ed8SAndrew Rybchenko 	if (length == 0 || pos + 3U + length > size) {
4285e111ed8SAndrew Rybchenko 		rc = EFAULT;
4295e111ed8SAndrew Rybchenko 		goto fail2;
4305e111ed8SAndrew Rybchenko 	}
4315e111ed8SAndrew Rybchenko 
4325e111ed8SAndrew Rybchenko 	*keywordp = keyword;
4335e111ed8SAndrew Rybchenko 	*lengthp = length;
4345e111ed8SAndrew Rybchenko 
4355e111ed8SAndrew Rybchenko 	return (0);
4365e111ed8SAndrew Rybchenko 
4375e111ed8SAndrew Rybchenko fail2:
4385e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
4395e111ed8SAndrew Rybchenko fail1:
4405e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4415e111ed8SAndrew Rybchenko 
4425e111ed8SAndrew Rybchenko 	return (rc);
4435e111ed8SAndrew Rybchenko }
4445e111ed8SAndrew Rybchenko 
4455e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_hunk_length(__in_bcount (size)caddr_t data,__in size_t size,__out size_t * lengthp)4465e111ed8SAndrew Rybchenko efx_vpd_hunk_length(
4475e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
4485e111ed8SAndrew Rybchenko 	__in			size_t size,
4495e111ed8SAndrew Rybchenko 	__out			size_t *lengthp)
4505e111ed8SAndrew Rybchenko {
4515e111ed8SAndrew Rybchenko 	efx_vpd_tag_t tag;
4525e111ed8SAndrew Rybchenko 	unsigned int offset;
4535e111ed8SAndrew Rybchenko 	uint16_t taglen;
4545e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4555e111ed8SAndrew Rybchenko 
4565e111ed8SAndrew Rybchenko 	offset = 0;
4575e111ed8SAndrew Rybchenko 	_NOTE(CONSTANTCONDITION)
4585e111ed8SAndrew Rybchenko 	while (1) {
4595e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_next_tag(data, size, &offset,
4605e111ed8SAndrew Rybchenko 		    &tag, &taglen)) != 0)
4615e111ed8SAndrew Rybchenko 			goto fail1;
4625e111ed8SAndrew Rybchenko 		offset += taglen;
4635e111ed8SAndrew Rybchenko 		if (tag == EFX_VPD_END)
4645e111ed8SAndrew Rybchenko 			break;
4655e111ed8SAndrew Rybchenko 	}
4665e111ed8SAndrew Rybchenko 
4675e111ed8SAndrew Rybchenko 	*lengthp = offset;
4685e111ed8SAndrew Rybchenko 
4695e111ed8SAndrew Rybchenko 	return (0);
4705e111ed8SAndrew Rybchenko 
4715e111ed8SAndrew Rybchenko fail1:
4725e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4735e111ed8SAndrew Rybchenko 
4745e111ed8SAndrew Rybchenko 	return (rc);
4755e111ed8SAndrew Rybchenko }
4765e111ed8SAndrew Rybchenko 
4775e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_hunk_verify(__in_bcount (size)caddr_t data,__in size_t size,__out_opt boolean_t * cksummedp)4785e111ed8SAndrew Rybchenko efx_vpd_hunk_verify(
4795e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
4805e111ed8SAndrew Rybchenko 	__in			size_t size,
4815e111ed8SAndrew Rybchenko 	__out_opt		boolean_t *cksummedp)
4825e111ed8SAndrew Rybchenko {
4835e111ed8SAndrew Rybchenko 	efx_vpd_tag_t tag;
4845e111ed8SAndrew Rybchenko 	efx_vpd_keyword_t keyword;
4855e111ed8SAndrew Rybchenko 	unsigned int offset;
4865e111ed8SAndrew Rybchenko 	unsigned int pos;
4875e111ed8SAndrew Rybchenko 	unsigned int i;
4885e111ed8SAndrew Rybchenko 	uint16_t taglen;
4895e111ed8SAndrew Rybchenko 	uint8_t keylen;
4905e111ed8SAndrew Rybchenko 	uint8_t cksum;
4915e111ed8SAndrew Rybchenko 	boolean_t cksummed = B_FALSE;
4925e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4935e111ed8SAndrew Rybchenko 
4945e111ed8SAndrew Rybchenko 	/*
4955e111ed8SAndrew Rybchenko 	 * Parse every tag,keyword in the existing VPD. If the csum is present,
4965e111ed8SAndrew Rybchenko 	 * the assert it is correct, and is the final keyword in the RO block.
4975e111ed8SAndrew Rybchenko 	 */
4985e111ed8SAndrew Rybchenko 	offset = 0;
4995e111ed8SAndrew Rybchenko 	_NOTE(CONSTANTCONDITION)
5005e111ed8SAndrew Rybchenko 	while (1) {
5015e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_next_tag(data, size, &offset,
5025e111ed8SAndrew Rybchenko 		    &tag, &taglen)) != 0)
5035e111ed8SAndrew Rybchenko 			goto fail1;
5045e111ed8SAndrew Rybchenko 		if (tag == EFX_VPD_END)
5055e111ed8SAndrew Rybchenko 			break;
5065e111ed8SAndrew Rybchenko 		else if (tag == EFX_VPD_ID)
5075e111ed8SAndrew Rybchenko 			goto done;
5085e111ed8SAndrew Rybchenko 
5095e111ed8SAndrew Rybchenko 		for (pos = 0; pos != taglen; pos += 3 + keylen) {
5105e111ed8SAndrew Rybchenko 			/* RV keyword must be the last in the block */
5115e111ed8SAndrew Rybchenko 			if (cksummed) {
5125e111ed8SAndrew Rybchenko 				rc = EFAULT;
5135e111ed8SAndrew Rybchenko 				goto fail2;
5145e111ed8SAndrew Rybchenko 			}
5155e111ed8SAndrew Rybchenko 
5165e111ed8SAndrew Rybchenko 			if ((rc = efx_vpd_next_keyword(data + offset,
5175e111ed8SAndrew Rybchenko 			    taglen, pos, &keyword, &keylen)) != 0)
5185e111ed8SAndrew Rybchenko 				goto fail3;
5195e111ed8SAndrew Rybchenko 
5205e111ed8SAndrew Rybchenko 			if (keyword == EFX_VPD_KEYWORD('R', 'V')) {
5215e111ed8SAndrew Rybchenko 				cksum = 0;
5225e111ed8SAndrew Rybchenko 				for (i = 0; i < offset + pos + 4; i++)
5235e111ed8SAndrew Rybchenko 					cksum += data[i];
5245e111ed8SAndrew Rybchenko 
5255e111ed8SAndrew Rybchenko 				if (cksum != 0) {
5265e111ed8SAndrew Rybchenko 					rc = EFAULT;
5275e111ed8SAndrew Rybchenko 					goto fail4;
5285e111ed8SAndrew Rybchenko 				}
5295e111ed8SAndrew Rybchenko 
5305e111ed8SAndrew Rybchenko 				cksummed = B_TRUE;
5315e111ed8SAndrew Rybchenko 			}
5325e111ed8SAndrew Rybchenko 		}
5335e111ed8SAndrew Rybchenko 
5345e111ed8SAndrew Rybchenko 	done:
5355e111ed8SAndrew Rybchenko 		offset += taglen;
5365e111ed8SAndrew Rybchenko 	}
5375e111ed8SAndrew Rybchenko 
5385e111ed8SAndrew Rybchenko 	if (!cksummed) {
5395e111ed8SAndrew Rybchenko 		rc = EFAULT;
5405e111ed8SAndrew Rybchenko 		goto fail5;
5415e111ed8SAndrew Rybchenko 	}
5425e111ed8SAndrew Rybchenko 
5435e111ed8SAndrew Rybchenko 	if (cksummedp != NULL)
5445e111ed8SAndrew Rybchenko 		*cksummedp = cksummed;
5455e111ed8SAndrew Rybchenko 
5465e111ed8SAndrew Rybchenko 	return (0);
5475e111ed8SAndrew Rybchenko 
5485e111ed8SAndrew Rybchenko fail5:
5495e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail5);
5505e111ed8SAndrew Rybchenko fail4:
5515e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail4);
5525e111ed8SAndrew Rybchenko fail3:
5535e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
5545e111ed8SAndrew Rybchenko fail2:
5555e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
5565e111ed8SAndrew Rybchenko fail1:
5575e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5585e111ed8SAndrew Rybchenko 
5595e111ed8SAndrew Rybchenko 	return (rc);
5605e111ed8SAndrew Rybchenko }
5615e111ed8SAndrew Rybchenko 
5625e111ed8SAndrew Rybchenko static	uint8_t	__efx_vpd_blank_pid[] = {
5635e111ed8SAndrew Rybchenko 	/* Large resource type ID length 1 */
5645e111ed8SAndrew Rybchenko 	0x82, 0x01, 0x00,
5655e111ed8SAndrew Rybchenko 	/* Product name ' ' */
5665e111ed8SAndrew Rybchenko 	0x32,
5675e111ed8SAndrew Rybchenko };
5685e111ed8SAndrew Rybchenko 
5695e111ed8SAndrew Rybchenko static uint8_t __efx_vpd_blank_r[] = {
5705e111ed8SAndrew Rybchenko 	/* Large resource type VPD-R length 4 */
5715e111ed8SAndrew Rybchenko 	0x90, 0x04, 0x00,
5725e111ed8SAndrew Rybchenko 	/* RV keyword length 1 */
5735e111ed8SAndrew Rybchenko 	'R', 'V', 0x01,
5745e111ed8SAndrew Rybchenko 	/* RV payload checksum */
5755e111ed8SAndrew Rybchenko 	0x00,
5765e111ed8SAndrew Rybchenko };
5775e111ed8SAndrew Rybchenko 
5785e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_hunk_reinit(__in_bcount (size)caddr_t data,__in size_t size,__in boolean_t wantpid)5795e111ed8SAndrew Rybchenko efx_vpd_hunk_reinit(
5805e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
5815e111ed8SAndrew Rybchenko 	__in			size_t size,
5825e111ed8SAndrew Rybchenko 	__in			boolean_t wantpid)
5835e111ed8SAndrew Rybchenko {
5845e111ed8SAndrew Rybchenko 	unsigned int offset = 0;
5855e111ed8SAndrew Rybchenko 	unsigned int pos;
5865e111ed8SAndrew Rybchenko 	efx_byte_t byte;
5875e111ed8SAndrew Rybchenko 	uint8_t cksum;
5885e111ed8SAndrew Rybchenko 	efx_rc_t rc;
5895e111ed8SAndrew Rybchenko 
5905e111ed8SAndrew Rybchenko 	if (size < 0x100) {
5915e111ed8SAndrew Rybchenko 		rc = ENOSPC;
5925e111ed8SAndrew Rybchenko 		goto fail1;
5935e111ed8SAndrew Rybchenko 	}
5945e111ed8SAndrew Rybchenko 
5955e111ed8SAndrew Rybchenko 	if (wantpid) {
5965e111ed8SAndrew Rybchenko 		memcpy(data + offset, __efx_vpd_blank_pid,
5975e111ed8SAndrew Rybchenko 		    sizeof (__efx_vpd_blank_pid));
5985e111ed8SAndrew Rybchenko 		offset += sizeof (__efx_vpd_blank_pid);
5995e111ed8SAndrew Rybchenko 	}
6005e111ed8SAndrew Rybchenko 
6015e111ed8SAndrew Rybchenko 	memcpy(data + offset, __efx_vpd_blank_r, sizeof (__efx_vpd_blank_r));
6025e111ed8SAndrew Rybchenko 	offset += sizeof (__efx_vpd_blank_r);
6035e111ed8SAndrew Rybchenko 
6045e111ed8SAndrew Rybchenko 	/* Update checksum */
6055e111ed8SAndrew Rybchenko 	cksum = 0;
6065e111ed8SAndrew Rybchenko 	for (pos = 0; pos < offset; pos++)
6075e111ed8SAndrew Rybchenko 		cksum += data[pos];
6085e111ed8SAndrew Rybchenko 	data[offset - 1] -= cksum;
6095e111ed8SAndrew Rybchenko 
6105e111ed8SAndrew Rybchenko 	/* Append trailing tag */
6115e111ed8SAndrew Rybchenko 	EFX_POPULATE_BYTE_3(byte,
6125e111ed8SAndrew Rybchenko 			    TAG_TYPE, TAG_TYPE_SMALL_ITEM_DECODE,
6135e111ed8SAndrew Rybchenko 			    TAG_SMALL_ITEM_NAME, TAG_NAME_END_DECODE,
6145e111ed8SAndrew Rybchenko 			    TAG_SMALL_ITEM_SIZE, 0);
6155e111ed8SAndrew Rybchenko 	data[offset] = EFX_BYTE_FIELD(byte, EFX_BYTE_0);
6165e111ed8SAndrew Rybchenko 	offset++;
6175e111ed8SAndrew Rybchenko 
6185e111ed8SAndrew Rybchenko 	return (0);
6195e111ed8SAndrew Rybchenko 
6205e111ed8SAndrew Rybchenko fail1:
6215e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
6225e111ed8SAndrew Rybchenko 
6235e111ed8SAndrew Rybchenko 	return (rc);
6245e111ed8SAndrew Rybchenko }
6255e111ed8SAndrew Rybchenko 
6265e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_vpd_hunk_next(__in_bcount (size)caddr_t data,__in size_t size,__out efx_vpd_tag_t * tagp,__out efx_vpd_keyword_t * keywordp,__out_opt unsigned int * payloadp,__out_opt uint8_t * paylenp,__inout unsigned int * contp)6275e111ed8SAndrew Rybchenko efx_vpd_hunk_next(
6285e111ed8SAndrew Rybchenko 	__in_bcount(size)		caddr_t data,
6295e111ed8SAndrew Rybchenko 	__in				size_t size,
6305e111ed8SAndrew Rybchenko 	__out				efx_vpd_tag_t *tagp,
6315e111ed8SAndrew Rybchenko 	__out				efx_vpd_keyword_t *keywordp,
6325e111ed8SAndrew Rybchenko 	__out_opt			unsigned int *payloadp,
6335e111ed8SAndrew Rybchenko 	__out_opt			uint8_t *paylenp,
6345e111ed8SAndrew Rybchenko 	__inout				unsigned int *contp)
6355e111ed8SAndrew Rybchenko {
6365e111ed8SAndrew Rybchenko 	efx_vpd_tag_t tag;
6375e111ed8SAndrew Rybchenko 	efx_vpd_keyword_t keyword = 0;
6385e111ed8SAndrew Rybchenko 	unsigned int offset;
6395e111ed8SAndrew Rybchenko 	unsigned int pos;
6405e111ed8SAndrew Rybchenko 	unsigned int index;
6415e111ed8SAndrew Rybchenko 	uint16_t taglen;
6425e111ed8SAndrew Rybchenko 	uint8_t keylen;
6435e111ed8SAndrew Rybchenko 	uint8_t paylen;
6445e111ed8SAndrew Rybchenko 	efx_rc_t rc;
6455e111ed8SAndrew Rybchenko 
6465e111ed8SAndrew Rybchenko 	offset = index = 0;
6475e111ed8SAndrew Rybchenko 	_NOTE(CONSTANTCONDITION)
6485e111ed8SAndrew Rybchenko 	while (1) {
6495e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_next_tag(data, size, &offset,
6505e111ed8SAndrew Rybchenko 		    &tag, &taglen)) != 0)
6515e111ed8SAndrew Rybchenko 			goto fail1;
6525e111ed8SAndrew Rybchenko 
6535e111ed8SAndrew Rybchenko 		if (tag == EFX_VPD_END) {
6545e111ed8SAndrew Rybchenko 			keyword = 0;
6555e111ed8SAndrew Rybchenko 			paylen = 0;
6565e111ed8SAndrew Rybchenko 			index = 0;
6575e111ed8SAndrew Rybchenko 			break;
6585e111ed8SAndrew Rybchenko 		}
6595e111ed8SAndrew Rybchenko 
6605e111ed8SAndrew Rybchenko 		if (tag == EFX_VPD_ID) {
6615e111ed8SAndrew Rybchenko 			if (index++ == *contp) {
6625e111ed8SAndrew Rybchenko 				EFSYS_ASSERT3U(taglen, <, 0x100);
6635e111ed8SAndrew Rybchenko 				keyword = 0;
6645e111ed8SAndrew Rybchenko 				paylen = (uint8_t)MIN(taglen, 0xff);
6655e111ed8SAndrew Rybchenko 
6665e111ed8SAndrew Rybchenko 				goto done;
6675e111ed8SAndrew Rybchenko 			}
6685e111ed8SAndrew Rybchenko 		} else {
6695e111ed8SAndrew Rybchenko 			for (pos = 0; pos != taglen; pos += 3 + keylen) {
6705e111ed8SAndrew Rybchenko 				if ((rc = efx_vpd_next_keyword(data + offset,
6715e111ed8SAndrew Rybchenko 				    taglen, pos, &keyword, &keylen)) != 0)
6725e111ed8SAndrew Rybchenko 					goto fail2;
6735e111ed8SAndrew Rybchenko 
6745e111ed8SAndrew Rybchenko 				if (index++ == *contp) {
6755e111ed8SAndrew Rybchenko 					offset += pos + 3;
6765e111ed8SAndrew Rybchenko 					paylen = keylen;
6775e111ed8SAndrew Rybchenko 
6785e111ed8SAndrew Rybchenko 					goto done;
6795e111ed8SAndrew Rybchenko 				}
6805e111ed8SAndrew Rybchenko 			}
6815e111ed8SAndrew Rybchenko 		}
6825e111ed8SAndrew Rybchenko 
6835e111ed8SAndrew Rybchenko 		offset += taglen;
6845e111ed8SAndrew Rybchenko 	}
6855e111ed8SAndrew Rybchenko 
6865e111ed8SAndrew Rybchenko done:
6875e111ed8SAndrew Rybchenko 	*tagp = tag;
6885e111ed8SAndrew Rybchenko 	*keywordp = keyword;
6895e111ed8SAndrew Rybchenko 	if (payloadp != NULL)
6905e111ed8SAndrew Rybchenko 		*payloadp = offset;
6915e111ed8SAndrew Rybchenko 	if (paylenp != NULL)
6925e111ed8SAndrew Rybchenko 		*paylenp = paylen;
6935e111ed8SAndrew Rybchenko 
6945e111ed8SAndrew Rybchenko 	*contp = index;
6955e111ed8SAndrew Rybchenko 	return (0);
6965e111ed8SAndrew Rybchenko 
6975e111ed8SAndrew Rybchenko fail2:
6985e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
6995e111ed8SAndrew Rybchenko fail1:
7005e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
7015e111ed8SAndrew Rybchenko 
7025e111ed8SAndrew Rybchenko 	return (rc);
7035e111ed8SAndrew Rybchenko }
7045e111ed8SAndrew Rybchenko 
7055e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_hunk_get(__in_bcount (size)caddr_t data,__in size_t size,__in efx_vpd_tag_t tag,__in efx_vpd_keyword_t keyword,__out unsigned int * payloadp,__out uint8_t * paylenp)7065e111ed8SAndrew Rybchenko efx_vpd_hunk_get(
7075e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
7085e111ed8SAndrew Rybchenko 	__in			size_t size,
7095e111ed8SAndrew Rybchenko 	__in			efx_vpd_tag_t tag,
7105e111ed8SAndrew Rybchenko 	__in			efx_vpd_keyword_t keyword,
7115e111ed8SAndrew Rybchenko 	__out			unsigned int *payloadp,
7125e111ed8SAndrew Rybchenko 	__out			uint8_t *paylenp)
7135e111ed8SAndrew Rybchenko {
7145e111ed8SAndrew Rybchenko 	efx_vpd_tag_t itag;
7155e111ed8SAndrew Rybchenko 	efx_vpd_keyword_t ikeyword;
7165e111ed8SAndrew Rybchenko 	unsigned int offset;
7175e111ed8SAndrew Rybchenko 	unsigned int pos;
7185e111ed8SAndrew Rybchenko 	uint16_t taglen;
7195e111ed8SAndrew Rybchenko 	uint8_t keylen;
7205e111ed8SAndrew Rybchenko 	efx_rc_t rc;
7215e111ed8SAndrew Rybchenko 
7225e111ed8SAndrew Rybchenko 	offset = 0;
7235e111ed8SAndrew Rybchenko 	_NOTE(CONSTANTCONDITION)
7245e111ed8SAndrew Rybchenko 	while (1) {
7255e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_next_tag(data, size, &offset,
7265e111ed8SAndrew Rybchenko 		    &itag, &taglen)) != 0)
7275e111ed8SAndrew Rybchenko 			goto fail1;
7285e111ed8SAndrew Rybchenko 		if (itag == EFX_VPD_END)
7295e111ed8SAndrew Rybchenko 			break;
7305e111ed8SAndrew Rybchenko 
7315e111ed8SAndrew Rybchenko 		if (itag == tag) {
7325e111ed8SAndrew Rybchenko 			if (itag == EFX_VPD_ID) {
7335e111ed8SAndrew Rybchenko 				EFSYS_ASSERT3U(taglen, <, 0x100);
7345e111ed8SAndrew Rybchenko 
7355e111ed8SAndrew Rybchenko 				*paylenp = (uint8_t)MIN(taglen, 0xff);
7365e111ed8SAndrew Rybchenko 				*payloadp = offset;
7375e111ed8SAndrew Rybchenko 				return (0);
7385e111ed8SAndrew Rybchenko 			}
7395e111ed8SAndrew Rybchenko 
7405e111ed8SAndrew Rybchenko 			for (pos = 0; pos != taglen; pos += 3 + keylen) {
7415e111ed8SAndrew Rybchenko 				if ((rc = efx_vpd_next_keyword(data + offset,
7425e111ed8SAndrew Rybchenko 				    taglen, pos, &ikeyword, &keylen)) != 0)
7435e111ed8SAndrew Rybchenko 					goto fail2;
7445e111ed8SAndrew Rybchenko 
7455e111ed8SAndrew Rybchenko 				if (ikeyword == keyword) {
7465e111ed8SAndrew Rybchenko 					*paylenp = keylen;
7475e111ed8SAndrew Rybchenko 					*payloadp = offset + pos + 3;
7485e111ed8SAndrew Rybchenko 					return (0);
7495e111ed8SAndrew Rybchenko 				}
7505e111ed8SAndrew Rybchenko 			}
7515e111ed8SAndrew Rybchenko 		}
7525e111ed8SAndrew Rybchenko 
7535e111ed8SAndrew Rybchenko 		offset += taglen;
7545e111ed8SAndrew Rybchenko 	}
7555e111ed8SAndrew Rybchenko 
7565e111ed8SAndrew Rybchenko 	/* Not an error */
7575e111ed8SAndrew Rybchenko 	return (ENOENT);
7585e111ed8SAndrew Rybchenko 
7595e111ed8SAndrew Rybchenko fail2:
7605e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
7615e111ed8SAndrew Rybchenko fail1:
7625e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
7635e111ed8SAndrew Rybchenko 
7645e111ed8SAndrew Rybchenko 	return (rc);
7655e111ed8SAndrew Rybchenko }
7665e111ed8SAndrew Rybchenko 
7675e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_vpd_hunk_set(__in_bcount (size)caddr_t data,__in size_t size,__in efx_vpd_value_t * evvp)7685e111ed8SAndrew Rybchenko efx_vpd_hunk_set(
7695e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
7705e111ed8SAndrew Rybchenko 	__in			size_t size,
7715e111ed8SAndrew Rybchenko 	__in			efx_vpd_value_t *evvp)
7725e111ed8SAndrew Rybchenko {
7735e111ed8SAndrew Rybchenko 	efx_word_t word;
7745e111ed8SAndrew Rybchenko 	efx_vpd_tag_t tag;
7755e111ed8SAndrew Rybchenko 	efx_vpd_keyword_t keyword;
7765e111ed8SAndrew Rybchenko 	unsigned int offset;
7775e111ed8SAndrew Rybchenko 	unsigned int pos;
7785e111ed8SAndrew Rybchenko 	unsigned int taghead;
7795e111ed8SAndrew Rybchenko 	unsigned int source;
7805e111ed8SAndrew Rybchenko 	unsigned int dest;
7815e111ed8SAndrew Rybchenko 	unsigned int i;
7825e111ed8SAndrew Rybchenko 	uint16_t taglen;
7835e111ed8SAndrew Rybchenko 	uint8_t keylen;
7845e111ed8SAndrew Rybchenko 	uint8_t cksum;
7855e111ed8SAndrew Rybchenko 	size_t used;
7865e111ed8SAndrew Rybchenko 	efx_rc_t rc;
7875e111ed8SAndrew Rybchenko 
7885e111ed8SAndrew Rybchenko 	switch (evvp->evv_tag) {
7895e111ed8SAndrew Rybchenko 	case EFX_VPD_ID:
7905e111ed8SAndrew Rybchenko 		if (evvp->evv_keyword != 0) {
7915e111ed8SAndrew Rybchenko 			rc = EINVAL;
7925e111ed8SAndrew Rybchenko 			goto fail1;
7935e111ed8SAndrew Rybchenko 		}
7945e111ed8SAndrew Rybchenko 
7955e111ed8SAndrew Rybchenko 		/* Can't delete the ID keyword */
7965e111ed8SAndrew Rybchenko 		if (evvp->evv_length == 0) {
7975e111ed8SAndrew Rybchenko 			rc = EINVAL;
7985e111ed8SAndrew Rybchenko 			goto fail1;
7995e111ed8SAndrew Rybchenko 		}
8005e111ed8SAndrew Rybchenko 		break;
8015e111ed8SAndrew Rybchenko 
8025e111ed8SAndrew Rybchenko 	case EFX_VPD_RO:
8035e111ed8SAndrew Rybchenko 		if (evvp->evv_keyword == EFX_VPD_KEYWORD('R', 'V')) {
8045e111ed8SAndrew Rybchenko 			rc = EINVAL;
8055e111ed8SAndrew Rybchenko 			goto fail1;
8065e111ed8SAndrew Rybchenko 		}
8075e111ed8SAndrew Rybchenko 		break;
8085e111ed8SAndrew Rybchenko 
8095e111ed8SAndrew Rybchenko 	default:
8105e111ed8SAndrew Rybchenko 		rc = EINVAL;
8115e111ed8SAndrew Rybchenko 		goto fail1;
8125e111ed8SAndrew Rybchenko 	}
8135e111ed8SAndrew Rybchenko 
8145e111ed8SAndrew Rybchenko 	/* Determine total size of all current tags */
8155e111ed8SAndrew Rybchenko 	if ((rc = efx_vpd_hunk_length(data, size, &used)) != 0)
8165e111ed8SAndrew Rybchenko 		goto fail2;
8175e111ed8SAndrew Rybchenko 
8185e111ed8SAndrew Rybchenko 	offset = 0;
8195e111ed8SAndrew Rybchenko 	_NOTE(CONSTANTCONDITION)
8205e111ed8SAndrew Rybchenko 	while (1) {
8215e111ed8SAndrew Rybchenko 		taghead = offset;
8225e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_next_tag(data, size, &offset,
8235e111ed8SAndrew Rybchenko 		    &tag, &taglen)) != 0)
8245e111ed8SAndrew Rybchenko 			goto fail3;
8255e111ed8SAndrew Rybchenko 		if (tag == EFX_VPD_END)
8265e111ed8SAndrew Rybchenko 			break;
8275e111ed8SAndrew Rybchenko 		else if (tag != evvp->evv_tag) {
8285e111ed8SAndrew Rybchenko 			offset += taglen;
8295e111ed8SAndrew Rybchenko 			continue;
8305e111ed8SAndrew Rybchenko 		}
8315e111ed8SAndrew Rybchenko 
8325e111ed8SAndrew Rybchenko 		/* We only support modifying large resource tags */
8335e111ed8SAndrew Rybchenko 		if (offset - taghead != 3) {
8345e111ed8SAndrew Rybchenko 			rc = EINVAL;
8355e111ed8SAndrew Rybchenko 			goto fail4;
8365e111ed8SAndrew Rybchenko 		}
8375e111ed8SAndrew Rybchenko 
8385e111ed8SAndrew Rybchenko 		/*
8395e111ed8SAndrew Rybchenko 		 * Work out the offset of the byte immediately after the
8405e111ed8SAndrew Rybchenko 		 * old (=source) and new (=dest) new keyword/tag
8415e111ed8SAndrew Rybchenko 		 */
8425e111ed8SAndrew Rybchenko 		pos = 0;
8435e111ed8SAndrew Rybchenko 		if (tag == EFX_VPD_ID) {
8445e111ed8SAndrew Rybchenko 			source = offset + taglen;
8455e111ed8SAndrew Rybchenko 			dest = offset + evvp->evv_length;
8465e111ed8SAndrew Rybchenko 			goto check_space;
8475e111ed8SAndrew Rybchenko 		}
8485e111ed8SAndrew Rybchenko 
8495e111ed8SAndrew Rybchenko 		EFSYS_ASSERT3U(tag, ==, EFX_VPD_RO);
8505e111ed8SAndrew Rybchenko 		source = dest = 0;
8515e111ed8SAndrew Rybchenko 		for (pos = 0; pos != taglen; pos += 3 + keylen) {
8525e111ed8SAndrew Rybchenko 			if ((rc = efx_vpd_next_keyword(data + offset,
8535e111ed8SAndrew Rybchenko 			    taglen, pos, &keyword, &keylen)) != 0)
8545e111ed8SAndrew Rybchenko 				goto fail5;
8555e111ed8SAndrew Rybchenko 
8565e111ed8SAndrew Rybchenko 			if (keyword == evvp->evv_keyword &&
8575e111ed8SAndrew Rybchenko 			    evvp->evv_length == 0) {
8585e111ed8SAndrew Rybchenko 				/* Deleting this keyword */
8595e111ed8SAndrew Rybchenko 				source = offset + pos + 3 + keylen;
8605e111ed8SAndrew Rybchenko 				dest = offset + pos;
8615e111ed8SAndrew Rybchenko 				break;
8625e111ed8SAndrew Rybchenko 
8635e111ed8SAndrew Rybchenko 			} else if (keyword == evvp->evv_keyword) {
8645e111ed8SAndrew Rybchenko 				/* Adjusting this keyword */
8655e111ed8SAndrew Rybchenko 				source = offset + pos + 3 + keylen;
8665e111ed8SAndrew Rybchenko 				dest = offset + pos + 3 + evvp->evv_length;
8675e111ed8SAndrew Rybchenko 				break;
8685e111ed8SAndrew Rybchenko 
8695e111ed8SAndrew Rybchenko 			} else if (keyword == EFX_VPD_KEYWORD('R', 'V')) {
8705e111ed8SAndrew Rybchenko 				/* The RV keyword must be at the end */
8715e111ed8SAndrew Rybchenko 				EFSYS_ASSERT3U(pos + 3 + keylen, ==, taglen);
8725e111ed8SAndrew Rybchenko 
8735e111ed8SAndrew Rybchenko 				/*
8745e111ed8SAndrew Rybchenko 				 * The keyword doesn't already exist. If the
8755e111ed8SAndrew Rybchenko 				 * user deleting a non-existant keyword then
8765e111ed8SAndrew Rybchenko 				 * this is a no-op.
8775e111ed8SAndrew Rybchenko 				 */
8785e111ed8SAndrew Rybchenko 				if (evvp->evv_length == 0)
8795e111ed8SAndrew Rybchenko 					return (0);
8805e111ed8SAndrew Rybchenko 
8815e111ed8SAndrew Rybchenko 				/* Insert this keyword before the RV keyword */
8825e111ed8SAndrew Rybchenko 				source = offset + pos;
8835e111ed8SAndrew Rybchenko 				dest = offset + pos + 3 + evvp->evv_length;
8845e111ed8SAndrew Rybchenko 				break;
8855e111ed8SAndrew Rybchenko 			}
8865e111ed8SAndrew Rybchenko 		}
8875e111ed8SAndrew Rybchenko 
8885e111ed8SAndrew Rybchenko 	check_space:
8895e111ed8SAndrew Rybchenko 		if (used + dest > size + source) {
8905e111ed8SAndrew Rybchenko 			rc = ENOSPC;
8915e111ed8SAndrew Rybchenko 			goto fail6;
8925e111ed8SAndrew Rybchenko 		}
8935e111ed8SAndrew Rybchenko 
8945e111ed8SAndrew Rybchenko 		/* Move trailing data */
8955e111ed8SAndrew Rybchenko 		(void) memmove(data + dest, data + source, used - source);
8965e111ed8SAndrew Rybchenko 
8975e111ed8SAndrew Rybchenko 		/* Copy contents */
8985e111ed8SAndrew Rybchenko 		memcpy(data + dest - evvp->evv_length, evvp->evv_value,
8995e111ed8SAndrew Rybchenko 		    evvp->evv_length);
9005e111ed8SAndrew Rybchenko 
9015e111ed8SAndrew Rybchenko 		/* Insert new keyword header if required */
9025e111ed8SAndrew Rybchenko 		if (tag != EFX_VPD_ID && evvp->evv_length > 0) {
9035e111ed8SAndrew Rybchenko 			EFX_POPULATE_WORD_1(word, EFX_WORD_0,
9045e111ed8SAndrew Rybchenko 					    evvp->evv_keyword);
9055e111ed8SAndrew Rybchenko 			data[offset + pos + 0] =
9065e111ed8SAndrew Rybchenko 			    EFX_WORD_FIELD(word, EFX_BYTE_0);
9075e111ed8SAndrew Rybchenko 			data[offset + pos + 1] =
9085e111ed8SAndrew Rybchenko 			    EFX_WORD_FIELD(word, EFX_BYTE_1);
9095e111ed8SAndrew Rybchenko 			data[offset + pos + 2] = evvp->evv_length;
9105e111ed8SAndrew Rybchenko 		}
9115e111ed8SAndrew Rybchenko 
9125e111ed8SAndrew Rybchenko 		/* Modify tag length (large resource type) */
9135e111ed8SAndrew Rybchenko 		taglen += (uint16_t)(dest - source);
9145e111ed8SAndrew Rybchenko 		EFX_POPULATE_WORD_1(word, EFX_WORD_0, taglen);
9155e111ed8SAndrew Rybchenko 		data[offset - 2] = EFX_WORD_FIELD(word, EFX_BYTE_0);
9165e111ed8SAndrew Rybchenko 		data[offset - 1] = EFX_WORD_FIELD(word, EFX_BYTE_1);
9175e111ed8SAndrew Rybchenko 
9185e111ed8SAndrew Rybchenko 		goto checksum;
9195e111ed8SAndrew Rybchenko 	}
9205e111ed8SAndrew Rybchenko 
9215e111ed8SAndrew Rybchenko 	/* Unable to find the matching tag */
9225e111ed8SAndrew Rybchenko 	rc = ENOENT;
9235e111ed8SAndrew Rybchenko 	goto fail7;
9245e111ed8SAndrew Rybchenko 
9255e111ed8SAndrew Rybchenko checksum:
9265e111ed8SAndrew Rybchenko 	/* Find the RV tag, and update the checksum */
9275e111ed8SAndrew Rybchenko 	offset = 0;
9285e111ed8SAndrew Rybchenko 	_NOTE(CONSTANTCONDITION)
9295e111ed8SAndrew Rybchenko 	while (1) {
9305e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_next_tag(data, size, &offset,
9315e111ed8SAndrew Rybchenko 		    &tag, &taglen)) != 0)
9325e111ed8SAndrew Rybchenko 			goto fail8;
9335e111ed8SAndrew Rybchenko 		if (tag == EFX_VPD_END)
9345e111ed8SAndrew Rybchenko 			break;
9355e111ed8SAndrew Rybchenko 		if (tag == EFX_VPD_RO) {
9365e111ed8SAndrew Rybchenko 			for (pos = 0; pos != taglen; pos += 3 + keylen) {
9375e111ed8SAndrew Rybchenko 				if ((rc = efx_vpd_next_keyword(data + offset,
9385e111ed8SAndrew Rybchenko 				    taglen, pos, &keyword, &keylen)) != 0)
9395e111ed8SAndrew Rybchenko 					goto fail9;
9405e111ed8SAndrew Rybchenko 
9415e111ed8SAndrew Rybchenko 				if (keyword == EFX_VPD_KEYWORD('R', 'V')) {
9425e111ed8SAndrew Rybchenko 					cksum = 0;
9435e111ed8SAndrew Rybchenko 					for (i = 0; i < offset + pos + 3; i++)
9445e111ed8SAndrew Rybchenko 						cksum += data[i];
9455e111ed8SAndrew Rybchenko 					data[i] = -cksum;
9465e111ed8SAndrew Rybchenko 					break;
9475e111ed8SAndrew Rybchenko 				}
9485e111ed8SAndrew Rybchenko 			}
9495e111ed8SAndrew Rybchenko 		}
9505e111ed8SAndrew Rybchenko 
9515e111ed8SAndrew Rybchenko 		offset += taglen;
9525e111ed8SAndrew Rybchenko 	}
9535e111ed8SAndrew Rybchenko 
9545e111ed8SAndrew Rybchenko 	/* Zero out the unused portion */
9555e111ed8SAndrew Rybchenko 	(void) memset(data + offset + taglen, 0xff, size - offset - taglen);
9565e111ed8SAndrew Rybchenko 
9575e111ed8SAndrew Rybchenko 	return (0);
9585e111ed8SAndrew Rybchenko 
9595e111ed8SAndrew Rybchenko fail9:
9605e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail9);
9615e111ed8SAndrew Rybchenko fail8:
9625e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail8);
9635e111ed8SAndrew Rybchenko fail7:
9645e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail7);
9655e111ed8SAndrew Rybchenko fail6:
9665e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail6);
9675e111ed8SAndrew Rybchenko fail5:
9685e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail5);
9695e111ed8SAndrew Rybchenko fail4:
9705e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail4);
9715e111ed8SAndrew Rybchenko fail3:
9725e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
9735e111ed8SAndrew Rybchenko fail2:
9745e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
9755e111ed8SAndrew Rybchenko fail1:
9765e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
9775e111ed8SAndrew Rybchenko 
9785e111ed8SAndrew Rybchenko 	return (rc);
9795e111ed8SAndrew Rybchenko }
9805e111ed8SAndrew Rybchenko 
9815e111ed8SAndrew Rybchenko 				void
efx_vpd_fini(__in efx_nic_t * enp)9825e111ed8SAndrew Rybchenko efx_vpd_fini(
9835e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp)
9845e111ed8SAndrew Rybchenko {
9855e111ed8SAndrew Rybchenko 	const efx_vpd_ops_t *evpdop = enp->en_evpdop;
9865e111ed8SAndrew Rybchenko 
9875e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
9885e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
9895e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
9905e111ed8SAndrew Rybchenko 
9915e111ed8SAndrew Rybchenko 	if (evpdop->evpdo_fini != NULL)
9925e111ed8SAndrew Rybchenko 		evpdop->evpdo_fini(enp);
9935e111ed8SAndrew Rybchenko 
9945e111ed8SAndrew Rybchenko 	enp->en_evpdop = NULL;
9955e111ed8SAndrew Rybchenko 	enp->en_mod_flags &= ~EFX_MOD_VPD;
9965e111ed8SAndrew Rybchenko }
9975e111ed8SAndrew Rybchenko 
9985e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_VPD */
999