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