2 * Copyright (c) 2009-2016 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
38 static __checkReturn efx_rc_t
42 __deref_out_bcount_opt(*sizep) caddr_t *svpdp,
45 siena_mc_static_config_hdr_t *scfg;
49 unsigned int vpd_offset;
50 unsigned int vpd_length;
51 unsigned int hdr_length;
56 EFSYS_ASSERT(partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 ||
57 partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1);
59 /* Allocate sufficient memory for the entire static cfg area */
60 if ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0)
63 EFSYS_KMEM_ALLOC(enp->en_esip, size, scfg);
69 if ((rc = siena_nvram_partn_read(enp, partn, 0,
70 (caddr_t)scfg, SIENA_NVRAM_CHUNK)) != 0)
73 /* Verify the magic number */
74 if (EFX_DWORD_FIELD(scfg->magic, EFX_DWORD_0) !=
75 SIENA_MC_STATIC_CONFIG_MAGIC) {
80 /* All future versions of the structure must be backwards compatible */
81 EFX_STATIC_ASSERT(SIENA_MC_STATIC_CONFIG_VERSION == 0);
83 hdr_length = EFX_WORD_FIELD(scfg->length, EFX_WORD_0);
84 vpd_offset = EFX_DWORD_FIELD(scfg->static_vpd_offset, EFX_DWORD_0);
85 vpd_length = EFX_DWORD_FIELD(scfg->static_vpd_length, EFX_DWORD_0);
87 /* Verify the hdr doesn't overflow the sector size */
88 if (hdr_length > size || vpd_offset > size || vpd_length > size ||
89 vpd_length + vpd_offset > size) {
94 /* Read the remainder of scfg + static vpd */
95 region = vpd_offset + vpd_length;
96 if (region > SIENA_NVRAM_CHUNK) {
97 if ((rc = siena_nvram_partn_read(enp, partn, SIENA_NVRAM_CHUNK,
98 (caddr_t)scfg + SIENA_NVRAM_CHUNK,
99 region - SIENA_NVRAM_CHUNK)) != 0)
103 /* Verify checksum */
105 for (pos = 0; pos < hdr_length; pos++)
106 cksum += ((uint8_t *)scfg)[pos];
115 /* Copy the vpd data out */
116 EFSYS_KMEM_ALLOC(enp->en_esip, vpd_length, svpd);
121 memcpy(svpd, (caddr_t)scfg + vpd_offset, vpd_length);
124 EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
144 EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
149 EFSYS_PROBE1(fail1, efx_rc_t, rc);
154 __checkReturn efx_rc_t
158 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
164 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
166 partn = (emip->emi_port == 1)
167 ? MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0
168 : MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1;
171 * We need the static VPD sector to present a unified static+dynamic
172 * VPD, that is, basically on every read, write, verify cycle. Since
173 * it should *never* change we can just cache it here.
175 if ((rc = siena_vpd_get_static(enp, partn, &svpd, &size)) != 0)
178 if (svpd != NULL && size > 0) {
179 if ((rc = efx_vpd_hunk_verify(svpd, size, NULL)) != 0)
183 enp->en_u.siena.enu_svpd = svpd;
184 enp->en_u.siena.enu_svpd_length = size;
191 EFSYS_KMEM_FREE(enp->en_esip, size, svpd);
193 EFSYS_PROBE1(fail1, efx_rc_t, rc);
198 __checkReturn efx_rc_t
203 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
207 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
210 * This function returns the total size the user should allocate
211 * for all VPD operations. We've already cached the static vpd,
212 * so we just need to return an upper bound on the dynamic vpd.
213 * Since the dynamic_config structure can change under our feet,
214 * (as version numbers are inserted), just be safe and return the
215 * total size of the dynamic_config *sector*
217 partn = (emip->emi_port == 1)
218 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
219 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
221 if ((rc = siena_nvram_partn_size(enp, partn, sizep)) != 0)
227 EFSYS_PROBE1(fail1, efx_rc_t, rc);
232 __checkReturn efx_rc_t
235 __out_bcount(size) caddr_t data,
238 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
239 siena_mc_dynamic_config_hdr_t *dcfg = NULL;
240 unsigned int vpd_length;
241 unsigned int vpd_offset;
242 unsigned int dcfg_partn;
246 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
248 dcfg_partn = (emip->emi_port == 1)
249 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
250 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
252 if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
253 B_TRUE, &dcfg, &dcfg_size)) != 0)
256 vpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0);
257 vpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0);
259 if (vpd_length > size) {
260 rc = EFAULT; /* Invalid dcfg: header bigger than sector */
264 EFSYS_ASSERT3U(vpd_length, <=, size);
265 memcpy(data, (caddr_t)dcfg + vpd_offset, vpd_length);
267 /* Pad data with all-1s, consistent with update operations */
268 memset(data + vpd_length, 0xff, size - vpd_length);
270 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
277 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
279 EFSYS_PROBE1(fail1, efx_rc_t, rc);
284 __checkReturn efx_rc_t
287 __in_bcount(size) caddr_t data,
292 efx_vpd_keyword_t skey;
293 efx_vpd_keyword_t dkey;
299 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
302 * Strictly you could take the view that dynamic vpd is optional.
303 * Instead, to conform more closely to the read/verify/reinit()
304 * paradigm, we require dynamic vpd. siena_vpd_reinit() will
305 * reinitialize it as required.
307 if ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0)
311 * Verify that there is no duplication between the static and
312 * dynamic cfg sectors.
314 if (enp->en_u.siena.enu_svpd_length == 0)
318 _NOTE(CONSTANTCONDITION)
320 if ((rc = efx_vpd_hunk_next(data, size, &dtag,
321 &dkey, NULL, NULL, &dcont)) != 0)
327 * Skip the RV keyword. It should be present in both the static
328 * and dynamic cfg sectors.
330 if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))
334 _NOTE(CONSTANTCONDITION)
336 if ((rc = efx_vpd_hunk_next(
337 enp->en_u.siena.enu_svpd,
338 enp->en_u.siena.enu_svpd_length, &stag, &skey,
339 NULL, NULL, &scont)) != 0)
344 if (stag == dtag && skey == dkey) {
361 EFSYS_PROBE1(fail1, efx_rc_t, rc);
366 __checkReturn efx_rc_t
369 __in_bcount(size) caddr_t data,
376 * Only create a PID if the dynamic cfg doesn't have one
378 if (enp->en_u.siena.enu_svpd_length == 0)
384 rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
385 enp->en_u.siena.enu_svpd_length,
386 EFX_VPD_ID, 0, &offset, &length);
389 else if (rc == ENOENT)
395 if ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0)
403 EFSYS_PROBE1(fail1, efx_rc_t, rc);
408 __checkReturn efx_rc_t
411 __in_bcount(size) caddr_t data,
413 __inout efx_vpd_value_t *evvp)
419 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
421 /* Attempt to satisfy the request from svpd first */
422 if (enp->en_u.siena.enu_svpd_length > 0) {
423 if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
424 enp->en_u.siena.enu_svpd_length, evvp->evv_tag,
425 evvp->evv_keyword, &offset, &length)) == 0) {
426 evvp->evv_length = length;
427 memcpy(evvp->evv_value,
428 enp->en_u.siena.enu_svpd + offset, length);
430 } else if (rc != ENOENT)
434 /* And then from the provided data buffer */
435 if ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag,
436 evvp->evv_keyword, &offset, &length)) != 0) {
443 evvp->evv_length = length;
444 memcpy(evvp->evv_value, data + offset, length);
451 EFSYS_PROBE1(fail1, efx_rc_t, rc);
456 __checkReturn efx_rc_t
459 __in_bcount(size) caddr_t data,
461 __in efx_vpd_value_t *evvp)
465 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
467 /* If the provided (tag,keyword) exists in svpd, then it is readonly */
468 if (enp->en_u.siena.enu_svpd_length > 0) {
472 if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
473 enp->en_u.siena.enu_svpd_length, evvp->evv_tag,
474 evvp->evv_keyword, &offset, &length)) == 0) {
480 if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)
488 EFSYS_PROBE1(fail1, efx_rc_t, rc);
493 __checkReturn efx_rc_t
496 __in_bcount(size) caddr_t data,
498 __out efx_vpd_value_t *evvp,
499 __inout unsigned int *contp)
501 _NOTE(ARGUNUSED(enp, data, size, evvp, contp))
506 __checkReturn efx_rc_t
509 __in_bcount(size) caddr_t data,
512 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
513 siena_mc_dynamic_config_hdr_t *dcfg = NULL;
514 unsigned int vpd_offset;
515 unsigned int dcfg_partn;
516 unsigned int hdr_length;
519 size_t partn_size, dcfg_size;
523 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
525 /* Determine total length of all tags */
526 if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)
529 /* Lock dynamic config sector for write, and read structure only */
530 dcfg_partn = (emip->emi_port == 1)
531 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
532 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
534 if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &partn_size)) != 0)
537 if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0)
540 if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
541 B_FALSE, &dcfg, &dcfg_size)) != 0)
544 hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);
546 /* Allocated memory should have room for the new VPD */
547 if (hdr_length + vpd_length > dcfg_size) {
552 /* Copy in new vpd and update header */
553 vpd_offset = dcfg_size - vpd_length;
554 EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset, EFX_DWORD_0, vpd_offset);
555 memcpy((caddr_t)dcfg + vpd_offset, data, vpd_length);
556 EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_length, EFX_DWORD_0, vpd_length);
558 /* Update the checksum */
560 for (pos = 0; pos < hdr_length; pos++)
561 cksum += ((uint8_t *)dcfg)[pos];
562 dcfg->csum.eb_u8[0] -= cksum;
564 /* Erase and write the new sector */
565 if ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, partn_size)) != 0)
568 /* Write out the new structure to nvram */
569 if ((rc = siena_nvram_partn_write(enp, dcfg_partn, 0, (caddr_t)dcfg,
570 vpd_offset + vpd_length)) != 0)
573 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
575 siena_nvram_partn_unlock(enp, dcfg_partn, NULL);
586 EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
590 siena_nvram_partn_unlock(enp, dcfg_partn, NULL);
596 EFSYS_PROBE1(fail1, efx_rc_t, rc);
605 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
607 if (enp->en_u.siena.enu_svpd_length > 0) {
608 EFSYS_KMEM_FREE(enp->en_esip, enp->en_u.siena.enu_svpd_length,
609 enp->en_u.siena.enu_svpd);
611 enp->en_u.siena.enu_svpd = NULL;
612 enp->en_u.siena.enu_svpd_length = 0;
616 #endif /* EFSYS_OPT_SIENA */
618 #endif /* EFSYS_OPT_VPD */