2 * Copyright (c) 2009-2015 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
37 #if EFSYS_OPT_LICENSING
41 static __checkReturn efx_rc_t
42 efx_mcdi_fc_license_update_license(
45 static __checkReturn efx_rc_t
46 efx_mcdi_fc_license_get_key_stats(
48 __out efx_key_stats_t *eksp);
50 static 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 */
57 #endif /* EFSYS_OPT_SIENA */
59 #if EFSYS_OPT_HUNTINGTON
61 static __checkReturn efx_rc_t
62 efx_mcdi_licensing_update_licenses(
65 static __checkReturn efx_rc_t
66 efx_mcdi_licensing_get_key_stats(
68 __out efx_key_stats_t *eksp);
70 static __checkReturn efx_rc_t
71 efx_mcdi_licensed_app_state(
74 __out boolean_t *licensedp);
76 static 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 */
83 #endif /* EFSYS_OPT_HUNTINGTON */
87 static __checkReturn efx_rc_t
88 efx_mcdi_licensing_v3_update_licenses(
91 static __checkReturn efx_rc_t
92 efx_mcdi_licensing_v3_report_license(
94 __out efx_key_stats_t *eksp);
96 static __checkReturn efx_rc_t
97 efx_mcdi_licensing_v3_app_state(
100 __out boolean_t *licensedp);
102 static __checkReturn efx_rc_t
103 efx_mcdi_licensing_v3_get_id(
105 __in size_t buffer_size,
106 __out uint32_t *typep,
107 __out size_t *lengthp,
108 __out_bcount_part_opt(buffer_size, *lengthp)
111 static 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 */
118 #endif /* EFSYS_OPT_MEDFORD */
121 /* V1 Licensing - used in Siena Modena only */
125 static __checkReturn efx_rc_t
126 efx_mcdi_fc_license_update_license(
130 uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
133 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
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;
142 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
143 MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
145 efx_mcdi_execute(enp, &req);
147 if (req.emr_rc != 0) {
152 if (req.emr_out_length_used != 0) {
162 EFSYS_PROBE1(fail1, efx_rc_t, rc);
167 static __checkReturn efx_rc_t
168 efx_mcdi_fc_license_get_key_stats(
170 __out efx_key_stats_t *eksp)
173 uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
174 MC_CMD_FC_OUT_LICENSE_LEN)];
177 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
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;
186 MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
187 MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
189 efx_mcdi_execute(enp, &req);
191 if (req.emr_rc != 0) {
196 if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
202 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
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;
219 EFSYS_PROBE1(fail1, efx_rc_t, rc);
224 #endif /* EFSYS_OPT_SIENA */
226 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
228 #if EFSYS_OPT_HUNTINGTON
230 static __checkReturn efx_rc_t
231 efx_mcdi_licensed_app_state(
233 __in uint64_t app_id,
234 __out boolean_t *licensedp)
237 uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
238 MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
242 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
244 /* V2 licensing supports 32bit app id only */
245 if ((app_id >> 32) != 0) {
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;
257 MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
258 app_id & 0xffffffff);
260 efx_mcdi_execute(enp, &req);
262 if (req.emr_rc != 0) {
267 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
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) {
276 *licensedp = B_FALSE;
286 EFSYS_PROBE1(fail1, efx_rc_t, rc);
291 static __checkReturn efx_rc_t
292 efx_mcdi_licensing_update_licenses(
296 uint8_t payload[MC_CMD_LICENSING_IN_LEN];
299 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
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;
308 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
309 MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
311 efx_mcdi_execute(enp, &req);
313 if (req.emr_rc != 0) {
318 if (req.emr_out_length_used != 0) {
328 EFSYS_PROBE1(fail1, efx_rc_t, rc);
333 static __checkReturn efx_rc_t
334 efx_mcdi_licensing_get_key_stats(
336 __out efx_key_stats_t *eksp)
339 uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
340 MC_CMD_LICENSING_OUT_LEN)];
343 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
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;
352 MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
353 MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
355 efx_mcdi_execute(enp, &req);
357 if (req.emr_rc != 0) {
362 if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
368 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
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;
387 EFSYS_PROBE1(fail1, efx_rc_t, rc);
392 #endif /* EFSYS_OPT_HUNTINGTON */
394 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
396 #if EFSYS_OPT_MEDFORD
398 static __checkReturn efx_rc_t
399 efx_mcdi_licensing_v3_update_licenses(
403 uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
406 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
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;
415 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
416 MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
418 efx_mcdi_execute(enp, &req);
420 if (req.emr_rc != 0) {
428 EFSYS_PROBE1(fail1, efx_rc_t, rc);
433 static __checkReturn efx_rc_t
434 efx_mcdi_licensing_v3_report_license(
436 __out efx_key_stats_t *eksp)
439 uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
440 MC_CMD_LICENSING_V3_OUT_LEN)];
443 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
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;
452 MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
453 MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
455 efx_mcdi_execute(enp, &req);
457 if (req.emr_rc != 0) {
462 if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
468 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
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);
490 EFSYS_PROBE1(fail1, efx_rc_t, rc);
495 static __checkReturn efx_rc_t
496 efx_mcdi_licensing_v3_app_state(
498 __in uint64_t app_id,
499 __out boolean_t *licensedp)
502 uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
503 MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
507 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
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;
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,
521 efx_mcdi_execute(enp, &req);
523 if (req.emr_rc != 0) {
528 if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
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) {
537 *licensedp = B_FALSE;
545 EFSYS_PROBE1(fail1, efx_rc_t, rc);
550 static __checkReturn efx_rc_t
551 efx_mcdi_licensing_v3_get_id(
553 __in size_t buffer_size,
554 __out uint32_t *typep,
555 __out size_t *lengthp,
556 __out_bcount_part_opt(buffer_size, *lengthp)
560 uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
561 MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
564 req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
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));
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);
582 efx_mcdi_execute(enp, &req);
584 if (req.emr_rc != 0) {
589 if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
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);
597 if (bufferp == NULL) {
598 /* modify length requirements to indicate to caller the extra buffering
599 ** needed to read the complete output.
601 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
603 /* Shift ID down to start of buffer */
605 bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
607 memset(bufferp+(*lengthp), 0, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
615 EFSYS_PROBE1(fail1, efx_rc_t, rc);
621 #endif /* EFSYS_OPT_MEDFORD */
623 __checkReturn efx_rc_t
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));
634 switch (enp->en_family) {
637 case EFX_FAMILY_SIENA:
638 elop = (efx_lic_ops_t *)&__efx_lic_v1_ops;
640 #endif /* EFSYS_OPT_SIENA */
642 #if EFSYS_OPT_HUNTINGTON
643 case EFX_FAMILY_HUNTINGTON:
644 elop = (efx_lic_ops_t *)&__efx_lic_v2_ops;
646 #endif /* EFSYS_OPT_HUNTINGTON */
648 #if EFSYS_OPT_MEDFORD
649 case EFX_FAMILY_MEDFORD:
650 elop = (efx_lic_ops_t *)&__efx_lic_v3_ops;
652 #endif /* EFSYS_OPT_MEDFORD */
661 enp->en_mod_flags |= EFX_MOD_LIC;
666 EFSYS_PROBE1(fail1, efx_rc_t, rc);
675 efx_lic_ops_t *elop = enp->en_elop;
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);
682 enp->en_mod_flags &= ~EFX_MOD_LIC;
686 __checkReturn efx_rc_t
687 efx_lic_update_licenses(
690 efx_lic_ops_t *elop = enp->en_elop;
693 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
694 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
696 if ((rc = elop->elo_update_licenses(enp)) != 0)
702 EFSYS_PROBE1(fail1, efx_rc_t, rc);
707 __checkReturn efx_rc_t
708 efx_lic_get_key_stats(
710 __out efx_key_stats_t *eksp)
712 efx_lic_ops_t *elop = enp->en_elop;
715 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
716 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
718 if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
724 EFSYS_PROBE1(fail1, efx_rc_t, rc);
729 __checkReturn efx_rc_t
732 __in uint64_t app_id,
733 __out boolean_t *licensedp)
735 efx_lic_ops_t *elop = enp->en_elop;
738 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
739 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
741 if (elop->elo_app_state == NULL) {
745 if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
753 EFSYS_PROBE1(fail1, efx_rc_t, rc);
758 __checkReturn efx_rc_t
761 __in size_t buffer_size,
762 __out uint32_t *typep,
763 __out size_t *lengthp,
764 __out_opt uint8_t *bufferp
767 efx_lic_ops_t *elop = enp->en_elop;
770 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
771 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
773 if (elop->elo_get_id == NULL) {
778 if ((rc = elop->elo_get_id(enp, buffer_size, typep,
779 lengthp, bufferp)) != 0)
787 EFSYS_PROBE1(fail1, efx_rc_t, rc);
792 #endif /* EFSYS_OPT_LICENSING */