4fb2e4268917f79a98baa8766e3be9793aae8c5e
[deb_dpdk.git] / drivers / net / sfc / base / siena_vpd.c
1 /*
2  * Copyright (c) 2009-2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
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.
13  *
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.
25  *
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.
29  */
30
31 #include "efx.h"
32 #include "efx_impl.h"
33
34 #if EFSYS_OPT_VPD
35
36 #if EFSYS_OPT_SIENA
37
38 static  __checkReturn                   efx_rc_t
39 siena_vpd_get_static(
40         __in                            efx_nic_t *enp,
41         __in                            uint32_t partn,
42         __deref_out_bcount_opt(*sizep)  caddr_t *svpdp,
43         __out                           size_t *sizep)
44 {
45         siena_mc_static_config_hdr_t *scfg;
46         caddr_t svpd;
47         size_t size;
48         uint8_t cksum;
49         unsigned int vpd_offset;
50         unsigned int vpd_length;
51         unsigned int hdr_length;
52         unsigned int pos;
53         unsigned int region;
54         efx_rc_t rc;
55
56         EFSYS_ASSERT(partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 ||
57                     partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1);
58
59         /* Allocate sufficient memory for the entire static cfg area */
60         if ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0)
61                 goto fail1;
62
63         EFSYS_KMEM_ALLOC(enp->en_esip, size, scfg);
64         if (scfg == NULL) {
65                 rc = ENOMEM;
66                 goto fail2;
67         }
68
69         if ((rc = siena_nvram_partn_read(enp, partn, 0,
70             (caddr_t)scfg, SIENA_NVRAM_CHUNK)) != 0)
71                 goto fail3;
72
73         /* Verify the magic number */
74         if (EFX_DWORD_FIELD(scfg->magic, EFX_DWORD_0) !=
75             SIENA_MC_STATIC_CONFIG_MAGIC) {
76                 rc = EINVAL;
77                 goto fail4;
78         }
79
80         /* All future versions of the structure must be backwards compatible */
81         EFX_STATIC_ASSERT(SIENA_MC_STATIC_CONFIG_VERSION == 0);
82
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);
86
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) {
90                 rc = EINVAL;
91                 goto fail5;
92         }
93
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)
100                         goto fail6;
101         }
102
103         /* Verify checksum */
104         cksum = 0;
105         for (pos = 0; pos < hdr_length; pos++)
106                 cksum += ((uint8_t *)scfg)[pos];
107         if (cksum != 0) {
108                 rc = EINVAL;
109                 goto fail7;
110         }
111
112         if (vpd_length == 0)
113                 svpd = NULL;
114         else {
115                 /* Copy the vpd data out */
116                 EFSYS_KMEM_ALLOC(enp->en_esip, vpd_length, svpd);
117                 if (svpd == NULL) {
118                         rc = ENOMEM;
119                         goto fail8;
120                 }
121                 memcpy(svpd, (caddr_t)scfg + vpd_offset, vpd_length);
122         }
123
124         EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
125
126         *svpdp = svpd;
127         *sizep = vpd_length;
128
129         return (0);
130
131 fail8:
132         EFSYS_PROBE(fail8);
133 fail7:
134         EFSYS_PROBE(fail7);
135 fail6:
136         EFSYS_PROBE(fail6);
137 fail5:
138         EFSYS_PROBE(fail5);
139 fail4:
140         EFSYS_PROBE(fail4);
141 fail3:
142         EFSYS_PROBE(fail3);
143
144         EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
145
146 fail2:
147         EFSYS_PROBE(fail2);
148 fail1:
149         EFSYS_PROBE1(fail1, efx_rc_t, rc);
150
151         return (rc);
152 }
153
154         __checkReturn           efx_rc_t
155 siena_vpd_init(
156         __in                    efx_nic_t *enp)
157 {
158         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
159         caddr_t svpd = NULL;
160         unsigned int partn;
161         size_t size = 0;
162         efx_rc_t rc;
163
164         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
165
166         partn = (emip->emi_port == 1)
167                 ? MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0
168                 : MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1;
169
170         /*
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.
174          */
175         if ((rc = siena_vpd_get_static(enp, partn, &svpd, &size)) != 0)
176                 goto fail1;
177
178         if (svpd != NULL && size > 0) {
179                 if ((rc = efx_vpd_hunk_verify(svpd, size, NULL)) != 0)
180                         goto fail2;
181         }
182
183         enp->en_u.siena.enu_svpd = svpd;
184         enp->en_u.siena.enu_svpd_length = size;
185
186         return (0);
187
188 fail2:
189         EFSYS_PROBE(fail2);
190
191         EFSYS_KMEM_FREE(enp->en_esip, size, svpd);
192 fail1:
193         EFSYS_PROBE1(fail1, efx_rc_t, rc);
194
195         return (rc);
196 }
197
198         __checkReturn           efx_rc_t
199 siena_vpd_size(
200         __in                    efx_nic_t *enp,
201         __out                   size_t *sizep)
202 {
203         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
204         uint32_t partn;
205         efx_rc_t rc;
206
207         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
208
209         /*
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*
216          */
217         partn = (emip->emi_port == 1)
218                 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
219                 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
220
221         if ((rc = siena_nvram_partn_size(enp, partn, sizep)) != 0)
222                 goto fail1;
223
224         return (0);
225
226 fail1:
227         EFSYS_PROBE1(fail1, efx_rc_t, rc);
228
229         return (rc);
230 }
231
232         __checkReturn           efx_rc_t
233 siena_vpd_read(
234         __in                    efx_nic_t *enp,
235         __out_bcount(size)      caddr_t data,
236         __in                    size_t size)
237 {
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;
243         size_t dcfg_size;
244         efx_rc_t rc;
245
246         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
247
248         dcfg_partn = (emip->emi_port == 1)
249                 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
250                 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
251
252         if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
253             B_TRUE, &dcfg, &dcfg_size)) != 0)
254                 goto fail1;
255
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);
258
259         if (vpd_length > size) {
260                 rc = EFAULT;    /* Invalid dcfg: header bigger than sector */
261                 goto fail2;
262         }
263
264         EFSYS_ASSERT3U(vpd_length, <=, size);
265         memcpy(data, (caddr_t)dcfg + vpd_offset, vpd_length);
266
267         /* Pad data with all-1s, consistent with update operations */
268         memset(data + vpd_length, 0xff, size - vpd_length);
269
270         EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
271
272         return (0);
273
274 fail2:
275         EFSYS_PROBE(fail2);
276
277         EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
278 fail1:
279         EFSYS_PROBE1(fail1, efx_rc_t, rc);
280
281         return (rc);
282 }
283
284         __checkReturn           efx_rc_t
285 siena_vpd_verify(
286         __in                    efx_nic_t *enp,
287         __in_bcount(size)       caddr_t data,
288         __in                    size_t size)
289 {
290         efx_vpd_tag_t stag;
291         efx_vpd_tag_t dtag;
292         efx_vpd_keyword_t skey;
293         efx_vpd_keyword_t dkey;
294         unsigned int scont;
295         unsigned int dcont;
296
297         efx_rc_t rc;
298
299         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
300
301         /*
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.
306          */
307         if ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0)
308                 goto fail1;
309
310         /*
311          * Verify that there is no duplication between the static and
312          * dynamic cfg sectors.
313          */
314         if (enp->en_u.siena.enu_svpd_length == 0)
315                 goto done;
316
317         dcont = 0;
318         _NOTE(CONSTANTCONDITION)
319         while (1) {
320                 if ((rc = efx_vpd_hunk_next(data, size, &dtag,
321                     &dkey, NULL, NULL, &dcont)) != 0)
322                         goto fail2;
323                 if (dcont == 0)
324                         break;
325
326                 /*
327                  * Skip the RV keyword. It should be present in both the static
328                  * and dynamic cfg sectors.
329                  */
330                 if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))
331                         continue;
332
333                 scont = 0;
334                 _NOTE(CONSTANTCONDITION)
335                 while (1) {
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)
340                                 goto fail3;
341                         if (scont == 0)
342                                 break;
343
344                         if (stag == dtag && skey == dkey) {
345                                 rc = EEXIST;
346                                 goto fail4;
347                         }
348                 }
349         }
350
351 done:
352         return (0);
353
354 fail4:
355         EFSYS_PROBE(fail4);
356 fail3:
357         EFSYS_PROBE(fail3);
358 fail2:
359         EFSYS_PROBE(fail2);
360 fail1:
361         EFSYS_PROBE1(fail1, efx_rc_t, rc);
362
363         return (rc);
364 }
365
366         __checkReturn           efx_rc_t
367 siena_vpd_reinit(
368         __in                    efx_nic_t *enp,
369         __in_bcount(size)       caddr_t data,
370         __in                    size_t size)
371 {
372         boolean_t wantpid;
373         efx_rc_t rc;
374
375         /*
376          * Only create a PID if the dynamic cfg doesn't have one
377          */
378         if (enp->en_u.siena.enu_svpd_length == 0)
379                 wantpid = B_TRUE;
380         else {
381                 unsigned int offset;
382                 uint8_t length;
383
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);
387                 if (rc == 0)
388                         wantpid = B_FALSE;
389                 else if (rc == ENOENT)
390                         wantpid = B_TRUE;
391                 else
392                         goto fail1;
393         }
394
395         if ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0)
396                 goto fail2;
397
398         return (0);
399
400 fail2:
401         EFSYS_PROBE(fail2);
402 fail1:
403         EFSYS_PROBE1(fail1, efx_rc_t, rc);
404
405         return (rc);
406 }
407
408         __checkReturn           efx_rc_t
409 siena_vpd_get(
410         __in                    efx_nic_t *enp,
411         __in_bcount(size)       caddr_t data,
412         __in                    size_t size,
413         __inout                 efx_vpd_value_t *evvp)
414 {
415         unsigned int offset;
416         uint8_t length;
417         efx_rc_t rc;
418
419         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
420
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);
429                         return (0);
430                 } else if (rc != ENOENT)
431                         goto fail1;
432         }
433
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) {
437                 if (rc == ENOENT)
438                         return (rc);
439
440                 goto fail2;
441         }
442
443         evvp->evv_length = length;
444         memcpy(evvp->evv_value, data + offset, length);
445
446         return (0);
447
448 fail2:
449         EFSYS_PROBE(fail2);
450 fail1:
451         EFSYS_PROBE1(fail1, efx_rc_t, rc);
452
453         return (rc);
454 }
455
456         __checkReturn           efx_rc_t
457 siena_vpd_set(
458         __in                    efx_nic_t *enp,
459         __in_bcount(size)       caddr_t data,
460         __in                    size_t size,
461         __in                    efx_vpd_value_t *evvp)
462 {
463         efx_rc_t rc;
464
465         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
466
467         /* If the provided (tag,keyword) exists in svpd, then it is readonly */
468         if (enp->en_u.siena.enu_svpd_length > 0) {
469                 unsigned int offset;
470                 uint8_t length;
471
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) {
475                         rc = EACCES;
476                         goto fail1;
477                 }
478         }
479
480         if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)
481                 goto fail2;
482
483         return (0);
484
485 fail2:
486         EFSYS_PROBE(fail2);
487 fail1:
488         EFSYS_PROBE1(fail1, efx_rc_t, rc);
489
490         return (rc);
491 }
492
493         __checkReturn           efx_rc_t
494 siena_vpd_next(
495         __in                    efx_nic_t *enp,
496         __in_bcount(size)       caddr_t data,
497         __in                    size_t size,
498         __out                   efx_vpd_value_t *evvp,
499         __inout                 unsigned int *contp)
500 {
501         _NOTE(ARGUNUSED(enp, data, size, evvp, contp))
502
503         return (ENOTSUP);
504 }
505
506         __checkReturn           efx_rc_t
507 siena_vpd_write(
508         __in                    efx_nic_t *enp,
509         __in_bcount(size)       caddr_t data,
510         __in                    size_t size)
511 {
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;
517         unsigned int pos;
518         uint8_t cksum;
519         size_t partn_size, dcfg_size;
520         size_t vpd_length;
521         efx_rc_t rc;
522
523         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
524
525         /* Determine total length of all tags */
526         if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)
527                 goto fail1;
528
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;
533
534         if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &partn_size)) != 0)
535                 goto fail2;
536
537         if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0)
538                 goto fail3;
539
540         if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
541             B_FALSE, &dcfg, &dcfg_size)) != 0)
542                 goto fail4;
543
544         hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);
545
546         /* Allocated memory should have room for the new VPD */
547         if (hdr_length + vpd_length > dcfg_size) {
548                 rc = ENOSPC;
549                 goto fail5;
550         }
551
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);
557
558         /* Update the checksum */
559         cksum = 0;
560         for (pos = 0; pos < hdr_length; pos++)
561                 cksum += ((uint8_t *)dcfg)[pos];
562         dcfg->csum.eb_u8[0] -= cksum;
563
564         /* Erase and write the new sector */
565         if ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, partn_size)) != 0)
566                 goto fail6;
567
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)
571                 goto fail7;
572
573         EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
574
575         siena_nvram_partn_unlock(enp, dcfg_partn);
576
577         return (0);
578
579 fail7:
580         EFSYS_PROBE(fail7);
581 fail6:
582         EFSYS_PROBE(fail6);
583 fail5:
584         EFSYS_PROBE(fail5);
585
586         EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
587 fail4:
588         EFSYS_PROBE(fail4);
589
590         siena_nvram_partn_unlock(enp, dcfg_partn);
591 fail3:
592         EFSYS_PROBE(fail3);
593 fail2:
594         EFSYS_PROBE(fail2);
595 fail1:
596         EFSYS_PROBE1(fail1, efx_rc_t, rc);
597
598         return (rc);
599 }
600
601                                 void
602 siena_vpd_fini(
603         __in                    efx_nic_t *enp)
604 {
605         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
606
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);
610
611                 enp->en_u.siena.enu_svpd = NULL;
612                 enp->en_u.siena.enu_svpd_length = 0;
613         }
614 }
615
616 #endif  /* EFSYS_OPT_SIENA */
617
618 #endif  /* EFSYS_OPT_VPD */