2 * Copyright 2009 Solarflare Communications Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
31 #include "efx_types.h"
39 static __checkReturn int
42 __in unsigned int partn,
43 __deref_out_bcount_opt(*sizep) caddr_t *svpdp,
46 siena_mc_static_config_hdr_t *scfg;
50 unsigned int vpd_offset;
51 unsigned int vpd_length;
52 unsigned int hdr_length;
57 EFSYS_ASSERT(partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 ||
58 partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1);
60 /* Allocate sufficient memory for the entire static cfg area */
61 if ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0)
64 EFSYS_KMEM_ALLOC(enp->en_esip, size, scfg);
70 if ((rc = siena_nvram_partn_read(enp, partn, 0,
71 (caddr_t)scfg, SIENA_NVRAM_CHUNK)) != 0)
74 /* Verify the magic number */
75 if (EFX_DWORD_FIELD(scfg->magic, EFX_DWORD_0) !=
76 SIENA_MC_STATIC_CONFIG_MAGIC) {
81 /* All future versions of the structure must be backwards compatable */
82 EFX_STATIC_ASSERT(SIENA_MC_STATIC_CONFIG_VERSION == 0);
84 hdr_length = EFX_WORD_FIELD(scfg->length, EFX_WORD_0);
85 vpd_offset = EFX_DWORD_FIELD(scfg->static_vpd_offset, EFX_DWORD_0);
86 vpd_length = EFX_DWORD_FIELD(scfg->static_vpd_length, EFX_DWORD_0);
88 /* Verify the hdr doesn't overflow the sector size */
89 if (hdr_length > size || vpd_offset > size || vpd_length > size ||
90 vpd_length + vpd_offset > size) {
95 /* Read the remainder of scfg + static vpd */
96 region = vpd_offset + vpd_length;
97 if (region > SIENA_NVRAM_CHUNK) {
98 if ((rc = siena_nvram_partn_read(enp, partn, SIENA_NVRAM_CHUNK,
99 (caddr_t)scfg + SIENA_NVRAM_CHUNK,
100 region - SIENA_NVRAM_CHUNK)) != 0)
104 /* Verify checksum */
106 for (pos = 0; pos < hdr_length; pos++)
107 cksum += ((uint8_t *)scfg)[pos];
116 /* Copy the vpd data out */
117 EFSYS_KMEM_ALLOC(enp->en_esip, vpd_length, svpd);
122 memcpy(svpd, (caddr_t)scfg + vpd_offset, vpd_length);
125 EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
147 EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
150 EFSYS_PROBE1(fail1, int, rc);
159 efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
165 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
167 partn = (emip->emi_port == 1)
168 ? MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0
169 : MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1;
172 * We need the static VPD sector to present a unified static+dynamic
173 * VPD, that is, basically on every read, write, verify cycle. Since
174 * it should *never* change we can just cache it here.
176 if ((rc = siena_vpd_get_static(enp, partn, &svpd, &size)) != 0)
179 if (svpd != NULL && size > 0) {
180 if ((rc = efx_vpd_hunk_verify(svpd, size, NULL)) != 0)
184 enp->en_u.siena.enu_svpd = svpd;
185 enp->en_u.siena.enu_svpd_length = size;
192 EFSYS_KMEM_FREE(enp->en_esip, size, svpd);
194 EFSYS_PROBE1(fail1, int, rc);
204 efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
208 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
211 * This function returns the total size the user should allocate
212 * for all VPD operations. We've already cached the static vpd,
213 * so we just need to return an upper bound on the dynamic vpd.
214 * Since the dynamic_config structure can change under our feet,
215 * (as version numbers are inserted), just be safe and return the
216 * total size of the dynamic_config *sector*
218 partn = (emip->emi_port == 1)
219 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
220 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
222 if ((rc = siena_nvram_partn_size(enp, partn, sizep)) != 0)
228 EFSYS_PROBE1(fail1, int, rc);
236 __out_bcount(size) caddr_t data,
239 efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
240 siena_mc_dynamic_config_hdr_t *dcfg;
241 unsigned int vpd_length;
242 unsigned int vpd_offset;
243 unsigned int dcfg_partn;
247 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
249 dcfg_partn = (emip->emi_port == 1)
250 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
251 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
253 if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
254 B_TRUE, &dcfg, &dcfg_size)) != 0)
257 vpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0);
258 vpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0);
260 if (vpd_length > size) {
261 rc = EFAULT; /* Invalid dcfg: header bigger than sector */
265 EFSYS_ASSERT3U(vpd_length, <=, size);
266 memcpy(data, (caddr_t)dcfg + vpd_offset, vpd_length);
268 /* Pad data with all-1s, consistent with update operations */
269 memset(data + vpd_length, 0xff, size - vpd_length);
271 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
278 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
280 EFSYS_PROBE1(fail1, int, rc);
288 __in_bcount(size) caddr_t data,
293 efx_vpd_keyword_t skey;
294 efx_vpd_keyword_t dkey;
300 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
303 * Strictly you could take the view that dynamic vpd is optional.
304 * Instead, to conform more closely to the read/verify/reinit()
305 * paradigm, we require dynamic vpd. siena_vpd_reinit() will
306 * reinitialize it as required.
308 if ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0)
312 * Verify that there is no duplication between the static and
313 * dynamic cfg sectors.
315 if (enp->en_u.siena.enu_svpd_length == 0)
319 _NOTE(CONSTANTCONDITION)
321 if ((rc = efx_vpd_hunk_next(data, size, &dtag,
322 &dkey, NULL, NULL, &dcont)) != 0)
328 _NOTE(CONSTANTCONDITION)
330 if ((rc = efx_vpd_hunk_next(
331 enp->en_u.siena.enu_svpd,
332 enp->en_u.siena.enu_svpd_length, &stag, &skey,
333 NULL, NULL, &scont)) != 0)
338 if (stag == dtag && skey == dkey) {
355 EFSYS_PROBE1(fail1, int, rc);
363 __in_bcount(size) caddr_t data,
370 * Only create a PID if the dynamic cfg doesn't have one
372 if (enp->en_u.siena.enu_svpd_length == 0)
378 rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
379 enp->en_u.siena.enu_svpd_length,
380 EFX_VPD_ID, 0, &offset, &length);
383 else if (rc == ENOENT)
389 if ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0)
397 EFSYS_PROBE1(fail1, int, rc);
405 __in_bcount(size) caddr_t data,
407 __inout efx_vpd_value_t *evvp)
413 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
415 /* Attempt to satisfy the request from svpd first */
416 if (enp->en_u.siena.enu_svpd_length > 0) {
417 if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
418 enp->en_u.siena.enu_svpd_length, evvp->evv_tag,
419 evvp->evv_keyword, &offset, &length)) == 0) {
420 evvp->evv_length = length;
421 memcpy(evvp->evv_value,
422 enp->en_u.siena.enu_svpd + offset, length);
424 } else if (rc != ENOENT)
428 /* And then from the provided data buffer */
429 if ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag,
430 evvp->evv_keyword, &offset, &length)) != 0)
433 evvp->evv_length = length;
434 memcpy(evvp->evv_value, data + offset, length);
441 EFSYS_PROBE1(fail1, int, rc);
449 __in_bcount(size) caddr_t data,
451 __in efx_vpd_value_t *evvp)
455 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
457 /* If the provided (tag,keyword) exists in svpd, then it is readonly */
458 if (enp->en_u.siena.enu_svpd_length > 0) {
462 if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
463 enp->en_u.siena.enu_svpd_length, evvp->evv_tag,
464 evvp->evv_keyword, &offset, &length)) == 0) {
470 if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)
478 EFSYS_PROBE1(fail1, int, rc);
486 __in_bcount(size) caddr_t data,
488 __out efx_vpd_value_t *evvp,
489 __inout unsigned int *contp)
491 _NOTE(ARGUNUSED(enp, data, size, evvp, contp))
499 __in_bcount(size) caddr_t data,
502 efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
503 siena_mc_dynamic_config_hdr_t *dcfg;
504 unsigned int vpd_offset;
505 unsigned int dcfg_partn;
506 unsigned int hdr_length;
509 size_t partn_size, dcfg_size;
513 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
515 /* Determine total length of all tags */
516 if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)
519 /* Lock dynamic config sector for write, and read structure only */
520 dcfg_partn = (emip->emi_port == 1)
521 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
522 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
524 if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &partn_size)) != 0)
527 if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0)
530 if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
531 B_FALSE, &dcfg, &dcfg_size)) != 0)
534 hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);
536 /* Allocated memory should have room for the new VPD */
537 if (hdr_length + vpd_length > dcfg_size) {
542 /* Copy in new vpd and update header */
543 vpd_offset = dcfg_size - vpd_length;
544 EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset,
545 EFX_DWORD_0, vpd_offset);
546 memcpy((caddr_t)dcfg + vpd_offset, data, vpd_length);
547 EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_length,
548 EFX_DWORD_0, vpd_length);
550 /* Update the checksum */
552 for (pos = 0; pos < hdr_length; pos++)
553 cksum += ((uint8_t *)dcfg)[pos];
554 dcfg->csum.eb_u8[0] -= cksum;
556 /* Erase and write the new sector */
557 if ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, partn_size)) != 0)
560 /* Write out the new structure to nvram */
561 if ((rc = siena_nvram_partn_write(enp, dcfg_partn, 0, (caddr_t)dcfg,
562 vpd_offset + vpd_length)) != 0)
565 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
567 siena_nvram_partn_unlock(enp, dcfg_partn);
578 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
582 siena_nvram_partn_unlock(enp, dcfg_partn);
584 EFSYS_PROBE1(fail1, int, rc);
593 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
595 if (enp->en_u.siena.enu_svpd_length > 0) {
596 EFSYS_KMEM_FREE(enp->en_esip, enp->en_u.siena.enu_svpd_length,
597 enp->en_u.siena.enu_svpd);
599 enp->en_u.siena.enu_svpd = NULL;
600 enp->en_u.siena.enu_svpd_length = 0;
604 #endif /* EFSYS_OPT_SIENA */
606 #endif /* EFSYS_OPT_VPD */