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 #if EFSYS_OPT_VPD
35*49ef7e06SGarrett D'Amore 
36*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
37*49ef7e06SGarrett D'Amore 
38*49ef7e06SGarrett D'Amore static	__checkReturn			efx_rc_t
siena_vpd_get_static(__in efx_nic_t * enp,__in uint32_t partn,__deref_out_bcount_opt (* sizep)caddr_t * svpdp,__out size_t * sizep)39*49ef7e06SGarrett D'Amore siena_vpd_get_static(
40*49ef7e06SGarrett D'Amore 	__in				efx_nic_t *enp,
41*49ef7e06SGarrett D'Amore 	__in				uint32_t partn,
42*49ef7e06SGarrett D'Amore 	__deref_out_bcount_opt(*sizep)	caddr_t *svpdp,
43*49ef7e06SGarrett D'Amore 	__out				size_t *sizep)
44*49ef7e06SGarrett D'Amore {
45*49ef7e06SGarrett D'Amore 	siena_mc_static_config_hdr_t *scfg;
46*49ef7e06SGarrett D'Amore 	caddr_t svpd;
47*49ef7e06SGarrett D'Amore 	size_t size;
48*49ef7e06SGarrett D'Amore 	uint8_t cksum;
49*49ef7e06SGarrett D'Amore 	unsigned int vpd_offset;
50*49ef7e06SGarrett D'Amore 	unsigned int vpd_length;
51*49ef7e06SGarrett D'Amore 	unsigned int hdr_length;
52*49ef7e06SGarrett D'Amore 	unsigned int pos;
53*49ef7e06SGarrett D'Amore 	unsigned int region;
54*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
55*49ef7e06SGarrett D'Amore 
56*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 ||
57*49ef7e06SGarrett D'Amore 		    partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1);
58*49ef7e06SGarrett D'Amore 
59*49ef7e06SGarrett D'Amore 	/* Allocate sufficient memory for the entire static cfg area */
60*49ef7e06SGarrett D'Amore 	if ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0)
61*49ef7e06SGarrett D'Amore 		goto fail1;
62*49ef7e06SGarrett D'Amore 
63*49ef7e06SGarrett D'Amore 	EFSYS_KMEM_ALLOC(enp->en_esip, size, scfg);
64*49ef7e06SGarrett D'Amore 	if (scfg == NULL) {
65*49ef7e06SGarrett D'Amore 		rc = ENOMEM;
66*49ef7e06SGarrett D'Amore 		goto fail2;
67*49ef7e06SGarrett D'Amore 	}
68*49ef7e06SGarrett D'Amore 
69*49ef7e06SGarrett D'Amore 	if ((rc = siena_nvram_partn_read(enp, partn, 0,
70*49ef7e06SGarrett D'Amore 	    (caddr_t)scfg, SIENA_NVRAM_CHUNK)) != 0)
71*49ef7e06SGarrett D'Amore 		goto fail3;
72*49ef7e06SGarrett D'Amore 
73*49ef7e06SGarrett D'Amore 	/* Verify the magic number */
74*49ef7e06SGarrett D'Amore 	if (EFX_DWORD_FIELD(scfg->magic, EFX_DWORD_0) !=
75*49ef7e06SGarrett D'Amore 	    SIENA_MC_STATIC_CONFIG_MAGIC) {
76*49ef7e06SGarrett D'Amore 		rc = EINVAL;
77*49ef7e06SGarrett D'Amore 		goto fail4;
78*49ef7e06SGarrett D'Amore 	}
79*49ef7e06SGarrett D'Amore 
80*49ef7e06SGarrett D'Amore 	/* All future versions of the structure must be backwards compatable */
81*49ef7e06SGarrett D'Amore 	EFX_STATIC_ASSERT(SIENA_MC_STATIC_CONFIG_VERSION == 0);
82*49ef7e06SGarrett D'Amore 
83*49ef7e06SGarrett D'Amore 	hdr_length = EFX_WORD_FIELD(scfg->length, EFX_WORD_0);
84*49ef7e06SGarrett D'Amore 	vpd_offset = EFX_DWORD_FIELD(scfg->static_vpd_offset, EFX_DWORD_0);
85*49ef7e06SGarrett D'Amore 	vpd_length = EFX_DWORD_FIELD(scfg->static_vpd_length, EFX_DWORD_0);
86*49ef7e06SGarrett D'Amore 
87*49ef7e06SGarrett D'Amore 	/* Verify the hdr doesn't overflow the sector size */
88*49ef7e06SGarrett D'Amore 	if (hdr_length > size || vpd_offset > size || vpd_length > size ||
89*49ef7e06SGarrett D'Amore 	    vpd_length + vpd_offset > size) {
90*49ef7e06SGarrett D'Amore 		rc = EINVAL;
91*49ef7e06SGarrett D'Amore 		goto fail5;
92*49ef7e06SGarrett D'Amore 	}
93*49ef7e06SGarrett D'Amore 
94*49ef7e06SGarrett D'Amore 	/* Read the remainder of scfg + static vpd */
95*49ef7e06SGarrett D'Amore 	region = vpd_offset + vpd_length;
96*49ef7e06SGarrett D'Amore 	if (region > SIENA_NVRAM_CHUNK) {
97*49ef7e06SGarrett D'Amore 		if ((rc = siena_nvram_partn_read(enp, partn, SIENA_NVRAM_CHUNK,
98*49ef7e06SGarrett D'Amore 		    (caddr_t)scfg + SIENA_NVRAM_CHUNK,
99*49ef7e06SGarrett D'Amore 		    region - SIENA_NVRAM_CHUNK)) != 0)
100*49ef7e06SGarrett D'Amore 			goto fail6;
101*49ef7e06SGarrett D'Amore 	}
102*49ef7e06SGarrett D'Amore 
103*49ef7e06SGarrett D'Amore 	/* Verify checksum */
104*49ef7e06SGarrett D'Amore 	cksum = 0;
105*49ef7e06SGarrett D'Amore 	for (pos = 0; pos < hdr_length; pos++)
106*49ef7e06SGarrett D'Amore 		cksum += ((uint8_t *)scfg)[pos];
107*49ef7e06SGarrett D'Amore 	if (cksum != 0) {
108*49ef7e06SGarrett D'Amore 		rc = EINVAL;
109*49ef7e06SGarrett D'Amore 		goto fail7;
110*49ef7e06SGarrett D'Amore 	}
111*49ef7e06SGarrett D'Amore 
112*49ef7e06SGarrett D'Amore 	if (vpd_length == 0)
113*49ef7e06SGarrett D'Amore 		svpd = NULL;
114*49ef7e06SGarrett D'Amore 	else {
115*49ef7e06SGarrett D'Amore 		/* Copy the vpd data out */
116*49ef7e06SGarrett D'Amore 		EFSYS_KMEM_ALLOC(enp->en_esip, vpd_length, svpd);
117*49ef7e06SGarrett D'Amore 		if (svpd == NULL) {
118*49ef7e06SGarrett D'Amore 			rc = ENOMEM;
119*49ef7e06SGarrett D'Amore 			goto fail8;
120*49ef7e06SGarrett D'Amore 		}
121*49ef7e06SGarrett D'Amore 		(void) memcpy(svpd, (caddr_t)scfg + vpd_offset, vpd_length);
122*49ef7e06SGarrett D'Amore 	}
123*49ef7e06SGarrett D'Amore 
124*49ef7e06SGarrett D'Amore 	EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
125*49ef7e06SGarrett D'Amore 
126*49ef7e06SGarrett D'Amore 	*svpdp = svpd;
127*49ef7e06SGarrett D'Amore 	*sizep = vpd_length;
128*49ef7e06SGarrett D'Amore 
129*49ef7e06SGarrett D'Amore 	return (0);
130*49ef7e06SGarrett D'Amore 
131*49ef7e06SGarrett D'Amore fail8:
132*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail8);
133*49ef7e06SGarrett D'Amore fail7:
134*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail7);
135*49ef7e06SGarrett D'Amore fail6:
136*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail6);
137*49ef7e06SGarrett D'Amore fail5:
138*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail5);
139*49ef7e06SGarrett D'Amore fail4:
140*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail4);
141*49ef7e06SGarrett D'Amore fail3:
142*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
143*49ef7e06SGarrett D'Amore 
144*49ef7e06SGarrett D'Amore 	EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
145*49ef7e06SGarrett D'Amore 
146*49ef7e06SGarrett D'Amore fail2:
147*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
148*49ef7e06SGarrett D'Amore fail1:
149*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
150*49ef7e06SGarrett D'Amore 
151*49ef7e06SGarrett D'Amore 	return (rc);
152*49ef7e06SGarrett D'Amore }
153*49ef7e06SGarrett D'Amore 
154*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
siena_vpd_init(__in efx_nic_t * enp)155*49ef7e06SGarrett D'Amore siena_vpd_init(
156*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp)
157*49ef7e06SGarrett D'Amore {
158*49ef7e06SGarrett D'Amore 	efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
159*49ef7e06SGarrett D'Amore 	caddr_t svpd = NULL;
160*49ef7e06SGarrett D'Amore 	unsigned partn;
161*49ef7e06SGarrett D'Amore 	size_t size = 0;
162*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
163*49ef7e06SGarrett D'Amore 
164*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
165*49ef7e06SGarrett D'Amore 
166*49ef7e06SGarrett D'Amore 	partn = (emip->emi_port == 1)
167*49ef7e06SGarrett D'Amore 		? MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0
168*49ef7e06SGarrett D'Amore 		: MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1;
169*49ef7e06SGarrett D'Amore 
170*49ef7e06SGarrett D'Amore 	/*
171*49ef7e06SGarrett D'Amore 	 * We need the static VPD sector to present a unified static+dynamic
172*49ef7e06SGarrett D'Amore 	 * VPD, that is, basically on every read, write, verify cycle. Since
173*49ef7e06SGarrett D'Amore 	 * it should *never* change we can just cache it here.
174*49ef7e06SGarrett D'Amore 	 */
175*49ef7e06SGarrett D'Amore 	if ((rc = siena_vpd_get_static(enp, partn, &svpd, &size)) != 0)
176*49ef7e06SGarrett D'Amore 		goto fail1;
177*49ef7e06SGarrett D'Amore 
178*49ef7e06SGarrett D'Amore 	if (svpd != NULL && size > 0) {
179*49ef7e06SGarrett D'Amore 		if ((rc = efx_vpd_hunk_verify(svpd, size, NULL)) != 0)
180*49ef7e06SGarrett D'Amore 			goto fail2;
181*49ef7e06SGarrett D'Amore 	}
182*49ef7e06SGarrett D'Amore 
183*49ef7e06SGarrett D'Amore 	enp->en_u.siena.enu_svpd = svpd;
184*49ef7e06SGarrett D'Amore 	enp->en_u.siena.enu_svpd_length = size;
185*49ef7e06SGarrett D'Amore 
186*49ef7e06SGarrett D'Amore 	return (0);
187*49ef7e06SGarrett D'Amore 
188*49ef7e06SGarrett D'Amore fail2:
189*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
190*49ef7e06SGarrett D'Amore 
191*49ef7e06SGarrett D'Amore 	EFSYS_KMEM_FREE(enp->en_esip, size, svpd);
192*49ef7e06SGarrett D'Amore fail1:
193*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
194*49ef7e06SGarrett D'Amore 
195*49ef7e06SGarrett D'Amore 	return (rc);
196*49ef7e06SGarrett D'Amore }
197*49ef7e06SGarrett D'Amore 
198*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
siena_vpd_size(__in efx_nic_t * enp,__out size_t * sizep)199*49ef7e06SGarrett D'Amore siena_vpd_size(
200*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
201*49ef7e06SGarrett D'Amore 	__out			size_t *sizep)
202*49ef7e06SGarrett D'Amore {
203*49ef7e06SGarrett D'Amore 	efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
204*49ef7e06SGarrett D'Amore 	uint32_t partn;
205*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
206*49ef7e06SGarrett D'Amore 
207*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
208*49ef7e06SGarrett D'Amore 
209*49ef7e06SGarrett D'Amore 	/*
210*49ef7e06SGarrett D'Amore 	 * This function returns the total size the user should allocate
211*49ef7e06SGarrett D'Amore 	 * for all VPD operations. We've already cached the static vpd,
212*49ef7e06SGarrett D'Amore 	 * so we just need to return an upper bound on the dynamic vpd.
213*49ef7e06SGarrett D'Amore 	 * Since the dynamic_config structure can change under our feet,
214*49ef7e06SGarrett D'Amore 	 * (as version numbers are inserted), just be safe and return the
215*49ef7e06SGarrett D'Amore 	 * total size of the dynamic_config *sector*
216*49ef7e06SGarrett D'Amore 	 */
217*49ef7e06SGarrett D'Amore 	partn = (emip->emi_port == 1)
218*49ef7e06SGarrett D'Amore 		? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
219*49ef7e06SGarrett D'Amore 		: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
220*49ef7e06SGarrett D'Amore 
221*49ef7e06SGarrett D'Amore 	if ((rc = siena_nvram_partn_size(enp, partn, sizep)) != 0)
222*49ef7e06SGarrett D'Amore 		goto fail1;
223*49ef7e06SGarrett D'Amore 
224*49ef7e06SGarrett D'Amore 	return (0);
225*49ef7e06SGarrett D'Amore 
226*49ef7e06SGarrett D'Amore fail1:
227*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
228*49ef7e06SGarrett D'Amore 
229*49ef7e06SGarrett D'Amore 	return (rc);
230*49ef7e06SGarrett D'Amore }
231*49ef7e06SGarrett D'Amore 
232*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
siena_vpd_read(__in efx_nic_t * enp,__out_bcount (size)caddr_t data,__in size_t size)233*49ef7e06SGarrett D'Amore siena_vpd_read(
234*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
235*49ef7e06SGarrett D'Amore 	__out_bcount(size)	caddr_t data,
236*49ef7e06SGarrett D'Amore 	__in			size_t size)
237*49ef7e06SGarrett D'Amore {
238*49ef7e06SGarrett D'Amore 	efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
239*49ef7e06SGarrett D'Amore 	siena_mc_dynamic_config_hdr_t *dcfg = NULL;
240*49ef7e06SGarrett D'Amore 	unsigned int vpd_length;
241*49ef7e06SGarrett D'Amore 	unsigned int vpd_offset;
242*49ef7e06SGarrett D'Amore 	unsigned int dcfg_partn;
243*49ef7e06SGarrett D'Amore 	size_t dcfg_size;
244*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
245*49ef7e06SGarrett D'Amore 
246*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
247*49ef7e06SGarrett D'Amore 
248*49ef7e06SGarrett D'Amore 	dcfg_partn = (emip->emi_port == 1)
249*49ef7e06SGarrett D'Amore 		? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
250*49ef7e06SGarrett D'Amore 		: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
251*49ef7e06SGarrett D'Amore 
252*49ef7e06SGarrett D'Amore 	if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
253*49ef7e06SGarrett D'Amore 	    B_TRUE, &dcfg, &dcfg_size)) != 0)
254*49ef7e06SGarrett D'Amore 		goto fail1;
255*49ef7e06SGarrett D'Amore 
256*49ef7e06SGarrett D'Amore 	vpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0);
257*49ef7e06SGarrett D'Amore 	vpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0);
258*49ef7e06SGarrett D'Amore 
259*49ef7e06SGarrett D'Amore 	if (vpd_length > size) {
260*49ef7e06SGarrett D'Amore 		rc = EFAULT;	/* Invalid dcfg: header bigger than sector */
261*49ef7e06SGarrett D'Amore 		goto fail2;
262*49ef7e06SGarrett D'Amore 	}
263*49ef7e06SGarrett D'Amore 
264*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(vpd_length, <=, size);
265*49ef7e06SGarrett D'Amore 	(void) memcpy(data, (caddr_t)dcfg + vpd_offset, vpd_length);
266*49ef7e06SGarrett D'Amore 
267*49ef7e06SGarrett D'Amore 	/* Pad data with all-1s, consistent with update operations */
268*49ef7e06SGarrett D'Amore 	(void) memset(data + vpd_length, 0xff, size - vpd_length);
269*49ef7e06SGarrett D'Amore 
270*49ef7e06SGarrett D'Amore 	EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
271*49ef7e06SGarrett D'Amore 
272*49ef7e06SGarrett D'Amore 	return (0);
273*49ef7e06SGarrett D'Amore 
274*49ef7e06SGarrett D'Amore fail2:
275*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
276*49ef7e06SGarrett D'Amore 
277*49ef7e06SGarrett D'Amore 	EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
278*49ef7e06SGarrett D'Amore fail1:
279*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
280*49ef7e06SGarrett D'Amore 
281*49ef7e06SGarrett D'Amore 	return (rc);
282*49ef7e06SGarrett D'Amore }
283*49ef7e06SGarrett D'Amore 
284*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
siena_vpd_verify(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)285*49ef7e06SGarrett D'Amore siena_vpd_verify(
286*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
287*49ef7e06SGarrett D'Amore 	__in_bcount(size)	caddr_t data,
288*49ef7e06SGarrett D'Amore 	__in			size_t size)
289*49ef7e06SGarrett D'Amore {
290*49ef7e06SGarrett D'Amore 	efx_vpd_tag_t stag;
291*49ef7e06SGarrett D'Amore 	efx_vpd_tag_t dtag;
292*49ef7e06SGarrett D'Amore 	efx_vpd_keyword_t skey;
293*49ef7e06SGarrett D'Amore 	efx_vpd_keyword_t dkey;
294*49ef7e06SGarrett D'Amore 	unsigned int scont;
295*49ef7e06SGarrett D'Amore 	unsigned int dcont;
296*49ef7e06SGarrett D'Amore 
297*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
298*49ef7e06SGarrett D'Amore 
299*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
300*49ef7e06SGarrett D'Amore 
301*49ef7e06SGarrett D'Amore 	/*
302*49ef7e06SGarrett D'Amore 	 * Strictly you could take the view that dynamic vpd is optional.
303*49ef7e06SGarrett D'Amore 	 * Instead, to conform more closely to the read/verify/reinit()
304*49ef7e06SGarrett D'Amore 	 * paradigm, we require dynamic vpd. siena_vpd_reinit() will
305*49ef7e06SGarrett D'Amore 	 * reinitialize it as required.
306*49ef7e06SGarrett D'Amore 	 */
307*49ef7e06SGarrett D'Amore 	if ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0)
308*49ef7e06SGarrett D'Amore 		goto fail1;
309*49ef7e06SGarrett D'Amore 
310*49ef7e06SGarrett D'Amore 	/*
311*49ef7e06SGarrett D'Amore 	 * Verify that there is no duplication between the static and
312*49ef7e06SGarrett D'Amore 	 * dynamic cfg sectors.
313*49ef7e06SGarrett D'Amore 	 */
314*49ef7e06SGarrett D'Amore 	if (enp->en_u.siena.enu_svpd_length == 0)
315*49ef7e06SGarrett D'Amore 		goto done;
316*49ef7e06SGarrett D'Amore 
317*49ef7e06SGarrett D'Amore 	dcont = 0;
318*49ef7e06SGarrett D'Amore 	_NOTE(CONSTANTCONDITION)
319*49ef7e06SGarrett D'Amore 	while (1) {
320*49ef7e06SGarrett D'Amore 		if ((rc = efx_vpd_hunk_next(data, size, &dtag,
321*49ef7e06SGarrett D'Amore 		    &dkey, NULL, NULL, &dcont)) != 0)
322*49ef7e06SGarrett D'Amore 			goto fail2;
323*49ef7e06SGarrett D'Amore 		if (dcont == 0)
324*49ef7e06SGarrett D'Amore 			break;
325*49ef7e06SGarrett D'Amore 
326*49ef7e06SGarrett D'Amore 		/*
327*49ef7e06SGarrett D'Amore 		 * Skip the RV keyword. It should be present in both the static
328*49ef7e06SGarrett D'Amore 		 * and dynamic cfg sectors.
329*49ef7e06SGarrett D'Amore 		 */
330*49ef7e06SGarrett D'Amore 		if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))
331*49ef7e06SGarrett D'Amore 			continue;
332*49ef7e06SGarrett D'Amore 
333*49ef7e06SGarrett D'Amore 		scont = 0;
334*49ef7e06SGarrett D'Amore 		_NOTE(CONSTANTCONDITION)
335*49ef7e06SGarrett D'Amore 		while (1) {
336*49ef7e06SGarrett D'Amore 			if ((rc = efx_vpd_hunk_next(
337*49ef7e06SGarrett D'Amore 			    enp->en_u.siena.enu_svpd,
338*49ef7e06SGarrett D'Amore 			    enp->en_u.siena.enu_svpd_length, &stag, &skey,
339*49ef7e06SGarrett D'Amore 			    NULL, NULL, &scont)) != 0)
340*49ef7e06SGarrett D'Amore 				goto fail3;
341*49ef7e06SGarrett D'Amore 			if (scont == 0)
342*49ef7e06SGarrett D'Amore 				break;
343*49ef7e06SGarrett D'Amore 
344*49ef7e06SGarrett D'Amore 			if (stag == dtag && skey == dkey) {
345*49ef7e06SGarrett D'Amore 				rc = EEXIST;
346*49ef7e06SGarrett D'Amore 				goto fail4;
347*49ef7e06SGarrett D'Amore 			}
348*49ef7e06SGarrett D'Amore 		}
349*49ef7e06SGarrett D'Amore 	}
350*49ef7e06SGarrett D'Amore 
351*49ef7e06SGarrett D'Amore done:
352*49ef7e06SGarrett D'Amore 	return (0);
353*49ef7e06SGarrett D'Amore 
354*49ef7e06SGarrett D'Amore fail4:
355*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail4);
356*49ef7e06SGarrett D'Amore fail3:
357*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
358*49ef7e06SGarrett D'Amore fail2:
359*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
360*49ef7e06SGarrett D'Amore fail1:
361*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
362*49ef7e06SGarrett D'Amore 
363*49ef7e06SGarrett D'Amore 	return (rc);
364*49ef7e06SGarrett D'Amore }
365*49ef7e06SGarrett D'Amore 
366*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
siena_vpd_reinit(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)367*49ef7e06SGarrett D'Amore siena_vpd_reinit(
368*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
369*49ef7e06SGarrett D'Amore 	__in_bcount(size)	caddr_t data,
370*49ef7e06SGarrett D'Amore 	__in			size_t size)
371*49ef7e06SGarrett D'Amore {
372*49ef7e06SGarrett D'Amore 	boolean_t wantpid;
373*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
374*49ef7e06SGarrett D'Amore 
375*49ef7e06SGarrett D'Amore 	/*
376*49ef7e06SGarrett D'Amore 	 * Only create a PID if the dynamic cfg doesn't have one
377*49ef7e06SGarrett D'Amore 	 */
378*49ef7e06SGarrett D'Amore 	if (enp->en_u.siena.enu_svpd_length == 0)
379*49ef7e06SGarrett D'Amore 		wantpid = B_TRUE;
380*49ef7e06SGarrett D'Amore 	else {
381*49ef7e06SGarrett D'Amore 		unsigned int offset;
382*49ef7e06SGarrett D'Amore 		uint8_t length;
383*49ef7e06SGarrett D'Amore 
384*49ef7e06SGarrett D'Amore 		rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
385*49ef7e06SGarrett D'Amore 				    enp->en_u.siena.enu_svpd_length,
386*49ef7e06SGarrett D'Amore 				    EFX_VPD_ID, 0, &offset, &length);
387*49ef7e06SGarrett D'Amore 		if (rc == 0)
388*49ef7e06SGarrett D'Amore 			wantpid = B_FALSE;
389*49ef7e06SGarrett D'Amore 		else if (rc == ENOENT)
390*49ef7e06SGarrett D'Amore 			wantpid = B_TRUE;
391*49ef7e06SGarrett D'Amore 		else
392*49ef7e06SGarrett D'Amore 			goto fail1;
393*49ef7e06SGarrett D'Amore 	}
394*49ef7e06SGarrett D'Amore 
395*49ef7e06SGarrett D'Amore 	if ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0)
396*49ef7e06SGarrett D'Amore 		goto fail2;
397*49ef7e06SGarrett D'Amore 
398*49ef7e06SGarrett D'Amore 	return (0);
399*49ef7e06SGarrett D'Amore 
400*49ef7e06SGarrett D'Amore fail2:
401*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
402*49ef7e06SGarrett D'Amore fail1:
403*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
404*49ef7e06SGarrett D'Amore 
405*49ef7e06SGarrett D'Amore 	return (rc);
406*49ef7e06SGarrett D'Amore }
407*49ef7e06SGarrett D'Amore 
408*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
siena_vpd_get(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size,__inout efx_vpd_value_t * evvp)409*49ef7e06SGarrett D'Amore siena_vpd_get(
410*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
411*49ef7e06SGarrett D'Amore 	__in_bcount(size)	caddr_t data,
412*49ef7e06SGarrett D'Amore 	__in			size_t size,
413*49ef7e06SGarrett D'Amore 	__inout			efx_vpd_value_t *evvp)
414*49ef7e06SGarrett D'Amore {
415*49ef7e06SGarrett D'Amore 	unsigned int offset;
416*49ef7e06SGarrett D'Amore 	uint8_t length;
417*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
418*49ef7e06SGarrett D'Amore 
419*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
420*49ef7e06SGarrett D'Amore 
421*49ef7e06SGarrett D'Amore 	/* Attempt to satisfy the request from svpd first */
422*49ef7e06SGarrett D'Amore 	if (enp->en_u.siena.enu_svpd_length > 0) {
423*49ef7e06SGarrett D'Amore 		if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
424*49ef7e06SGarrett D'Amore 		    enp->en_u.siena.enu_svpd_length, evvp->evv_tag,
425*49ef7e06SGarrett D'Amore 		    evvp->evv_keyword, &offset, &length)) == 0) {
426*49ef7e06SGarrett D'Amore 			evvp->evv_length = length;
427*49ef7e06SGarrett D'Amore 			(void) memcpy(evvp->evv_value,
428*49ef7e06SGarrett D'Amore 			    enp->en_u.siena.enu_svpd + offset, length);
429*49ef7e06SGarrett D'Amore 			return (0);
430*49ef7e06SGarrett D'Amore 		} else if (rc != ENOENT)
431*49ef7e06SGarrett D'Amore 			goto fail1;
432*49ef7e06SGarrett D'Amore 	}
433*49ef7e06SGarrett D'Amore 
434*49ef7e06SGarrett D'Amore 	/* And then from the provided data buffer */
435*49ef7e06SGarrett D'Amore 	if ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag,
436*49ef7e06SGarrett D'Amore 	    evvp->evv_keyword, &offset, &length)) != 0)
437*49ef7e06SGarrett D'Amore 		goto fail2;
438*49ef7e06SGarrett D'Amore 
439*49ef7e06SGarrett D'Amore 	evvp->evv_length = length;
440*49ef7e06SGarrett D'Amore 	(void) memcpy(evvp->evv_value, data + offset, length);
441*49ef7e06SGarrett D'Amore 
442*49ef7e06SGarrett D'Amore 	return (0);
443*49ef7e06SGarrett D'Amore 
444*49ef7e06SGarrett D'Amore fail2:
445*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
446*49ef7e06SGarrett D'Amore fail1:
447*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
448*49ef7e06SGarrett D'Amore 
449*49ef7e06SGarrett D'Amore 	return (rc);
450*49ef7e06SGarrett D'Amore }
451*49ef7e06SGarrett D'Amore 
452*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
siena_vpd_set(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size,__in efx_vpd_value_t * evvp)453*49ef7e06SGarrett D'Amore siena_vpd_set(
454*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
455*49ef7e06SGarrett D'Amore 	__in_bcount(size)	caddr_t data,
456*49ef7e06SGarrett D'Amore 	__in			size_t size,
457*49ef7e06SGarrett D'Amore 	__in			efx_vpd_value_t *evvp)
458*49ef7e06SGarrett D'Amore {
459*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
460*49ef7e06SGarrett D'Amore 
461*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
462*49ef7e06SGarrett D'Amore 
463*49ef7e06SGarrett D'Amore 	/* If the provided (tag,keyword) exists in svpd, then it is readonly */
464*49ef7e06SGarrett D'Amore 	if (enp->en_u.siena.enu_svpd_length > 0) {
465*49ef7e06SGarrett D'Amore 		unsigned int offset;
466*49ef7e06SGarrett D'Amore 		uint8_t length;
467*49ef7e06SGarrett D'Amore 
468*49ef7e06SGarrett D'Amore 		if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
469*49ef7e06SGarrett D'Amore 		    enp->en_u.siena.enu_svpd_length, evvp->evv_tag,
470*49ef7e06SGarrett D'Amore 		    evvp->evv_keyword, &offset, &length)) == 0) {
471*49ef7e06SGarrett D'Amore 			rc = EACCES;
472*49ef7e06SGarrett D'Amore 			goto fail1;
473*49ef7e06SGarrett D'Amore 		}
474*49ef7e06SGarrett D'Amore 	}
475*49ef7e06SGarrett D'Amore 
476*49ef7e06SGarrett D'Amore 	if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)
477*49ef7e06SGarrett D'Amore 		goto fail2;
478*49ef7e06SGarrett D'Amore 
479*49ef7e06SGarrett D'Amore 	return (0);
480*49ef7e06SGarrett D'Amore 
481*49ef7e06SGarrett D'Amore fail2:
482*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
483*49ef7e06SGarrett D'Amore fail1:
484*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
485*49ef7e06SGarrett D'Amore 
486*49ef7e06SGarrett D'Amore 	return (rc);
487*49ef7e06SGarrett D'Amore }
488*49ef7e06SGarrett D'Amore 
489*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
siena_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)490*49ef7e06SGarrett D'Amore siena_vpd_next(
491*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
492*49ef7e06SGarrett D'Amore 	__in_bcount(size)	caddr_t data,
493*49ef7e06SGarrett D'Amore 	__in			size_t size,
494*49ef7e06SGarrett D'Amore 	__out			efx_vpd_value_t *evvp,
495*49ef7e06SGarrett D'Amore 	__inout			unsigned int *contp)
496*49ef7e06SGarrett D'Amore {
497*49ef7e06SGarrett D'Amore 	_NOTE(ARGUNUSED(enp, data, size, evvp, contp))
498*49ef7e06SGarrett D'Amore 
499*49ef7e06SGarrett D'Amore 	return (ENOTSUP);
500*49ef7e06SGarrett D'Amore }
501*49ef7e06SGarrett D'Amore 
502*49ef7e06SGarrett D'Amore 	__checkReturn		efx_rc_t
siena_vpd_write(__in efx_nic_t * enp,__in_bcount (size)caddr_t data,__in size_t size)503*49ef7e06SGarrett D'Amore siena_vpd_write(
504*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
505*49ef7e06SGarrett D'Amore 	__in_bcount(size)	caddr_t data,
506*49ef7e06SGarrett D'Amore 	__in			size_t size)
507*49ef7e06SGarrett D'Amore {
508*49ef7e06SGarrett D'Amore 	efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
509*49ef7e06SGarrett D'Amore 	siena_mc_dynamic_config_hdr_t *dcfg = NULL;
510*49ef7e06SGarrett D'Amore 	unsigned int vpd_offset;
511*49ef7e06SGarrett D'Amore 	unsigned int dcfg_partn;
512*49ef7e06SGarrett D'Amore 	unsigned int hdr_length;
513*49ef7e06SGarrett D'Amore 	unsigned int pos;
514*49ef7e06SGarrett D'Amore 	uint8_t cksum;
515*49ef7e06SGarrett D'Amore 	size_t partn_size, dcfg_size;
516*49ef7e06SGarrett D'Amore 	size_t vpd_length;
517*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
518*49ef7e06SGarrett D'Amore 
519*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
520*49ef7e06SGarrett D'Amore 
521*49ef7e06SGarrett D'Amore 	/* Determine total length of all tags */
522*49ef7e06SGarrett D'Amore 	if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)
523*49ef7e06SGarrett D'Amore 		goto fail1;
524*49ef7e06SGarrett D'Amore 
525*49ef7e06SGarrett D'Amore 	/* Lock dynamic config sector for write, and read structure only */
526*49ef7e06SGarrett D'Amore 	dcfg_partn = (emip->emi_port == 1)
527*49ef7e06SGarrett D'Amore 		? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
528*49ef7e06SGarrett D'Amore 		: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
529*49ef7e06SGarrett D'Amore 
530*49ef7e06SGarrett D'Amore 	if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &partn_size)) != 0)
531*49ef7e06SGarrett D'Amore 		goto fail2;
532*49ef7e06SGarrett D'Amore 
533*49ef7e06SGarrett D'Amore 	if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0)
534*49ef7e06SGarrett D'Amore 		goto fail3;
535*49ef7e06SGarrett D'Amore 
536*49ef7e06SGarrett D'Amore 	if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
537*49ef7e06SGarrett D'Amore 	    B_FALSE, &dcfg, &dcfg_size)) != 0)
538*49ef7e06SGarrett D'Amore 		goto fail4;
539*49ef7e06SGarrett D'Amore 
540*49ef7e06SGarrett D'Amore 	hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);
541*49ef7e06SGarrett D'Amore 
542*49ef7e06SGarrett D'Amore 	/* Allocated memory should have room for the new VPD */
543*49ef7e06SGarrett D'Amore 	if (hdr_length + vpd_length > dcfg_size) {
544*49ef7e06SGarrett D'Amore 		rc = ENOSPC;
545*49ef7e06SGarrett D'Amore 		goto fail5;
546*49ef7e06SGarrett D'Amore 	}
547*49ef7e06SGarrett D'Amore 
548*49ef7e06SGarrett D'Amore 	/* Copy in new vpd and update header */
549*49ef7e06SGarrett D'Amore 	vpd_offset = dcfg_size - vpd_length;
550*49ef7e06SGarrett D'Amore 	EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset, EFX_DWORD_0, vpd_offset);
551*49ef7e06SGarrett D'Amore 	(void) memcpy((caddr_t)dcfg + vpd_offset, data, vpd_length);
552*49ef7e06SGarrett D'Amore 	EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_length, EFX_DWORD_0, vpd_length);
553*49ef7e06SGarrett D'Amore 
554*49ef7e06SGarrett D'Amore 	/* Update the checksum */
555*49ef7e06SGarrett D'Amore 	cksum = 0;
556*49ef7e06SGarrett D'Amore 	for (pos = 0; pos < hdr_length; pos++)
557*49ef7e06SGarrett D'Amore 		cksum += ((uint8_t *)dcfg)[pos];
558*49ef7e06SGarrett D'Amore 	dcfg->csum.eb_u8[0] -= cksum;
559*49ef7e06SGarrett D'Amore 
560*49ef7e06SGarrett D'Amore 	/* Erase and write the new sector */
561*49ef7e06SGarrett D'Amore 	if ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, partn_size)) != 0)
562*49ef7e06SGarrett D'Amore 		goto fail6;
563*49ef7e06SGarrett D'Amore 
564*49ef7e06SGarrett D'Amore 	/* Write out the new structure to nvram */
565*49ef7e06SGarrett D'Amore 	if ((rc = siena_nvram_partn_write(enp, dcfg_partn, 0, (caddr_t)dcfg,
566*49ef7e06SGarrett D'Amore 	    vpd_offset + vpd_length)) != 0)
567*49ef7e06SGarrett D'Amore 		goto fail7;
568*49ef7e06SGarrett D'Amore 
569*49ef7e06SGarrett D'Amore 	EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
570*49ef7e06SGarrett D'Amore 
571*49ef7e06SGarrett D'Amore 	siena_nvram_partn_unlock(enp, dcfg_partn);
572*49ef7e06SGarrett D'Amore 
573*49ef7e06SGarrett D'Amore 	return (0);
574*49ef7e06SGarrett D'Amore 
575*49ef7e06SGarrett D'Amore fail7:
576*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail7);
577*49ef7e06SGarrett D'Amore fail6:
578*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail6);
579*49ef7e06SGarrett D'Amore fail5:
580*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail5);
581*49ef7e06SGarrett D'Amore 
582*49ef7e06SGarrett D'Amore 	EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
583*49ef7e06SGarrett D'Amore fail4:
584*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail4);
585*49ef7e06SGarrett D'Amore 
586*49ef7e06SGarrett D'Amore 	siena_nvram_partn_unlock(enp, dcfg_partn);
587*49ef7e06SGarrett D'Amore fail3:
588*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
589*49ef7e06SGarrett D'Amore fail2:
590*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
591*49ef7e06SGarrett D'Amore fail1:
592*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
593*49ef7e06SGarrett D'Amore 
594*49ef7e06SGarrett D'Amore 	return (rc);
595*49ef7e06SGarrett D'Amore }
596*49ef7e06SGarrett D'Amore 
597*49ef7e06SGarrett D'Amore 				void
siena_vpd_fini(__in efx_nic_t * enp)598*49ef7e06SGarrett D'Amore siena_vpd_fini(
599*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp)
600*49ef7e06SGarrett D'Amore {
601*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
602*49ef7e06SGarrett D'Amore 
603*49ef7e06SGarrett D'Amore 	if (enp->en_u.siena.enu_svpd_length > 0) {
604*49ef7e06SGarrett D'Amore 		EFSYS_KMEM_FREE(enp->en_esip, enp->en_u.siena.enu_svpd_length,
605*49ef7e06SGarrett D'Amore 				enp->en_u.siena.enu_svpd);
606*49ef7e06SGarrett D'Amore 
607*49ef7e06SGarrett D'Amore 		enp->en_u.siena.enu_svpd = NULL;
608*49ef7e06SGarrett D'Amore 		enp->en_u.siena.enu_svpd_length = 0;
609*49ef7e06SGarrett D'Amore 	}
610*49ef7e06SGarrett D'Amore }
611*49ef7e06SGarrett D'Amore 
612*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_SIENA */
613*49ef7e06SGarrett D'Amore 
614*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_VPD */
615