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