net/sfc/base: move RxDP config get to EF10 NIC code
[dpdk.git] / drivers / net / sfc / base / efx_lic.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_LICENSING
11
12 #include "ef10_tlv_layout.h"
13 #if EFSYS_OPT_SIENA
14 #include "efx_regs_mcdi_aoe.h"
15 #endif
16
17 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
18
19         __checkReturn           efx_rc_t
20 efx_lic_v1v2_find_start(
21         __in                    efx_nic_t *enp,
22         __in_bcount(buffer_size)
23                                 caddr_t bufferp,
24         __in                    size_t buffer_size,
25         __out                   uint32_t *startp);
26
27         __checkReturn           efx_rc_t
28 efx_lic_v1v2_find_end(
29         __in                    efx_nic_t *enp,
30         __in_bcount(buffer_size)
31                                 caddr_t bufferp,
32         __in                    size_t buffer_size,
33         __in                    uint32_t offset,
34         __out                   uint32_t *endp);
35
36         __checkReturn   __success(return != B_FALSE)    boolean_t
37 efx_lic_v1v2_find_key(
38         __in                    efx_nic_t *enp,
39         __in_bcount(buffer_size)
40                                 caddr_t bufferp,
41         __in                    size_t buffer_size,
42         __in                    uint32_t offset,
43         __out                   uint32_t *startp,
44         __out                   uint32_t *lengthp);
45
46         __checkReturn   __success(return != B_FALSE)    boolean_t
47 efx_lic_v1v2_validate_key(
48         __in                    efx_nic_t *enp,
49         __in_bcount(length)     caddr_t keyp,
50         __in                    uint32_t length);
51
52         __checkReturn           efx_rc_t
53 efx_lic_v1v2_read_key(
54         __in                    efx_nic_t *enp,
55         __in_bcount(buffer_size)
56                                 caddr_t bufferp,
57         __in                    size_t buffer_size,
58         __in                    uint32_t offset,
59         __in                    uint32_t length,
60         __out_bcount_part(key_max_size, *lengthp)
61                                 caddr_t keyp,
62         __in                    size_t key_max_size,
63         __out                   uint32_t *lengthp);
64
65         __checkReturn           efx_rc_t
66 efx_lic_v1v2_write_key(
67         __in                    efx_nic_t *enp,
68         __in_bcount(buffer_size)
69                                 caddr_t bufferp,
70         __in                    size_t buffer_size,
71         __in                    uint32_t offset,
72         __in_bcount(length)     caddr_t keyp,
73         __in                    uint32_t length,
74         __out                   uint32_t *lengthp);
75
76         __checkReturn           efx_rc_t
77 efx_lic_v1v2_delete_key(
78         __in                    efx_nic_t *enp,
79         __in_bcount(buffer_size)
80                                 caddr_t bufferp,
81         __in                    size_t buffer_size,
82         __in                    uint32_t offset,
83         __in                    uint32_t length,
84         __in                    uint32_t end,
85         __out                   uint32_t *deltap);
86
87         __checkReturn           efx_rc_t
88 efx_lic_v1v2_create_partition(
89         __in                    efx_nic_t *enp,
90         __in_bcount(buffer_size)
91                                 caddr_t bufferp,
92         __in                    size_t buffer_size);
93
94         __checkReturn           efx_rc_t
95 efx_lic_v1v2_finish_partition(
96         __in                    efx_nic_t *enp,
97         __in_bcount(buffer_size)
98                                 caddr_t bufferp,
99         __in                    size_t buffer_size);
100
101 #endif  /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
102
103
104 #if EFSYS_OPT_SIENA
105
106 static  __checkReturn   efx_rc_t
107 efx_mcdi_fc_license_update_license(
108         __in            efx_nic_t *enp);
109
110 static  __checkReturn   efx_rc_t
111 efx_mcdi_fc_license_get_key_stats(
112         __in            efx_nic_t *enp,
113         __out           efx_key_stats_t *eksp);
114
115 static const efx_lic_ops_t      __efx_lic_v1_ops = {
116         efx_mcdi_fc_license_update_license,     /* elo_update_licenses */
117         efx_mcdi_fc_license_get_key_stats,      /* elo_get_key_stats */
118         NULL,                                   /* elo_app_state */
119         NULL,                                   /* elo_get_id */
120         efx_lic_v1v2_find_start,                /* elo_find_start */
121         efx_lic_v1v2_find_end,                  /* elo_find_end */
122         efx_lic_v1v2_find_key,                  /* elo_find_key */
123         efx_lic_v1v2_validate_key,              /* elo_validate_key */
124         efx_lic_v1v2_read_key,                  /* elo_read_key */
125         efx_lic_v1v2_write_key,                 /* elo_write_key */
126         efx_lic_v1v2_delete_key,                /* elo_delete_key */
127         efx_lic_v1v2_create_partition,          /* elo_create_partition */
128         efx_lic_v1v2_finish_partition,          /* elo_finish_partition */
129 };
130
131 #endif  /* EFSYS_OPT_SIENA */
132
133 #if EFSYS_OPT_HUNTINGTON
134
135 static  __checkReturn   efx_rc_t
136 efx_mcdi_licensing_update_licenses(
137         __in            efx_nic_t *enp);
138
139 static  __checkReturn   efx_rc_t
140 efx_mcdi_licensing_get_key_stats(
141         __in            efx_nic_t *enp,
142         __out           efx_key_stats_t *eksp);
143
144 static  __checkReturn   efx_rc_t
145 efx_mcdi_licensed_app_state(
146         __in            efx_nic_t *enp,
147         __in            uint64_t app_id,
148         __out           boolean_t *licensedp);
149
150 static const efx_lic_ops_t      __efx_lic_v2_ops = {
151         efx_mcdi_licensing_update_licenses,     /* elo_update_licenses */
152         efx_mcdi_licensing_get_key_stats,       /* elo_get_key_stats */
153         efx_mcdi_licensed_app_state,            /* elo_app_state */
154         NULL,                                   /* elo_get_id */
155         efx_lic_v1v2_find_start,                /* elo_find_start */
156         efx_lic_v1v2_find_end,                  /* elo_find_end */
157         efx_lic_v1v2_find_key,                  /* elo_find_key */
158         efx_lic_v1v2_validate_key,              /* elo_validate_key */
159         efx_lic_v1v2_read_key,                  /* elo_read_key */
160         efx_lic_v1v2_write_key,                 /* elo_write_key */
161         efx_lic_v1v2_delete_key,                /* elo_delete_key */
162         efx_lic_v1v2_create_partition,          /* elo_create_partition */
163         efx_lic_v1v2_finish_partition,          /* elo_finish_partition */
164 };
165
166 #endif  /* EFSYS_OPT_HUNTINGTON */
167
168 #if EFSYS_OPT_MEDFORD
169
170 static  __checkReturn   efx_rc_t
171 efx_mcdi_licensing_v3_update_licenses(
172         __in            efx_nic_t *enp);
173
174 static  __checkReturn   efx_rc_t
175 efx_mcdi_licensing_v3_report_license(
176         __in            efx_nic_t *enp,
177         __out           efx_key_stats_t *eksp);
178
179 static  __checkReturn   efx_rc_t
180 efx_mcdi_licensing_v3_app_state(
181         __in            efx_nic_t *enp,
182         __in            uint64_t app_id,
183         __out           boolean_t *licensedp);
184
185 static  __checkReturn   efx_rc_t
186 efx_mcdi_licensing_v3_get_id(
187         __in            efx_nic_t *enp,
188         __in            size_t buffer_size,
189         __out           uint32_t *typep,
190         __out           size_t *lengthp,
191         __out_bcount_part_opt(buffer_size, *lengthp)
192                         uint8_t *bufferp);
193
194         __checkReturn           efx_rc_t
195 efx_lic_v3_find_start(
196         __in                    efx_nic_t *enp,
197         __in_bcount(buffer_size)
198                                 caddr_t bufferp,
199         __in                    size_t buffer_size,
200         __out                   uint32_t *startp);
201
202         __checkReturn           efx_rc_t
203 efx_lic_v3_find_end(
204         __in                    efx_nic_t *enp,
205         __in_bcount(buffer_size)
206                                 caddr_t bufferp,
207         __in                    size_t buffer_size,
208         __in                    uint32_t offset,
209         __out                   uint32_t *endp);
210
211         __checkReturn   __success(return != B_FALSE)    boolean_t
212 efx_lic_v3_find_key(
213         __in                    efx_nic_t *enp,
214         __in_bcount(buffer_size)
215                                 caddr_t bufferp,
216         __in                    size_t buffer_size,
217         __in                    uint32_t offset,
218         __out                   uint32_t *startp,
219         __out                   uint32_t *lengthp);
220
221         __checkReturn   __success(return != B_FALSE)    boolean_t
222 efx_lic_v3_validate_key(
223         __in                    efx_nic_t *enp,
224         __in_bcount(length)     caddr_t keyp,
225         __in                    uint32_t length);
226
227         __checkReturn           efx_rc_t
228 efx_lic_v3_read_key(
229         __in                    efx_nic_t *enp,
230         __in_bcount(buffer_size)
231                                 caddr_t bufferp,
232         __in                    size_t buffer_size,
233         __in                    uint32_t offset,
234         __in                    uint32_t length,
235         __out_bcount_part(key_max_size, *lengthp)
236                                 caddr_t keyp,
237         __in                    size_t key_max_size,
238         __out                   uint32_t *lengthp);
239
240         __checkReturn           efx_rc_t
241 efx_lic_v3_write_key(
242         __in                    efx_nic_t *enp,
243         __in_bcount(buffer_size)
244                                 caddr_t bufferp,
245         __in                    size_t buffer_size,
246         __in                    uint32_t offset,
247         __in_bcount(length)     caddr_t keyp,
248         __in                    uint32_t length,
249         __out                   uint32_t *lengthp);
250
251         __checkReturn           efx_rc_t
252 efx_lic_v3_delete_key(
253         __in                    efx_nic_t *enp,
254         __in_bcount(buffer_size)
255                                 caddr_t bufferp,
256         __in                    size_t buffer_size,
257         __in                    uint32_t offset,
258         __in                    uint32_t length,
259         __in                    uint32_t end,
260         __out                   uint32_t *deltap);
261
262         __checkReturn           efx_rc_t
263 efx_lic_v3_create_partition(
264         __in                    efx_nic_t *enp,
265         __in_bcount(buffer_size)
266                                 caddr_t bufferp,
267         __in                    size_t buffer_size);
268
269         __checkReturn           efx_rc_t
270 efx_lic_v3_finish_partition(
271         __in                    efx_nic_t *enp,
272         __in_bcount(buffer_size)
273                                 caddr_t bufferp,
274         __in                    size_t buffer_size);
275
276 static const efx_lic_ops_t      __efx_lic_v3_ops = {
277         efx_mcdi_licensing_v3_update_licenses,  /* elo_update_licenses */
278         efx_mcdi_licensing_v3_report_license,   /* elo_get_key_stats */
279         efx_mcdi_licensing_v3_app_state,        /* elo_app_state */
280         efx_mcdi_licensing_v3_get_id,           /* elo_get_id */
281         efx_lic_v3_find_start,                  /* elo_find_start */
282         efx_lic_v3_find_end,                    /* elo_find_end */
283         efx_lic_v3_find_key,                    /* elo_find_key */
284         efx_lic_v3_validate_key,                /* elo_validate_key */
285         efx_lic_v3_read_key,                    /* elo_read_key */
286         efx_lic_v3_write_key,                   /* elo_write_key */
287         efx_lic_v3_delete_key,                  /* elo_delete_key */
288         efx_lic_v3_create_partition,            /* elo_create_partition */
289         efx_lic_v3_finish_partition,            /* elo_finish_partition */
290 };
291
292 #endif  /* EFSYS_OPT_MEDFORD */
293
294
295 /* V1 Licensing - used in Siena Modena only */
296
297 #if EFSYS_OPT_SIENA
298
299 static  __checkReturn   efx_rc_t
300 efx_mcdi_fc_license_update_license(
301         __in            efx_nic_t *enp)
302 {
303         efx_mcdi_req_t req;
304         uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
305         efx_rc_t rc;
306
307         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
308
309         (void) memset(payload, 0, sizeof (payload));
310         req.emr_cmd = MC_CMD_FC;
311         req.emr_in_buf = payload;
312         req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
313         req.emr_out_buf = payload;
314         req.emr_out_length = 0;
315
316         MCDI_IN_SET_DWORD(req, FC_IN_CMD,
317             MC_CMD_FC_OP_LICENSE);
318
319         MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
320             MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
321
322         efx_mcdi_execute(enp, &req);
323
324         if (req.emr_rc != 0) {
325                 rc = req.emr_rc;
326                 goto fail1;
327         }
328
329         if (req.emr_out_length_used != 0) {
330                 rc = EIO;
331                 goto fail2;
332         }
333
334         return (0);
335
336 fail2:
337         EFSYS_PROBE(fail2);
338 fail1:
339         EFSYS_PROBE1(fail1, efx_rc_t, rc);
340
341         return (rc);
342 }
343
344 static  __checkReturn   efx_rc_t
345 efx_mcdi_fc_license_get_key_stats(
346         __in            efx_nic_t *enp,
347         __out           efx_key_stats_t *eksp)
348 {
349         efx_mcdi_req_t req;
350         uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
351                             MC_CMD_FC_OUT_LICENSE_LEN)];
352         efx_rc_t rc;
353
354         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
355
356         (void) memset(payload, 0, sizeof (payload));
357         req.emr_cmd = MC_CMD_FC;
358         req.emr_in_buf = payload;
359         req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
360         req.emr_out_buf = payload;
361         req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
362
363         MCDI_IN_SET_DWORD(req, FC_IN_CMD,
364             MC_CMD_FC_OP_LICENSE);
365
366         MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
367             MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
368
369         efx_mcdi_execute_quiet(enp, &req);
370
371         if (req.emr_rc != 0) {
372                 rc = req.emr_rc;
373                 goto fail1;
374         }
375
376         if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
377                 rc = EMSGSIZE;
378                 goto fail2;
379         }
380
381         eksp->eks_valid =
382                 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
383         eksp->eks_invalid =
384                 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
385         eksp->eks_blacklisted =
386                 MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
387         eksp->eks_unverifiable = 0;
388         eksp->eks_wrong_node = 0;
389         eksp->eks_licensed_apps_lo = 0;
390         eksp->eks_licensed_apps_hi = 0;
391         eksp->eks_licensed_features_lo = 0;
392         eksp->eks_licensed_features_hi = 0;
393
394         return (0);
395
396 fail2:
397         EFSYS_PROBE(fail2);
398 fail1:
399         EFSYS_PROBE1(fail1, efx_rc_t, rc);
400
401         return (rc);
402 }
403
404 #endif  /* EFSYS_OPT_SIENA */
405
406 /* V1 and V2 Partition format - based on a 16-bit TLV format */
407
408 #if EFSYS_OPT_SIENA | EFSYS_OPT_HUNTINGTON
409
410 /*
411  * V1/V2 format - defined in SF-108542-TC section 4.2:
412  *  Type (T):   16bit - revision/HMAC algorithm
413  *  Length (L): 16bit - value length in bytes
414  *  Value (V):  L bytes - payload
415  */
416 #define EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX     (256)
417 #define EFX_LICENSE_V1V2_HEADER_LENGTH          (2 * sizeof (uint16_t))
418
419         __checkReturn           efx_rc_t
420 efx_lic_v1v2_find_start(
421         __in                    efx_nic_t *enp,
422         __in_bcount(buffer_size)
423                                 caddr_t bufferp,
424         __in                    size_t buffer_size,
425         __out                   uint32_t *startp)
426 {
427         _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
428
429         *startp = 0;
430         return (0);
431 }
432
433         __checkReturn           efx_rc_t
434 efx_lic_v1v2_find_end(
435         __in                    efx_nic_t *enp,
436         __in_bcount(buffer_size)
437                                 caddr_t bufferp,
438         __in                    size_t buffer_size,
439         __in                    uint32_t offset,
440         __out                   uint32_t *endp)
441 {
442         _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
443
444         *endp = offset + EFX_LICENSE_V1V2_HEADER_LENGTH;
445         return (0);
446 }
447
448         __checkReturn   __success(return != B_FALSE)    boolean_t
449 efx_lic_v1v2_find_key(
450         __in                    efx_nic_t *enp,
451         __in_bcount(buffer_size)
452                                 caddr_t bufferp,
453         __in                    size_t buffer_size,
454         __in                    uint32_t offset,
455         __out                   uint32_t *startp,
456         __out                   uint32_t *lengthp)
457 {
458         boolean_t found;
459         uint16_t tlv_type;
460         uint16_t tlv_length;
461
462         _NOTE(ARGUNUSED(enp))
463
464         if ((size_t)buffer_size - offset < EFX_LICENSE_V1V2_HEADER_LENGTH)
465                 goto fail1;
466
467         tlv_type = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[0]);
468         tlv_length = __LE_TO_CPU_16(((uint16_t *)&bufferp[offset])[1]);
469         if ((tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) ||
470             (tlv_type == 0 && tlv_length == 0)) {
471                 found = B_FALSE;
472         } else {
473                 *startp = offset;
474                 *lengthp = tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH;
475                 found = B_TRUE;
476         }
477         return (found);
478
479 fail1:
480         EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
481
482         return (B_FALSE);
483 }
484
485         __checkReturn   __success(return != B_FALSE)    boolean_t
486 efx_lic_v1v2_validate_key(
487         __in                    efx_nic_t *enp,
488         __in_bcount(length)     caddr_t keyp,
489         __in                    uint32_t length)
490 {
491         uint16_t tlv_type;
492         uint16_t tlv_length;
493
494         _NOTE(ARGUNUSED(enp))
495
496         if (length < EFX_LICENSE_V1V2_HEADER_LENGTH) {
497                 goto fail1;
498         }
499
500         tlv_type = __LE_TO_CPU_16(((uint16_t *)keyp)[0]);
501         tlv_length = __LE_TO_CPU_16(((uint16_t *)keyp)[1]);
502
503         if (tlv_length > EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX) {
504                 goto fail2;
505         }
506         if (tlv_type == 0) {
507                 goto fail3;
508         }
509         if ((tlv_length + EFX_LICENSE_V1V2_HEADER_LENGTH) != length) {
510                 goto fail4;
511         }
512
513         return (B_TRUE);
514
515 fail4:
516         EFSYS_PROBE(fail4);
517 fail3:
518         EFSYS_PROBE(fail3);
519 fail2:
520         EFSYS_PROBE(fail2);
521 fail1:
522         EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
523
524         return (B_FALSE);
525 }
526
527
528         __checkReturn           efx_rc_t
529 efx_lic_v1v2_read_key(
530         __in                    efx_nic_t *enp,
531         __in_bcount(buffer_size)
532                                 caddr_t bufferp,
533         __in                    size_t buffer_size,
534         __in                    uint32_t offset,
535         __in                    uint32_t length,
536         __out_bcount_part(key_max_size, *lengthp)
537                                 caddr_t keyp,
538         __in                    size_t key_max_size,
539         __out                   uint32_t *lengthp)
540 {
541         efx_rc_t rc;
542
543         _NOTE(ARGUNUSED(enp, buffer_size))
544         EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
545             EFX_LICENSE_V1V2_HEADER_LENGTH));
546
547         if (key_max_size < length) {
548                 rc = ENOSPC;
549                 goto fail1;
550         }
551         memcpy(keyp, &bufferp[offset], length);
552
553         *lengthp = length;
554
555         return (0);
556
557 fail1:
558         EFSYS_PROBE1(fail1, efx_rc_t, rc);
559
560         return (rc);
561 }
562
563         __checkReturn           efx_rc_t
564 efx_lic_v1v2_write_key(
565         __in                    efx_nic_t *enp,
566         __in_bcount(buffer_size)
567                                 caddr_t bufferp,
568         __in                    size_t buffer_size,
569         __in                    uint32_t offset,
570         __in_bcount(length)     caddr_t keyp,
571         __in                    uint32_t length,
572         __out                   uint32_t *lengthp)
573 {
574         efx_rc_t rc;
575
576         _NOTE(ARGUNUSED(enp))
577         EFSYS_ASSERT(length <= (EFX_LICENSE_V1V2_PAYLOAD_LENGTH_MAX +
578             EFX_LICENSE_V1V2_HEADER_LENGTH));
579
580         /* Ensure space for terminator remains */
581         if ((offset + length) >
582             (buffer_size - EFX_LICENSE_V1V2_HEADER_LENGTH)) {
583                 rc = ENOSPC;
584                 goto fail1;
585         }
586
587         memcpy(bufferp + offset, keyp, length);
588
589         *lengthp = length;
590
591         return (0);
592
593 fail1:
594         EFSYS_PROBE1(fail1, efx_rc_t, rc);
595
596         return (rc);
597 }
598
599         __checkReturn           efx_rc_t
600 efx_lic_v1v2_delete_key(
601         __in                    efx_nic_t *enp,
602         __in_bcount(buffer_size)
603                                 caddr_t bufferp,
604         __in                    size_t buffer_size,
605         __in                    uint32_t offset,
606         __in                    uint32_t length,
607         __in                    uint32_t end,
608         __out                   uint32_t *deltap)
609 {
610         uint32_t move_start = offset + length;
611         uint32_t move_length = end - move_start;
612
613         _NOTE(ARGUNUSED(enp, buffer_size))
614         EFSYS_ASSERT(end <= buffer_size);
615
616         /* Shift everything after the key down */
617         memmove(bufferp + offset, bufferp + move_start, move_length);
618
619         *deltap = length;
620
621         return (0);
622 }
623
624         __checkReturn           efx_rc_t
625 efx_lic_v1v2_create_partition(
626         __in                    efx_nic_t *enp,
627         __in_bcount(buffer_size)
628                                 caddr_t bufferp,
629         __in                    size_t buffer_size)
630 {
631         _NOTE(ARGUNUSED(enp, buffer_size))
632         EFSYS_ASSERT(EFX_LICENSE_V1V2_HEADER_LENGTH <= buffer_size);
633
634         /* Write terminator */
635         memset(bufferp, '\0', EFX_LICENSE_V1V2_HEADER_LENGTH);
636         return (0);
637 }
638
639
640         __checkReturn           efx_rc_t
641 efx_lic_v1v2_finish_partition(
642         __in                    efx_nic_t *enp,
643         __in_bcount(buffer_size)
644                                 caddr_t bufferp,
645         __in                    size_t buffer_size)
646 {
647         _NOTE(ARGUNUSED(enp, bufferp, buffer_size))
648
649         return (0);
650 }
651
652 #endif  /* EFSYS_OPT_HUNTINGTON | EFSYS_OPT_SIENA */
653
654
655 /* V2 Licensing - used by Huntington family only. See SF-113611-TC */
656
657 #if EFSYS_OPT_HUNTINGTON
658
659 static  __checkReturn   efx_rc_t
660 efx_mcdi_licensed_app_state(
661         __in            efx_nic_t *enp,
662         __in            uint64_t app_id,
663         __out           boolean_t *licensedp)
664 {
665         efx_mcdi_req_t req;
666         uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
667                             MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
668         uint32_t app_state;
669         efx_rc_t rc;
670
671         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
672
673         /* V2 licensing supports 32bit app id only */
674         if ((app_id >> 32) != 0) {
675                 rc = EINVAL;
676                 goto fail1;
677         }
678
679         (void) memset(payload, 0, sizeof (payload));
680         req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
681         req.emr_in_buf = payload;
682         req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
683         req.emr_out_buf = payload;
684         req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
685
686         MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
687                     app_id & 0xffffffff);
688
689         efx_mcdi_execute(enp, &req);
690
691         if (req.emr_rc != 0) {
692                 rc = req.emr_rc;
693                 goto fail2;
694         }
695
696         if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
697                 rc = EMSGSIZE;
698                 goto fail3;
699         }
700
701         app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
702         if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
703                 *licensedp = B_TRUE;
704         } else {
705                 *licensedp = B_FALSE;
706         }
707
708         return (0);
709
710 fail3:
711         EFSYS_PROBE(fail3);
712 fail2:
713         EFSYS_PROBE(fail2);
714 fail1:
715         EFSYS_PROBE1(fail1, efx_rc_t, rc);
716
717         return (rc);
718 }
719
720 static  __checkReturn   efx_rc_t
721 efx_mcdi_licensing_update_licenses(
722         __in            efx_nic_t *enp)
723 {
724         efx_mcdi_req_t req;
725         uint8_t payload[MC_CMD_LICENSING_IN_LEN];
726         efx_rc_t rc;
727
728         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
729
730         (void) memset(payload, 0, sizeof (payload));
731         req.emr_cmd = MC_CMD_LICENSING;
732         req.emr_in_buf = payload;
733         req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
734         req.emr_out_buf = payload;
735         req.emr_out_length = 0;
736
737         MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
738             MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
739
740         efx_mcdi_execute(enp, &req);
741
742         if (req.emr_rc != 0) {
743                 rc = req.emr_rc;
744                 goto fail1;
745         }
746
747         if (req.emr_out_length_used != 0) {
748                 rc = EIO;
749                 goto fail2;
750         }
751
752         return (0);
753
754 fail2:
755         EFSYS_PROBE(fail2);
756 fail1:
757         EFSYS_PROBE1(fail1, efx_rc_t, rc);
758
759         return (rc);
760 }
761
762 static  __checkReturn   efx_rc_t
763 efx_mcdi_licensing_get_key_stats(
764         __in            efx_nic_t *enp,
765         __out           efx_key_stats_t *eksp)
766 {
767         efx_mcdi_req_t req;
768         uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
769                             MC_CMD_LICENSING_OUT_LEN)];
770         efx_rc_t rc;
771
772         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
773
774         (void) memset(payload, 0, sizeof (payload));
775         req.emr_cmd = MC_CMD_LICENSING;
776         req.emr_in_buf = payload;
777         req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
778         req.emr_out_buf = payload;
779         req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
780
781         MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
782             MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
783
784         efx_mcdi_execute(enp, &req);
785
786         if (req.emr_rc != 0) {
787                 rc = req.emr_rc;
788                 goto fail1;
789         }
790
791         if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
792                 rc = EMSGSIZE;
793                 goto fail2;
794         }
795
796         eksp->eks_valid =
797                 MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
798         eksp->eks_invalid =
799                 MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
800         eksp->eks_blacklisted =
801                 MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
802         eksp->eks_unverifiable =
803                 MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
804         eksp->eks_wrong_node =
805                 MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
806         eksp->eks_licensed_apps_lo = 0;
807         eksp->eks_licensed_apps_hi = 0;
808         eksp->eks_licensed_features_lo = 0;
809         eksp->eks_licensed_features_hi = 0;
810
811         return (0);
812
813 fail2:
814         EFSYS_PROBE(fail2);
815 fail1:
816         EFSYS_PROBE1(fail1, efx_rc_t, rc);
817
818         return (rc);
819 }
820
821 #endif  /* EFSYS_OPT_HUNTINGTON */
822
823 /* V3 Licensing - used starting from Medford family. See SF-114884-SW */
824
825 #if EFSYS_OPT_MEDFORD
826
827 static  __checkReturn   efx_rc_t
828 efx_mcdi_licensing_v3_update_licenses(
829         __in            efx_nic_t *enp)
830 {
831         efx_mcdi_req_t req;
832         uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
833         efx_rc_t rc;
834
835         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
836
837         (void) memset(payload, 0, sizeof (payload));
838         req.emr_cmd = MC_CMD_LICENSING_V3;
839         req.emr_in_buf = payload;
840         req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
841         req.emr_out_buf = NULL;
842         req.emr_out_length = 0;
843
844         MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
845             MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
846
847         efx_mcdi_execute(enp, &req);
848
849         if (req.emr_rc != 0) {
850                 rc = req.emr_rc;
851                 goto fail1;
852         }
853
854         return (0);
855
856 fail1:
857         EFSYS_PROBE1(fail1, efx_rc_t, rc);
858
859         return (rc);
860 }
861
862 static  __checkReturn   efx_rc_t
863 efx_mcdi_licensing_v3_report_license(
864         __in            efx_nic_t *enp,
865         __out           efx_key_stats_t *eksp)
866 {
867         efx_mcdi_req_t req;
868         uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
869                             MC_CMD_LICENSING_V3_OUT_LEN)];
870         efx_rc_t rc;
871
872         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
873
874         (void) memset(payload, 0, sizeof (payload));
875         req.emr_cmd = MC_CMD_LICENSING_V3;
876         req.emr_in_buf = payload;
877         req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
878         req.emr_out_buf = payload;
879         req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
880
881         MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
882             MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
883
884         efx_mcdi_execute_quiet(enp, &req);
885
886         if (req.emr_rc != 0) {
887                 rc = req.emr_rc;
888                 goto fail1;
889         }
890
891         if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
892                 rc = EMSGSIZE;
893                 goto fail2;
894         }
895
896         eksp->eks_valid =
897                 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
898         eksp->eks_invalid =
899                 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
900         eksp->eks_blacklisted = 0;
901         eksp->eks_unverifiable =
902                 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
903         eksp->eks_wrong_node =
904                 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
905         eksp->eks_licensed_apps_lo =
906                 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
907         eksp->eks_licensed_apps_hi =
908                 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
909         eksp->eks_licensed_features_lo =
910                 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
911         eksp->eks_licensed_features_hi =
912                 MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
913
914         return (0);
915
916 fail2:
917         EFSYS_PROBE(fail2);
918 fail1:
919         EFSYS_PROBE1(fail1, efx_rc_t, rc);
920
921         return (rc);
922 }
923
924 static  __checkReturn   efx_rc_t
925 efx_mcdi_licensing_v3_app_state(
926         __in            efx_nic_t *enp,
927         __in            uint64_t app_id,
928         __out           boolean_t *licensedp)
929 {
930         efx_mcdi_req_t req;
931         uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
932                             MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
933         uint32_t app_state;
934         efx_rc_t rc;
935
936         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
937
938         (void) memset(payload, 0, sizeof (payload));
939         req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
940         req.emr_in_buf = payload;
941         req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
942         req.emr_out_buf = payload;
943         req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
944
945         MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
946                     app_id & 0xffffffff);
947         MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
948                     app_id >> 32);
949
950         efx_mcdi_execute(enp, &req);
951
952         if (req.emr_rc != 0) {
953                 rc = req.emr_rc;
954                 goto fail1;
955         }
956
957         if (req.emr_out_length_used <
958             MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
959                 rc = EMSGSIZE;
960                 goto fail2;
961         }
962
963         app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
964         if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
965                 *licensedp = B_TRUE;
966         } else {
967                 *licensedp = B_FALSE;
968         }
969
970         return (0);
971
972 fail2:
973         EFSYS_PROBE(fail2);
974 fail1:
975         EFSYS_PROBE1(fail1, efx_rc_t, rc);
976
977         return (rc);
978 }
979
980 static  __checkReturn   efx_rc_t
981 efx_mcdi_licensing_v3_get_id(
982         __in            efx_nic_t *enp,
983         __in            size_t buffer_size,
984         __out           uint32_t *typep,
985         __out           size_t *lengthp,
986         __out_bcount_part_opt(buffer_size, *lengthp)
987                         uint8_t *bufferp)
988 {
989         efx_mcdi_req_t req;
990         uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
991                             MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
992         efx_rc_t rc;
993
994         req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
995
996         if (bufferp == NULL) {
997                 /* Request id type and length only */
998                 req.emr_in_buf = bufferp;
999                 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1000                 req.emr_out_buf = bufferp;
1001                 req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1002                 (void) memset(payload, 0, sizeof (payload));
1003         } else {
1004                 /* Request full buffer */
1005                 req.emr_in_buf = bufferp;
1006                 req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
1007                 req.emr_out_buf = bufferp;
1008                 req.emr_out_length =
1009                     MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMAX);
1010                 (void) memset(bufferp, 0, req.emr_out_length);
1011         }
1012
1013         efx_mcdi_execute_quiet(enp, &req);
1014
1015         if (req.emr_rc != 0) {
1016                 rc = req.emr_rc;
1017                 goto fail1;
1018         }
1019
1020         if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
1021                 rc = EMSGSIZE;
1022                 goto fail2;
1023         }
1024
1025         *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
1026         *lengthp =
1027             MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
1028
1029         if (bufferp == NULL) {
1030                 /*
1031                  * Modify length requirements to indicate to caller the extra
1032                  * buffering needed to read the complete output.
1033                  */
1034                 *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
1035         } else {
1036                 /* Shift ID down to start of buffer */
1037                 memmove(bufferp,
1038                     bufferp + MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
1039                     *lengthp);
1040                 memset(bufferp + (*lengthp), 0,
1041                     MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
1042         }
1043
1044         return (0);
1045
1046 fail2:
1047         EFSYS_PROBE(fail2);
1048 fail1:
1049         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1050
1051         return (rc);
1052 }
1053
1054 /* V3 format uses Huntington TLV format partition. See SF-108797-SW */
1055 #define EFX_LICENSE_V3_KEY_LENGTH_MIN   (64)
1056 #define EFX_LICENSE_V3_KEY_LENGTH_MAX   (160)
1057
1058         __checkReturn           efx_rc_t
1059 efx_lic_v3_find_start(
1060         __in                    efx_nic_t *enp,
1061         __in_bcount(buffer_size)
1062                                 caddr_t bufferp,
1063         __in                    size_t buffer_size,
1064         __out                   uint32_t *startp)
1065 {
1066         _NOTE(ARGUNUSED(enp))
1067
1068         return (ef10_nvram_buffer_find_item_start(bufferp, buffer_size,
1069             startp));
1070 }
1071
1072         __checkReturn           efx_rc_t
1073 efx_lic_v3_find_end(
1074         __in                    efx_nic_t *enp,
1075         __in_bcount(buffer_size)
1076                                 caddr_t bufferp,
1077         __in                    size_t buffer_size,
1078         __in                    uint32_t offset,
1079         __out                   uint32_t *endp)
1080 {
1081         _NOTE(ARGUNUSED(enp))
1082
1083         return (ef10_nvram_buffer_find_end(bufferp, buffer_size, offset, endp));
1084 }
1085
1086         __checkReturn   __success(return != B_FALSE)    boolean_t
1087 efx_lic_v3_find_key(
1088         __in                    efx_nic_t *enp,
1089         __in_bcount(buffer_size)
1090                                 caddr_t bufferp,
1091         __in                    size_t buffer_size,
1092         __in                    uint32_t offset,
1093         __out                   uint32_t *startp,
1094         __out                   uint32_t *lengthp)
1095 {
1096         _NOTE(ARGUNUSED(enp))
1097
1098         return ef10_nvram_buffer_find_item(bufferp, buffer_size,
1099             offset, startp, lengthp);
1100 }
1101
1102         __checkReturn   __success(return != B_FALSE)    boolean_t
1103 efx_lic_v3_validate_key(
1104         __in                    efx_nic_t *enp,
1105         __in_bcount(length)     caddr_t keyp,
1106         __in                    uint32_t length)
1107 {
1108         /* Check key is a valid V3 key */
1109         uint8_t key_type;
1110         uint8_t key_length;
1111
1112         _NOTE(ARGUNUSED(enp))
1113
1114         if (length < EFX_LICENSE_V3_KEY_LENGTH_MIN) {
1115                 goto fail1;
1116         }
1117
1118         if (length > EFX_LICENSE_V3_KEY_LENGTH_MAX) {
1119                 goto fail2;
1120         }
1121
1122         key_type = ((uint8_t *)keyp)[0];
1123         key_length = ((uint8_t *)keyp)[1];
1124
1125         if (key_type < 3) {
1126                 goto fail3;
1127         }
1128         if (key_length > length) {
1129                 goto fail4;
1130         }
1131         return (B_TRUE);
1132
1133 fail4:
1134         EFSYS_PROBE(fail4);
1135 fail3:
1136         EFSYS_PROBE(fail3);
1137 fail2:
1138         EFSYS_PROBE(fail2);
1139 fail1:
1140         EFSYS_PROBE1(fail1, boolean_t, B_FALSE);
1141
1142         return (B_FALSE);
1143 }
1144
1145         __checkReturn           efx_rc_t
1146 efx_lic_v3_read_key(
1147         __in                    efx_nic_t *enp,
1148         __in_bcount(buffer_size)
1149                                 caddr_t bufferp,
1150         __in                    size_t buffer_size,
1151         __in                    uint32_t offset,
1152         __in                    uint32_t length,
1153         __out_bcount_part(key_max_size, *lengthp)
1154                                 caddr_t keyp,
1155         __in                    size_t key_max_size,
1156         __out                   uint32_t *lengthp)
1157 {
1158         _NOTE(ARGUNUSED(enp))
1159
1160         return ef10_nvram_buffer_get_item(bufferp, buffer_size,
1161                     offset, length, keyp, key_max_size, lengthp);
1162 }
1163
1164         __checkReturn           efx_rc_t
1165 efx_lic_v3_write_key(
1166         __in                    efx_nic_t *enp,
1167         __in_bcount(buffer_size)
1168                                 caddr_t bufferp,
1169         __in                    size_t buffer_size,
1170         __in                    uint32_t offset,
1171         __in_bcount(length)     caddr_t keyp,
1172         __in                    uint32_t length,
1173         __out                   uint32_t *lengthp)
1174 {
1175         _NOTE(ARGUNUSED(enp))
1176         EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX);
1177
1178         return ef10_nvram_buffer_insert_item(bufferp, buffer_size,
1179                     offset, keyp, length, lengthp);
1180 }
1181
1182         __checkReturn           efx_rc_t
1183 efx_lic_v3_delete_key(
1184         __in                    efx_nic_t *enp,
1185         __in_bcount(buffer_size)
1186                                 caddr_t bufferp,
1187         __in                    size_t buffer_size,
1188         __in                    uint32_t offset,
1189         __in                    uint32_t length,
1190         __in                    uint32_t end,
1191         __out                   uint32_t *deltap)
1192 {
1193         efx_rc_t rc;
1194
1195         _NOTE(ARGUNUSED(enp))
1196
1197         if ((rc = ef10_nvram_buffer_delete_item(bufferp,
1198                         buffer_size, offset, length, end)) != 0) {
1199                 goto fail1;
1200         }
1201
1202         *deltap = length;
1203
1204         return (0);
1205
1206 fail1:
1207         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1208
1209         return (rc);
1210 }
1211
1212         __checkReturn           efx_rc_t
1213 efx_lic_v3_create_partition(
1214         __in                    efx_nic_t *enp,
1215         __in_bcount(buffer_size)
1216                                 caddr_t bufferp,
1217         __in                    size_t buffer_size)
1218 {
1219         efx_rc_t rc;
1220
1221         /* Construct empty partition */
1222         if ((rc = ef10_nvram_buffer_create(enp,
1223             NVRAM_PARTITION_TYPE_LICENSE,
1224             bufferp, buffer_size)) != 0) {
1225                 rc = EFAULT;
1226                 goto fail1;
1227         }
1228
1229         return (0);
1230
1231 fail1:
1232         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1233
1234         return (rc);
1235 }
1236
1237         __checkReturn           efx_rc_t
1238 efx_lic_v3_finish_partition(
1239         __in                    efx_nic_t *enp,
1240         __in_bcount(buffer_size)
1241                                 caddr_t bufferp,
1242         __in                    size_t buffer_size)
1243 {
1244         efx_rc_t rc;
1245
1246         if ((rc = ef10_nvram_buffer_finish(bufferp,
1247                         buffer_size)) != 0) {
1248                 goto fail1;
1249         }
1250
1251         /* Validate completed partition */
1252         if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE,
1253                                         bufferp, buffer_size)) != 0) {
1254                 goto fail2;
1255         }
1256
1257         return (0);
1258
1259 fail2:
1260         EFSYS_PROBE(fail2);
1261 fail1:
1262         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1263
1264         return (rc);
1265 }
1266
1267
1268 #endif  /* EFSYS_OPT_MEDFORD */
1269
1270         __checkReturn           efx_rc_t
1271 efx_lic_init(
1272         __in                    efx_nic_t *enp)
1273 {
1274         const efx_lic_ops_t *elop;
1275         efx_key_stats_t eks;
1276         efx_rc_t rc;
1277
1278         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1279         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1280         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
1281
1282         switch (enp->en_family) {
1283
1284 #if EFSYS_OPT_SIENA
1285         case EFX_FAMILY_SIENA:
1286                 elop = &__efx_lic_v1_ops;
1287                 break;
1288 #endif  /* EFSYS_OPT_SIENA */
1289
1290 #if EFSYS_OPT_HUNTINGTON
1291         case EFX_FAMILY_HUNTINGTON:
1292                 elop = &__efx_lic_v2_ops;
1293                 break;
1294 #endif  /* EFSYS_OPT_HUNTINGTON */
1295
1296 #if EFSYS_OPT_MEDFORD
1297         case EFX_FAMILY_MEDFORD:
1298                 elop = &__efx_lic_v3_ops;
1299                 break;
1300 #endif  /* EFSYS_OPT_MEDFORD */
1301
1302         default:
1303                 EFSYS_ASSERT(0);
1304                 rc = ENOTSUP;
1305                 goto fail1;
1306         }
1307
1308         enp->en_elop = elop;
1309         enp->en_mod_flags |= EFX_MOD_LIC;
1310
1311         /* Probe for support */
1312         if (efx_lic_get_key_stats(enp, &eks) == 0) {
1313                 enp->en_licensing_supported = B_TRUE;
1314         } else {
1315                 enp->en_licensing_supported = B_FALSE;
1316         }
1317
1318         return (0);
1319
1320 fail1:
1321         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1322
1323         return (rc);
1324 }
1325
1326 extern  __checkReturn   boolean_t
1327 efx_lic_check_support(
1328         __in                    efx_nic_t *enp)
1329 {
1330         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1331         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1332         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1333
1334         return (enp->en_licensing_supported);
1335 }
1336
1337                                 void
1338 efx_lic_fini(
1339         __in                    efx_nic_t *enp)
1340 {
1341         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1342         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1343         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1344
1345         enp->en_elop = NULL;
1346         enp->en_mod_flags &= ~EFX_MOD_LIC;
1347 }
1348
1349
1350         __checkReturn   efx_rc_t
1351 efx_lic_update_licenses(
1352         __in            efx_nic_t *enp)
1353 {
1354         const efx_lic_ops_t *elop = enp->en_elop;
1355         efx_rc_t rc;
1356
1357         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1358         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1359
1360         if ((rc = elop->elo_update_licenses(enp)) != 0)
1361                 goto fail1;
1362
1363         return (0);
1364
1365 fail1:
1366         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1367
1368         return (rc);
1369 }
1370
1371         __checkReturn   efx_rc_t
1372 efx_lic_get_key_stats(
1373         __in            efx_nic_t *enp,
1374         __out           efx_key_stats_t *eksp)
1375 {
1376         const efx_lic_ops_t *elop = enp->en_elop;
1377         efx_rc_t rc;
1378
1379         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1380         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1381
1382         if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
1383                 goto fail1;
1384
1385         return (0);
1386
1387 fail1:
1388         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1389
1390         return (rc);
1391 }
1392
1393         __checkReturn   efx_rc_t
1394 efx_lic_app_state(
1395         __in            efx_nic_t *enp,
1396         __in            uint64_t app_id,
1397         __out           boolean_t *licensedp)
1398 {
1399         const efx_lic_ops_t *elop = enp->en_elop;
1400         efx_rc_t rc;
1401
1402         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1403         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1404
1405         if (elop->elo_app_state == NULL)
1406                 return (ENOTSUP);
1407
1408         if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
1409                 goto fail1;
1410
1411         return (0);
1412
1413 fail1:
1414         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1415
1416         return (rc);
1417 }
1418
1419         __checkReturn   efx_rc_t
1420 efx_lic_get_id(
1421         __in            efx_nic_t *enp,
1422         __in            size_t buffer_size,
1423         __out           uint32_t *typep,
1424         __out           size_t *lengthp,
1425         __out_opt       uint8_t *bufferp)
1426 {
1427         const efx_lic_ops_t *elop = enp->en_elop;
1428         efx_rc_t rc;
1429
1430         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1431         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1432
1433         if (elop->elo_get_id == NULL)
1434                 return (ENOTSUP);
1435
1436         if ((rc = elop->elo_get_id(enp, buffer_size, typep,
1437                                     lengthp, bufferp)) != 0)
1438                 goto fail1;
1439
1440         return (0);
1441
1442 fail1:
1443         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1444
1445         return (rc);
1446 }
1447
1448 /*
1449  * Buffer management API - abstracts varying TLV format used for License
1450  * partition.
1451  */
1452
1453         __checkReturn           efx_rc_t
1454 efx_lic_find_start(
1455         __in                    efx_nic_t *enp,
1456         __in_bcount(buffer_size)
1457                                 caddr_t bufferp,
1458         __in                    size_t buffer_size,
1459         __out                   uint32_t *startp)
1460 {
1461         const efx_lic_ops_t *elop = enp->en_elop;
1462         efx_rc_t rc;
1463
1464         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1465         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1466
1467         if ((rc = elop->elo_find_start(enp, bufferp, buffer_size, startp)) != 0)
1468                 goto fail1;
1469
1470         return (0);
1471
1472 fail1:
1473         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1474
1475         return (rc);
1476 }
1477
1478         __checkReturn           efx_rc_t
1479 efx_lic_find_end(
1480         __in                    efx_nic_t *enp,
1481         __in_bcount(buffer_size)
1482                                 caddr_t bufferp,
1483         __in                    size_t buffer_size,
1484         __in                    uint32_t offset,
1485         __out                   uint32_t *endp)
1486 {
1487         const efx_lic_ops_t *elop = enp->en_elop;
1488         efx_rc_t rc;
1489
1490         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1491         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1492
1493         rc = elop->elo_find_end(enp, bufferp, buffer_size, offset, endp);
1494         if (rc != 0)
1495                 goto fail1;
1496
1497         return (0);
1498
1499 fail1:
1500         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1501
1502         return (rc);
1503 }
1504
1505         __checkReturn   __success(return != B_FALSE)    boolean_t
1506 efx_lic_find_key(
1507         __in                    efx_nic_t *enp,
1508         __in_bcount(buffer_size)
1509                                 caddr_t bufferp,
1510         __in                    size_t buffer_size,
1511         __in                    uint32_t offset,
1512         __out                   uint32_t *startp,
1513         __out                   uint32_t *lengthp)
1514 {
1515         const efx_lic_ops_t *elop = enp->en_elop;
1516
1517         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1518         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1519
1520         EFSYS_ASSERT(bufferp);
1521         EFSYS_ASSERT(startp);
1522         EFSYS_ASSERT(lengthp);
1523
1524         return (elop->elo_find_key(enp, bufferp, buffer_size, offset,
1525                                     startp, lengthp));
1526 }
1527
1528
1529 /*
1530  * Validate that the buffer contains a single key in a recognised format.
1531  * An empty or terminator buffer is not accepted as a valid key.
1532  */
1533         __checkReturn   __success(return != B_FALSE)    boolean_t
1534 efx_lic_validate_key(
1535         __in                    efx_nic_t *enp,
1536         __in_bcount(length)     caddr_t keyp,
1537         __in                    uint32_t length)
1538 {
1539         const efx_lic_ops_t *elop = enp->en_elop;
1540         boolean_t rc;
1541
1542         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1543         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1544
1545         if ((rc = elop->elo_validate_key(enp, keyp, length)) == B_FALSE)
1546                 goto fail1;
1547
1548         return (B_TRUE);
1549
1550 fail1:
1551         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1552
1553         return (rc);
1554 }
1555
1556         __checkReturn           efx_rc_t
1557 efx_lic_read_key(
1558         __in                    efx_nic_t *enp,
1559         __in_bcount(buffer_size)
1560                                 caddr_t bufferp,
1561         __in                    size_t buffer_size,
1562         __in                    uint32_t offset,
1563         __in                    uint32_t length,
1564         __out_bcount_part(key_max_size, *lengthp)
1565                                 caddr_t keyp,
1566         __in                    size_t key_max_size,
1567         __out                   uint32_t *lengthp)
1568 {
1569         const efx_lic_ops_t *elop = enp->en_elop;
1570         efx_rc_t rc;
1571
1572         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1573         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1574
1575         if ((rc = elop->elo_read_key(enp, bufferp, buffer_size, offset,
1576                                     length, keyp, key_max_size, lengthp)) != 0)
1577                 goto fail1;
1578
1579         return (0);
1580
1581 fail1:
1582         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1583
1584         return (rc);
1585 }
1586
1587         __checkReturn           efx_rc_t
1588 efx_lic_write_key(
1589         __in                    efx_nic_t *enp,
1590         __in_bcount(buffer_size)
1591                                 caddr_t bufferp,
1592         __in                    size_t buffer_size,
1593         __in                    uint32_t offset,
1594         __in_bcount(length)     caddr_t keyp,
1595         __in                    uint32_t length,
1596         __out                   uint32_t *lengthp)
1597 {
1598         const efx_lic_ops_t *elop = enp->en_elop;
1599         efx_rc_t rc;
1600
1601         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1602         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1603
1604         if ((rc = elop->elo_write_key(enp, bufferp, buffer_size, offset,
1605                                     keyp, length, lengthp)) != 0)
1606                 goto fail1;
1607
1608         return (0);
1609
1610 fail1:
1611         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1612
1613         return (rc);
1614 }
1615
1616         __checkReturn           efx_rc_t
1617 efx_lic_delete_key(
1618         __in                    efx_nic_t *enp,
1619         __in_bcount(buffer_size)
1620                                 caddr_t bufferp,
1621         __in                    size_t buffer_size,
1622         __in                    uint32_t offset,
1623         __in                    uint32_t length,
1624         __in                    uint32_t end,
1625         __out                   uint32_t *deltap)
1626 {
1627         const efx_lic_ops_t *elop = enp->en_elop;
1628         efx_rc_t rc;
1629
1630         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1631         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1632
1633         if ((rc = elop->elo_delete_key(enp, bufferp, buffer_size, offset,
1634                                     length, end, deltap)) != 0)
1635                 goto fail1;
1636
1637         return (0);
1638
1639 fail1:
1640         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1641
1642         return (rc);
1643 }
1644
1645         __checkReturn           efx_rc_t
1646 efx_lic_create_partition(
1647         __in                    efx_nic_t *enp,
1648         __in_bcount(buffer_size)
1649                                 caddr_t bufferp,
1650         __in                    size_t buffer_size)
1651 {
1652         const efx_lic_ops_t *elop = enp->en_elop;
1653         efx_rc_t rc;
1654
1655         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1656         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1657
1658         if ((rc = elop->elo_create_partition(enp, bufferp, buffer_size)) != 0)
1659                 goto fail1;
1660
1661         return (0);
1662
1663 fail1:
1664         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1665
1666         return (rc);
1667 }
1668
1669
1670         __checkReturn           efx_rc_t
1671 efx_lic_finish_partition(
1672         __in                    efx_nic_t *enp,
1673         __in_bcount(buffer_size)
1674                                 caddr_t bufferp,
1675         __in                    size_t buffer_size)
1676 {
1677         const efx_lic_ops_t *elop = enp->en_elop;
1678         efx_rc_t rc;
1679
1680         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1681         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
1682
1683         if ((rc = elop->elo_finish_partition(enp, bufferp, buffer_size)) != 0)
1684                 goto fail1;
1685
1686         return (0);
1687
1688 fail1:
1689         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1690
1691         return (rc);
1692 }
1693
1694 #endif  /* EFSYS_OPT_LICENSING */