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