efx_lic.c revision 299517
1/*-
2 * Copyright (c) 2009-2015 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 <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_lic.c 299517 2016-05-12 06:19:06Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36
37#if EFSYS_OPT_LICENSING
38
39#if EFSYS_OPT_SIENA
40
41static	__checkReturn	efx_rc_t
42efx_mcdi_fc_license_update_license(
43	__in		efx_nic_t *enp);
44
45static	__checkReturn	efx_rc_t
46efx_mcdi_fc_license_get_key_stats(
47	__in		efx_nic_t *enp,
48	__out		efx_key_stats_t *eksp);
49
50static const efx_lic_ops_t	__efx_lic_v1_ops = {
51	efx_mcdi_fc_license_update_license,	/* elo_update_licenses */
52	efx_mcdi_fc_license_get_key_stats,	/* elo_get_key_stats */
53	NULL,					/* elo_app_state */
54	NULL,					/* elo_get_id */
55};
56
57#endif	/* EFSYS_OPT_SIENA */
58
59#if EFSYS_OPT_HUNTINGTON
60
61static	__checkReturn	efx_rc_t
62efx_mcdi_licensing_update_licenses(
63	__in		efx_nic_t *enp);
64
65static	__checkReturn	efx_rc_t
66efx_mcdi_licensing_get_key_stats(
67	__in		efx_nic_t *enp,
68	__out		efx_key_stats_t *eksp);
69
70static	__checkReturn	efx_rc_t
71efx_mcdi_licensed_app_state(
72	__in		efx_nic_t *enp,
73	__in		uint64_t app_id,
74	__out		boolean_t *licensedp);
75
76static const efx_lic_ops_t	__efx_lic_v2_ops = {
77	efx_mcdi_licensing_update_licenses,	/* elo_update_licenses */
78	efx_mcdi_licensing_get_key_stats,	/* elo_get_key_stats */
79	efx_mcdi_licensed_app_state,		/* elo_app_state */
80	NULL,					/* elo_get_id */
81};
82
83#endif	/* EFSYS_OPT_HUNTINGTON */
84
85#if EFSYS_OPT_MEDFORD
86
87static	__checkReturn	efx_rc_t
88efx_mcdi_licensing_v3_update_licenses(
89	__in		efx_nic_t *enp);
90
91static	__checkReturn	efx_rc_t
92efx_mcdi_licensing_v3_report_license(
93	__in		efx_nic_t *enp,
94	__out		efx_key_stats_t *eksp);
95
96static	__checkReturn	efx_rc_t
97efx_mcdi_licensing_v3_app_state(
98	__in		efx_nic_t *enp,
99	__in		uint64_t app_id,
100	__out		boolean_t *licensedp);
101
102static	__checkReturn	efx_rc_t
103efx_mcdi_licensing_v3_get_id(
104	__in		efx_nic_t *enp,
105	__in		size_t buffer_size,
106	__out		uint32_t *typep,
107	__out		size_t *lengthp,
108	__out_bcount_part_opt(buffer_size, *lengthp)
109			uint8_t *bufferp);
110
111static const efx_lic_ops_t	__efx_lic_v3_ops = {
112	efx_mcdi_licensing_v3_update_licenses,	/* elo_update_licenses */
113	efx_mcdi_licensing_v3_report_license,	/* elo_get_key_stats */
114	efx_mcdi_licensing_v3_app_state,	/* elo_app_state */
115	efx_mcdi_licensing_v3_get_id,		/* elo_get_id */
116};
117
118#endif	/* EFSYS_OPT_MEDFORD */
119
120
121/* V1 Licensing - used in Siena Modena only */
122
123#if EFSYS_OPT_SIENA
124
125static	__checkReturn	efx_rc_t
126efx_mcdi_fc_license_update_license(
127	__in		efx_nic_t *enp)
128{
129	efx_mcdi_req_t req;
130	uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
131	efx_rc_t rc;
132
133	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
134
135	(void) memset(payload, 0, sizeof (payload));
136	req.emr_cmd = MC_CMD_FC_OP_LICENSE;
137	req.emr_in_buf = payload;
138	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
139	req.emr_out_buf = payload;
140	req.emr_out_length = 0;
141
142	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
143	    MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
144
145	efx_mcdi_execute(enp, &req);
146
147	if (req.emr_rc != 0) {
148		rc = req.emr_rc;
149		goto fail1;
150	}
151
152	if (req.emr_out_length_used != 0) {
153		rc = EIO;
154		goto fail2;
155	}
156
157	return (0);
158
159fail2:
160	EFSYS_PROBE(fail2);
161fail1:
162	EFSYS_PROBE1(fail1, efx_rc_t, rc);
163
164	return (rc);
165}
166
167static	__checkReturn	efx_rc_t
168efx_mcdi_fc_license_get_key_stats(
169	__in		efx_nic_t *enp,
170	__out		efx_key_stats_t *eksp)
171{
172	efx_mcdi_req_t req;
173	uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
174			    MC_CMD_FC_OUT_LICENSE_LEN)];
175	efx_rc_t rc;
176
177	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
178
179	(void) memset(payload, 0, sizeof (payload));
180	req.emr_cmd = MC_CMD_FC_OP_LICENSE;
181	req.emr_in_buf = payload;
182	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
183	req.emr_out_buf = payload;
184	req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
185
186	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
187	    MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
188
189	efx_mcdi_execute(enp, &req);
190
191	if (req.emr_rc != 0) {
192		rc = req.emr_rc;
193		goto fail1;
194	}
195
196	if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
197		rc = EMSGSIZE;
198		goto fail2;
199	}
200
201	eksp->eks_valid =
202		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
203	eksp->eks_invalid =
204		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
205	eksp->eks_blacklisted =
206		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
207	eksp->eks_unverifiable = 0;
208	eksp->eks_wrong_node = 0;
209	eksp->eks_licensed_apps_lo = 0;
210	eksp->eks_licensed_apps_hi = 0;
211	eksp->eks_licensed_features_lo = 0;
212	eksp->eks_licensed_features_hi = 0;
213
214	return (0);
215
216fail2:
217	EFSYS_PROBE(fail2);
218fail1:
219	EFSYS_PROBE1(fail1, efx_rc_t, rc);
220
221	return (rc);
222}
223
224#endif	/* EFSYS_OPT_SIENA */
225
226/* V2 Licensing - used by Huntington family only. See SF-113611-TC */
227
228#if EFSYS_OPT_HUNTINGTON
229
230static	__checkReturn	efx_rc_t
231efx_mcdi_licensed_app_state(
232	__in		efx_nic_t *enp,
233	__in		uint64_t app_id,
234	__out		boolean_t *licensedp)
235{
236	efx_mcdi_req_t req;
237	uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
238			    MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
239	uint32_t app_state;
240	efx_rc_t rc;
241
242	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
243
244	/* V2 licensing supports 32bit app id only */
245	if ((app_id >> 32) != 0) {
246		rc = EINVAL;
247		goto fail1;
248	}
249
250	(void) memset(payload, 0, sizeof (payload));
251	req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
252	req.emr_in_buf = payload;
253	req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
254	req.emr_out_buf = payload;
255	req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
256
257	MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
258		    app_id & 0xffffffff);
259
260	efx_mcdi_execute(enp, &req);
261
262	if (req.emr_rc != 0) {
263		rc = req.emr_rc;
264		goto fail2;
265	}
266
267	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
268		rc = EMSGSIZE;
269		goto fail3;
270	}
271
272	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
273	if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
274		*licensedp = B_TRUE;
275	} else {
276		*licensedp = B_FALSE;
277	}
278
279	return (0);
280
281fail3:
282	EFSYS_PROBE(fail3);
283fail2:
284	EFSYS_PROBE(fail2);
285fail1:
286	EFSYS_PROBE1(fail1, efx_rc_t, rc);
287
288	return (rc);
289}
290
291static	__checkReturn	efx_rc_t
292efx_mcdi_licensing_update_licenses(
293	__in		efx_nic_t *enp)
294{
295	efx_mcdi_req_t req;
296	uint8_t payload[MC_CMD_LICENSING_IN_LEN];
297	efx_rc_t rc;
298
299	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
300
301	(void) memset(payload, 0, sizeof (payload));
302	req.emr_cmd = MC_CMD_LICENSING;
303	req.emr_in_buf = payload;
304	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
305	req.emr_out_buf = payload;
306	req.emr_out_length = 0;
307
308	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
309	    MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
310
311	efx_mcdi_execute(enp, &req);
312
313	if (req.emr_rc != 0) {
314		rc = req.emr_rc;
315		goto fail1;
316	}
317
318	if (req.emr_out_length_used != 0) {
319		rc = EIO;
320		goto fail2;
321	}
322
323	return (0);
324
325fail2:
326	EFSYS_PROBE(fail2);
327fail1:
328	EFSYS_PROBE1(fail1, efx_rc_t, rc);
329
330	return (rc);
331}
332
333static	__checkReturn	efx_rc_t
334efx_mcdi_licensing_get_key_stats(
335	__in		efx_nic_t *enp,
336	__out		efx_key_stats_t *eksp)
337{
338	efx_mcdi_req_t req;
339	uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
340			    MC_CMD_LICENSING_OUT_LEN)];
341	efx_rc_t rc;
342
343	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
344
345	(void) memset(payload, 0, sizeof (payload));
346	req.emr_cmd = MC_CMD_LICENSING;
347	req.emr_in_buf = payload;
348	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
349	req.emr_out_buf = payload;
350	req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
351
352	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
353	    MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
354
355	efx_mcdi_execute(enp, &req);
356
357	if (req.emr_rc != 0) {
358		rc = req.emr_rc;
359		goto fail1;
360	}
361
362	if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
363		rc = EMSGSIZE;
364		goto fail2;
365	}
366
367	eksp->eks_valid =
368		MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
369	eksp->eks_invalid =
370		MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
371	eksp->eks_blacklisted =
372		MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
373	eksp->eks_unverifiable =
374		MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
375	eksp->eks_wrong_node =
376		MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
377	eksp->eks_licensed_apps_lo = 0;
378	eksp->eks_licensed_apps_hi = 0;
379	eksp->eks_licensed_features_lo = 0;
380	eksp->eks_licensed_features_hi = 0;
381
382	return (0);
383
384fail2:
385	EFSYS_PROBE(fail2);
386fail1:
387	EFSYS_PROBE1(fail1, efx_rc_t, rc);
388
389	return (rc);
390}
391
392#endif	/* EFSYS_OPT_HUNTINGTON */
393
394/* V3 Licensing - used starting from Medford family. See SF-114884-SW */
395
396#if EFSYS_OPT_MEDFORD
397
398static	__checkReturn	efx_rc_t
399efx_mcdi_licensing_v3_update_licenses(
400	__in		efx_nic_t *enp)
401{
402	efx_mcdi_req_t req;
403	uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
404	efx_rc_t rc;
405
406	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
407
408	(void) memset(payload, 0, sizeof (payload));
409	req.emr_cmd = MC_CMD_LICENSING_V3;
410	req.emr_in_buf = payload;
411	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
412	req.emr_out_buf = NULL;
413	req.emr_out_length = 0;
414
415	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
416	    MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
417
418	efx_mcdi_execute(enp, &req);
419
420	if (req.emr_rc != 0) {
421		rc = req.emr_rc;
422		goto fail1;
423	}
424
425	return (0);
426
427fail1:
428	EFSYS_PROBE1(fail1, efx_rc_t, rc);
429
430	return (rc);
431}
432
433static	__checkReturn	efx_rc_t
434efx_mcdi_licensing_v3_report_license(
435	__in		efx_nic_t *enp,
436	__out		efx_key_stats_t *eksp)
437{
438	efx_mcdi_req_t req;
439	uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
440			    MC_CMD_LICENSING_V3_OUT_LEN)];
441	efx_rc_t rc;
442
443	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
444
445	(void) memset(payload, 0, sizeof (payload));
446	req.emr_cmd = MC_CMD_LICENSING_V3;
447	req.emr_in_buf = payload;
448	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
449	req.emr_out_buf = payload;
450	req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
451
452	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
453	    MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
454
455	efx_mcdi_execute(enp, &req);
456
457	if (req.emr_rc != 0) {
458		rc = req.emr_rc;
459		goto fail1;
460	}
461
462	if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
463		rc = EMSGSIZE;
464		goto fail2;
465	}
466
467	eksp->eks_valid =
468		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
469	eksp->eks_invalid =
470		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
471	eksp->eks_blacklisted = 0;
472	eksp->eks_unverifiable =
473		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
474	eksp->eks_wrong_node =
475		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
476	eksp->eks_licensed_apps_lo =
477		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
478	eksp->eks_licensed_apps_hi =
479		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
480	eksp->eks_licensed_features_lo =
481		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
482	eksp->eks_licensed_features_hi =
483		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
484
485	return (0);
486
487fail2:
488	EFSYS_PROBE(fail2);
489fail1:
490	EFSYS_PROBE1(fail1, efx_rc_t, rc);
491
492	return (rc);
493}
494
495static	__checkReturn	efx_rc_t
496efx_mcdi_licensing_v3_app_state(
497	__in		efx_nic_t *enp,
498	__in		uint64_t app_id,
499	__out		boolean_t *licensedp)
500{
501	efx_mcdi_req_t req;
502	uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
503			    MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
504	uint32_t app_state;
505	efx_rc_t rc;
506
507	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
508
509	(void) memset(payload, 0, sizeof (payload));
510	req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
511	req.emr_in_buf = payload;
512	req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
513	req.emr_out_buf = payload;
514	req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
515
516	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
517		    app_id & 0xffffffff);
518	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
519		    app_id >> 32);
520
521	efx_mcdi_execute(enp, &req);
522
523	if (req.emr_rc != 0) {
524		rc = req.emr_rc;
525		goto fail1;
526	}
527
528	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
529		rc = EMSGSIZE;
530		goto fail2;
531	}
532
533	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
534	if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
535		*licensedp = B_TRUE;
536	} else {
537		*licensedp = B_FALSE;
538	}
539
540	return (0);
541
542fail2:
543	EFSYS_PROBE(fail2);
544fail1:
545	EFSYS_PROBE1(fail1, efx_rc_t, rc);
546
547	return (rc);
548}
549
550static	__checkReturn	efx_rc_t
551efx_mcdi_licensing_v3_get_id(
552	__in		efx_nic_t *enp,
553	__in		size_t buffer_size,
554	__out		uint32_t *typep,
555	__out		size_t *lengthp,
556	__out_bcount_part_opt(buffer_size, *lengthp)
557			uint8_t *bufferp)
558{
559	efx_mcdi_req_t req;
560	uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
561			    MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
562	efx_rc_t rc;
563
564	req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
565
566	if (bufferp == NULL) {
567		/* Request id type and length only */
568		req.emr_in_buf = bufferp;
569		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
570		req.emr_out_buf = bufferp;
571		req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
572		(void) memset(payload, 0, sizeof (payload));
573	} else {
574		/* Request full buffer */
575		req.emr_in_buf = bufferp;
576		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
577		req.emr_out_buf = bufferp;
578		req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN);
579		(void) memset(bufferp, 0, req.emr_out_length);
580	}
581
582	efx_mcdi_execute(enp, &req);
583
584	if (req.emr_rc != 0) {
585		rc = req.emr_rc;
586		goto fail1;
587	}
588
589	if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
590		rc = EMSGSIZE;
591		goto fail2;
592	}
593
594	*typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
595	*lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
596
597	if (bufferp == NULL) {
598		/* modify length requirements to indicate to caller the extra buffering
599		** needed to read the complete output.
600		*/
601		*lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
602	} else {
603		/* Shift ID down to start of buffer */
604		memmove(bufferp,
605		  bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
606		  *lengthp);
607		memset(bufferp+(*lengthp), 0, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
608	}
609
610	return (0);
611
612fail2:
613	EFSYS_PROBE(fail2);
614fail1:
615	EFSYS_PROBE1(fail1, efx_rc_t, rc);
616
617	return (rc);
618}
619
620
621#endif	/* EFSYS_OPT_MEDFORD */
622
623	__checkReturn		efx_rc_t
624efx_lic_init(
625	__in			efx_nic_t *enp)
626{
627	const efx_lic_ops_t *elop;
628	efx_rc_t rc;
629
630	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
631	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
632	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
633
634	switch (enp->en_family) {
635
636#if EFSYS_OPT_SIENA
637	case EFX_FAMILY_SIENA:
638		elop = &__efx_lic_v1_ops;
639		break;
640#endif	/* EFSYS_OPT_SIENA */
641
642#if EFSYS_OPT_HUNTINGTON
643	case EFX_FAMILY_HUNTINGTON:
644		elop = &__efx_lic_v2_ops;
645		break;
646#endif	/* EFSYS_OPT_HUNTINGTON */
647
648#if EFSYS_OPT_MEDFORD
649	case EFX_FAMILY_MEDFORD:
650		elop = &__efx_lic_v3_ops;
651		break;
652#endif	/* EFSYS_OPT_MEDFORD */
653
654	default:
655		EFSYS_ASSERT(0);
656		rc = ENOTSUP;
657		goto fail1;
658	}
659
660	enp->en_elop = elop;
661	enp->en_mod_flags |= EFX_MOD_LIC;
662
663	return (0);
664
665fail1:
666	EFSYS_PROBE1(fail1, efx_rc_t, rc);
667
668	return (rc);
669}
670
671				void
672efx_lic_fini(
673	__in			efx_nic_t *enp)
674{
675	const efx_lic_ops_t *elop = enp->en_elop;
676
677	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
678	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
679	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
680
681	enp->en_elop = NULL;
682	enp->en_mod_flags &= ~EFX_MOD_LIC;
683}
684
685
686	__checkReturn	efx_rc_t
687efx_lic_update_licenses(
688	__in		efx_nic_t *enp)
689{
690	const efx_lic_ops_t *elop = enp->en_elop;
691	efx_rc_t rc;
692
693	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
694	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
695
696	if ((rc = elop->elo_update_licenses(enp)) != 0)
697		goto fail1;
698
699	return (0);
700
701fail1:
702	EFSYS_PROBE1(fail1, efx_rc_t, rc);
703
704	return (rc);
705}
706
707	__checkReturn	efx_rc_t
708efx_lic_get_key_stats(
709	__in		efx_nic_t *enp,
710	__out		efx_key_stats_t *eksp)
711{
712	const efx_lic_ops_t *elop = enp->en_elop;
713	efx_rc_t rc;
714
715	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
716	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
717
718	if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
719		goto fail1;
720
721	return (0);
722
723fail1:
724	EFSYS_PROBE1(fail1, efx_rc_t, rc);
725
726	return (rc);
727}
728
729	__checkReturn	efx_rc_t
730efx_lic_app_state(
731	__in		efx_nic_t *enp,
732	__in		uint64_t app_id,
733	__out		boolean_t *licensedp)
734{
735	const efx_lic_ops_t *elop = enp->en_elop;
736	efx_rc_t rc;
737
738	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
739	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
740
741	if (elop->elo_app_state == NULL) {
742		rc = ENOTSUP;
743		goto fail1;
744	}
745	if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
746		goto fail2;
747
748	return (0);
749
750fail2:
751	EFSYS_PROBE(fail2);
752fail1:
753	EFSYS_PROBE1(fail1, efx_rc_t, rc);
754
755	return (rc);
756}
757
758	__checkReturn	efx_rc_t
759efx_lic_get_id(
760	__in		efx_nic_t *enp,
761	__in		size_t buffer_size,
762	__out		uint32_t *typep,
763	__out		size_t *lengthp,
764	__out_opt	uint8_t *bufferp
765	)
766{
767	const efx_lic_ops_t *elop = enp->en_elop;
768	efx_rc_t rc;
769
770	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
771	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
772
773	if (elop->elo_get_id == NULL) {
774		rc = ENOTSUP;
775		goto fail1;
776	}
777
778	if ((rc = elop->elo_get_id(enp, buffer_size, typep,
779				    lengthp, bufferp)) != 0)
780		goto fail2;
781
782	return (0);
783
784fail2:
785	EFSYS_PROBE(fail2);
786fail1:
787	EFSYS_PROBE1(fail1, efx_rc_t, rc);
788
789	return (rc);
790}
791
792#endif	/* EFSYS_OPT_LICENSING */
793