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