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