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