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