1*49ef7e06SGarrett D'Amore /*
2*49ef7e06SGarrett D'Amore * Copyright (c) 2009-2015 Solarflare Communications Inc.
3*49ef7e06SGarrett D'Amore * All rights reserved.
4*49ef7e06SGarrett D'Amore *
5*49ef7e06SGarrett D'Amore * Redistribution and use in source and binary forms, with or without
6*49ef7e06SGarrett D'Amore * modification, are permitted provided that the following conditions are met:
7*49ef7e06SGarrett D'Amore *
8*49ef7e06SGarrett D'Amore * 1. Redistributions of source code must retain the above copyright notice,
9*49ef7e06SGarrett D'Amore * this list of conditions and the following disclaimer.
10*49ef7e06SGarrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright notice,
11*49ef7e06SGarrett D'Amore * this list of conditions and the following disclaimer in the documentation
12*49ef7e06SGarrett D'Amore * and/or other materials provided with the distribution.
13*49ef7e06SGarrett D'Amore *
14*49ef7e06SGarrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15*49ef7e06SGarrett D'Amore * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*49ef7e06SGarrett D'Amore * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17*49ef7e06SGarrett D'Amore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18*49ef7e06SGarrett D'Amore * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*49ef7e06SGarrett D'Amore * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*49ef7e06SGarrett D'Amore * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*49ef7e06SGarrett D'Amore * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*49ef7e06SGarrett D'Amore * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*49ef7e06SGarrett D'Amore * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24*49ef7e06SGarrett D'Amore * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*49ef7e06SGarrett D'Amore *
26*49ef7e06SGarrett D'Amore * The views and conclusions contained in the software and documentation are
27*49ef7e06SGarrett D'Amore * those of the authors and should not be interpreted as representing official
28*49ef7e06SGarrett D'Amore * policies, either expressed or implied, of the FreeBSD Project.
29*49ef7e06SGarrett D'Amore */
30*49ef7e06SGarrett D'Amore
31*49ef7e06SGarrett D'Amore #include "efx.h"
32*49ef7e06SGarrett D'Amore #include "efx_impl.h"
33*49ef7e06SGarrett D'Amore
34*49ef7e06SGarrett D'Amore
35*49ef7e06SGarrett D'Amore #if EFSYS_OPT_VPD
36*49ef7e06SGarrett D'Amore
37*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
38*49ef7e06SGarrett D'Amore
39*49ef7e06SGarrett D'Amore #include "ef10_tlv_layout.h"
40*49ef7e06SGarrett D'Amore
41*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_vpd_init(__in efx_nic_t * enp)42*49ef7e06SGarrett D'Amore ef10_vpd_init(
43*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
44*49ef7e06SGarrett D'Amore {
45*49ef7e06SGarrett D'Amore caddr_t svpd;
46*49ef7e06SGarrett D'Amore size_t svpd_size;
47*49ef7e06SGarrett D'Amore uint32_t pci_pf;
48*49ef7e06SGarrett D'Amore uint32_t tag;
49*49ef7e06SGarrett D'Amore efx_rc_t rc;
50*49ef7e06SGarrett D'Amore
51*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
52*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
53*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
54*49ef7e06SGarrett D'Amore
55*49ef7e06SGarrett D'Amore if (enp->en_nic_cfg.enc_vpd_is_global) {
56*49ef7e06SGarrett D'Amore tag = TLV_TAG_GLOBAL_STATIC_VPD;
57*49ef7e06SGarrett D'Amore } else {
58*49ef7e06SGarrett D'Amore pci_pf = enp->en_nic_cfg.enc_pf;
59*49ef7e06SGarrett D'Amore tag = TLV_TAG_PF_STATIC_VPD(pci_pf);
60*49ef7e06SGarrett D'Amore }
61*49ef7e06SGarrett D'Amore
62*49ef7e06SGarrett D'Amore /*
63*49ef7e06SGarrett D'Amore * The VPD interface exposes VPD resources from the combined static and
64*49ef7e06SGarrett D'Amore * dynamic VPD storage. As the static VPD configuration should *never*
65*49ef7e06SGarrett D'Amore * change, we can cache it.
66*49ef7e06SGarrett D'Amore */
67*49ef7e06SGarrett D'Amore svpd = NULL;
68*49ef7e06SGarrett D'Amore svpd_size = 0;
69*49ef7e06SGarrett D'Amore rc = ef10_nvram_partn_read_tlv(enp,
70*49ef7e06SGarrett D'Amore NVRAM_PARTITION_TYPE_STATIC_CONFIG,
71*49ef7e06SGarrett D'Amore tag, &svpd, &svpd_size);
72*49ef7e06SGarrett D'Amore if (rc != 0) {
73*49ef7e06SGarrett D'Amore if (rc == EACCES) {
74*49ef7e06SGarrett D'Amore /* Unprivileged functions cannot access VPD */
75*49ef7e06SGarrett D'Amore goto out;
76*49ef7e06SGarrett D'Amore }
77*49ef7e06SGarrett D'Amore goto fail1;
78*49ef7e06SGarrett D'Amore }
79*49ef7e06SGarrett D'Amore
80*49ef7e06SGarrett D'Amore if (svpd != NULL && svpd_size > 0) {
81*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_verify(svpd, svpd_size, NULL)) != 0)
82*49ef7e06SGarrett D'Amore goto fail2;
83*49ef7e06SGarrett D'Amore }
84*49ef7e06SGarrett D'Amore
85*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd = svpd;
86*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd_length = svpd_size;
87*49ef7e06SGarrett D'Amore
88*49ef7e06SGarrett D'Amore out:
89*49ef7e06SGarrett D'Amore return (0);
90*49ef7e06SGarrett D'Amore
91*49ef7e06SGarrett D'Amore fail2:
92*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
93*49ef7e06SGarrett D'Amore
94*49ef7e06SGarrett D'Amore EFSYS_KMEM_FREE(enp->en_esip, svpd_size, svpd);
95*49ef7e06SGarrett D'Amore fail1:
96*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
97*49ef7e06SGarrett D'Amore
98*49ef7e06SGarrett D'Amore return (rc);
99*49ef7e06SGarrett D'Amore }
100*49ef7e06SGarrett D'Amore
101*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_vpd_size(__in efx_nic_t * enp,__out size_t * sizep)102*49ef7e06SGarrett D'Amore ef10_vpd_size(
103*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
104*49ef7e06SGarrett D'Amore __out size_t *sizep)
105*49ef7e06SGarrett D'Amore {
106*49ef7e06SGarrett D'Amore efx_rc_t rc;
107*49ef7e06SGarrett D'Amore
108*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
109*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
110*49ef7e06SGarrett D'Amore
111*49ef7e06SGarrett D'Amore /*
112*49ef7e06SGarrett D'Amore * This function returns the total size the user should allocate
113*49ef7e06SGarrett D'Amore * for all VPD operations. We've already cached the static vpd,
114*49ef7e06SGarrett D'Amore * so we just need to return an upper bound on the dynamic vpd,
115*49ef7e06SGarrett D'Amore * which is the size of the DYNAMIC_CONFIG partition.
116*49ef7e06SGarrett D'Amore */
117*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_nvram_info(enp, NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,
118*49ef7e06SGarrett D'Amore sizep, NULL, NULL, NULL)) != 0)
119*49ef7e06SGarrett D'Amore goto fail1;
120*49ef7e06SGarrett D'Amore
121*49ef7e06SGarrett D'Amore return (0);
122*49ef7e06SGarrett D'Amore
123*49ef7e06SGarrett D'Amore fail1:
124*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
125*49ef7e06SGarrett D'Amore
126*49ef7e06SGarrett D'Amore return (rc);
127*49ef7e06SGarrett D'Amore }
128*49ef7e06SGarrett D'Amore
129*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_vpd_read(__in efx_nic_t * enp,__out_bcount (size)caddr_t data,__in size_t size)130*49ef7e06SGarrett D'Amore ef10_vpd_read(
131*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
132*49ef7e06SGarrett D'Amore __out_bcount(size) caddr_t data,
133*49ef7e06SGarrett D'Amore __in size_t size)
134*49ef7e06SGarrett D'Amore {
135*49ef7e06SGarrett D'Amore caddr_t dvpd;
136*49ef7e06SGarrett D'Amore size_t dvpd_size;
137*49ef7e06SGarrett D'Amore uint32_t pci_pf;
138*49ef7e06SGarrett D'Amore uint32_t tag;
139*49ef7e06SGarrett D'Amore efx_rc_t rc;
140*49ef7e06SGarrett D'Amore
141*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
142*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
143*49ef7e06SGarrett D'Amore
144*49ef7e06SGarrett D'Amore if (enp->en_nic_cfg.enc_vpd_is_global) {
145*49ef7e06SGarrett D'Amore tag = TLV_TAG_GLOBAL_DYNAMIC_VPD;
146*49ef7e06SGarrett D'Amore } else {
147*49ef7e06SGarrett D'Amore pci_pf = enp->en_nic_cfg.enc_pf;
148*49ef7e06SGarrett D'Amore tag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf);
149*49ef7e06SGarrett D'Amore }
150*49ef7e06SGarrett D'Amore
151*49ef7e06SGarrett D'Amore if ((rc = ef10_nvram_partn_read_tlv(enp,
152*49ef7e06SGarrett D'Amore NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,
153*49ef7e06SGarrett D'Amore tag, &dvpd, &dvpd_size)) != 0)
154*49ef7e06SGarrett D'Amore goto fail1;
155*49ef7e06SGarrett D'Amore
156*49ef7e06SGarrett D'Amore if (dvpd_size > size) {
157*49ef7e06SGarrett D'Amore rc = ENOSPC;
158*49ef7e06SGarrett D'Amore goto fail2;
159*49ef7e06SGarrett D'Amore }
160*49ef7e06SGarrett D'Amore (void) memcpy(data, dvpd, dvpd_size);
161*49ef7e06SGarrett D'Amore
162*49ef7e06SGarrett D'Amore /* Pad data with all-1s, consistent with update operations */
163*49ef7e06SGarrett D'Amore (void) memset(data + dvpd_size, 0xff, size - dvpd_size);
164*49ef7e06SGarrett D'Amore
165*49ef7e06SGarrett D'Amore EFSYS_KMEM_FREE(enp->en_esip, dvpd_size, dvpd);
166*49ef7e06SGarrett D'Amore
167*49ef7e06SGarrett D'Amore return (0);
168*49ef7e06SGarrett D'Amore
169*49ef7e06SGarrett D'Amore fail2:
170*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
171*49ef7e06SGarrett D'Amore
172*49ef7e06SGarrett D'Amore EFSYS_KMEM_FREE(enp->en_esip, dvpd_size, dvpd);
173*49ef7e06SGarrett D'Amore fail1:
174*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
175*49ef7e06SGarrett D'Amore
176*49ef7e06SGarrett D'Amore return (rc);
177*49ef7e06SGarrett D'Amore }
178*49ef7e06SGarrett D'Amore
179*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_vpd_verify(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)180*49ef7e06SGarrett D'Amore ef10_vpd_verify(
181*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
182*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
183*49ef7e06SGarrett D'Amore __in size_t size)
184*49ef7e06SGarrett D'Amore {
185*49ef7e06SGarrett D'Amore efx_vpd_tag_t stag;
186*49ef7e06SGarrett D'Amore efx_vpd_tag_t dtag;
187*49ef7e06SGarrett D'Amore efx_vpd_keyword_t skey;
188*49ef7e06SGarrett D'Amore efx_vpd_keyword_t dkey;
189*49ef7e06SGarrett D'Amore unsigned int scont;
190*49ef7e06SGarrett D'Amore unsigned int dcont;
191*49ef7e06SGarrett D'Amore efx_rc_t rc;
192*49ef7e06SGarrett D'Amore
193*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
194*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
195*49ef7e06SGarrett D'Amore
196*49ef7e06SGarrett D'Amore /*
197*49ef7e06SGarrett D'Amore * Strictly you could take the view that dynamic vpd is optional.
198*49ef7e06SGarrett D'Amore * Instead, to conform more closely to the read/verify/reinit()
199*49ef7e06SGarrett D'Amore * paradigm, we require dynamic vpd. ef10_vpd_reinit() will
200*49ef7e06SGarrett D'Amore * reinitialize it as required.
201*49ef7e06SGarrett D'Amore */
202*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0)
203*49ef7e06SGarrett D'Amore goto fail1;
204*49ef7e06SGarrett D'Amore
205*49ef7e06SGarrett D'Amore /*
206*49ef7e06SGarrett D'Amore * Verify that there is no duplication between the static and
207*49ef7e06SGarrett D'Amore * dynamic cfg sectors.
208*49ef7e06SGarrett D'Amore */
209*49ef7e06SGarrett D'Amore if (enp->en_arch.ef10.ena_svpd_length == 0)
210*49ef7e06SGarrett D'Amore goto done;
211*49ef7e06SGarrett D'Amore
212*49ef7e06SGarrett D'Amore dcont = 0;
213*49ef7e06SGarrett D'Amore _NOTE(CONSTANTCONDITION)
214*49ef7e06SGarrett D'Amore while (1) {
215*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_next(data, size, &dtag,
216*49ef7e06SGarrett D'Amore &dkey, NULL, NULL, &dcont)) != 0)
217*49ef7e06SGarrett D'Amore goto fail2;
218*49ef7e06SGarrett D'Amore if (dcont == 0)
219*49ef7e06SGarrett D'Amore break;
220*49ef7e06SGarrett D'Amore
221*49ef7e06SGarrett D'Amore /*
222*49ef7e06SGarrett D'Amore * Skip the RV keyword. It should be present in both the static
223*49ef7e06SGarrett D'Amore * and dynamic cfg sectors.
224*49ef7e06SGarrett D'Amore */
225*49ef7e06SGarrett D'Amore if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))
226*49ef7e06SGarrett D'Amore continue;
227*49ef7e06SGarrett D'Amore
228*49ef7e06SGarrett D'Amore scont = 0;
229*49ef7e06SGarrett D'Amore _NOTE(CONSTANTCONDITION)
230*49ef7e06SGarrett D'Amore while (1) {
231*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_next(
232*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd,
233*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd_length, &stag, &skey,
234*49ef7e06SGarrett D'Amore NULL, NULL, &scont)) != 0)
235*49ef7e06SGarrett D'Amore goto fail3;
236*49ef7e06SGarrett D'Amore if (scont == 0)
237*49ef7e06SGarrett D'Amore break;
238*49ef7e06SGarrett D'Amore
239*49ef7e06SGarrett D'Amore if (stag == dtag && skey == dkey) {
240*49ef7e06SGarrett D'Amore rc = EEXIST;
241*49ef7e06SGarrett D'Amore goto fail4;
242*49ef7e06SGarrett D'Amore }
243*49ef7e06SGarrett D'Amore }
244*49ef7e06SGarrett D'Amore }
245*49ef7e06SGarrett D'Amore
246*49ef7e06SGarrett D'Amore done:
247*49ef7e06SGarrett D'Amore return (0);
248*49ef7e06SGarrett D'Amore
249*49ef7e06SGarrett D'Amore fail4:
250*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail4);
251*49ef7e06SGarrett D'Amore fail3:
252*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
253*49ef7e06SGarrett D'Amore fail2:
254*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
255*49ef7e06SGarrett D'Amore fail1:
256*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
257*49ef7e06SGarrett D'Amore
258*49ef7e06SGarrett D'Amore return (rc);
259*49ef7e06SGarrett D'Amore }
260*49ef7e06SGarrett D'Amore
261*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_vpd_reinit(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)262*49ef7e06SGarrett D'Amore ef10_vpd_reinit(
263*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
264*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
265*49ef7e06SGarrett D'Amore __in size_t size)
266*49ef7e06SGarrett D'Amore {
267*49ef7e06SGarrett D'Amore boolean_t wantpid;
268*49ef7e06SGarrett D'Amore efx_rc_t rc;
269*49ef7e06SGarrett D'Amore
270*49ef7e06SGarrett D'Amore /*
271*49ef7e06SGarrett D'Amore * Only create an ID string if the dynamic cfg doesn't have one
272*49ef7e06SGarrett D'Amore */
273*49ef7e06SGarrett D'Amore if (enp->en_arch.ef10.ena_svpd_length == 0)
274*49ef7e06SGarrett D'Amore wantpid = B_TRUE;
275*49ef7e06SGarrett D'Amore else {
276*49ef7e06SGarrett D'Amore unsigned int offset;
277*49ef7e06SGarrett D'Amore uint8_t length;
278*49ef7e06SGarrett D'Amore
279*49ef7e06SGarrett D'Amore rc = efx_vpd_hunk_get(enp->en_arch.ef10.ena_svpd,
280*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd_length,
281*49ef7e06SGarrett D'Amore EFX_VPD_ID, 0, &offset, &length);
282*49ef7e06SGarrett D'Amore if (rc == 0)
283*49ef7e06SGarrett D'Amore wantpid = B_FALSE;
284*49ef7e06SGarrett D'Amore else if (rc == ENOENT)
285*49ef7e06SGarrett D'Amore wantpid = B_TRUE;
286*49ef7e06SGarrett D'Amore else
287*49ef7e06SGarrett D'Amore goto fail1;
288*49ef7e06SGarrett D'Amore }
289*49ef7e06SGarrett D'Amore
290*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0)
291*49ef7e06SGarrett D'Amore goto fail2;
292*49ef7e06SGarrett D'Amore
293*49ef7e06SGarrett D'Amore return (0);
294*49ef7e06SGarrett D'Amore
295*49ef7e06SGarrett D'Amore fail2:
296*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
297*49ef7e06SGarrett D'Amore fail1:
298*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
299*49ef7e06SGarrett D'Amore
300*49ef7e06SGarrett D'Amore return (rc);
301*49ef7e06SGarrett D'Amore }
302*49ef7e06SGarrett D'Amore
303*49ef7e06SGarrett D'Amore __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)304*49ef7e06SGarrett D'Amore ef10_vpd_get(
305*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
306*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
307*49ef7e06SGarrett D'Amore __in size_t size,
308*49ef7e06SGarrett D'Amore __inout efx_vpd_value_t *evvp)
309*49ef7e06SGarrett D'Amore {
310*49ef7e06SGarrett D'Amore unsigned int offset;
311*49ef7e06SGarrett D'Amore uint8_t length;
312*49ef7e06SGarrett D'Amore efx_rc_t rc;
313*49ef7e06SGarrett D'Amore
314*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
315*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
316*49ef7e06SGarrett D'Amore
317*49ef7e06SGarrett D'Amore /* Attempt to satisfy the request from svpd first */
318*49ef7e06SGarrett D'Amore if (enp->en_arch.ef10.ena_svpd_length > 0) {
319*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_get(enp->en_arch.ef10.ena_svpd,
320*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd_length, evvp->evv_tag,
321*49ef7e06SGarrett D'Amore evvp->evv_keyword, &offset, &length)) == 0) {
322*49ef7e06SGarrett D'Amore evvp->evv_length = length;
323*49ef7e06SGarrett D'Amore (void) memcpy(evvp->evv_value,
324*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd + offset, length);
325*49ef7e06SGarrett D'Amore return (0);
326*49ef7e06SGarrett D'Amore } else if (rc != ENOENT)
327*49ef7e06SGarrett D'Amore goto fail1;
328*49ef7e06SGarrett D'Amore }
329*49ef7e06SGarrett D'Amore
330*49ef7e06SGarrett D'Amore /* And then from the provided data buffer */
331*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag,
332*49ef7e06SGarrett D'Amore evvp->evv_keyword, &offset, &length)) != 0)
333*49ef7e06SGarrett D'Amore goto fail2;
334*49ef7e06SGarrett D'Amore
335*49ef7e06SGarrett D'Amore evvp->evv_length = length;
336*49ef7e06SGarrett D'Amore (void) memcpy(evvp->evv_value, data + offset, length);
337*49ef7e06SGarrett D'Amore
338*49ef7e06SGarrett D'Amore return (0);
339*49ef7e06SGarrett D'Amore
340*49ef7e06SGarrett D'Amore fail2:
341*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
342*49ef7e06SGarrett D'Amore fail1:
343*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
344*49ef7e06SGarrett D'Amore
345*49ef7e06SGarrett D'Amore return (rc);
346*49ef7e06SGarrett D'Amore }
347*49ef7e06SGarrett D'Amore
348*49ef7e06SGarrett D'Amore __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)349*49ef7e06SGarrett D'Amore ef10_vpd_set(
350*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
351*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
352*49ef7e06SGarrett D'Amore __in size_t size,
353*49ef7e06SGarrett D'Amore __in efx_vpd_value_t *evvp)
354*49ef7e06SGarrett D'Amore {
355*49ef7e06SGarrett D'Amore efx_rc_t rc;
356*49ef7e06SGarrett D'Amore
357*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
358*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
359*49ef7e06SGarrett D'Amore
360*49ef7e06SGarrett D'Amore /* If the provided (tag,keyword) exists in svpd, then it is readonly */
361*49ef7e06SGarrett D'Amore if (enp->en_arch.ef10.ena_svpd_length > 0) {
362*49ef7e06SGarrett D'Amore unsigned int offset;
363*49ef7e06SGarrett D'Amore uint8_t length;
364*49ef7e06SGarrett D'Amore
365*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_get(enp->en_arch.ef10.ena_svpd,
366*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd_length, evvp->evv_tag,
367*49ef7e06SGarrett D'Amore evvp->evv_keyword, &offset, &length)) == 0) {
368*49ef7e06SGarrett D'Amore rc = EACCES;
369*49ef7e06SGarrett D'Amore goto fail1;
370*49ef7e06SGarrett D'Amore }
371*49ef7e06SGarrett D'Amore }
372*49ef7e06SGarrett D'Amore
373*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)
374*49ef7e06SGarrett D'Amore goto fail2;
375*49ef7e06SGarrett D'Amore
376*49ef7e06SGarrett D'Amore return (0);
377*49ef7e06SGarrett D'Amore
378*49ef7e06SGarrett D'Amore fail2:
379*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
380*49ef7e06SGarrett D'Amore fail1:
381*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
382*49ef7e06SGarrett D'Amore
383*49ef7e06SGarrett D'Amore return (rc);
384*49ef7e06SGarrett D'Amore }
385*49ef7e06SGarrett D'Amore
386*49ef7e06SGarrett D'Amore __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)387*49ef7e06SGarrett D'Amore ef10_vpd_next(
388*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
389*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
390*49ef7e06SGarrett D'Amore __in size_t size,
391*49ef7e06SGarrett D'Amore __out efx_vpd_value_t *evvp,
392*49ef7e06SGarrett D'Amore __inout unsigned int *contp)
393*49ef7e06SGarrett D'Amore {
394*49ef7e06SGarrett D'Amore _NOTE(ARGUNUSED(enp, data, size, evvp, contp))
395*49ef7e06SGarrett D'Amore
396*49ef7e06SGarrett D'Amore return (ENOTSUP);
397*49ef7e06SGarrett D'Amore }
398*49ef7e06SGarrett D'Amore
399*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_vpd_write(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)400*49ef7e06SGarrett D'Amore ef10_vpd_write(
401*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
402*49ef7e06SGarrett D'Amore __in_bcount(size) caddr_t data,
403*49ef7e06SGarrett D'Amore __in size_t size)
404*49ef7e06SGarrett D'Amore {
405*49ef7e06SGarrett D'Amore size_t vpd_length;
406*49ef7e06SGarrett D'Amore uint32_t pci_pf;
407*49ef7e06SGarrett D'Amore uint32_t tag;
408*49ef7e06SGarrett D'Amore efx_rc_t rc;
409*49ef7e06SGarrett D'Amore
410*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
411*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
412*49ef7e06SGarrett D'Amore
413*49ef7e06SGarrett D'Amore if (enp->en_nic_cfg.enc_vpd_is_global) {
414*49ef7e06SGarrett D'Amore tag = TLV_TAG_GLOBAL_DYNAMIC_VPD;
415*49ef7e06SGarrett D'Amore } else {
416*49ef7e06SGarrett D'Amore pci_pf = enp->en_nic_cfg.enc_pf;
417*49ef7e06SGarrett D'Amore tag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf);
418*49ef7e06SGarrett D'Amore }
419*49ef7e06SGarrett D'Amore
420*49ef7e06SGarrett D'Amore /* Determine total length of new dynamic VPD */
421*49ef7e06SGarrett D'Amore if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)
422*49ef7e06SGarrett D'Amore goto fail1;
423*49ef7e06SGarrett D'Amore
424*49ef7e06SGarrett D'Amore /* Store new dynamic VPD in all segments in DYNAMIC_CONFIG partition */
425*49ef7e06SGarrett D'Amore if ((rc = ef10_nvram_partn_write_segment_tlv(enp,
426*49ef7e06SGarrett D'Amore NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,
427*49ef7e06SGarrett D'Amore tag, data, vpd_length, B_TRUE)) != 0) {
428*49ef7e06SGarrett D'Amore goto fail2;
429*49ef7e06SGarrett D'Amore }
430*49ef7e06SGarrett D'Amore
431*49ef7e06SGarrett D'Amore return (0);
432*49ef7e06SGarrett D'Amore
433*49ef7e06SGarrett D'Amore fail2:
434*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
435*49ef7e06SGarrett D'Amore
436*49ef7e06SGarrett D'Amore fail1:
437*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
438*49ef7e06SGarrett D'Amore
439*49ef7e06SGarrett D'Amore return (rc);
440*49ef7e06SGarrett D'Amore }
441*49ef7e06SGarrett D'Amore
442*49ef7e06SGarrett D'Amore void
ef10_vpd_fini(__in efx_nic_t * enp)443*49ef7e06SGarrett D'Amore ef10_vpd_fini(
444*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
445*49ef7e06SGarrett D'Amore {
446*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
447*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
448*49ef7e06SGarrett D'Amore
449*49ef7e06SGarrett D'Amore if (enp->en_arch.ef10.ena_svpd_length > 0) {
450*49ef7e06SGarrett D'Amore EFSYS_KMEM_FREE(enp->en_esip, enp->en_arch.ef10.ena_svpd_length,
451*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd);
452*49ef7e06SGarrett D'Amore
453*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd = NULL;
454*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_svpd_length = 0;
455*49ef7e06SGarrett D'Amore }
456*49ef7e06SGarrett D'Amore }
457*49ef7e06SGarrett D'Amore
458*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
459*49ef7e06SGarrett D'Amore
460*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_VPD */
461