1 /*-
2 * Copyright (c) 2012-2016 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "efx.h"
35 #include "efx_impl.h"
36 #if EFSYS_OPT_MON_MCDI
37 #include "mcdi_mon.h"
38 #endif
39
40 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
41
42 #include "ef10_tlv_layout.h"
43
44 __checkReturn efx_rc_t
efx_mcdi_get_port_assignment(__in efx_nic_t * enp,__out uint32_t * portp)45 efx_mcdi_get_port_assignment(
46 __in efx_nic_t *enp,
47 __out uint32_t *portp)
48 {
49 efx_mcdi_req_t req;
50 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN,
51 MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
52 efx_rc_t rc;
53
54 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
55 enp->en_family == EFX_FAMILY_MEDFORD);
56
57 req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
58 req.emr_in_buf = payload;
59 req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN;
60 req.emr_out_buf = payload;
61 req.emr_out_length = MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN;
62
63 efx_mcdi_execute(enp, &req);
64
65 if (req.emr_rc != 0) {
66 rc = req.emr_rc;
67 goto fail1;
68 }
69
70 if (req.emr_out_length_used < MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN) {
71 rc = EMSGSIZE;
72 goto fail2;
73 }
74
75 *portp = MCDI_OUT_DWORD(req, GET_PORT_ASSIGNMENT_OUT_PORT);
76
77 return (0);
78
79 fail2:
80 EFSYS_PROBE(fail2);
81 fail1:
82 EFSYS_PROBE1(fail1, efx_rc_t, rc);
83
84 return (rc);
85 }
86
87 __checkReturn efx_rc_t
efx_mcdi_get_port_modes(__in efx_nic_t * enp,__out uint32_t * modesp,__out_opt uint32_t * current_modep)88 efx_mcdi_get_port_modes(
89 __in efx_nic_t *enp,
90 __out uint32_t *modesp,
91 __out_opt uint32_t *current_modep)
92 {
93 efx_mcdi_req_t req;
94 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PORT_MODES_IN_LEN,
95 MC_CMD_GET_PORT_MODES_OUT_LEN);
96 efx_rc_t rc;
97
98 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
99 enp->en_family == EFX_FAMILY_MEDFORD);
100
101 req.emr_cmd = MC_CMD_GET_PORT_MODES;
102 req.emr_in_buf = payload;
103 req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN;
104 req.emr_out_buf = payload;
105 req.emr_out_length = MC_CMD_GET_PORT_MODES_OUT_LEN;
106
107 efx_mcdi_execute(enp, &req);
108
109 if (req.emr_rc != 0) {
110 rc = req.emr_rc;
111 goto fail1;
112 }
113
114 /*
115 * Require only Modes and DefaultMode fields, unless the current mode
116 * was requested (CurrentMode field was added for Medford).
117 */
118 if (req.emr_out_length_used <
119 MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) {
120 rc = EMSGSIZE;
121 goto fail2;
122 }
123 if ((current_modep != NULL) && (req.emr_out_length_used <
124 MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST + 4)) {
125 rc = EMSGSIZE;
126 goto fail3;
127 }
128
129 *modesp = MCDI_OUT_DWORD(req, GET_PORT_MODES_OUT_MODES);
130
131 if (current_modep != NULL) {
132 *current_modep = MCDI_OUT_DWORD(req,
133 GET_PORT_MODES_OUT_CURRENT_MODE);
134 }
135
136 return (0);
137
138 fail3:
139 EFSYS_PROBE(fail3);
140 fail2:
141 EFSYS_PROBE(fail2);
142 fail1:
143 EFSYS_PROBE1(fail1, efx_rc_t, rc);
144
145 return (rc);
146 }
147
148 __checkReturn efx_rc_t
ef10_nic_get_port_mode_bandwidth(__in uint32_t port_mode,__out uint32_t * bandwidth_mbpsp)149 ef10_nic_get_port_mode_bandwidth(
150 __in uint32_t port_mode,
151 __out uint32_t *bandwidth_mbpsp)
152 {
153 uint32_t bandwidth;
154 efx_rc_t rc;
155
156 switch (port_mode) {
157 case TLV_PORT_MODE_10G:
158 bandwidth = 10000;
159 break;
160 case TLV_PORT_MODE_10G_10G:
161 bandwidth = 10000 * 2;
162 break;
163 case TLV_PORT_MODE_10G_10G_10G_10G:
164 case TLV_PORT_MODE_10G_10G_10G_10G_Q:
165 case TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2:
166 case TLV_PORT_MODE_10G_10G_10G_10G_Q2:
167 bandwidth = 10000 * 4;
168 break;
169 case TLV_PORT_MODE_40G:
170 bandwidth = 40000;
171 break;
172 case TLV_PORT_MODE_40G_40G:
173 bandwidth = 40000 * 2;
174 break;
175 case TLV_PORT_MODE_40G_10G_10G:
176 case TLV_PORT_MODE_10G_10G_40G:
177 bandwidth = 40000 + (10000 * 2);
178 break;
179 default:
180 rc = EINVAL;
181 goto fail1;
182 }
183
184 *bandwidth_mbpsp = bandwidth;
185
186 return (0);
187
188 fail1:
189 EFSYS_PROBE1(fail1, efx_rc_t, rc);
190
191 return (rc);
192 }
193
194 static __checkReturn efx_rc_t
efx_mcdi_vadaptor_alloc(__in efx_nic_t * enp,__in uint32_t port_id)195 efx_mcdi_vadaptor_alloc(
196 __in efx_nic_t *enp,
197 __in uint32_t port_id)
198 {
199 efx_mcdi_req_t req;
200 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VADAPTOR_ALLOC_IN_LEN,
201 MC_CMD_VADAPTOR_ALLOC_OUT_LEN);
202 efx_rc_t rc;
203
204 EFSYS_ASSERT3U(enp->en_vport_id, ==, EVB_PORT_ID_NULL);
205
206 req.emr_cmd = MC_CMD_VADAPTOR_ALLOC;
207 req.emr_in_buf = payload;
208 req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN;
209 req.emr_out_buf = payload;
210 req.emr_out_length = MC_CMD_VADAPTOR_ALLOC_OUT_LEN;
211
212 MCDI_IN_SET_DWORD(req, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
213 MCDI_IN_POPULATE_DWORD_1(req, VADAPTOR_ALLOC_IN_FLAGS,
214 VADAPTOR_ALLOC_IN_FLAG_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED,
215 enp->en_nic_cfg.enc_allow_set_mac_with_installed_filters ? 1 : 0);
216
217 efx_mcdi_execute(enp, &req);
218
219 if (req.emr_rc != 0) {
220 rc = req.emr_rc;
221 goto fail1;
222 }
223
224 return (0);
225
226 fail1:
227 EFSYS_PROBE1(fail1, efx_rc_t, rc);
228
229 return (rc);
230 }
231
232 static __checkReturn efx_rc_t
efx_mcdi_vadaptor_free(__in efx_nic_t * enp,__in uint32_t port_id)233 efx_mcdi_vadaptor_free(
234 __in efx_nic_t *enp,
235 __in uint32_t port_id)
236 {
237 efx_mcdi_req_t req;
238 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VADAPTOR_FREE_IN_LEN,
239 MC_CMD_VADAPTOR_FREE_OUT_LEN);
240 efx_rc_t rc;
241
242 req.emr_cmd = MC_CMD_VADAPTOR_FREE;
243 req.emr_in_buf = payload;
244 req.emr_in_length = MC_CMD_VADAPTOR_FREE_IN_LEN;
245 req.emr_out_buf = payload;
246 req.emr_out_length = MC_CMD_VADAPTOR_FREE_OUT_LEN;
247
248 MCDI_IN_SET_DWORD(req, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
249
250 efx_mcdi_execute(enp, &req);
251
252 if (req.emr_rc != 0) {
253 rc = req.emr_rc;
254 goto fail1;
255 }
256
257 return (0);
258
259 fail1:
260 EFSYS_PROBE1(fail1, efx_rc_t, rc);
261
262 return (rc);
263 }
264
265 __checkReturn efx_rc_t
266 efx_mcdi_get_mac_address_pf(
267 __in efx_nic_t *enp,
268 __out_ecount_opt(6) uint8_t mac_addrp[6])
269 {
270 efx_mcdi_req_t req;
271 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_MAC_ADDRESSES_IN_LEN,
272 MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
273 efx_rc_t rc;
274
275 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
276 enp->en_family == EFX_FAMILY_MEDFORD);
277
278 req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
279 req.emr_in_buf = payload;
280 req.emr_in_length = MC_CMD_GET_MAC_ADDRESSES_IN_LEN;
281 req.emr_out_buf = payload;
282 req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN;
283
284 efx_mcdi_execute(enp, &req);
285
286 if (req.emr_rc != 0) {
287 rc = req.emr_rc;
288 goto fail1;
289 }
290
291 if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) {
292 rc = EMSGSIZE;
293 goto fail2;
294 }
295
296 if (MCDI_OUT_DWORD(req, GET_MAC_ADDRESSES_OUT_MAC_COUNT) < 1) {
297 rc = ENOENT;
298 goto fail3;
299 }
300
301 if (mac_addrp != NULL) {
302 uint8_t *addrp;
303
304 addrp = MCDI_OUT2(req, uint8_t,
305 GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE);
306
307 EFX_MAC_ADDR_COPY(mac_addrp, addrp);
308 }
309
310 return (0);
311
312 fail3:
313 EFSYS_PROBE(fail3);
314 fail2:
315 EFSYS_PROBE(fail2);
316 fail1:
317 EFSYS_PROBE1(fail1, efx_rc_t, rc);
318
319 return (rc);
320 }
321
322 __checkReturn efx_rc_t
323 efx_mcdi_get_mac_address_vf(
324 __in efx_nic_t *enp,
325 __out_ecount_opt(6) uint8_t mac_addrp[6])
326 {
327 efx_mcdi_req_t req;
328 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN,
329 MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX);
330 efx_rc_t rc;
331
332 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
333 enp->en_family == EFX_FAMILY_MEDFORD);
334
335 req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES;
336 req.emr_in_buf = payload;
337 req.emr_in_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN;
338 req.emr_out_buf = payload;
339 req.emr_out_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX;
340
341 MCDI_IN_SET_DWORD(req, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID,
342 EVB_PORT_ID_ASSIGNED);
343
344 efx_mcdi_execute(enp, &req);
345
346 if (req.emr_rc != 0) {
347 rc = req.emr_rc;
348 goto fail1;
349 }
350
351 if (req.emr_out_length_used <
352 MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN) {
353 rc = EMSGSIZE;
354 goto fail2;
355 }
356
357 if (MCDI_OUT_DWORD(req,
358 VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT) < 1) {
359 rc = ENOENT;
360 goto fail3;
361 }
362
363 if (mac_addrp != NULL) {
364 uint8_t *addrp;
365
366 addrp = MCDI_OUT2(req, uint8_t,
367 VPORT_GET_MAC_ADDRESSES_OUT_MACADDR);
368
369 EFX_MAC_ADDR_COPY(mac_addrp, addrp);
370 }
371
372 return (0);
373
374 fail3:
375 EFSYS_PROBE(fail3);
376 fail2:
377 EFSYS_PROBE(fail2);
378 fail1:
379 EFSYS_PROBE1(fail1, efx_rc_t, rc);
380
381 return (rc);
382 }
383
384 __checkReturn efx_rc_t
efx_mcdi_get_clock(__in efx_nic_t * enp,__out uint32_t * sys_freqp,__out uint32_t * dpcpu_freqp)385 efx_mcdi_get_clock(
386 __in efx_nic_t *enp,
387 __out uint32_t *sys_freqp,
388 __out uint32_t *dpcpu_freqp)
389 {
390 efx_mcdi_req_t req;
391 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CLOCK_IN_LEN,
392 MC_CMD_GET_CLOCK_OUT_LEN);
393 efx_rc_t rc;
394
395 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
396 enp->en_family == EFX_FAMILY_MEDFORD);
397
398 req.emr_cmd = MC_CMD_GET_CLOCK;
399 req.emr_in_buf = payload;
400 req.emr_in_length = MC_CMD_GET_CLOCK_IN_LEN;
401 req.emr_out_buf = payload;
402 req.emr_out_length = MC_CMD_GET_CLOCK_OUT_LEN;
403
404 efx_mcdi_execute(enp, &req);
405
406 if (req.emr_rc != 0) {
407 rc = req.emr_rc;
408 goto fail1;
409 }
410
411 if (req.emr_out_length_used < MC_CMD_GET_CLOCK_OUT_LEN) {
412 rc = EMSGSIZE;
413 goto fail2;
414 }
415
416 *sys_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_SYS_FREQ);
417 if (*sys_freqp == 0) {
418 rc = EINVAL;
419 goto fail3;
420 }
421 *dpcpu_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_DPCPU_FREQ);
422 if (*dpcpu_freqp == 0) {
423 rc = EINVAL;
424 goto fail4;
425 }
426
427 return (0);
428
429 fail4:
430 EFSYS_PROBE(fail4);
431 fail3:
432 EFSYS_PROBE(fail3);
433 fail2:
434 EFSYS_PROBE(fail2);
435 fail1:
436 EFSYS_PROBE1(fail1, efx_rc_t, rc);
437
438 return (rc);
439 }
440
441 __checkReturn efx_rc_t
efx_mcdi_get_vector_cfg(__in efx_nic_t * enp,__out_opt uint32_t * vec_basep,__out_opt uint32_t * pf_nvecp,__out_opt uint32_t * vf_nvecp)442 efx_mcdi_get_vector_cfg(
443 __in efx_nic_t *enp,
444 __out_opt uint32_t *vec_basep,
445 __out_opt uint32_t *pf_nvecp,
446 __out_opt uint32_t *vf_nvecp)
447 {
448 efx_mcdi_req_t req;
449 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_VECTOR_CFG_IN_LEN,
450 MC_CMD_GET_VECTOR_CFG_OUT_LEN);
451 efx_rc_t rc;
452
453 req.emr_cmd = MC_CMD_GET_VECTOR_CFG;
454 req.emr_in_buf = payload;
455 req.emr_in_length = MC_CMD_GET_VECTOR_CFG_IN_LEN;
456 req.emr_out_buf = payload;
457 req.emr_out_length = MC_CMD_GET_VECTOR_CFG_OUT_LEN;
458
459 efx_mcdi_execute(enp, &req);
460
461 if (req.emr_rc != 0) {
462 rc = req.emr_rc;
463 goto fail1;
464 }
465
466 if (req.emr_out_length_used < MC_CMD_GET_VECTOR_CFG_OUT_LEN) {
467 rc = EMSGSIZE;
468 goto fail2;
469 }
470
471 if (vec_basep != NULL)
472 *vec_basep = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VEC_BASE);
473 if (pf_nvecp != NULL)
474 *pf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_PF);
475 if (vf_nvecp != NULL)
476 *vf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_VF);
477
478 return (0);
479
480 fail2:
481 EFSYS_PROBE(fail2);
482 fail1:
483 EFSYS_PROBE1(fail1, efx_rc_t, rc);
484
485 return (rc);
486 }
487
488 static __checkReturn efx_rc_t
efx_mcdi_get_capabilities(__in efx_nic_t * enp,__out uint32_t * flagsp,__out uint32_t * flags2p,__out uint32_t * tso2ncp)489 efx_mcdi_get_capabilities(
490 __in efx_nic_t *enp,
491 __out uint32_t *flagsp,
492 __out uint32_t *flags2p,
493 __out uint32_t *tso2ncp)
494 {
495 efx_mcdi_req_t req;
496 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CAPABILITIES_IN_LEN,
497 MC_CMD_GET_CAPABILITIES_V2_OUT_LEN);
498 efx_rc_t rc;
499
500 req.emr_cmd = MC_CMD_GET_CAPABILITIES;
501 req.emr_in_buf = payload;
502 req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN;
503 req.emr_out_buf = payload;
504 req.emr_out_length = MC_CMD_GET_CAPABILITIES_V2_OUT_LEN;
505
506 efx_mcdi_execute(enp, &req);
507
508 if (req.emr_rc != 0) {
509 rc = req.emr_rc;
510 goto fail1;
511 }
512
513 if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) {
514 rc = EMSGSIZE;
515 goto fail2;
516 }
517
518 *flagsp = MCDI_OUT_DWORD(req, GET_CAPABILITIES_OUT_FLAGS1);
519
520 if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) {
521 *flags2p = 0;
522 *tso2ncp = 0;
523 } else {
524 *flags2p = MCDI_OUT_DWORD(req, GET_CAPABILITIES_V2_OUT_FLAGS2);
525 *tso2ncp = MCDI_OUT_WORD(req,
526 GET_CAPABILITIES_V2_OUT_TX_TSO_V2_N_CONTEXTS);
527 }
528
529 return (0);
530
531 fail2:
532 EFSYS_PROBE(fail2);
533 fail1:
534 EFSYS_PROBE1(fail1, efx_rc_t, rc);
535
536 return (rc);
537 }
538
539
540 static __checkReturn efx_rc_t
efx_mcdi_alloc_vis(__in efx_nic_t * enp,__in uint32_t min_vi_count,__in uint32_t max_vi_count,__out uint32_t * vi_basep,__out uint32_t * vi_countp,__out uint32_t * vi_shiftp)541 efx_mcdi_alloc_vis(
542 __in efx_nic_t *enp,
543 __in uint32_t min_vi_count,
544 __in uint32_t max_vi_count,
545 __out uint32_t *vi_basep,
546 __out uint32_t *vi_countp,
547 __out uint32_t *vi_shiftp)
548 {
549 efx_mcdi_req_t req;
550 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ALLOC_VIS_IN_LEN,
551 MC_CMD_ALLOC_VIS_EXT_OUT_LEN);
552 efx_rc_t rc;
553
554 if (vi_countp == NULL) {
555 rc = EINVAL;
556 goto fail1;
557 }
558
559 req.emr_cmd = MC_CMD_ALLOC_VIS;
560 req.emr_in_buf = payload;
561 req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN;
562 req.emr_out_buf = payload;
563 req.emr_out_length = MC_CMD_ALLOC_VIS_EXT_OUT_LEN;
564
565 MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count);
566 MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count);
567
568 efx_mcdi_execute(enp, &req);
569
570 if (req.emr_rc != 0) {
571 rc = req.emr_rc;
572 goto fail2;
573 }
574
575 if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) {
576 rc = EMSGSIZE;
577 goto fail3;
578 }
579
580 *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE);
581 *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT);
582
583 /* Report VI_SHIFT if available (always zero for Huntington) */
584 if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_EXT_OUT_LEN)
585 *vi_shiftp = 0;
586 else
587 *vi_shiftp = MCDI_OUT_DWORD(req, ALLOC_VIS_EXT_OUT_VI_SHIFT);
588
589 return (0);
590
591 fail3:
592 EFSYS_PROBE(fail3);
593 fail2:
594 EFSYS_PROBE(fail2);
595 fail1:
596 EFSYS_PROBE1(fail1, efx_rc_t, rc);
597
598 return (rc);
599 }
600
601
602 static __checkReturn efx_rc_t
efx_mcdi_free_vis(__in efx_nic_t * enp)603 efx_mcdi_free_vis(
604 __in efx_nic_t *enp)
605 {
606 efx_mcdi_req_t req;
607 efx_rc_t rc;
608
609 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0);
610 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0);
611
612 req.emr_cmd = MC_CMD_FREE_VIS;
613 req.emr_in_buf = NULL;
614 req.emr_in_length = 0;
615 req.emr_out_buf = NULL;
616 req.emr_out_length = 0;
617
618 efx_mcdi_execute_quiet(enp, &req);
619
620 /* Ignore ELREADY (no allocated VIs, so nothing to free) */
621 if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) {
622 rc = req.emr_rc;
623 goto fail1;
624 }
625
626 return (0);
627
628 fail1:
629 EFSYS_PROBE1(fail1, efx_rc_t, rc);
630
631 return (rc);
632 }
633
634
635 static __checkReturn efx_rc_t
efx_mcdi_alloc_piobuf(__in efx_nic_t * enp,__out efx_piobuf_handle_t * handlep)636 efx_mcdi_alloc_piobuf(
637 __in efx_nic_t *enp,
638 __out efx_piobuf_handle_t *handlep)
639 {
640 efx_mcdi_req_t req;
641 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ALLOC_PIOBUF_IN_LEN,
642 MC_CMD_ALLOC_PIOBUF_OUT_LEN);
643 efx_rc_t rc;
644
645 if (handlep == NULL) {
646 rc = EINVAL;
647 goto fail1;
648 }
649
650 req.emr_cmd = MC_CMD_ALLOC_PIOBUF;
651 req.emr_in_buf = payload;
652 req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN;
653 req.emr_out_buf = payload;
654 req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN;
655
656 efx_mcdi_execute_quiet(enp, &req);
657
658 if (req.emr_rc != 0) {
659 rc = req.emr_rc;
660 goto fail2;
661 }
662
663 if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) {
664 rc = EMSGSIZE;
665 goto fail3;
666 }
667
668 *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE);
669
670 return (0);
671
672 fail3:
673 EFSYS_PROBE(fail3);
674 fail2:
675 EFSYS_PROBE(fail2);
676 fail1:
677 EFSYS_PROBE1(fail1, efx_rc_t, rc);
678
679 return (rc);
680 }
681
682 static __checkReturn efx_rc_t
efx_mcdi_free_piobuf(__in efx_nic_t * enp,__in efx_piobuf_handle_t handle)683 efx_mcdi_free_piobuf(
684 __in efx_nic_t *enp,
685 __in efx_piobuf_handle_t handle)
686 {
687 efx_mcdi_req_t req;
688 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FREE_PIOBUF_IN_LEN,
689 MC_CMD_FREE_PIOBUF_OUT_LEN);
690 efx_rc_t rc;
691
692 req.emr_cmd = MC_CMD_FREE_PIOBUF;
693 req.emr_in_buf = payload;
694 req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN;
695 req.emr_out_buf = payload;
696 req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN;
697
698 MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle);
699
700 efx_mcdi_execute_quiet(enp, &req);
701
702 if (req.emr_rc != 0) {
703 rc = req.emr_rc;
704 goto fail1;
705 }
706
707 return (0);
708
709 fail1:
710 EFSYS_PROBE1(fail1, efx_rc_t, rc);
711
712 return (rc);
713 }
714
715 static __checkReturn efx_rc_t
efx_mcdi_link_piobuf(__in efx_nic_t * enp,__in uint32_t vi_index,__in efx_piobuf_handle_t handle)716 efx_mcdi_link_piobuf(
717 __in efx_nic_t *enp,
718 __in uint32_t vi_index,
719 __in efx_piobuf_handle_t handle)
720 {
721 efx_mcdi_req_t req;
722 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LINK_PIOBUF_IN_LEN,
723 MC_CMD_LINK_PIOBUF_OUT_LEN);
724 efx_rc_t rc;
725
726 req.emr_cmd = MC_CMD_LINK_PIOBUF;
727 req.emr_in_buf = payload;
728 req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN;
729 req.emr_out_buf = payload;
730 req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN;
731
732 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle);
733 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
734
735 efx_mcdi_execute(enp, &req);
736
737 if (req.emr_rc != 0) {
738 rc = req.emr_rc;
739 goto fail1;
740 }
741
742 return (0);
743
744 fail1:
745 EFSYS_PROBE1(fail1, efx_rc_t, rc);
746
747 return (rc);
748 }
749
750 static __checkReturn efx_rc_t
efx_mcdi_unlink_piobuf(__in efx_nic_t * enp,__in uint32_t vi_index)751 efx_mcdi_unlink_piobuf(
752 __in efx_nic_t *enp,
753 __in uint32_t vi_index)
754 {
755 efx_mcdi_req_t req;
756 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_UNLINK_PIOBUF_IN_LEN,
757 MC_CMD_UNLINK_PIOBUF_OUT_LEN);
758 efx_rc_t rc;
759
760 req.emr_cmd = MC_CMD_UNLINK_PIOBUF;
761 req.emr_in_buf = payload;
762 req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN;
763 req.emr_out_buf = payload;
764 req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN;
765
766 MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
767
768 efx_mcdi_execute_quiet(enp, &req);
769
770 if (req.emr_rc != 0) {
771 rc = req.emr_rc;
772 goto fail1;
773 }
774
775 return (0);
776
777 fail1:
778 EFSYS_PROBE1(fail1, efx_rc_t, rc);
779
780 return (rc);
781 }
782
783 static void
ef10_nic_alloc_piobufs(__in efx_nic_t * enp,__in uint32_t max_piobuf_count)784 ef10_nic_alloc_piobufs(
785 __in efx_nic_t *enp,
786 __in uint32_t max_piobuf_count)
787 {
788 efx_piobuf_handle_t *handlep;
789 unsigned int i;
790
791 EFSYS_ASSERT3U(max_piobuf_count, <=,
792 EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle));
793
794 enp->en_arch.ef10.ena_piobuf_count = 0;
795
796 for (i = 0; i < max_piobuf_count; i++) {
797 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
798
799 if (efx_mcdi_alloc_piobuf(enp, handlep) != 0)
800 goto fail1;
801
802 enp->en_arch.ef10.ena_pio_alloc_map[i] = 0;
803 enp->en_arch.ef10.ena_piobuf_count++;
804 }
805
806 return;
807
808 fail1:
809 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
810 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
811
812 (void) efx_mcdi_free_piobuf(enp, *handlep);
813 *handlep = EFX_PIOBUF_HANDLE_INVALID;
814 }
815 enp->en_arch.ef10.ena_piobuf_count = 0;
816 }
817
818
819 static void
ef10_nic_free_piobufs(__in efx_nic_t * enp)820 ef10_nic_free_piobufs(
821 __in efx_nic_t *enp)
822 {
823 efx_piobuf_handle_t *handlep;
824 unsigned int i;
825
826 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
827 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
828
829 (void) efx_mcdi_free_piobuf(enp, *handlep);
830 *handlep = EFX_PIOBUF_HANDLE_INVALID;
831 }
832 enp->en_arch.ef10.ena_piobuf_count = 0;
833 }
834
835 /* Sub-allocate a block from a piobuf */
836 __checkReturn efx_rc_t
ef10_nic_pio_alloc(__inout efx_nic_t * enp,__out uint32_t * bufnump,__out efx_piobuf_handle_t * handlep,__out uint32_t * blknump,__out uint32_t * offsetp,__out size_t * sizep)837 ef10_nic_pio_alloc(
838 __inout efx_nic_t *enp,
839 __out uint32_t *bufnump,
840 __out efx_piobuf_handle_t *handlep,
841 __out uint32_t *blknump,
842 __out uint32_t *offsetp,
843 __out size_t *sizep)
844 {
845 efx_nic_cfg_t *encp = &enp->en_nic_cfg;
846 efx_drv_cfg_t *edcp = &enp->en_drv_cfg;
847 uint32_t blk_per_buf;
848 uint32_t buf, blk;
849 efx_rc_t rc;
850
851 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
852 enp->en_family == EFX_FAMILY_MEDFORD);
853 EFSYS_ASSERT(bufnump);
854 EFSYS_ASSERT(handlep);
855 EFSYS_ASSERT(blknump);
856 EFSYS_ASSERT(offsetp);
857 EFSYS_ASSERT(sizep);
858
859 if ((edcp->edc_pio_alloc_size == 0) ||
860 (enp->en_arch.ef10.ena_piobuf_count == 0)) {
861 rc = ENOMEM;
862 goto fail1;
863 }
864 blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size;
865
866 for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) {
867 uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf];
868
869 if (~(*map) == 0)
870 continue;
871
872 EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map)));
873 for (blk = 0; blk < blk_per_buf; blk++) {
874 if ((*map & (1u << blk)) == 0) {
875 *map |= (1u << blk);
876 goto done;
877 }
878 }
879 }
880 rc = ENOMEM;
881 goto fail2;
882
883 done:
884 *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf];
885 *bufnump = buf;
886 *blknump = blk;
887 *sizep = edcp->edc_pio_alloc_size;
888 *offsetp = blk * (*sizep);
889
890 return (0);
891
892 fail2:
893 EFSYS_PROBE(fail2);
894 fail1:
895 EFSYS_PROBE1(fail1, efx_rc_t, rc);
896
897 return (rc);
898 }
899
900 /* Free a piobuf sub-allocated block */
901 __checkReturn efx_rc_t
ef10_nic_pio_free(__inout efx_nic_t * enp,__in uint32_t bufnum,__in uint32_t blknum)902 ef10_nic_pio_free(
903 __inout efx_nic_t *enp,
904 __in uint32_t bufnum,
905 __in uint32_t blknum)
906 {
907 uint32_t *map;
908 efx_rc_t rc;
909
910 if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) ||
911 (blknum >= (8 * sizeof (*map)))) {
912 rc = EINVAL;
913 goto fail1;
914 }
915
916 map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum];
917 if ((*map & (1u << blknum)) == 0) {
918 rc = ENOENT;
919 goto fail2;
920 }
921 *map &= ~(1u << blknum);
922
923 return (0);
924
925 fail2:
926 EFSYS_PROBE(fail2);
927 fail1:
928 EFSYS_PROBE1(fail1, efx_rc_t, rc);
929
930 return (rc);
931 }
932
933 __checkReturn efx_rc_t
ef10_nic_pio_link(__inout efx_nic_t * enp,__in uint32_t vi_index,__in efx_piobuf_handle_t handle)934 ef10_nic_pio_link(
935 __inout efx_nic_t *enp,
936 __in uint32_t vi_index,
937 __in efx_piobuf_handle_t handle)
938 {
939 return (efx_mcdi_link_piobuf(enp, vi_index, handle));
940 }
941
942 __checkReturn efx_rc_t
ef10_nic_pio_unlink(__inout efx_nic_t * enp,__in uint32_t vi_index)943 ef10_nic_pio_unlink(
944 __inout efx_nic_t *enp,
945 __in uint32_t vi_index)
946 {
947 return (efx_mcdi_unlink_piobuf(enp, vi_index));
948 }
949
950 static __checkReturn efx_rc_t
ef10_mcdi_get_pf_count(__in efx_nic_t * enp,__out uint32_t * pf_countp)951 ef10_mcdi_get_pf_count(
952 __in efx_nic_t *enp,
953 __out uint32_t *pf_countp)
954 {
955 efx_mcdi_req_t req;
956 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PF_COUNT_IN_LEN,
957 MC_CMD_GET_PF_COUNT_OUT_LEN);
958 efx_rc_t rc;
959
960 req.emr_cmd = MC_CMD_GET_PF_COUNT;
961 req.emr_in_buf = payload;
962 req.emr_in_length = MC_CMD_GET_PF_COUNT_IN_LEN;
963 req.emr_out_buf = payload;
964 req.emr_out_length = MC_CMD_GET_PF_COUNT_OUT_LEN;
965
966 efx_mcdi_execute(enp, &req);
967
968 if (req.emr_rc != 0) {
969 rc = req.emr_rc;
970 goto fail1;
971 }
972
973 if (req.emr_out_length_used < MC_CMD_GET_PF_COUNT_OUT_LEN) {
974 rc = EMSGSIZE;
975 goto fail2;
976 }
977
978 *pf_countp = *MCDI_OUT(req, uint8_t,
979 MC_CMD_GET_PF_COUNT_OUT_PF_COUNT_OFST);
980
981 EFSYS_ASSERT(*pf_countp != 0);
982
983 return (0);
984
985 fail2:
986 EFSYS_PROBE(fail2);
987 fail1:
988 EFSYS_PROBE1(fail1, efx_rc_t, rc);
989
990 return (rc);
991 }
992
993 __checkReturn efx_rc_t
ef10_get_datapath_caps(__in efx_nic_t * enp)994 ef10_get_datapath_caps(
995 __in efx_nic_t *enp)
996 {
997 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
998 uint32_t flags;
999 uint32_t flags2;
1000 uint32_t tso2nc;
1001 efx_rc_t rc;
1002
1003 if ((rc = efx_mcdi_get_capabilities(enp, &flags, &flags2,
1004 &tso2nc)) != 0)
1005 goto fail1;
1006
1007 if ((rc = ef10_mcdi_get_pf_count(enp, &encp->enc_hw_pf_count)) != 0)
1008 goto fail1;
1009
1010 #define CAP_FLAG(flags1, field) \
1011 ((flags1) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN)))
1012
1013 #define CAP_FLAG2(flags2, field) \
1014 ((flags2) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN)))
1015
1016 /*
1017 * Huntington RXDP firmware inserts a 0 or 14 byte prefix.
1018 * We only support the 14 byte prefix here.
1019 */
1020 if (CAP_FLAG(flags, RX_PREFIX_LEN_14) == 0) {
1021 rc = ENOTSUP;
1022 goto fail2;
1023 }
1024 encp->enc_rx_prefix_size = 14;
1025
1026 /* Check if the firmware supports TSO */
1027 encp->enc_fw_assisted_tso_enabled =
1028 CAP_FLAG(flags, TX_TSO) ? B_TRUE : B_FALSE;
1029
1030 /* Check if the firmware supports FATSOv2 */
1031 encp->enc_fw_assisted_tso_v2_enabled =
1032 CAP_FLAG2(flags2, TX_TSO_V2) ? B_TRUE : B_FALSE;
1033
1034 /* Get the number of TSO contexts (FATSOv2) */
1035 encp->enc_fw_assisted_tso_v2_n_contexts =
1036 CAP_FLAG2(flags2, TX_TSO_V2) ? tso2nc : 0;
1037
1038 /* Check if the firmware has vadapter/vport/vswitch support */
1039 encp->enc_datapath_cap_evb =
1040 CAP_FLAG(flags, EVB) ? B_TRUE : B_FALSE;
1041
1042 /* Check if the firmware supports VLAN insertion */
1043 encp->enc_hw_tx_insert_vlan_enabled =
1044 CAP_FLAG(flags, TX_VLAN_INSERTION) ? B_TRUE : B_FALSE;
1045
1046 /* Check if the firmware supports RX event batching */
1047 encp->enc_rx_batching_enabled =
1048 CAP_FLAG(flags, RX_BATCHING) ? B_TRUE : B_FALSE;
1049
1050 /*
1051 * Even if batching isn't reported as supported, we may still get
1052 * batched events.
1053 */
1054 encp->enc_rx_batch_max = 16;
1055
1056 /* Check if the firmware supports disabling scatter on RXQs */
1057 encp->enc_rx_disable_scatter_supported =
1058 CAP_FLAG(flags, RX_DISABLE_SCATTER) ? B_TRUE : B_FALSE;
1059
1060 /* Check if the firmware supports set mac with running filters */
1061 encp->enc_allow_set_mac_with_installed_filters =
1062 CAP_FLAG(flags, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) ?
1063 B_TRUE : B_FALSE;
1064
1065 /*
1066 * Check if firmware supports the extended MC_CMD_SET_MAC, which allows
1067 * specifying which parameters to configure.
1068 */
1069 encp->enc_enhanced_set_mac_supported =
1070 CAP_FLAG(flags, SET_MAC_ENHANCED) ? B_TRUE : B_FALSE;
1071
1072 /*
1073 * Check if firmware supports version 2 of MC_CMD_INIT_EVQ, which allows
1074 * us to let the firmware choose the settings to use on an EVQ.
1075 */
1076 encp->enc_init_evq_v2_supported =
1077 CAP_FLAG2(flags2, INIT_EVQ_V2) ? B_TRUE : B_FALSE;
1078
1079 /*
1080 * Check if firmware-verified NVRAM updates must be used.
1081 *
1082 * The firmware trusted installer requires all NVRAM updates to use
1083 * version 2 of MC_CMD_NVRAM_UPDATE_START (to enable verified update)
1084 * and version 2 of MC_CMD_NVRAM_UPDATE_FINISH (to verify the updated
1085 * partition and report the result).
1086 */
1087 encp->enc_fw_verified_nvram_update_required =
1088 CAP_FLAG2(flags2, NVRAM_UPDATE_REPORT_VERIFY_RESULT) ?
1089 B_TRUE : B_FALSE;
1090
1091 /*
1092 * Check if firmware provides packet memory and Rx datapath
1093 * counters.
1094 */
1095 encp->enc_pm_and_rxdp_counters =
1096 CAP_FLAG(flags, PM_AND_RXDP_COUNTERS) ? B_TRUE : B_FALSE;
1097
1098 /*
1099 * Check if the 40G MAC hardware is capable of reporting
1100 * statistics for Tx size bins.
1101 */
1102 encp->enc_mac_stats_40g_tx_size_bins =
1103 CAP_FLAG2(flags2, MAC_STATS_40G_TX_SIZE_BINS) ? B_TRUE : B_FALSE;
1104
1105 /*
1106 * Check if firmware supports VXLAN and NVGRE tunnels.
1107 * The capability indicates Geneve protocol support as well.
1108 */
1109 if (CAP_FLAG(flags, VXLAN_NVGRE))
1110 encp->enc_tunnel_encapsulations_supported =
1111 (1u << EFX_TUNNEL_PROTOCOL_VXLAN) |
1112 (1u << EFX_TUNNEL_PROTOCOL_GENEVE) |
1113 (1u << EFX_TUNNEL_PROTOCOL_NVGRE);
1114
1115 #undef CAP_FLAG
1116 #undef CAP_FLAG2
1117
1118 return (0);
1119
1120 fail2:
1121 EFSYS_PROBE(fail2);
1122 fail1:
1123 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1124
1125 return (rc);
1126 }
1127
1128
1129 #define EF10_LEGACY_PF_PRIVILEGE_MASK \
1130 (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN | \
1131 MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK | \
1132 MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD | \
1133 MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP | \
1134 MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS | \
1135 MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING | \
1136 MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST | \
1137 MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST | \
1138 MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST | \
1139 MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST | \
1140 MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS)
1141
1142 #define EF10_LEGACY_VF_PRIVILEGE_MASK 0
1143
1144
1145 __checkReturn efx_rc_t
ef10_get_privilege_mask(__in efx_nic_t * enp,__out uint32_t * maskp)1146 ef10_get_privilege_mask(
1147 __in efx_nic_t *enp,
1148 __out uint32_t *maskp)
1149 {
1150 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1151 uint32_t mask;
1152 efx_rc_t rc;
1153
1154 if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
1155 &mask)) != 0) {
1156 if (rc != ENOTSUP)
1157 goto fail1;
1158
1159 /* Fallback for old firmware without privilege mask support */
1160 if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1161 /* Assume PF has admin privilege */
1162 mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
1163 } else {
1164 /* VF is always unprivileged by default */
1165 mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
1166 }
1167 }
1168
1169 *maskp = mask;
1170
1171 return (0);
1172
1173 fail1:
1174 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1175
1176 return (rc);
1177 }
1178
1179
1180 /*
1181 * Table of mapping schemes from port number to the number of the external
1182 * connector on the board. The external numbering does not distinguish
1183 * off-board separated outputs such as from multi-headed cables.
1184 *
1185 * The count of adjacent port numbers that map to each external port
1186 * and the offset in the numbering, is determined by the chip family and
1187 * current port mode.
1188 *
1189 * For the Huntington family, the current port mode cannot be discovered,
1190 * so the mapping used is instead the last match in the table to the full
1191 * set of port modes to which the NIC can be configured. Therefore the
1192 * ordering of entries in the the mapping table is significant.
1193 */
1194 static struct {
1195 efx_family_t family;
1196 uint32_t modes_mask;
1197 int32_t count;
1198 int32_t offset;
1199 } __ef10_external_port_mappings[] = {
1200 /* Supported modes with 1 output per external port */
1201 {
1202 EFX_FAMILY_HUNTINGTON,
1203 (1 << TLV_PORT_MODE_10G) |
1204 (1 << TLV_PORT_MODE_10G_10G) |
1205 (1 << TLV_PORT_MODE_10G_10G_10G_10G),
1206 1,
1207 1
1208 },
1209 {
1210 EFX_FAMILY_MEDFORD,
1211 (1 << TLV_PORT_MODE_10G) |
1212 (1 << TLV_PORT_MODE_10G_10G),
1213 1,
1214 1
1215 },
1216 /* Supported modes with 2 outputs per external port */
1217 {
1218 EFX_FAMILY_HUNTINGTON,
1219 (1 << TLV_PORT_MODE_40G) |
1220 (1 << TLV_PORT_MODE_40G_40G) |
1221 (1 << TLV_PORT_MODE_40G_10G_10G) |
1222 (1 << TLV_PORT_MODE_10G_10G_40G),
1223 2,
1224 1
1225 },
1226 {
1227 EFX_FAMILY_MEDFORD,
1228 (1 << TLV_PORT_MODE_40G) |
1229 (1 << TLV_PORT_MODE_40G_40G) |
1230 (1 << TLV_PORT_MODE_40G_10G_10G) |
1231 (1 << TLV_PORT_MODE_10G_10G_40G) |
1232 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2),
1233 2,
1234 1
1235 },
1236 /* Supported modes with 4 outputs per external port */
1237 {
1238 EFX_FAMILY_MEDFORD,
1239 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) |
1240 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q1),
1241 4,
1242 1,
1243 },
1244 {
1245 EFX_FAMILY_MEDFORD,
1246 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2),
1247 4,
1248 2
1249 },
1250 };
1251
1252 __checkReturn efx_rc_t
ef10_external_port_mapping(__in efx_nic_t * enp,__in uint32_t port,__out uint8_t * external_portp)1253 ef10_external_port_mapping(
1254 __in efx_nic_t *enp,
1255 __in uint32_t port,
1256 __out uint8_t *external_portp)
1257 {
1258 efx_rc_t rc;
1259 int i;
1260 uint32_t port_modes;
1261 uint32_t matches;
1262 uint32_t current;
1263 int32_t count = 1; /* Default 1-1 mapping */
1264 int32_t offset = 1; /* Default starting external port number */
1265
1266 if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, ¤t)) != 0) {
1267 /*
1268 * No current port mode information
1269 * - infer mapping from available modes
1270 */
1271 if ((rc = efx_mcdi_get_port_modes(enp,
1272 &port_modes, NULL)) != 0) {
1273 /*
1274 * No port mode information available
1275 * - use default mapping
1276 */
1277 goto out;
1278 }
1279 } else {
1280 /* Only need to scan the current mode */
1281 port_modes = 1 << current;
1282 }
1283
1284 /*
1285 * Infer the internal port -> external port mapping from
1286 * the possible port modes for this NIC.
1287 */
1288 for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
1289 if (__ef10_external_port_mappings[i].family !=
1290 enp->en_family)
1291 continue;
1292 matches = (__ef10_external_port_mappings[i].modes_mask &
1293 port_modes);
1294 if (matches != 0) {
1295 count = __ef10_external_port_mappings[i].count;
1296 offset = __ef10_external_port_mappings[i].offset;
1297 port_modes &= ~matches;
1298 }
1299 }
1300
1301 if (port_modes != 0) {
1302 /* Some advertised modes are not supported */
1303 rc = ENOTSUP;
1304 goto fail1;
1305 }
1306
1307 out:
1308 /*
1309 * Scale as required by last matched mode and then convert to
1310 * correctly offset numbering
1311 */
1312 *external_portp = (uint8_t)((port / count) + offset);
1313 return (0);
1314
1315 fail1:
1316 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1317
1318 return (rc);
1319 }
1320
1321
1322 __checkReturn efx_rc_t
ef10_nic_probe(__in efx_nic_t * enp)1323 ef10_nic_probe(
1324 __in efx_nic_t *enp)
1325 {
1326 const efx_nic_ops_t *enop = enp->en_enop;
1327 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1328 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1329 efx_rc_t rc;
1330
1331 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1332 enp->en_family == EFX_FAMILY_MEDFORD);
1333
1334 /* Read and clear any assertion state */
1335 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1336 goto fail1;
1337
1338 /* Exit the assertion handler */
1339 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1340 if (rc != EACCES)
1341 goto fail2;
1342
1343 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1344 goto fail3;
1345
1346 if ((rc = enop->eno_board_cfg(enp)) != 0)
1347 if (rc != EACCES)
1348 goto fail4;
1349
1350 /*
1351 * Set default driver config limits (based on board config).
1352 *
1353 * FIXME: For now allocate a fixed number of VIs which is likely to be
1354 * sufficient and small enough to allow multiple functions on the same
1355 * port.
1356 */
1357 edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1358 MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1359
1360 /* The client driver must configure and enable PIO buffer support */
1361 edcp->edc_max_piobuf_count = 0;
1362 edcp->edc_pio_alloc_size = 0;
1363
1364 #if EFSYS_OPT_MAC_STATS
1365 /* Wipe the MAC statistics */
1366 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1367 goto fail5;
1368 #endif
1369
1370 #if EFSYS_OPT_LOOPBACK
1371 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1372 goto fail6;
1373 #endif
1374
1375 #if EFSYS_OPT_MON_STATS
1376 if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1377 /* Unprivileged functions do not have access to sensors */
1378 if (rc != EACCES)
1379 goto fail7;
1380 }
1381 #endif
1382
1383 encp->enc_features = enp->en_features;
1384
1385 return (0);
1386
1387 #if EFSYS_OPT_MON_STATS
1388 fail7:
1389 EFSYS_PROBE(fail7);
1390 #endif
1391 #if EFSYS_OPT_LOOPBACK
1392 fail6:
1393 EFSYS_PROBE(fail6);
1394 #endif
1395 #if EFSYS_OPT_MAC_STATS
1396 fail5:
1397 EFSYS_PROBE(fail5);
1398 #endif
1399 fail4:
1400 EFSYS_PROBE(fail4);
1401 fail3:
1402 EFSYS_PROBE(fail3);
1403 fail2:
1404 EFSYS_PROBE(fail2);
1405 fail1:
1406 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1407
1408 return (rc);
1409 }
1410
1411 __checkReturn efx_rc_t
ef10_nic_set_drv_limits(__inout efx_nic_t * enp,__in efx_drv_limits_t * edlp)1412 ef10_nic_set_drv_limits(
1413 __inout efx_nic_t *enp,
1414 __in efx_drv_limits_t *edlp)
1415 {
1416 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1417 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1418 uint32_t min_evq_count, max_evq_count;
1419 uint32_t min_rxq_count, max_rxq_count;
1420 uint32_t min_txq_count, max_txq_count;
1421 efx_rc_t rc;
1422
1423 if (edlp == NULL) {
1424 rc = EINVAL;
1425 goto fail1;
1426 }
1427
1428 /* Get minimum required and maximum usable VI limits */
1429 min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
1430 min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
1431 min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
1432
1433 edcp->edc_min_vi_count =
1434 MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
1435
1436 max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
1437 max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
1438 max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
1439
1440 edcp->edc_max_vi_count =
1441 MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
1442
1443 /*
1444 * Check limits for sub-allocated piobuf blocks.
1445 * PIO is optional, so don't fail if the limits are incorrect.
1446 */
1447 if ((encp->enc_piobuf_size == 0) ||
1448 (encp->enc_piobuf_limit == 0) ||
1449 (edlp->edl_min_pio_alloc_size == 0) ||
1450 (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
1451 /* Disable PIO */
1452 edcp->edc_max_piobuf_count = 0;
1453 edcp->edc_pio_alloc_size = 0;
1454 } else {
1455 uint32_t blk_size, blk_count, blks_per_piobuf;
1456
1457 blk_size =
1458 MAX(edlp->edl_min_pio_alloc_size,
1459 encp->enc_piobuf_min_alloc_size);
1460
1461 blks_per_piobuf = encp->enc_piobuf_size / blk_size;
1462 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
1463
1464 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
1465
1466 /* A zero max pio alloc count means unlimited */
1467 if ((edlp->edl_max_pio_alloc_count > 0) &&
1468 (edlp->edl_max_pio_alloc_count < blk_count)) {
1469 blk_count = edlp->edl_max_pio_alloc_count;
1470 }
1471
1472 edcp->edc_pio_alloc_size = blk_size;
1473 edcp->edc_max_piobuf_count =
1474 (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
1475 }
1476
1477 return (0);
1478
1479 fail1:
1480 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1481
1482 return (rc);
1483 }
1484
1485
1486 __checkReturn efx_rc_t
ef10_nic_reset(__in efx_nic_t * enp)1487 ef10_nic_reset(
1488 __in efx_nic_t *enp)
1489 {
1490 efx_mcdi_req_t req;
1491 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ENTITY_RESET_IN_LEN,
1492 MC_CMD_ENTITY_RESET_OUT_LEN);
1493 efx_rc_t rc;
1494
1495 /* ef10_nic_reset() is called to recover from BADASSERT failures. */
1496 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1497 goto fail1;
1498 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1499 goto fail2;
1500
1501 req.emr_cmd = MC_CMD_ENTITY_RESET;
1502 req.emr_in_buf = payload;
1503 req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
1504 req.emr_out_buf = payload;
1505 req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
1506
1507 MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
1508 ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1509
1510 efx_mcdi_execute(enp, &req);
1511
1512 if (req.emr_rc != 0) {
1513 rc = req.emr_rc;
1514 goto fail3;
1515 }
1516
1517 /* Clear RX/TX DMA queue errors */
1518 enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
1519
1520 return (0);
1521
1522 fail3:
1523 EFSYS_PROBE(fail3);
1524 fail2:
1525 EFSYS_PROBE(fail2);
1526 fail1:
1527 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1528
1529 return (rc);
1530 }
1531
1532 __checkReturn efx_rc_t
ef10_nic_init(__in efx_nic_t * enp)1533 ef10_nic_init(
1534 __in efx_nic_t *enp)
1535 {
1536 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1537 uint32_t min_vi_count, max_vi_count;
1538 uint32_t vi_count, vi_base, vi_shift;
1539 uint32_t i;
1540 uint32_t retry;
1541 uint32_t delay_us;
1542 efx_rc_t rc;
1543
1544 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1545 enp->en_family == EFX_FAMILY_MEDFORD);
1546
1547 /* Enable reporting of some events (e.g. link change) */
1548 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
1549 goto fail1;
1550
1551 /* Allocate (optional) on-chip PIO buffers */
1552 ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
1553
1554 /*
1555 * For best performance, PIO writes should use a write-combined
1556 * (WC) memory mapping. Using a separate WC mapping for the PIO
1557 * aperture of each VI would be a burden to drivers (and not
1558 * possible if the host page size is >4Kbyte).
1559 *
1560 * To avoid this we use a single uncached (UC) mapping for VI
1561 * register access, and a single WC mapping for extra VIs used
1562 * for PIO writes.
1563 *
1564 * Each piobuf must be linked to a VI in the WC mapping, and to
1565 * each VI that is using a sub-allocated block from the piobuf.
1566 */
1567 min_vi_count = edcp->edc_min_vi_count;
1568 max_vi_count =
1569 edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
1570
1571 /* Ensure that the previously attached driver's VIs are freed */
1572 if ((rc = efx_mcdi_free_vis(enp)) != 0)
1573 goto fail2;
1574
1575 /*
1576 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
1577 * fails then retrying the request for fewer VI resources may succeed.
1578 */
1579 vi_count = 0;
1580 if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
1581 &vi_base, &vi_count, &vi_shift)) != 0)
1582 goto fail3;
1583
1584 EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
1585
1586 if (vi_count < min_vi_count) {
1587 rc = ENOMEM;
1588 goto fail4;
1589 }
1590
1591 enp->en_arch.ef10.ena_vi_base = vi_base;
1592 enp->en_arch.ef10.ena_vi_count = vi_count;
1593 enp->en_arch.ef10.ena_vi_shift = vi_shift;
1594
1595 if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
1596 /* Not enough extra VIs to map piobufs */
1597 ef10_nic_free_piobufs(enp);
1598 }
1599
1600 enp->en_arch.ef10.ena_pio_write_vi_base =
1601 vi_count - enp->en_arch.ef10.ena_piobuf_count;
1602
1603 /* Save UC memory mapping details */
1604 enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
1605 if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1606 enp->en_arch.ef10.ena_uc_mem_map_size =
1607 (ER_DZ_TX_PIOBUF_STEP *
1608 enp->en_arch.ef10.ena_pio_write_vi_base);
1609 } else {
1610 enp->en_arch.ef10.ena_uc_mem_map_size =
1611 (ER_DZ_TX_PIOBUF_STEP *
1612 enp->en_arch.ef10.ena_vi_count);
1613 }
1614
1615 /* Save WC memory mapping details */
1616 enp->en_arch.ef10.ena_wc_mem_map_offset =
1617 enp->en_arch.ef10.ena_uc_mem_map_offset +
1618 enp->en_arch.ef10.ena_uc_mem_map_size;
1619
1620 enp->en_arch.ef10.ena_wc_mem_map_size =
1621 (ER_DZ_TX_PIOBUF_STEP *
1622 enp->en_arch.ef10.ena_piobuf_count);
1623
1624 /* Link piobufs to extra VIs in WC mapping */
1625 if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1626 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1627 rc = efx_mcdi_link_piobuf(enp,
1628 enp->en_arch.ef10.ena_pio_write_vi_base + i,
1629 enp->en_arch.ef10.ena_piobuf_handle[i]);
1630 if (rc != 0)
1631 break;
1632 }
1633 }
1634
1635 /*
1636 * Allocate a vAdaptor attached to our upstream vPort/pPort.
1637 *
1638 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
1639 * driver has yet to bring up the EVB port. See bug 56147. In this case,
1640 * retry the request several times after waiting a while. The wait time
1641 * between retries starts small (10ms) and exponentially increases.
1642 * Total wait time is a little over two seconds. Retry logic in the
1643 * client driver may mean this whole loop is repeated if it continues to
1644 * fail.
1645 */
1646 retry = 0;
1647 delay_us = 10000;
1648 while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
1649 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
1650 (rc != ENOENT)) {
1651 /*
1652 * Do not retry alloc for PF, or for other errors on
1653 * a VF.
1654 */
1655 goto fail5;
1656 }
1657
1658 /* VF startup before PF is ready. Retry allocation. */
1659 if (retry > 5) {
1660 /* Too many attempts */
1661 rc = EINVAL;
1662 goto fail6;
1663 }
1664 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
1665 EFSYS_SLEEP(delay_us);
1666 retry++;
1667 if (delay_us < 500000)
1668 delay_us <<= 2;
1669 }
1670
1671 enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
1672 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
1673
1674 return (0);
1675
1676 fail6:
1677 EFSYS_PROBE(fail6);
1678 fail5:
1679 EFSYS_PROBE(fail5);
1680 fail4:
1681 EFSYS_PROBE(fail4);
1682 fail3:
1683 EFSYS_PROBE(fail3);
1684 fail2:
1685 EFSYS_PROBE(fail2);
1686
1687 ef10_nic_free_piobufs(enp);
1688
1689 fail1:
1690 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1691
1692 return (rc);
1693 }
1694
1695 __checkReturn efx_rc_t
ef10_nic_get_vi_pool(__in efx_nic_t * enp,__out uint32_t * vi_countp)1696 ef10_nic_get_vi_pool(
1697 __in efx_nic_t *enp,
1698 __out uint32_t *vi_countp)
1699 {
1700 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1701 enp->en_family == EFX_FAMILY_MEDFORD);
1702
1703 /*
1704 * Report VIs that the client driver can use.
1705 * Do not include VIs used for PIO buffer writes.
1706 */
1707 *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
1708
1709 return (0);
1710 }
1711
1712 __checkReturn efx_rc_t
ef10_nic_get_bar_region(__in efx_nic_t * enp,__in efx_nic_region_t region,__out uint32_t * offsetp,__out size_t * sizep)1713 ef10_nic_get_bar_region(
1714 __in efx_nic_t *enp,
1715 __in efx_nic_region_t region,
1716 __out uint32_t *offsetp,
1717 __out size_t *sizep)
1718 {
1719 efx_rc_t rc;
1720
1721 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1722 enp->en_family == EFX_FAMILY_MEDFORD);
1723
1724 /*
1725 * TODO: Specify host memory mapping alignment and granularity
1726 * in efx_drv_limits_t so that they can be taken into account
1727 * when allocating extra VIs for PIO writes.
1728 */
1729 switch (region) {
1730 case EFX_REGION_VI:
1731 /* UC mapped memory BAR region for VI registers */
1732 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
1733 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
1734 break;
1735
1736 case EFX_REGION_PIO_WRITE_VI:
1737 /* WC mapped memory BAR region for piobuf writes */
1738 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
1739 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
1740 break;
1741
1742 default:
1743 rc = EINVAL;
1744 goto fail1;
1745 }
1746
1747 return (0);
1748
1749 fail1:
1750 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1751
1752 return (rc);
1753 }
1754
1755 void
ef10_nic_fini(__in efx_nic_t * enp)1756 ef10_nic_fini(
1757 __in efx_nic_t *enp)
1758 {
1759 uint32_t i;
1760 efx_rc_t rc;
1761
1762 (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
1763 enp->en_vport_id = 0;
1764
1765 /* Unlink piobufs from extra VIs in WC mapping */
1766 if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1767 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1768 rc = efx_mcdi_unlink_piobuf(enp,
1769 enp->en_arch.ef10.ena_pio_write_vi_base + i);
1770 if (rc != 0)
1771 break;
1772 }
1773 }
1774
1775 ef10_nic_free_piobufs(enp);
1776
1777 (void) efx_mcdi_free_vis(enp);
1778 enp->en_arch.ef10.ena_vi_count = 0;
1779 }
1780
1781 void
ef10_nic_unprobe(__in efx_nic_t * enp)1782 ef10_nic_unprobe(
1783 __in efx_nic_t *enp)
1784 {
1785 #if EFSYS_OPT_MON_STATS
1786 mcdi_mon_cfg_free(enp);
1787 #endif /* EFSYS_OPT_MON_STATS */
1788 (void) efx_mcdi_drv_attach(enp, B_FALSE);
1789 }
1790
1791 #if EFSYS_OPT_DIAG
1792
1793 __checkReturn efx_rc_t
ef10_nic_register_test(__in efx_nic_t * enp)1794 ef10_nic_register_test(
1795 __in efx_nic_t *enp)
1796 {
1797 efx_rc_t rc;
1798
1799 /* FIXME */
1800 _NOTE(ARGUNUSED(enp))
1801 _NOTE(CONSTANTCONDITION)
1802 if (B_FALSE) {
1803 rc = ENOTSUP;
1804 goto fail1;
1805 }
1806 /* FIXME */
1807
1808 return (0);
1809
1810 fail1:
1811 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1812
1813 return (rc);
1814 }
1815
1816 #endif /* EFSYS_OPT_DIAG */
1817
1818 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
1819