1293901Sarybchik/*-
2293901Sarybchik * Copyright (c) 2009-2015 Solarflare Communications Inc.
3293901Sarybchik * All rights reserved.
4293901Sarybchik *
5293901Sarybchik * Redistribution and use in source and binary forms, with or without
6293901Sarybchik * modification, are permitted provided that the following conditions are met:
7293901Sarybchik *
8293901Sarybchik * 1. Redistributions of source code must retain the above copyright notice,
9293901Sarybchik *    this list of conditions and the following disclaimer.
10293901Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice,
11293901Sarybchik *    this list of conditions and the following disclaimer in the documentation
12293901Sarybchik *    and/or other materials provided with the distribution.
13293901Sarybchik *
14293901Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15293901Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16293901Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17293901Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18293901Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19293901Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20293901Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21293901Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22293901Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23293901Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24293901Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25293901Sarybchik *
26293901Sarybchik * The views and conclusions contained in the software and documentation are
27293901Sarybchik * those of the authors and should not be interpreted as representing official
28293901Sarybchik * policies, either expressed or implied, of the FreeBSD Project.
29293901Sarybchik */
30293901Sarybchik
31293901Sarybchik#include <sys/cdefs.h>
32293901Sarybchik__FBSDID("$FreeBSD: releng/10.3/sys/dev/sfxge/common/efx_lic.c 294386 2016-01-20 08:01:21Z arybchik $");
33293901Sarybchik
34293901Sarybchik#include "efx.h"
35293901Sarybchik#include "efx_impl.h"
36293901Sarybchik
37293901Sarybchik#if EFSYS_OPT_LICENSING
38293901Sarybchik
39293901Sarybchik#if EFSYS_OPT_SIENA
40293901Sarybchik
41293901Sarybchikstatic	__checkReturn	efx_rc_t
42293901Sarybchikefx_mcdi_fc_license_update_license(
43293901Sarybchik	__in		efx_nic_t *enp);
44293901Sarybchik
45293901Sarybchikstatic	__checkReturn	efx_rc_t
46293901Sarybchikefx_mcdi_fc_license_get_key_stats(
47293901Sarybchik	__in		efx_nic_t *enp,
48293901Sarybchik	__out		efx_key_stats_t *eksp);
49293901Sarybchik
50293901Sarybchikstatic efx_lic_ops_t	__efx_lic_v1_ops = {
51293901Sarybchik	efx_mcdi_fc_license_update_license,	/* elo_update_licenses */
52293901Sarybchik	efx_mcdi_fc_license_get_key_stats,	/* elo_get_key_stats */
53293901Sarybchik	NULL,					/* elo_app_state */
54293901Sarybchik	NULL,					/* elo_get_id */
55293901Sarybchik};
56293901Sarybchik
57293901Sarybchik#endif	/* EFSYS_OPT_SIENA */
58293901Sarybchik
59293901Sarybchik#if EFSYS_OPT_HUNTINGTON
60293901Sarybchik
61293901Sarybchikstatic	__checkReturn	efx_rc_t
62293901Sarybchikefx_mcdi_licensing_update_licenses(
63293901Sarybchik	__in		efx_nic_t *enp);
64293901Sarybchik
65293901Sarybchikstatic	__checkReturn	efx_rc_t
66293901Sarybchikefx_mcdi_licensing_get_key_stats(
67293901Sarybchik	__in		efx_nic_t *enp,
68293901Sarybchik	__out		efx_key_stats_t *eksp);
69293901Sarybchik
70293901Sarybchikstatic	__checkReturn	efx_rc_t
71293901Sarybchikefx_mcdi_licensed_app_state(
72293901Sarybchik	__in		efx_nic_t *enp,
73293901Sarybchik	__in		uint64_t app_id,
74293901Sarybchik	__out		boolean_t *licensedp);
75293901Sarybchik
76293901Sarybchikstatic efx_lic_ops_t	__efx_lic_v2_ops = {
77293901Sarybchik	efx_mcdi_licensing_update_licenses,	/* elo_update_licenses */
78293901Sarybchik	efx_mcdi_licensing_get_key_stats,	/* elo_get_key_stats */
79293901Sarybchik	efx_mcdi_licensed_app_state,		/* elo_app_state */
80293901Sarybchik	NULL,					/* elo_get_id */
81293901Sarybchik};
82293901Sarybchik
83293901Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON */
84293901Sarybchik
85293901Sarybchik#if EFSYS_OPT_MEDFORD
86293901Sarybchik
87293901Sarybchikstatic	__checkReturn	efx_rc_t
88293901Sarybchikefx_mcdi_licensing_v3_update_licenses(
89293901Sarybchik	__in		efx_nic_t *enp);
90293901Sarybchik
91293901Sarybchikstatic	__checkReturn	efx_rc_t
92293901Sarybchikefx_mcdi_licensing_v3_report_license(
93293901Sarybchik	__in		efx_nic_t *enp,
94293901Sarybchik	__out		efx_key_stats_t *eksp);
95293901Sarybchik
96293901Sarybchikstatic	__checkReturn	efx_rc_t
97293901Sarybchikefx_mcdi_licensing_v3_app_state(
98293901Sarybchik	__in		efx_nic_t *enp,
99293901Sarybchik	__in		uint64_t app_id,
100293901Sarybchik	__out		boolean_t *licensedp);
101293901Sarybchik
102293901Sarybchikstatic	__checkReturn	efx_rc_t
103293901Sarybchikefx_mcdi_licensing_v3_get_id(
104293901Sarybchik	__in		efx_nic_t *enp,
105293901Sarybchik	__in		size_t buffer_size,
106293901Sarybchik	__out		uint32_t *typep,
107293901Sarybchik	__out		size_t *lengthp,
108293901Sarybchik	__out_bcount_part_opt(buffer_size, *lengthp)
109293901Sarybchik			uint8_t *bufferp);
110293901Sarybchik
111293901Sarybchikstatic efx_lic_ops_t	__efx_lic_v3_ops = {
112293901Sarybchik	efx_mcdi_licensing_v3_update_licenses,	/* elo_update_licenses */
113293901Sarybchik	efx_mcdi_licensing_v3_report_license,	/* elo_get_key_stats */
114293901Sarybchik	efx_mcdi_licensing_v3_app_state,	/* elo_app_state */
115293901Sarybchik	efx_mcdi_licensing_v3_get_id,		/* elo_get_id */
116293901Sarybchik};
117293901Sarybchik
118293901Sarybchik#endif	/* EFSYS_OPT_MEDFORD */
119293901Sarybchik
120293901Sarybchik
121293901Sarybchik/* V1 Licensing - used in Siena Modena only */
122293901Sarybchik
123293901Sarybchik#if EFSYS_OPT_SIENA
124293901Sarybchik
125293901Sarybchikstatic	__checkReturn	efx_rc_t
126293901Sarybchikefx_mcdi_fc_license_update_license(
127293901Sarybchik	__in		efx_nic_t *enp)
128293901Sarybchik{
129293901Sarybchik	efx_mcdi_req_t req;
130293901Sarybchik	uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
131293901Sarybchik	efx_rc_t rc;
132293901Sarybchik
133293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
134293901Sarybchik
135293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
136293901Sarybchik	req.emr_cmd = MC_CMD_FC_OP_LICENSE;
137293901Sarybchik	req.emr_in_buf = payload;
138293901Sarybchik	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
139293901Sarybchik	req.emr_out_buf = payload;
140293901Sarybchik	req.emr_out_length = 0;
141293901Sarybchik
142293901Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
143293901Sarybchik	    MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
144293901Sarybchik
145293901Sarybchik	efx_mcdi_execute(enp, &req);
146293901Sarybchik
147293901Sarybchik	if (req.emr_rc != 0) {
148293901Sarybchik		rc = req.emr_rc;
149293901Sarybchik		goto fail1;
150293901Sarybchik	}
151293901Sarybchik
152293901Sarybchik	if (req.emr_out_length_used != 0) {
153293901Sarybchik		rc = EIO;
154293901Sarybchik		goto fail2;
155293901Sarybchik	}
156293901Sarybchik
157293901Sarybchik	return (0);
158293901Sarybchik
159293901Sarybchikfail2:
160293901Sarybchik	EFSYS_PROBE(fail2);
161293901Sarybchikfail1:
162293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
163293901Sarybchik
164293901Sarybchik	return (rc);
165293901Sarybchik}
166293901Sarybchik
167293901Sarybchikstatic	__checkReturn	efx_rc_t
168293901Sarybchikefx_mcdi_fc_license_get_key_stats(
169293901Sarybchik	__in		efx_nic_t *enp,
170293901Sarybchik	__out		efx_key_stats_t *eksp)
171293901Sarybchik{
172293901Sarybchik	efx_mcdi_req_t req;
173293901Sarybchik	uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
174293901Sarybchik			    MC_CMD_FC_OUT_LICENSE_LEN)];
175293901Sarybchik	efx_rc_t rc;
176293901Sarybchik
177293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
178293901Sarybchik
179293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
180293901Sarybchik	req.emr_cmd = MC_CMD_FC_OP_LICENSE;
181293901Sarybchik	req.emr_in_buf = payload;
182293901Sarybchik	req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
183293901Sarybchik	req.emr_out_buf = payload;
184293901Sarybchik	req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
185293901Sarybchik
186293901Sarybchik	MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
187293901Sarybchik	    MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
188293901Sarybchik
189293901Sarybchik	efx_mcdi_execute(enp, &req);
190293901Sarybchik
191293901Sarybchik	if (req.emr_rc != 0) {
192293901Sarybchik		rc = req.emr_rc;
193293901Sarybchik		goto fail1;
194293901Sarybchik	}
195293901Sarybchik
196293901Sarybchik	if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
197293901Sarybchik		rc = EMSGSIZE;
198293901Sarybchik		goto fail2;
199293901Sarybchik	}
200293901Sarybchik
201293901Sarybchik	eksp->eks_valid =
202293901Sarybchik		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
203293901Sarybchik	eksp->eks_invalid =
204293901Sarybchik		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
205293901Sarybchik	eksp->eks_blacklisted =
206293901Sarybchik		MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
207293901Sarybchik	eksp->eks_unverifiable = 0;
208293901Sarybchik	eksp->eks_wrong_node = 0;
209293901Sarybchik	eksp->eks_licensed_apps_lo = 0;
210293901Sarybchik	eksp->eks_licensed_apps_hi = 0;
211293901Sarybchik	eksp->eks_licensed_features_lo = 0;
212293901Sarybchik	eksp->eks_licensed_features_hi = 0;
213293901Sarybchik
214293901Sarybchik	return (0);
215293901Sarybchik
216293901Sarybchikfail2:
217293901Sarybchik	EFSYS_PROBE(fail2);
218293901Sarybchikfail1:
219293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
220293901Sarybchik
221293901Sarybchik	return (rc);
222293901Sarybchik}
223293901Sarybchik
224293901Sarybchik#endif	/* EFSYS_OPT_SIENA */
225293901Sarybchik
226293901Sarybchik/* V2 Licensing - used by Huntington family only. See SF-113611-TC */
227293901Sarybchik
228293901Sarybchik#if EFSYS_OPT_HUNTINGTON
229293901Sarybchik
230293901Sarybchikstatic	__checkReturn	efx_rc_t
231293901Sarybchikefx_mcdi_licensed_app_state(
232293901Sarybchik	__in		efx_nic_t *enp,
233293901Sarybchik	__in		uint64_t app_id,
234293901Sarybchik	__out		boolean_t *licensedp)
235293901Sarybchik{
236293901Sarybchik	efx_mcdi_req_t req;
237293901Sarybchik	uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
238293901Sarybchik			    MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
239293901Sarybchik	uint32_t app_state;
240293901Sarybchik	efx_rc_t rc;
241293901Sarybchik
242293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
243293901Sarybchik
244293901Sarybchik	/* V2 licensing supports 32bit app id only */
245293901Sarybchik	if ((app_id >> 32) != 0) {
246293901Sarybchik		rc = EINVAL;
247293901Sarybchik		goto fail1;
248293901Sarybchik	}
249293901Sarybchik
250293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
251293901Sarybchik	req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
252293901Sarybchik	req.emr_in_buf = payload;
253293901Sarybchik	req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
254293901Sarybchik	req.emr_out_buf = payload;
255293901Sarybchik	req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
256293901Sarybchik
257293901Sarybchik	MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
258293901Sarybchik		    app_id & 0xffffffff);
259293901Sarybchik
260293901Sarybchik	efx_mcdi_execute(enp, &req);
261293901Sarybchik
262293901Sarybchik	if (req.emr_rc != 0) {
263293901Sarybchik		rc = req.emr_rc;
264293901Sarybchik		goto fail2;
265293901Sarybchik	}
266293901Sarybchik
267293901Sarybchik	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
268293901Sarybchik		rc = EMSGSIZE;
269293901Sarybchik		goto fail3;
270293901Sarybchik	}
271293901Sarybchik
272293901Sarybchik	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
273293901Sarybchik	if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
274293901Sarybchik		*licensedp = B_TRUE;
275293901Sarybchik	} else {
276293901Sarybchik		*licensedp = B_FALSE;
277293901Sarybchik	}
278293901Sarybchik
279293901Sarybchik	return (0);
280293901Sarybchik
281293901Sarybchikfail3:
282293901Sarybchik	EFSYS_PROBE(fail3);
283293901Sarybchikfail2:
284293901Sarybchik	EFSYS_PROBE(fail2);
285293901Sarybchikfail1:
286293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
287293901Sarybchik
288293901Sarybchik	return (rc);
289293901Sarybchik}
290293901Sarybchik
291293901Sarybchikstatic	__checkReturn	efx_rc_t
292293901Sarybchikefx_mcdi_licensing_update_licenses(
293293901Sarybchik	__in		efx_nic_t *enp)
294293901Sarybchik{
295293901Sarybchik	efx_mcdi_req_t req;
296293901Sarybchik	uint8_t payload[MC_CMD_LICENSING_IN_LEN];
297293901Sarybchik	efx_rc_t rc;
298293901Sarybchik
299293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
300293901Sarybchik
301293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
302293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING;
303293901Sarybchik	req.emr_in_buf = payload;
304293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
305293901Sarybchik	req.emr_out_buf = payload;
306293901Sarybchik	req.emr_out_length = 0;
307293901Sarybchik
308293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
309293901Sarybchik	    MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
310293901Sarybchik
311293901Sarybchik	efx_mcdi_execute(enp, &req);
312293901Sarybchik
313293901Sarybchik	if (req.emr_rc != 0) {
314293901Sarybchik		rc = req.emr_rc;
315293901Sarybchik		goto fail1;
316293901Sarybchik	}
317293901Sarybchik
318293901Sarybchik	if (req.emr_out_length_used != 0) {
319293901Sarybchik		rc = EIO;
320293901Sarybchik		goto fail2;
321293901Sarybchik	}
322293901Sarybchik
323293901Sarybchik	return (0);
324293901Sarybchik
325293901Sarybchikfail2:
326293901Sarybchik	EFSYS_PROBE(fail2);
327293901Sarybchikfail1:
328293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
329293901Sarybchik
330293901Sarybchik	return (rc);
331293901Sarybchik}
332293901Sarybchik
333293901Sarybchikstatic	__checkReturn	efx_rc_t
334293901Sarybchikefx_mcdi_licensing_get_key_stats(
335293901Sarybchik	__in		efx_nic_t *enp,
336293901Sarybchik	__out		efx_key_stats_t *eksp)
337293901Sarybchik{
338293901Sarybchik	efx_mcdi_req_t req;
339293901Sarybchik	uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
340293901Sarybchik			    MC_CMD_LICENSING_OUT_LEN)];
341293901Sarybchik	efx_rc_t rc;
342293901Sarybchik
343293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
344293901Sarybchik
345293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
346293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING;
347293901Sarybchik	req.emr_in_buf = payload;
348293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
349293901Sarybchik	req.emr_out_buf = payload;
350293901Sarybchik	req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
351293901Sarybchik
352293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
353293901Sarybchik	    MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
354293901Sarybchik
355293901Sarybchik	efx_mcdi_execute(enp, &req);
356293901Sarybchik
357293901Sarybchik	if (req.emr_rc != 0) {
358293901Sarybchik		rc = req.emr_rc;
359293901Sarybchik		goto fail1;
360293901Sarybchik	}
361293901Sarybchik
362293901Sarybchik	if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
363293901Sarybchik		rc = EMSGSIZE;
364293901Sarybchik		goto fail2;
365293901Sarybchik	}
366293901Sarybchik
367293901Sarybchik	eksp->eks_valid =
368293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
369293901Sarybchik	eksp->eks_invalid =
370293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
371293901Sarybchik	eksp->eks_blacklisted =
372293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
373293901Sarybchik	eksp->eks_unverifiable =
374293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
375293901Sarybchik	eksp->eks_wrong_node =
376293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
377293901Sarybchik	eksp->eks_licensed_apps_lo = 0;
378293901Sarybchik	eksp->eks_licensed_apps_hi = 0;
379293901Sarybchik	eksp->eks_licensed_features_lo = 0;
380293901Sarybchik	eksp->eks_licensed_features_hi = 0;
381293901Sarybchik
382293901Sarybchik	return (0);
383293901Sarybchik
384293901Sarybchikfail2:
385293901Sarybchik	EFSYS_PROBE(fail2);
386293901Sarybchikfail1:
387293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
388293901Sarybchik
389293901Sarybchik	return (rc);
390293901Sarybchik}
391293901Sarybchik
392293901Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON */
393293901Sarybchik
394293901Sarybchik/* V3 Licensing - used starting from Medford family. See SF-114884-SW */
395293901Sarybchik
396293901Sarybchik#if EFSYS_OPT_MEDFORD
397293901Sarybchik
398293901Sarybchikstatic	__checkReturn	efx_rc_t
399293901Sarybchikefx_mcdi_licensing_v3_update_licenses(
400293901Sarybchik	__in		efx_nic_t *enp)
401293901Sarybchik{
402293901Sarybchik	efx_mcdi_req_t req;
403293901Sarybchik	uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
404293901Sarybchik	efx_rc_t rc;
405293901Sarybchik
406293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
407293901Sarybchik
408293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
409293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING_V3;
410293901Sarybchik	req.emr_in_buf = payload;
411293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
412293901Sarybchik	req.emr_out_buf = NULL;
413293901Sarybchik	req.emr_out_length = 0;
414293901Sarybchik
415293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
416293901Sarybchik	    MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
417293901Sarybchik
418293901Sarybchik	efx_mcdi_execute(enp, &req);
419293901Sarybchik
420293901Sarybchik	if (req.emr_rc != 0) {
421293901Sarybchik		rc = req.emr_rc;
422293901Sarybchik		goto fail1;
423293901Sarybchik	}
424293901Sarybchik
425293901Sarybchik	return (0);
426293901Sarybchik
427293901Sarybchikfail1:
428293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
429293901Sarybchik
430293901Sarybchik	return (rc);
431293901Sarybchik}
432293901Sarybchik
433293901Sarybchikstatic	__checkReturn	efx_rc_t
434293901Sarybchikefx_mcdi_licensing_v3_report_license(
435293901Sarybchik	__in		efx_nic_t *enp,
436293901Sarybchik	__out		efx_key_stats_t *eksp)
437293901Sarybchik{
438293901Sarybchik	efx_mcdi_req_t req;
439293901Sarybchik	uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
440293901Sarybchik			    MC_CMD_LICENSING_V3_OUT_LEN)];
441293901Sarybchik	efx_rc_t rc;
442293901Sarybchik
443293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
444293901Sarybchik
445293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
446293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING_V3;
447293901Sarybchik	req.emr_in_buf = payload;
448293901Sarybchik	req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
449293901Sarybchik	req.emr_out_buf = payload;
450293901Sarybchik	req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
451293901Sarybchik
452293901Sarybchik	MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
453293901Sarybchik	    MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
454293901Sarybchik
455293901Sarybchik	efx_mcdi_execute(enp, &req);
456293901Sarybchik
457293901Sarybchik	if (req.emr_rc != 0) {
458293901Sarybchik		rc = req.emr_rc;
459293901Sarybchik		goto fail1;
460293901Sarybchik	}
461293901Sarybchik
462293901Sarybchik	if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
463293901Sarybchik		rc = EMSGSIZE;
464293901Sarybchik		goto fail2;
465293901Sarybchik	}
466293901Sarybchik
467293901Sarybchik	eksp->eks_valid =
468293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
469293901Sarybchik	eksp->eks_invalid =
470293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
471293901Sarybchik	eksp->eks_blacklisted = 0;
472293901Sarybchik	eksp->eks_unverifiable =
473293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
474293901Sarybchik	eksp->eks_wrong_node =
475293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
476293901Sarybchik	eksp->eks_licensed_apps_lo =
477293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
478293901Sarybchik	eksp->eks_licensed_apps_hi =
479293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
480293901Sarybchik	eksp->eks_licensed_features_lo =
481293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
482293901Sarybchik	eksp->eks_licensed_features_hi =
483293901Sarybchik		MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
484293901Sarybchik
485293901Sarybchik	return (0);
486293901Sarybchik
487293901Sarybchikfail2:
488293901Sarybchik	EFSYS_PROBE(fail2);
489293901Sarybchikfail1:
490293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
491293901Sarybchik
492293901Sarybchik	return (rc);
493293901Sarybchik}
494293901Sarybchik
495293901Sarybchikstatic	__checkReturn	efx_rc_t
496293901Sarybchikefx_mcdi_licensing_v3_app_state(
497293901Sarybchik	__in		efx_nic_t *enp,
498293901Sarybchik	__in		uint64_t app_id,
499293901Sarybchik	__out		boolean_t *licensedp)
500293901Sarybchik{
501293901Sarybchik	efx_mcdi_req_t req;
502293901Sarybchik	uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
503293901Sarybchik			    MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
504293901Sarybchik	uint32_t app_state;
505293901Sarybchik	efx_rc_t rc;
506293901Sarybchik
507293901Sarybchik	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
508293901Sarybchik
509293901Sarybchik	(void) memset(payload, 0, sizeof (payload));
510293901Sarybchik	req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
511293901Sarybchik	req.emr_in_buf = payload;
512293901Sarybchik	req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
513293901Sarybchik	req.emr_out_buf = payload;
514293901Sarybchik	req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
515293901Sarybchik
516293901Sarybchik	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
517293901Sarybchik		    app_id & 0xffffffff);
518293901Sarybchik	MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
519293901Sarybchik		    app_id >> 32);
520293901Sarybchik
521293901Sarybchik	efx_mcdi_execute(enp, &req);
522293901Sarybchik
523293901Sarybchik	if (req.emr_rc != 0) {
524293901Sarybchik		rc = req.emr_rc;
525293901Sarybchik		goto fail1;
526293901Sarybchik	}
527293901Sarybchik
528293901Sarybchik	if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
529293901Sarybchik		rc = EMSGSIZE;
530293901Sarybchik		goto fail2;
531293901Sarybchik	}
532293901Sarybchik
533293901Sarybchik	app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
534293901Sarybchik	if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
535293901Sarybchik		*licensedp = B_TRUE;
536293901Sarybchik	} else {
537293901Sarybchik		*licensedp = B_FALSE;
538293901Sarybchik	}
539293901Sarybchik
540293901Sarybchik	return (0);
541293901Sarybchik
542293901Sarybchikfail2:
543293901Sarybchik	EFSYS_PROBE(fail2);
544293901Sarybchikfail1:
545293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
546293901Sarybchik
547293901Sarybchik	return (rc);
548293901Sarybchik}
549293901Sarybchik
550293901Sarybchikstatic	__checkReturn	efx_rc_t
551293901Sarybchikefx_mcdi_licensing_v3_get_id(
552293901Sarybchik	__in		efx_nic_t *enp,
553293901Sarybchik	__in		size_t buffer_size,
554293901Sarybchik	__out		uint32_t *typep,
555293901Sarybchik	__out		size_t *lengthp,
556293901Sarybchik	__out_bcount_part_opt(buffer_size, *lengthp)
557293901Sarybchik			uint8_t *bufferp)
558293901Sarybchik{
559293901Sarybchik	efx_mcdi_req_t req;
560293901Sarybchik	uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
561293901Sarybchik			    MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
562293901Sarybchik	efx_rc_t rc;
563293901Sarybchik
564293901Sarybchik	req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
565293901Sarybchik
566293901Sarybchik	if (bufferp == NULL) {
567293901Sarybchik		/* Request id type and length only */
568293901Sarybchik		req.emr_in_buf = bufferp;
569293901Sarybchik		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
570293901Sarybchik		req.emr_out_buf = bufferp;
571293901Sarybchik		req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
572293901Sarybchik		(void) memset(payload, 0, sizeof (payload));
573293901Sarybchik	} else {
574293901Sarybchik		/* Request full buffer */
575293901Sarybchik		req.emr_in_buf = bufferp;
576293901Sarybchik		req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
577293901Sarybchik		req.emr_out_buf = bufferp;
578293901Sarybchik		req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN);
579293901Sarybchik		(void) memset(bufferp, 0, req.emr_out_length);
580293901Sarybchik	}
581293901Sarybchik
582293901Sarybchik	efx_mcdi_execute(enp, &req);
583293901Sarybchik
584293901Sarybchik	if (req.emr_rc != 0) {
585293901Sarybchik		rc = req.emr_rc;
586293901Sarybchik		goto fail1;
587293901Sarybchik	}
588293901Sarybchik
589293901Sarybchik	if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
590293901Sarybchik		rc = EMSGSIZE;
591293901Sarybchik		goto fail2;
592293901Sarybchik	}
593293901Sarybchik
594293901Sarybchik	*typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
595293901Sarybchik	*lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
596293901Sarybchik
597293901Sarybchik	if (bufferp == NULL) {
598293901Sarybchik		/* modify length requirements to indicate to caller the extra buffering
599293901Sarybchik		** needed to read the complete output.
600293901Sarybchik		*/
601293901Sarybchik		*lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
602293901Sarybchik	} else {
603293901Sarybchik		/* Shift ID down to start of buffer */
604293901Sarybchik		memmove(bufferp,
605293901Sarybchik		  bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
606293901Sarybchik		  *lengthp);
607293901Sarybchik		memset(bufferp+(*lengthp), 0, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
608293901Sarybchik	}
609293901Sarybchik
610293901Sarybchik	return (0);
611293901Sarybchik
612293901Sarybchikfail2:
613293901Sarybchik	EFSYS_PROBE(fail2);
614293901Sarybchikfail1:
615293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
616293901Sarybchik
617293901Sarybchik	return (rc);
618293901Sarybchik}
619293901Sarybchik
620293901Sarybchik
621293901Sarybchik#endif	/* EFSYS_OPT_MEDFORD */
622293901Sarybchik
623293901Sarybchik	__checkReturn		efx_rc_t
624293901Sarybchikefx_lic_init(
625293901Sarybchik	__in			efx_nic_t *enp)
626293901Sarybchik{
627293901Sarybchik	efx_lic_ops_t *elop;
628293901Sarybchik	efx_rc_t rc;
629293901Sarybchik
630293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
631293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
632293901Sarybchik	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
633293901Sarybchik
634293901Sarybchik	switch (enp->en_family) {
635293901Sarybchik
636293901Sarybchik#if EFSYS_OPT_SIENA
637293901Sarybchik	case EFX_FAMILY_SIENA:
638293901Sarybchik		elop = (efx_lic_ops_t *)&__efx_lic_v1_ops;
639293901Sarybchik		break;
640293901Sarybchik#endif	/* EFSYS_OPT_SIENA */
641293901Sarybchik
642293901Sarybchik#if EFSYS_OPT_HUNTINGTON
643293901Sarybchik	case EFX_FAMILY_HUNTINGTON:
644293901Sarybchik		elop = (efx_lic_ops_t *)&__efx_lic_v2_ops;
645293901Sarybchik		break;
646293901Sarybchik#endif	/* EFSYS_OPT_HUNTINGTON */
647293901Sarybchik
648293901Sarybchik#if EFSYS_OPT_MEDFORD
649293901Sarybchik	case EFX_FAMILY_MEDFORD:
650293901Sarybchik		elop = (efx_lic_ops_t *)&__efx_lic_v3_ops;
651293901Sarybchik		break;
652293901Sarybchik#endif	/* EFSYS_OPT_MEDFORD */
653293901Sarybchik
654293901Sarybchik	default:
655293901Sarybchik		EFSYS_ASSERT(0);
656293901Sarybchik		rc = ENOTSUP;
657293901Sarybchik		goto fail1;
658293901Sarybchik	}
659293901Sarybchik
660293901Sarybchik	enp->en_elop = elop;
661293901Sarybchik	enp->en_mod_flags |= EFX_MOD_LIC;
662293901Sarybchik
663293901Sarybchik	return (0);
664293901Sarybchik
665293901Sarybchikfail1:
666293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
667293901Sarybchik
668293901Sarybchik	return (rc);
669293901Sarybchik}
670293901Sarybchik
671293901Sarybchik				void
672293901Sarybchikefx_lic_fini(
673293901Sarybchik	__in			efx_nic_t *enp)
674293901Sarybchik{
675293901Sarybchik	efx_lic_ops_t *elop = enp->en_elop;
676293901Sarybchik
677293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
678293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
679293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
680293901Sarybchik
681293901Sarybchik	enp->en_elop = NULL;
682293901Sarybchik	enp->en_mod_flags &= ~EFX_MOD_LIC;
683293901Sarybchik}
684293901Sarybchik
685293901Sarybchik
686293901Sarybchik	__checkReturn	efx_rc_t
687293901Sarybchikefx_lic_update_licenses(
688293901Sarybchik	__in		efx_nic_t *enp)
689293901Sarybchik{
690293901Sarybchik	efx_lic_ops_t *elop = enp->en_elop;
691293901Sarybchik	efx_rc_t rc;
692293901Sarybchik
693293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
694293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
695293901Sarybchik
696293901Sarybchik	if ((rc = elop->elo_update_licenses(enp)) != 0)
697293901Sarybchik		goto fail1;
698293901Sarybchik
699293901Sarybchik	return (0);
700293901Sarybchik
701293901Sarybchikfail1:
702293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
703293901Sarybchik
704293901Sarybchik	return (rc);
705293901Sarybchik}
706293901Sarybchik
707293901Sarybchik	__checkReturn	efx_rc_t
708293901Sarybchikefx_lic_get_key_stats(
709293901Sarybchik	__in		efx_nic_t *enp,
710293901Sarybchik	__out		efx_key_stats_t *eksp)
711293901Sarybchik{
712293901Sarybchik	efx_lic_ops_t *elop = enp->en_elop;
713293901Sarybchik	efx_rc_t rc;
714293901Sarybchik
715293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
716293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
717293901Sarybchik
718293901Sarybchik	if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
719293901Sarybchik		goto fail1;
720293901Sarybchik
721293901Sarybchik	return (0);
722293901Sarybchik
723293901Sarybchikfail1:
724293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
725293901Sarybchik
726293901Sarybchik	return (rc);
727293901Sarybchik}
728293901Sarybchik
729293901Sarybchik	__checkReturn	efx_rc_t
730293901Sarybchikefx_lic_app_state(
731293901Sarybchik	__in		efx_nic_t *enp,
732293901Sarybchik	__in		uint64_t app_id,
733293901Sarybchik	__out		boolean_t *licensedp)
734293901Sarybchik{
735293901Sarybchik	efx_lic_ops_t *elop = enp->en_elop;
736293901Sarybchik	efx_rc_t rc;
737293901Sarybchik
738293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
739293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
740293901Sarybchik
741293901Sarybchik	if (elop->elo_app_state == NULL) {
742293901Sarybchik		rc = ENOTSUP;
743293901Sarybchik		goto fail1;
744293901Sarybchik	}
745293901Sarybchik	if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
746293901Sarybchik		goto fail2;
747293901Sarybchik
748293901Sarybchik	return (0);
749293901Sarybchik
750293901Sarybchikfail2:
751293901Sarybchik	EFSYS_PROBE(fail2);
752293901Sarybchikfail1:
753293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
754293901Sarybchik
755293901Sarybchik	return (rc);
756293901Sarybchik}
757293901Sarybchik
758293901Sarybchik	__checkReturn	efx_rc_t
759293901Sarybchikefx_lic_get_id(
760293901Sarybchik	__in		efx_nic_t *enp,
761293901Sarybchik	__in		size_t buffer_size,
762293901Sarybchik	__out		uint32_t *typep,
763293901Sarybchik	__out		size_t *lengthp,
764293901Sarybchik	__out_opt	uint8_t *bufferp
765293901Sarybchik	)
766293901Sarybchik{
767293901Sarybchik	efx_lic_ops_t *elop = enp->en_elop;
768293901Sarybchik	efx_rc_t rc;
769293901Sarybchik
770293901Sarybchik	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
771293901Sarybchik	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
772293901Sarybchik
773293901Sarybchik	if (elop->elo_get_id == NULL) {
774293901Sarybchik		rc = ENOTSUP;
775293901Sarybchik		goto fail1;
776293901Sarybchik	}
777293901Sarybchik
778293901Sarybchik	if ((rc = elop->elo_get_id(enp, buffer_size, typep,
779293901Sarybchik				    lengthp, bufferp)) != 0)
780293901Sarybchik		goto fail2;
781293901Sarybchik
782293901Sarybchik	return (0);
783293901Sarybchik
784293901Sarybchikfail2:
785293901Sarybchik	EFSYS_PROBE(fail2);
786293901Sarybchikfail1:
787293901Sarybchik	EFSYS_PROBE1(fail1, efx_rc_t, rc);
788293901Sarybchik
789293901Sarybchik	return (rc);
790293901Sarybchik}
791293901Sarybchik
792293901Sarybchik#endif	/* EFSYS_OPT_LICENSING */
793