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