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