xref: /dpdk/drivers/common/sfc_efx/base/ef10_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 
115e111ed8SAndrew Rybchenko #if EFSYS_OPT_VPD
125e111ed8SAndrew Rybchenko 
135e111ed8SAndrew Rybchenko #if EFX_OPTS_EF10()
145e111ed8SAndrew Rybchenko 
155e111ed8SAndrew Rybchenko #include "ef10_tlv_layout.h"
165e111ed8SAndrew Rybchenko 
175e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_vpd_init(__in efx_nic_t * enp)185e111ed8SAndrew Rybchenko ef10_vpd_init(
195e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp)
205e111ed8SAndrew Rybchenko {
215e111ed8SAndrew Rybchenko 	caddr_t svpd;
225e111ed8SAndrew Rybchenko 	size_t svpd_size;
235e111ed8SAndrew Rybchenko 	uint32_t pci_pf;
245e111ed8SAndrew Rybchenko 	uint32_t tag;
255e111ed8SAndrew Rybchenko 	efx_rc_t rc;
265e111ed8SAndrew Rybchenko 
275e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
285e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
295e111ed8SAndrew Rybchenko 
305e111ed8SAndrew Rybchenko 	if (enp->en_nic_cfg.enc_vpd_is_global) {
315e111ed8SAndrew Rybchenko 		tag = TLV_TAG_GLOBAL_STATIC_VPD;
325e111ed8SAndrew Rybchenko 	} else {
335e111ed8SAndrew Rybchenko 		pci_pf = enp->en_nic_cfg.enc_pf;
345e111ed8SAndrew Rybchenko 		tag = TLV_TAG_PF_STATIC_VPD(pci_pf);
355e111ed8SAndrew Rybchenko 	}
365e111ed8SAndrew Rybchenko 
375e111ed8SAndrew Rybchenko 	/*
385e111ed8SAndrew Rybchenko 	 * The VPD interface exposes VPD resources from the combined static and
395e111ed8SAndrew Rybchenko 	 * dynamic VPD storage. As the static VPD configuration should *never*
405e111ed8SAndrew Rybchenko 	 * change, we can cache it.
415e111ed8SAndrew Rybchenko 	 */
425e111ed8SAndrew Rybchenko 	svpd = NULL;
435e111ed8SAndrew Rybchenko 	svpd_size = 0;
445e111ed8SAndrew Rybchenko 	rc = ef10_nvram_partn_read_tlv(enp,
455e111ed8SAndrew Rybchenko 	    NVRAM_PARTITION_TYPE_STATIC_CONFIG,
465e111ed8SAndrew Rybchenko 	    tag, &svpd, &svpd_size);
475e111ed8SAndrew Rybchenko 	if (rc != 0) {
485e111ed8SAndrew Rybchenko 		if (rc == EACCES) {
495e111ed8SAndrew Rybchenko 			/* Unprivileged functions cannot access VPD */
505e111ed8SAndrew Rybchenko 			goto out;
515e111ed8SAndrew Rybchenko 		}
525e111ed8SAndrew Rybchenko 		goto fail1;
535e111ed8SAndrew Rybchenko 	}
545e111ed8SAndrew Rybchenko 
555e111ed8SAndrew Rybchenko 	if (svpd != NULL && svpd_size > 0) {
565e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_hunk_verify(svpd, svpd_size, NULL)) != 0)
575e111ed8SAndrew Rybchenko 			goto fail2;
585e111ed8SAndrew Rybchenko 	}
595e111ed8SAndrew Rybchenko 
605e111ed8SAndrew Rybchenko 	enp->en_arch.ef10.ena_svpd = svpd;
615e111ed8SAndrew Rybchenko 	enp->en_arch.ef10.ena_svpd_length = svpd_size;
625e111ed8SAndrew Rybchenko 
635e111ed8SAndrew Rybchenko out:
645e111ed8SAndrew Rybchenko 	return (0);
655e111ed8SAndrew Rybchenko 
665e111ed8SAndrew Rybchenko fail2:
675e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
685e111ed8SAndrew Rybchenko 
695e111ed8SAndrew Rybchenko 	EFSYS_KMEM_FREE(enp->en_esip, svpd_size, svpd);
705e111ed8SAndrew Rybchenko fail1:
715e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
725e111ed8SAndrew Rybchenko 
735e111ed8SAndrew Rybchenko 	return (rc);
745e111ed8SAndrew Rybchenko }
755e111ed8SAndrew Rybchenko 
765e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_vpd_size(__in efx_nic_t * enp,__out size_t * sizep)775e111ed8SAndrew Rybchenko ef10_vpd_size(
785e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
795e111ed8SAndrew Rybchenko 	__out			size_t *sizep)
805e111ed8SAndrew Rybchenko {
815e111ed8SAndrew Rybchenko 	efx_rc_t rc;
825e111ed8SAndrew Rybchenko 	efx_nvram_info_t eni = { 0 };
835e111ed8SAndrew Rybchenko 
845e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
855e111ed8SAndrew Rybchenko 
865e111ed8SAndrew Rybchenko 	/*
875e111ed8SAndrew Rybchenko 	 * This function returns the total size the user should allocate
885e111ed8SAndrew Rybchenko 	 * for all VPD operations. We've already cached the static vpd,
895e111ed8SAndrew Rybchenko 	 * so we just need to return an upper bound on the dynamic vpd,
905e111ed8SAndrew Rybchenko 	 * which is the size of the DYNAMIC_CONFIG partition.
915e111ed8SAndrew Rybchenko 	 */
925e111ed8SAndrew Rybchenko 	if ((rc = efx_mcdi_nvram_info(enp,
935e111ed8SAndrew Rybchenko 		    NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG, &eni)) != 0)
945e111ed8SAndrew Rybchenko 		goto fail1;
955e111ed8SAndrew Rybchenko 
965e111ed8SAndrew Rybchenko 	*sizep = eni.eni_partn_size;
975e111ed8SAndrew Rybchenko 
985e111ed8SAndrew Rybchenko 	return (0);
995e111ed8SAndrew Rybchenko 
1005e111ed8SAndrew Rybchenko fail1:
1015e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1025e111ed8SAndrew Rybchenko 
1035e111ed8SAndrew Rybchenko 	return (rc);
1045e111ed8SAndrew Rybchenko }
1055e111ed8SAndrew Rybchenko 
1065e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_vpd_read(__in efx_nic_t * enp,__out_bcount (size)caddr_t data,__in size_t size)1075e111ed8SAndrew Rybchenko ef10_vpd_read(
1085e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
1095e111ed8SAndrew Rybchenko 	__out_bcount(size)	caddr_t data,
1105e111ed8SAndrew Rybchenko 	__in			size_t size)
1115e111ed8SAndrew Rybchenko {
1125e111ed8SAndrew Rybchenko 	caddr_t dvpd;
1135e111ed8SAndrew Rybchenko 	size_t dvpd_size;
1145e111ed8SAndrew Rybchenko 	uint32_t pci_pf;
1155e111ed8SAndrew Rybchenko 	uint32_t tag;
1165e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1175e111ed8SAndrew Rybchenko 
1185e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
1195e111ed8SAndrew Rybchenko 
1205e111ed8SAndrew Rybchenko 	if (enp->en_nic_cfg.enc_vpd_is_global) {
1215e111ed8SAndrew Rybchenko 		tag = TLV_TAG_GLOBAL_DYNAMIC_VPD;
1225e111ed8SAndrew Rybchenko 	} else {
1235e111ed8SAndrew Rybchenko 		pci_pf = enp->en_nic_cfg.enc_pf;
1245e111ed8SAndrew Rybchenko 		tag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf);
1255e111ed8SAndrew Rybchenko 	}
1265e111ed8SAndrew Rybchenko 
1275e111ed8SAndrew Rybchenko 	if ((rc = ef10_nvram_partn_read_tlv(enp,
1285e111ed8SAndrew Rybchenko 		    NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,
1295e111ed8SAndrew Rybchenko 		    tag, &dvpd, &dvpd_size)) != 0)
1305e111ed8SAndrew Rybchenko 		goto fail1;
1315e111ed8SAndrew Rybchenko 
1325e111ed8SAndrew Rybchenko 	if (dvpd_size > size) {
1335e111ed8SAndrew Rybchenko 		rc = ENOSPC;
1345e111ed8SAndrew Rybchenko 		goto fail2;
1355e111ed8SAndrew Rybchenko 	}
1365e111ed8SAndrew Rybchenko 	if (dvpd != NULL)
1375e111ed8SAndrew Rybchenko 		memcpy(data, dvpd, dvpd_size);
1385e111ed8SAndrew Rybchenko 
1395e111ed8SAndrew Rybchenko 	/* Pad data with all-1s, consistent with update operations */
1405e111ed8SAndrew Rybchenko 	memset(data + dvpd_size, 0xff, size - dvpd_size);
1415e111ed8SAndrew Rybchenko 
1425e111ed8SAndrew Rybchenko 	if (dvpd != NULL)
1435e111ed8SAndrew Rybchenko 		EFSYS_KMEM_FREE(enp->en_esip, dvpd_size, dvpd);
1445e111ed8SAndrew Rybchenko 
1455e111ed8SAndrew Rybchenko 	return (0);
1465e111ed8SAndrew Rybchenko 
1475e111ed8SAndrew Rybchenko fail2:
1485e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1495e111ed8SAndrew Rybchenko 
1505e111ed8SAndrew Rybchenko 	if (dvpd != NULL)
1515e111ed8SAndrew Rybchenko 		EFSYS_KMEM_FREE(enp->en_esip, dvpd_size, dvpd);
1525e111ed8SAndrew Rybchenko fail1:
1535e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1545e111ed8SAndrew Rybchenko 
1555e111ed8SAndrew Rybchenko 	return (rc);
1565e111ed8SAndrew Rybchenko }
1575e111ed8SAndrew Rybchenko 
1585e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_vpd_verify(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)1595e111ed8SAndrew Rybchenko ef10_vpd_verify(
1605e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
1615e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
1625e111ed8SAndrew Rybchenko 	__in			size_t size)
1635e111ed8SAndrew Rybchenko {
1645e111ed8SAndrew Rybchenko 	efx_vpd_tag_t stag;
1655e111ed8SAndrew Rybchenko 	efx_vpd_tag_t dtag;
1665e111ed8SAndrew Rybchenko 	efx_vpd_keyword_t skey;
1675e111ed8SAndrew Rybchenko 	efx_vpd_keyword_t dkey;
1685e111ed8SAndrew Rybchenko 	unsigned int scont;
1695e111ed8SAndrew Rybchenko 	unsigned int dcont;
1705e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1715e111ed8SAndrew Rybchenko 
1725e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
1735e111ed8SAndrew Rybchenko 
1745e111ed8SAndrew Rybchenko 	/*
1755e111ed8SAndrew Rybchenko 	 * Strictly you could take the view that dynamic vpd is optional.
1765e111ed8SAndrew Rybchenko 	 * Instead, to conform more closely to the read/verify/reinit()
1775e111ed8SAndrew Rybchenko 	 * paradigm, we require dynamic vpd. ef10_vpd_reinit() will
1785e111ed8SAndrew Rybchenko 	 * reinitialize it as required.
1795e111ed8SAndrew Rybchenko 	 */
1805e111ed8SAndrew Rybchenko 	if ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0)
1815e111ed8SAndrew Rybchenko 		goto fail1;
1825e111ed8SAndrew Rybchenko 
1835e111ed8SAndrew Rybchenko 	/*
1845e111ed8SAndrew Rybchenko 	 * Verify that there is no duplication between the static and
1855e111ed8SAndrew Rybchenko 	 * dynamic cfg sectors.
1865e111ed8SAndrew Rybchenko 	 */
1875e111ed8SAndrew Rybchenko 	if (enp->en_arch.ef10.ena_svpd_length == 0)
1885e111ed8SAndrew Rybchenko 		goto done;
1895e111ed8SAndrew Rybchenko 
1905e111ed8SAndrew Rybchenko 	dcont = 0;
1915e111ed8SAndrew Rybchenko 	_NOTE(CONSTANTCONDITION)
1925e111ed8SAndrew Rybchenko 	while (1) {
1935e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_hunk_next(data, size, &dtag,
1945e111ed8SAndrew Rybchenko 		    &dkey, NULL, NULL, &dcont)) != 0)
1955e111ed8SAndrew Rybchenko 			goto fail2;
1965e111ed8SAndrew Rybchenko 		if (dcont == 0)
1975e111ed8SAndrew Rybchenko 			break;
1985e111ed8SAndrew Rybchenko 
1995e111ed8SAndrew Rybchenko 		/*
2005e111ed8SAndrew Rybchenko 		 * Skip the RV keyword. It should be present in both the static
2015e111ed8SAndrew Rybchenko 		 * and dynamic cfg sectors.
2025e111ed8SAndrew Rybchenko 		 */
2035e111ed8SAndrew Rybchenko 		if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))
2045e111ed8SAndrew Rybchenko 			continue;
2055e111ed8SAndrew Rybchenko 
2065e111ed8SAndrew Rybchenko 		scont = 0;
2075e111ed8SAndrew Rybchenko 		_NOTE(CONSTANTCONDITION)
2085e111ed8SAndrew Rybchenko 		while (1) {
2095e111ed8SAndrew Rybchenko 			if ((rc = efx_vpd_hunk_next(
2105e111ed8SAndrew Rybchenko 			    enp->en_arch.ef10.ena_svpd,
2115e111ed8SAndrew Rybchenko 			    enp->en_arch.ef10.ena_svpd_length, &stag, &skey,
2125e111ed8SAndrew Rybchenko 			    NULL, NULL, &scont)) != 0)
2135e111ed8SAndrew Rybchenko 				goto fail3;
2145e111ed8SAndrew Rybchenko 			if (scont == 0)
2155e111ed8SAndrew Rybchenko 				break;
2165e111ed8SAndrew Rybchenko 
2175e111ed8SAndrew Rybchenko 			if (stag == dtag && skey == dkey) {
2185e111ed8SAndrew Rybchenko 				rc = EEXIST;
2195e111ed8SAndrew Rybchenko 				goto fail4;
2205e111ed8SAndrew Rybchenko 			}
2215e111ed8SAndrew Rybchenko 		}
2225e111ed8SAndrew Rybchenko 	}
2235e111ed8SAndrew Rybchenko 
2245e111ed8SAndrew Rybchenko done:
2255e111ed8SAndrew Rybchenko 	return (0);
2265e111ed8SAndrew Rybchenko 
2275e111ed8SAndrew Rybchenko fail4:
2285e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail4);
2295e111ed8SAndrew Rybchenko fail3:
2305e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
2315e111ed8SAndrew Rybchenko fail2:
2325e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
2335e111ed8SAndrew Rybchenko fail1:
2345e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2355e111ed8SAndrew Rybchenko 
2365e111ed8SAndrew Rybchenko 	return (rc);
2375e111ed8SAndrew Rybchenko }
2385e111ed8SAndrew Rybchenko 
2395e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_vpd_reinit(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)2405e111ed8SAndrew Rybchenko ef10_vpd_reinit(
2415e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
2425e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
2435e111ed8SAndrew Rybchenko 	__in			size_t size)
2445e111ed8SAndrew Rybchenko {
2455e111ed8SAndrew Rybchenko 	boolean_t wantpid;
2465e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2475e111ed8SAndrew Rybchenko 
2485e111ed8SAndrew Rybchenko 	/*
2495e111ed8SAndrew Rybchenko 	 * Only create an ID string if the dynamic cfg doesn't have one
2505e111ed8SAndrew Rybchenko 	 */
2515e111ed8SAndrew Rybchenko 	if (enp->en_arch.ef10.ena_svpd_length == 0)
2525e111ed8SAndrew Rybchenko 		wantpid = B_TRUE;
2535e111ed8SAndrew Rybchenko 	else {
2545e111ed8SAndrew Rybchenko 		unsigned int offset;
2555e111ed8SAndrew Rybchenko 		uint8_t length;
2565e111ed8SAndrew Rybchenko 
2575e111ed8SAndrew Rybchenko 		rc = efx_vpd_hunk_get(enp->en_arch.ef10.ena_svpd,
2585e111ed8SAndrew Rybchenko 				    enp->en_arch.ef10.ena_svpd_length,
2595e111ed8SAndrew Rybchenko 				    EFX_VPD_ID, 0, &offset, &length);
2605e111ed8SAndrew Rybchenko 		if (rc == 0)
2615e111ed8SAndrew Rybchenko 			wantpid = B_FALSE;
2625e111ed8SAndrew Rybchenko 		else if (rc == ENOENT)
2635e111ed8SAndrew Rybchenko 			wantpid = B_TRUE;
2645e111ed8SAndrew Rybchenko 		else
2655e111ed8SAndrew Rybchenko 			goto fail1;
2665e111ed8SAndrew Rybchenko 	}
2675e111ed8SAndrew Rybchenko 
2685e111ed8SAndrew Rybchenko 	if ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0)
2695e111ed8SAndrew Rybchenko 		goto fail2;
2705e111ed8SAndrew Rybchenko 
2715e111ed8SAndrew Rybchenko 	return (0);
2725e111ed8SAndrew Rybchenko 
2735e111ed8SAndrew Rybchenko fail2:
2745e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
2755e111ed8SAndrew Rybchenko fail1:
2765e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2775e111ed8SAndrew Rybchenko 
2785e111ed8SAndrew Rybchenko 	return (rc);
2795e111ed8SAndrew Rybchenko }
2805e111ed8SAndrew Rybchenko 
2815e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_vpd_get(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size,__inout efx_vpd_value_t * evvp)2825e111ed8SAndrew Rybchenko ef10_vpd_get(
2835e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
2845e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
2855e111ed8SAndrew Rybchenko 	__in			size_t size,
2865e111ed8SAndrew Rybchenko 	__inout			efx_vpd_value_t *evvp)
2875e111ed8SAndrew Rybchenko {
2885e111ed8SAndrew Rybchenko 	unsigned int offset;
2895e111ed8SAndrew Rybchenko 	uint8_t length;
2905e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2915e111ed8SAndrew Rybchenko 
2925e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
2935e111ed8SAndrew Rybchenko 
2945e111ed8SAndrew Rybchenko 	/* Attempt to satisfy the request from svpd first */
2955e111ed8SAndrew Rybchenko 	if (enp->en_arch.ef10.ena_svpd_length > 0) {
2965e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_hunk_get(enp->en_arch.ef10.ena_svpd,
2975e111ed8SAndrew Rybchenko 		    enp->en_arch.ef10.ena_svpd_length, evvp->evv_tag,
2985e111ed8SAndrew Rybchenko 		    evvp->evv_keyword, &offset, &length)) == 0) {
2995e111ed8SAndrew Rybchenko 			evvp->evv_length = length;
3005e111ed8SAndrew Rybchenko 			memcpy(evvp->evv_value,
3015e111ed8SAndrew Rybchenko 			    enp->en_arch.ef10.ena_svpd + offset, length);
3025e111ed8SAndrew Rybchenko 			return (0);
3035e111ed8SAndrew Rybchenko 		} else if (rc != ENOENT)
3045e111ed8SAndrew Rybchenko 			goto fail1;
3055e111ed8SAndrew Rybchenko 	}
3065e111ed8SAndrew Rybchenko 
3075e111ed8SAndrew Rybchenko 	/* And then from the provided data buffer */
3085e111ed8SAndrew Rybchenko 	if ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag,
3095e111ed8SAndrew Rybchenko 	    evvp->evv_keyword, &offset, &length)) != 0) {
3105e111ed8SAndrew Rybchenko 		if (rc == ENOENT)
3115e111ed8SAndrew Rybchenko 			return (rc);
3125e111ed8SAndrew Rybchenko 		goto fail2;
3135e111ed8SAndrew Rybchenko 	}
3145e111ed8SAndrew Rybchenko 
3155e111ed8SAndrew Rybchenko 	evvp->evv_length = length;
3165e111ed8SAndrew Rybchenko 	memcpy(evvp->evv_value, data + offset, length);
3175e111ed8SAndrew Rybchenko 
3185e111ed8SAndrew Rybchenko 	return (0);
3195e111ed8SAndrew Rybchenko 
3205e111ed8SAndrew Rybchenko fail2:
3215e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
3225e111ed8SAndrew Rybchenko fail1:
3235e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3245e111ed8SAndrew Rybchenko 
3255e111ed8SAndrew Rybchenko 	return (rc);
3265e111ed8SAndrew Rybchenko }
3275e111ed8SAndrew Rybchenko 
3285e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_vpd_set(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size,__in efx_vpd_value_t * evvp)3295e111ed8SAndrew Rybchenko ef10_vpd_set(
3305e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
3315e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
3325e111ed8SAndrew Rybchenko 	__in			size_t size,
3335e111ed8SAndrew Rybchenko 	__in			efx_vpd_value_t *evvp)
3345e111ed8SAndrew Rybchenko {
3355e111ed8SAndrew Rybchenko 	efx_rc_t rc;
3365e111ed8SAndrew Rybchenko 
3375e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
3385e111ed8SAndrew Rybchenko 
3395e111ed8SAndrew Rybchenko 	/* If the provided (tag,keyword) exists in svpd, then it is readonly */
3405e111ed8SAndrew Rybchenko 	if (enp->en_arch.ef10.ena_svpd_length > 0) {
3415e111ed8SAndrew Rybchenko 		unsigned int offset;
3425e111ed8SAndrew Rybchenko 		uint8_t length;
3435e111ed8SAndrew Rybchenko 
3445e111ed8SAndrew Rybchenko 		if ((rc = efx_vpd_hunk_get(enp->en_arch.ef10.ena_svpd,
3455e111ed8SAndrew Rybchenko 		    enp->en_arch.ef10.ena_svpd_length, evvp->evv_tag,
3465e111ed8SAndrew Rybchenko 		    evvp->evv_keyword, &offset, &length)) == 0) {
3475e111ed8SAndrew Rybchenko 			rc = EACCES;
3485e111ed8SAndrew Rybchenko 			goto fail1;
3495e111ed8SAndrew Rybchenko 		}
3505e111ed8SAndrew Rybchenko 	}
3515e111ed8SAndrew Rybchenko 
3525e111ed8SAndrew Rybchenko 	if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)
3535e111ed8SAndrew Rybchenko 		goto fail2;
3545e111ed8SAndrew Rybchenko 
3555e111ed8SAndrew Rybchenko 	return (0);
3565e111ed8SAndrew Rybchenko 
3575e111ed8SAndrew Rybchenko fail2:
3585e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
3595e111ed8SAndrew Rybchenko fail1:
3605e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3615e111ed8SAndrew Rybchenko 
3625e111ed8SAndrew Rybchenko 	return (rc);
3635e111ed8SAndrew Rybchenko }
3645e111ed8SAndrew Rybchenko 
3655e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_vpd_next(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size,__out efx_vpd_value_t * evvp,__inout unsigned int * contp)3665e111ed8SAndrew Rybchenko ef10_vpd_next(
3675e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
3685e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
3695e111ed8SAndrew Rybchenko 	__in			size_t size,
3705e111ed8SAndrew Rybchenko 	__out			efx_vpd_value_t *evvp,
3715e111ed8SAndrew Rybchenko 	__inout			unsigned int *contp)
3725e111ed8SAndrew Rybchenko {
3735e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp, data, size, evvp, contp))
3745e111ed8SAndrew Rybchenko 
3755e111ed8SAndrew Rybchenko 	return (ENOTSUP);
3765e111ed8SAndrew Rybchenko }
3775e111ed8SAndrew Rybchenko 
3785e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_vpd_write(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)3795e111ed8SAndrew Rybchenko ef10_vpd_write(
3805e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
3815e111ed8SAndrew Rybchenko 	__in_bcount(size)	caddr_t data,
3825e111ed8SAndrew Rybchenko 	__in			size_t size)
3835e111ed8SAndrew Rybchenko {
3845e111ed8SAndrew Rybchenko 	size_t vpd_length;
3855e111ed8SAndrew Rybchenko 	uint32_t pci_pf;
3865e111ed8SAndrew Rybchenko 	uint32_t tag;
3875e111ed8SAndrew Rybchenko 	efx_rc_t rc;
3885e111ed8SAndrew Rybchenko 
3895e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
3905e111ed8SAndrew Rybchenko 
3915e111ed8SAndrew Rybchenko 	if (enp->en_nic_cfg.enc_vpd_is_global) {
3925e111ed8SAndrew Rybchenko 		tag = TLV_TAG_GLOBAL_DYNAMIC_VPD;
3935e111ed8SAndrew Rybchenko 	} else {
3945e111ed8SAndrew Rybchenko 		pci_pf = enp->en_nic_cfg.enc_pf;
3955e111ed8SAndrew Rybchenko 		tag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf);
3965e111ed8SAndrew Rybchenko 	}
3975e111ed8SAndrew Rybchenko 
3985e111ed8SAndrew Rybchenko 	/* Determine total length of new dynamic VPD */
3995e111ed8SAndrew Rybchenko 	if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)
4005e111ed8SAndrew Rybchenko 		goto fail1;
4015e111ed8SAndrew Rybchenko 
4025e111ed8SAndrew Rybchenko 	/* Store new dynamic VPD in all segments in DYNAMIC_CONFIG partition */
4035e111ed8SAndrew Rybchenko 	if ((rc = ef10_nvram_partn_write_segment_tlv(enp,
4045e111ed8SAndrew Rybchenko 		    NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,
4055e111ed8SAndrew Rybchenko 		    tag, data, vpd_length, B_TRUE)) != 0) {
4065e111ed8SAndrew Rybchenko 		goto fail2;
4075e111ed8SAndrew Rybchenko 	}
4085e111ed8SAndrew Rybchenko 
4095e111ed8SAndrew Rybchenko 	return (0);
4105e111ed8SAndrew Rybchenko 
4115e111ed8SAndrew Rybchenko fail2:
4125e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
4135e111ed8SAndrew Rybchenko 
4145e111ed8SAndrew Rybchenko fail1:
4155e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4165e111ed8SAndrew Rybchenko 
4175e111ed8SAndrew Rybchenko 	return (rc);
4185e111ed8SAndrew Rybchenko }
4195e111ed8SAndrew Rybchenko 
4205e111ed8SAndrew Rybchenko 				void
ef10_vpd_fini(__in efx_nic_t * enp)4215e111ed8SAndrew Rybchenko ef10_vpd_fini(
4225e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp)
4235e111ed8SAndrew Rybchenko {
4245e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
4255e111ed8SAndrew Rybchenko 
4265e111ed8SAndrew Rybchenko 	if (enp->en_arch.ef10.ena_svpd_length > 0) {
4275e111ed8SAndrew Rybchenko 		EFSYS_KMEM_FREE(enp->en_esip, enp->en_arch.ef10.ena_svpd_length,
4285e111ed8SAndrew Rybchenko 				enp->en_arch.ef10.ena_svpd);
4295e111ed8SAndrew Rybchenko 
4305e111ed8SAndrew Rybchenko 		enp->en_arch.ef10.ena_svpd = NULL;
4315e111ed8SAndrew Rybchenko 		enp->en_arch.ef10.ena_svpd_length = 0;
4325e111ed8SAndrew Rybchenko 	}
4335e111ed8SAndrew Rybchenko }
4345e111ed8SAndrew Rybchenko 
4355e111ed8SAndrew Rybchenko #endif	/* EFX_OPTS_EF10() */
4365e111ed8SAndrew Rybchenko 
4375e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_VPD */
438