131bf5f03SAndrew Rybchenko /*-
2929c7febSAndrew Rybchenko * Copyright (c) 2012-2016 Solarflare Communications Inc.
331bf5f03SAndrew Rybchenko * All rights reserved.
431bf5f03SAndrew Rybchenko *
531bf5f03SAndrew Rybchenko * Redistribution and use in source and binary forms, with or without
631bf5f03SAndrew Rybchenko * modification, are permitted provided that the following conditions are met:
731bf5f03SAndrew Rybchenko *
831bf5f03SAndrew Rybchenko * 1. Redistributions of source code must retain the above copyright notice,
931bf5f03SAndrew Rybchenko * this list of conditions and the following disclaimer.
1031bf5f03SAndrew Rybchenko * 2. Redistributions in binary form must reproduce the above copyright notice,
1131bf5f03SAndrew Rybchenko * this list of conditions and the following disclaimer in the documentation
1231bf5f03SAndrew Rybchenko * and/or other materials provided with the distribution.
1331bf5f03SAndrew Rybchenko *
1431bf5f03SAndrew Rybchenko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1531bf5f03SAndrew Rybchenko * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1631bf5f03SAndrew Rybchenko * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1731bf5f03SAndrew Rybchenko * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
1831bf5f03SAndrew Rybchenko * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1931bf5f03SAndrew Rybchenko * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2031bf5f03SAndrew Rybchenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2131bf5f03SAndrew Rybchenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2231bf5f03SAndrew Rybchenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2331bf5f03SAndrew Rybchenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
2431bf5f03SAndrew Rybchenko * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2531bf5f03SAndrew Rybchenko *
2631bf5f03SAndrew Rybchenko * The views and conclusions contained in the software and documentation are
2731bf5f03SAndrew Rybchenko * those of the authors and should not be interpreted as representing official
2831bf5f03SAndrew Rybchenko * policies, either expressed or implied, of the FreeBSD Project.
2931bf5f03SAndrew Rybchenko */
3031bf5f03SAndrew Rybchenko
3131bf5f03SAndrew Rybchenko #include <sys/cdefs.h>
3231bf5f03SAndrew Rybchenko #include "efx.h"
3331bf5f03SAndrew Rybchenko #include "efx_impl.h"
3431bf5f03SAndrew Rybchenko #if EFSYS_OPT_MON_MCDI
3531bf5f03SAndrew Rybchenko #include "mcdi_mon.h"
3631bf5f03SAndrew Rybchenko #endif
3731bf5f03SAndrew Rybchenko
38ae64ac93SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
3931bf5f03SAndrew Rybchenko
4031bf5f03SAndrew Rybchenko #include "ef10_tlv_layout.h"
4131bf5f03SAndrew Rybchenko
4231bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_port_assignment(__in efx_nic_t * enp,__out uint32_t * portp)4331bf5f03SAndrew Rybchenko efx_mcdi_get_port_assignment(
4431bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
4531bf5f03SAndrew Rybchenko __out uint32_t *portp)
4631bf5f03SAndrew Rybchenko {
4731bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
48315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN,
49315bbbaaSAndrew Rybchenko MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
5031bf5f03SAndrew Rybchenko efx_rc_t rc;
5131bf5f03SAndrew Rybchenko
5231bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
53ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
54ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
5531bf5f03SAndrew Rybchenko
5631bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
5731bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
5831bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN;
5931bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
6031bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN;
6131bf5f03SAndrew Rybchenko
6231bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
6331bf5f03SAndrew Rybchenko
6431bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
6531bf5f03SAndrew Rybchenko rc = req.emr_rc;
6631bf5f03SAndrew Rybchenko goto fail1;
6731bf5f03SAndrew Rybchenko }
6831bf5f03SAndrew Rybchenko
6931bf5f03SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN) {
7031bf5f03SAndrew Rybchenko rc = EMSGSIZE;
7131bf5f03SAndrew Rybchenko goto fail2;
7231bf5f03SAndrew Rybchenko }
7331bf5f03SAndrew Rybchenko
7431bf5f03SAndrew Rybchenko *portp = MCDI_OUT_DWORD(req, GET_PORT_ASSIGNMENT_OUT_PORT);
7531bf5f03SAndrew Rybchenko
7631bf5f03SAndrew Rybchenko return (0);
7731bf5f03SAndrew Rybchenko
7831bf5f03SAndrew Rybchenko fail2:
7931bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
8031bf5f03SAndrew Rybchenko fail1:
8131bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
8231bf5f03SAndrew Rybchenko
8331bf5f03SAndrew Rybchenko return (rc);
8431bf5f03SAndrew Rybchenko }
8531bf5f03SAndrew Rybchenko
8631bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_port_modes(__in efx_nic_t * enp,__out uint32_t * modesp,__out_opt uint32_t * current_modep,__out_opt uint32_t * default_modep)8731bf5f03SAndrew Rybchenko efx_mcdi_get_port_modes(
8831bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
89f6d61784SAndrew Rybchenko __out uint32_t *modesp,
90cd5e3371SAndrew Rybchenko __out_opt uint32_t *current_modep,
91cd5e3371SAndrew Rybchenko __out_opt uint32_t *default_modep)
9231bf5f03SAndrew Rybchenko {
9331bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
94315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PORT_MODES_IN_LEN,
95315bbbaaSAndrew Rybchenko MC_CMD_GET_PORT_MODES_OUT_LEN);
9631bf5f03SAndrew Rybchenko efx_rc_t rc;
9731bf5f03SAndrew Rybchenko
9831bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
99ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
100ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
10131bf5f03SAndrew Rybchenko
10231bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_PORT_MODES;
10331bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
10431bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN;
10531bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
10631bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_PORT_MODES_OUT_LEN;
10731bf5f03SAndrew Rybchenko
10831bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
10931bf5f03SAndrew Rybchenko
11031bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
11131bf5f03SAndrew Rybchenko rc = req.emr_rc;
11231bf5f03SAndrew Rybchenko goto fail1;
11331bf5f03SAndrew Rybchenko }
11431bf5f03SAndrew Rybchenko
11531bf5f03SAndrew Rybchenko /*
116f6d61784SAndrew Rybchenko * Require only Modes and DefaultMode fields, unless the current mode
117f6d61784SAndrew Rybchenko * was requested (CurrentMode field was added for Medford).
11831bf5f03SAndrew Rybchenko */
11931bf5f03SAndrew Rybchenko if (req.emr_out_length_used <
12031bf5f03SAndrew Rybchenko MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) {
12131bf5f03SAndrew Rybchenko rc = EMSGSIZE;
12231bf5f03SAndrew Rybchenko goto fail2;
12331bf5f03SAndrew Rybchenko }
124f6d61784SAndrew Rybchenko if ((current_modep != NULL) && (req.emr_out_length_used <
125f6d61784SAndrew Rybchenko MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST + 4)) {
126f6d61784SAndrew Rybchenko rc = EMSGSIZE;
127f6d61784SAndrew Rybchenko goto fail3;
128f6d61784SAndrew Rybchenko }
12931bf5f03SAndrew Rybchenko
13031bf5f03SAndrew Rybchenko *modesp = MCDI_OUT_DWORD(req, GET_PORT_MODES_OUT_MODES);
13131bf5f03SAndrew Rybchenko
132f6d61784SAndrew Rybchenko if (current_modep != NULL) {
133f6d61784SAndrew Rybchenko *current_modep = MCDI_OUT_DWORD(req,
134f6d61784SAndrew Rybchenko GET_PORT_MODES_OUT_CURRENT_MODE);
135f6d61784SAndrew Rybchenko }
136f6d61784SAndrew Rybchenko
137cd5e3371SAndrew Rybchenko if (default_modep != NULL) {
138cd5e3371SAndrew Rybchenko *default_modep = MCDI_OUT_DWORD(req,
139cd5e3371SAndrew Rybchenko GET_PORT_MODES_OUT_DEFAULT_MODE);
140cd5e3371SAndrew Rybchenko }
141cd5e3371SAndrew Rybchenko
14231bf5f03SAndrew Rybchenko return (0);
14331bf5f03SAndrew Rybchenko
144f6d61784SAndrew Rybchenko fail3:
145f6d61784SAndrew Rybchenko EFSYS_PROBE(fail3);
14631bf5f03SAndrew Rybchenko fail2:
14731bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
14831bf5f03SAndrew Rybchenko fail1:
14931bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
15031bf5f03SAndrew Rybchenko
15131bf5f03SAndrew Rybchenko return (rc);
15231bf5f03SAndrew Rybchenko }
15331bf5f03SAndrew Rybchenko
154f6d61784SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_get_port_mode_bandwidth(__in efx_nic_t * enp,__out uint32_t * bandwidth_mbpsp)155f6d61784SAndrew Rybchenko ef10_nic_get_port_mode_bandwidth(
156c42b6a35SAndrew Rybchenko __in efx_nic_t *enp,
157f6d61784SAndrew Rybchenko __out uint32_t *bandwidth_mbpsp)
158f6d61784SAndrew Rybchenko {
159c42b6a35SAndrew Rybchenko uint32_t port_modes;
160c42b6a35SAndrew Rybchenko uint32_t current_mode;
161109f5727SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
162109f5727SAndrew Rybchenko
163109f5727SAndrew Rybchenko uint32_t single_lane;
164109f5727SAndrew Rybchenko uint32_t dual_lane;
165109f5727SAndrew Rybchenko uint32_t quad_lane;
166f6d61784SAndrew Rybchenko uint32_t bandwidth;
167f6d61784SAndrew Rybchenko efx_rc_t rc;
168f6d61784SAndrew Rybchenko
169c42b6a35SAndrew Rybchenko if ((rc = efx_mcdi_get_port_modes(enp, &port_modes,
170c42b6a35SAndrew Rybchenko ¤t_mode, NULL)) != 0) {
171c42b6a35SAndrew Rybchenko /* No port mode info available. */
172c42b6a35SAndrew Rybchenko goto fail1;
173c42b6a35SAndrew Rybchenko }
174c42b6a35SAndrew Rybchenko
175109f5727SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_25000FDX))
176109f5727SAndrew Rybchenko single_lane = 25000;
177109f5727SAndrew Rybchenko else
178109f5727SAndrew Rybchenko single_lane = 10000;
179109f5727SAndrew Rybchenko
180109f5727SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_50000FDX))
181109f5727SAndrew Rybchenko dual_lane = 50000;
182109f5727SAndrew Rybchenko else
183109f5727SAndrew Rybchenko dual_lane = 20000;
184109f5727SAndrew Rybchenko
185109f5727SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_100000FDX))
186109f5727SAndrew Rybchenko quad_lane = 100000;
187109f5727SAndrew Rybchenko else
188109f5727SAndrew Rybchenko quad_lane = 40000;
189109f5727SAndrew Rybchenko
190c42b6a35SAndrew Rybchenko switch (current_mode) {
191e12a751bSAndrew Rybchenko case TLV_PORT_MODE_1x1_NA: /* mode 0 */
1927e370b0eSAndrew Rybchenko bandwidth = single_lane;
1937e370b0eSAndrew Rybchenko break;
1947e370b0eSAndrew Rybchenko case TLV_PORT_MODE_1x2_NA: /* mode 10 */
1957e370b0eSAndrew Rybchenko case TLV_PORT_MODE_NA_1x2: /* mode 11 */
1967e370b0eSAndrew Rybchenko bandwidth = dual_lane;
197f6d61784SAndrew Rybchenko break;
198e12a751bSAndrew Rybchenko case TLV_PORT_MODE_1x1_1x1: /* mode 2 */
1997e370b0eSAndrew Rybchenko bandwidth = single_lane + single_lane;
200f6d61784SAndrew Rybchenko break;
201e12a751bSAndrew Rybchenko case TLV_PORT_MODE_4x1_NA: /* mode 4 */
202e12a751bSAndrew Rybchenko case TLV_PORT_MODE_NA_4x1: /* mode 8 */
2037e370b0eSAndrew Rybchenko bandwidth = 4 * single_lane;
2047e370b0eSAndrew Rybchenko break;
2057e370b0eSAndrew Rybchenko case TLV_PORT_MODE_2x1_2x1: /* mode 5 */
2067e370b0eSAndrew Rybchenko bandwidth = (2 * single_lane) + (2 * single_lane);
2077e370b0eSAndrew Rybchenko break;
2087e370b0eSAndrew Rybchenko case TLV_PORT_MODE_1x2_1x2: /* mode 12 */
2097e370b0eSAndrew Rybchenko bandwidth = dual_lane + dual_lane;
2107e370b0eSAndrew Rybchenko break;
2117e370b0eSAndrew Rybchenko case TLV_PORT_MODE_1x2_2x1: /* mode 17 */
2127e370b0eSAndrew Rybchenko case TLV_PORT_MODE_2x1_1x2: /* mode 18 */
2137e370b0eSAndrew Rybchenko bandwidth = dual_lane + (2 * single_lane);
214f6d61784SAndrew Rybchenko break;
215e12a751bSAndrew Rybchenko /* Legacy Medford-only mode. Do not use (see bug63270) */
216e12a751bSAndrew Rybchenko case TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2: /* mode 9 */
2177e370b0eSAndrew Rybchenko bandwidth = 4 * single_lane;
218e12a751bSAndrew Rybchenko break;
219e12a751bSAndrew Rybchenko case TLV_PORT_MODE_1x4_NA: /* mode 1 */
2207e370b0eSAndrew Rybchenko case TLV_PORT_MODE_NA_1x4: /* mode 22 */
2217e370b0eSAndrew Rybchenko bandwidth = quad_lane;
222f6d61784SAndrew Rybchenko break;
2237e370b0eSAndrew Rybchenko case TLV_PORT_MODE_2x2_NA: /* mode 13 */
2247e370b0eSAndrew Rybchenko case TLV_PORT_MODE_NA_2x2: /* mode 14 */
2257e370b0eSAndrew Rybchenko bandwidth = 2 * dual_lane;
226f6d61784SAndrew Rybchenko break;
227e12a751bSAndrew Rybchenko case TLV_PORT_MODE_1x4_2x1: /* mode 6 */
228e12a751bSAndrew Rybchenko case TLV_PORT_MODE_2x1_1x4: /* mode 7 */
2297e370b0eSAndrew Rybchenko bandwidth = quad_lane + (2 * single_lane);
2307e370b0eSAndrew Rybchenko break;
2317e370b0eSAndrew Rybchenko case TLV_PORT_MODE_1x4_1x2: /* mode 15 */
2327e370b0eSAndrew Rybchenko case TLV_PORT_MODE_1x2_1x4: /* mode 16 */
2337e370b0eSAndrew Rybchenko bandwidth = quad_lane + dual_lane;
2347e370b0eSAndrew Rybchenko break;
2357e370b0eSAndrew Rybchenko case TLV_PORT_MODE_1x4_1x4: /* mode 3 */
2367e370b0eSAndrew Rybchenko bandwidth = quad_lane + quad_lane;
237f6d61784SAndrew Rybchenko break;
238f6d61784SAndrew Rybchenko default:
239f6d61784SAndrew Rybchenko rc = EINVAL;
240c42b6a35SAndrew Rybchenko goto fail2;
241f6d61784SAndrew Rybchenko }
242f6d61784SAndrew Rybchenko
243f6d61784SAndrew Rybchenko *bandwidth_mbpsp = bandwidth;
244f6d61784SAndrew Rybchenko
245f6d61784SAndrew Rybchenko return (0);
246f6d61784SAndrew Rybchenko
247c42b6a35SAndrew Rybchenko fail2:
248c42b6a35SAndrew Rybchenko EFSYS_PROBE(fail2);
249f6d61784SAndrew Rybchenko fail1:
250f6d61784SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
251f6d61784SAndrew Rybchenko
252f6d61784SAndrew Rybchenko return (rc);
253f6d61784SAndrew Rybchenko }
25431bf5f03SAndrew Rybchenko
25531bf5f03SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_vadaptor_alloc(__in efx_nic_t * enp,__in uint32_t port_id)25631bf5f03SAndrew Rybchenko efx_mcdi_vadaptor_alloc(
25731bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
25831bf5f03SAndrew Rybchenko __in uint32_t port_id)
25931bf5f03SAndrew Rybchenko {
26031bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
261315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VADAPTOR_ALLOC_IN_LEN,
262315bbbaaSAndrew Rybchenko MC_CMD_VADAPTOR_ALLOC_OUT_LEN);
26331bf5f03SAndrew Rybchenko efx_rc_t rc;
26431bf5f03SAndrew Rybchenko
26531bf5f03SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_vport_id, ==, EVB_PORT_ID_NULL);
26631bf5f03SAndrew Rybchenko
26731bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_VADAPTOR_ALLOC;
26831bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
26931bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN;
27031bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
27131bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_VADAPTOR_ALLOC_OUT_LEN;
27231bf5f03SAndrew Rybchenko
27331bf5f03SAndrew Rybchenko MCDI_IN_SET_DWORD(req, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
27431bf5f03SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, VADAPTOR_ALLOC_IN_FLAGS,
27531bf5f03SAndrew Rybchenko VADAPTOR_ALLOC_IN_FLAG_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED,
27631bf5f03SAndrew Rybchenko enp->en_nic_cfg.enc_allow_set_mac_with_installed_filters ? 1 : 0);
27731bf5f03SAndrew Rybchenko
27831bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
27931bf5f03SAndrew Rybchenko
28031bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
28131bf5f03SAndrew Rybchenko rc = req.emr_rc;
28231bf5f03SAndrew Rybchenko goto fail1;
28331bf5f03SAndrew Rybchenko }
28431bf5f03SAndrew Rybchenko
28531bf5f03SAndrew Rybchenko return (0);
28631bf5f03SAndrew Rybchenko
28731bf5f03SAndrew Rybchenko fail1:
28831bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
28931bf5f03SAndrew Rybchenko
29031bf5f03SAndrew Rybchenko return (rc);
29131bf5f03SAndrew Rybchenko }
29231bf5f03SAndrew Rybchenko
29331bf5f03SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_vadaptor_free(__in efx_nic_t * enp,__in uint32_t port_id)29431bf5f03SAndrew Rybchenko efx_mcdi_vadaptor_free(
29531bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
29631bf5f03SAndrew Rybchenko __in uint32_t port_id)
29731bf5f03SAndrew Rybchenko {
29831bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
299315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VADAPTOR_FREE_IN_LEN,
300315bbbaaSAndrew Rybchenko MC_CMD_VADAPTOR_FREE_OUT_LEN);
30131bf5f03SAndrew Rybchenko efx_rc_t rc;
30231bf5f03SAndrew Rybchenko
30331bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_VADAPTOR_FREE;
30431bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
30531bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_VADAPTOR_FREE_IN_LEN;
30631bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
30731bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_VADAPTOR_FREE_OUT_LEN;
30831bf5f03SAndrew Rybchenko
30931bf5f03SAndrew Rybchenko MCDI_IN_SET_DWORD(req, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
31031bf5f03SAndrew Rybchenko
31131bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
31231bf5f03SAndrew Rybchenko
31331bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
31431bf5f03SAndrew Rybchenko rc = req.emr_rc;
31531bf5f03SAndrew Rybchenko goto fail1;
31631bf5f03SAndrew Rybchenko }
31731bf5f03SAndrew Rybchenko
31831bf5f03SAndrew Rybchenko return (0);
31931bf5f03SAndrew Rybchenko
32031bf5f03SAndrew Rybchenko fail1:
32131bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
32231bf5f03SAndrew Rybchenko
32331bf5f03SAndrew Rybchenko return (rc);
32431bf5f03SAndrew Rybchenko }
32531bf5f03SAndrew Rybchenko
32631bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
32731bf5f03SAndrew Rybchenko efx_mcdi_get_mac_address_pf(
32831bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
32931bf5f03SAndrew Rybchenko __out_ecount_opt(6) uint8_t mac_addrp[6])
33031bf5f03SAndrew Rybchenko {
33131bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
332315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_MAC_ADDRESSES_IN_LEN,
333315bbbaaSAndrew Rybchenko MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
33431bf5f03SAndrew Rybchenko efx_rc_t rc;
33531bf5f03SAndrew Rybchenko
33631bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
337ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
338ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
33931bf5f03SAndrew Rybchenko
34031bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
34131bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
34231bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_MAC_ADDRESSES_IN_LEN;
34331bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
34431bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN;
34531bf5f03SAndrew Rybchenko
34631bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
34731bf5f03SAndrew Rybchenko
34831bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
34931bf5f03SAndrew Rybchenko rc = req.emr_rc;
35031bf5f03SAndrew Rybchenko goto fail1;
35131bf5f03SAndrew Rybchenko }
35231bf5f03SAndrew Rybchenko
35331bf5f03SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) {
35431bf5f03SAndrew Rybchenko rc = EMSGSIZE;
35531bf5f03SAndrew Rybchenko goto fail2;
35631bf5f03SAndrew Rybchenko }
35731bf5f03SAndrew Rybchenko
35831bf5f03SAndrew Rybchenko if (MCDI_OUT_DWORD(req, GET_MAC_ADDRESSES_OUT_MAC_COUNT) < 1) {
35931bf5f03SAndrew Rybchenko rc = ENOENT;
36031bf5f03SAndrew Rybchenko goto fail3;
36131bf5f03SAndrew Rybchenko }
36231bf5f03SAndrew Rybchenko
36331bf5f03SAndrew Rybchenko if (mac_addrp != NULL) {
36431bf5f03SAndrew Rybchenko uint8_t *addrp;
36531bf5f03SAndrew Rybchenko
36631bf5f03SAndrew Rybchenko addrp = MCDI_OUT2(req, uint8_t,
36731bf5f03SAndrew Rybchenko GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE);
36831bf5f03SAndrew Rybchenko
36931bf5f03SAndrew Rybchenko EFX_MAC_ADDR_COPY(mac_addrp, addrp);
37031bf5f03SAndrew Rybchenko }
37131bf5f03SAndrew Rybchenko
37231bf5f03SAndrew Rybchenko return (0);
37331bf5f03SAndrew Rybchenko
37431bf5f03SAndrew Rybchenko fail3:
37531bf5f03SAndrew Rybchenko EFSYS_PROBE(fail3);
37631bf5f03SAndrew Rybchenko fail2:
37731bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
37831bf5f03SAndrew Rybchenko fail1:
37931bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
38031bf5f03SAndrew Rybchenko
38131bf5f03SAndrew Rybchenko return (rc);
38231bf5f03SAndrew Rybchenko }
38331bf5f03SAndrew Rybchenko
38431bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
38531bf5f03SAndrew Rybchenko efx_mcdi_get_mac_address_vf(
38631bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
38731bf5f03SAndrew Rybchenko __out_ecount_opt(6) uint8_t mac_addrp[6])
38831bf5f03SAndrew Rybchenko {
38931bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
390315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN,
391315bbbaaSAndrew Rybchenko MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX);
39231bf5f03SAndrew Rybchenko efx_rc_t rc;
39331bf5f03SAndrew Rybchenko
39431bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
395ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
396ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
39731bf5f03SAndrew Rybchenko
39831bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES;
39931bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
40031bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN;
40131bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
40231bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX;
40331bf5f03SAndrew Rybchenko
40431bf5f03SAndrew Rybchenko MCDI_IN_SET_DWORD(req, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID,
40531bf5f03SAndrew Rybchenko EVB_PORT_ID_ASSIGNED);
40631bf5f03SAndrew Rybchenko
40731bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
40831bf5f03SAndrew Rybchenko
40931bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
41031bf5f03SAndrew Rybchenko rc = req.emr_rc;
41131bf5f03SAndrew Rybchenko goto fail1;
41231bf5f03SAndrew Rybchenko }
41331bf5f03SAndrew Rybchenko
41431bf5f03SAndrew Rybchenko if (req.emr_out_length_used <
41531bf5f03SAndrew Rybchenko MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN) {
41631bf5f03SAndrew Rybchenko rc = EMSGSIZE;
41731bf5f03SAndrew Rybchenko goto fail2;
41831bf5f03SAndrew Rybchenko }
41931bf5f03SAndrew Rybchenko
42031bf5f03SAndrew Rybchenko if (MCDI_OUT_DWORD(req,
42131bf5f03SAndrew Rybchenko VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT) < 1) {
42231bf5f03SAndrew Rybchenko rc = ENOENT;
42331bf5f03SAndrew Rybchenko goto fail3;
42431bf5f03SAndrew Rybchenko }
42531bf5f03SAndrew Rybchenko
42631bf5f03SAndrew Rybchenko if (mac_addrp != NULL) {
42731bf5f03SAndrew Rybchenko uint8_t *addrp;
42831bf5f03SAndrew Rybchenko
42931bf5f03SAndrew Rybchenko addrp = MCDI_OUT2(req, uint8_t,
43031bf5f03SAndrew Rybchenko VPORT_GET_MAC_ADDRESSES_OUT_MACADDR);
43131bf5f03SAndrew Rybchenko
43231bf5f03SAndrew Rybchenko EFX_MAC_ADDR_COPY(mac_addrp, addrp);
43331bf5f03SAndrew Rybchenko }
43431bf5f03SAndrew Rybchenko
43531bf5f03SAndrew Rybchenko return (0);
43631bf5f03SAndrew Rybchenko
43731bf5f03SAndrew Rybchenko fail3:
43831bf5f03SAndrew Rybchenko EFSYS_PROBE(fail3);
43931bf5f03SAndrew Rybchenko fail2:
44031bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
44131bf5f03SAndrew Rybchenko fail1:
44231bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
44331bf5f03SAndrew Rybchenko
44431bf5f03SAndrew Rybchenko return (rc);
44531bf5f03SAndrew Rybchenko }
44631bf5f03SAndrew Rybchenko
44731bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_clock(__in efx_nic_t * enp,__out uint32_t * sys_freqp,__out uint32_t * dpcpu_freqp)44831bf5f03SAndrew Rybchenko efx_mcdi_get_clock(
44931bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
45078e5c87cSAndrew Rybchenko __out uint32_t *sys_freqp,
45178e5c87cSAndrew Rybchenko __out uint32_t *dpcpu_freqp)
45231bf5f03SAndrew Rybchenko {
45331bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
454315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CLOCK_IN_LEN,
455315bbbaaSAndrew Rybchenko MC_CMD_GET_CLOCK_OUT_LEN);
45631bf5f03SAndrew Rybchenko efx_rc_t rc;
45731bf5f03SAndrew Rybchenko
45831bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
459ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
460ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
46131bf5f03SAndrew Rybchenko
46231bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_CLOCK;
46331bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
46431bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_CLOCK_IN_LEN;
46531bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
46631bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_CLOCK_OUT_LEN;
46731bf5f03SAndrew Rybchenko
46831bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
46931bf5f03SAndrew Rybchenko
47031bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
47131bf5f03SAndrew Rybchenko rc = req.emr_rc;
47231bf5f03SAndrew Rybchenko goto fail1;
47331bf5f03SAndrew Rybchenko }
47431bf5f03SAndrew Rybchenko
47531bf5f03SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_CLOCK_OUT_LEN) {
47631bf5f03SAndrew Rybchenko rc = EMSGSIZE;
47731bf5f03SAndrew Rybchenko goto fail2;
47831bf5f03SAndrew Rybchenko }
47931bf5f03SAndrew Rybchenko
48031bf5f03SAndrew Rybchenko *sys_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_SYS_FREQ);
48131bf5f03SAndrew Rybchenko if (*sys_freqp == 0) {
48231bf5f03SAndrew Rybchenko rc = EINVAL;
48331bf5f03SAndrew Rybchenko goto fail3;
48431bf5f03SAndrew Rybchenko }
48578e5c87cSAndrew Rybchenko *dpcpu_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_DPCPU_FREQ);
48678e5c87cSAndrew Rybchenko if (*dpcpu_freqp == 0) {
48778e5c87cSAndrew Rybchenko rc = EINVAL;
48878e5c87cSAndrew Rybchenko goto fail4;
48978e5c87cSAndrew Rybchenko }
49031bf5f03SAndrew Rybchenko
49131bf5f03SAndrew Rybchenko return (0);
49231bf5f03SAndrew Rybchenko
49378e5c87cSAndrew Rybchenko fail4:
49478e5c87cSAndrew Rybchenko EFSYS_PROBE(fail4);
49531bf5f03SAndrew Rybchenko fail3:
49631bf5f03SAndrew Rybchenko EFSYS_PROBE(fail3);
49731bf5f03SAndrew Rybchenko fail2:
49831bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
49931bf5f03SAndrew Rybchenko fail1:
50031bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
50131bf5f03SAndrew Rybchenko
50231bf5f03SAndrew Rybchenko return (rc);
50331bf5f03SAndrew Rybchenko }
50431bf5f03SAndrew Rybchenko
50531bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_rxdp_config(__in efx_nic_t * enp,__out uint32_t * end_paddingp)50645becd76SAndrew Rybchenko efx_mcdi_get_rxdp_config(
50745becd76SAndrew Rybchenko __in efx_nic_t *enp,
50845becd76SAndrew Rybchenko __out uint32_t *end_paddingp)
50945becd76SAndrew Rybchenko {
51045becd76SAndrew Rybchenko efx_mcdi_req_t req;
511315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_RXDP_CONFIG_IN_LEN,
512315bbbaaSAndrew Rybchenko MC_CMD_GET_RXDP_CONFIG_OUT_LEN);
51345becd76SAndrew Rybchenko uint32_t end_padding;
51445becd76SAndrew Rybchenko efx_rc_t rc;
51545becd76SAndrew Rybchenko
51645becd76SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_RXDP_CONFIG;
51745becd76SAndrew Rybchenko req.emr_in_buf = payload;
51845becd76SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_RXDP_CONFIG_IN_LEN;
51945becd76SAndrew Rybchenko req.emr_out_buf = payload;
52045becd76SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_RXDP_CONFIG_OUT_LEN;
52145becd76SAndrew Rybchenko
52245becd76SAndrew Rybchenko efx_mcdi_execute(enp, &req);
52345becd76SAndrew Rybchenko if (req.emr_rc != 0) {
52445becd76SAndrew Rybchenko rc = req.emr_rc;
52545becd76SAndrew Rybchenko goto fail1;
52645becd76SAndrew Rybchenko }
52745becd76SAndrew Rybchenko
52845becd76SAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA,
52945becd76SAndrew Rybchenko GET_RXDP_CONFIG_OUT_PAD_HOST_DMA) == 0) {
53045becd76SAndrew Rybchenko /* RX DMA end padding is disabled */
53145becd76SAndrew Rybchenko end_padding = 0;
53245becd76SAndrew Rybchenko } else {
53345becd76SAndrew Rybchenko switch (MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA,
53445becd76SAndrew Rybchenko GET_RXDP_CONFIG_OUT_PAD_HOST_LEN)) {
53545becd76SAndrew Rybchenko case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_64:
53645becd76SAndrew Rybchenko end_padding = 64;
53745becd76SAndrew Rybchenko break;
53845becd76SAndrew Rybchenko case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_128:
53945becd76SAndrew Rybchenko end_padding = 128;
54045becd76SAndrew Rybchenko break;
54145becd76SAndrew Rybchenko case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_256:
54245becd76SAndrew Rybchenko end_padding = 256;
54345becd76SAndrew Rybchenko break;
54445becd76SAndrew Rybchenko default:
54545becd76SAndrew Rybchenko rc = ENOTSUP;
54645becd76SAndrew Rybchenko goto fail2;
54745becd76SAndrew Rybchenko }
54845becd76SAndrew Rybchenko }
54945becd76SAndrew Rybchenko
55045becd76SAndrew Rybchenko *end_paddingp = end_padding;
55145becd76SAndrew Rybchenko
55245becd76SAndrew Rybchenko return (0);
55345becd76SAndrew Rybchenko
55445becd76SAndrew Rybchenko fail2:
55545becd76SAndrew Rybchenko EFSYS_PROBE(fail2);
55645becd76SAndrew Rybchenko fail1:
55745becd76SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
55845becd76SAndrew Rybchenko
55945becd76SAndrew Rybchenko return (rc);
56045becd76SAndrew Rybchenko }
56145becd76SAndrew Rybchenko
56245becd76SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_vector_cfg(__in efx_nic_t * enp,__out_opt uint32_t * vec_basep,__out_opt uint32_t * pf_nvecp,__out_opt uint32_t * vf_nvecp)56331bf5f03SAndrew Rybchenko efx_mcdi_get_vector_cfg(
56431bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
56531bf5f03SAndrew Rybchenko __out_opt uint32_t *vec_basep,
56631bf5f03SAndrew Rybchenko __out_opt uint32_t *pf_nvecp,
56731bf5f03SAndrew Rybchenko __out_opt uint32_t *vf_nvecp)
56831bf5f03SAndrew Rybchenko {
56931bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
570315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_VECTOR_CFG_IN_LEN,
571315bbbaaSAndrew Rybchenko MC_CMD_GET_VECTOR_CFG_OUT_LEN);
57231bf5f03SAndrew Rybchenko efx_rc_t rc;
57331bf5f03SAndrew Rybchenko
57431bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_VECTOR_CFG;
57531bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
57631bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_VECTOR_CFG_IN_LEN;
57731bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
57831bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_VECTOR_CFG_OUT_LEN;
57931bf5f03SAndrew Rybchenko
58031bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
58131bf5f03SAndrew Rybchenko
58231bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
58331bf5f03SAndrew Rybchenko rc = req.emr_rc;
58431bf5f03SAndrew Rybchenko goto fail1;
58531bf5f03SAndrew Rybchenko }
58631bf5f03SAndrew Rybchenko
58731bf5f03SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_VECTOR_CFG_OUT_LEN) {
58831bf5f03SAndrew Rybchenko rc = EMSGSIZE;
58931bf5f03SAndrew Rybchenko goto fail2;
59031bf5f03SAndrew Rybchenko }
59131bf5f03SAndrew Rybchenko
59231bf5f03SAndrew Rybchenko if (vec_basep != NULL)
59331bf5f03SAndrew Rybchenko *vec_basep = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VEC_BASE);
59431bf5f03SAndrew Rybchenko if (pf_nvecp != NULL)
59531bf5f03SAndrew Rybchenko *pf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_PF);
59631bf5f03SAndrew Rybchenko if (vf_nvecp != NULL)
59731bf5f03SAndrew Rybchenko *vf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_VF);
59831bf5f03SAndrew Rybchenko
59931bf5f03SAndrew Rybchenko return (0);
60031bf5f03SAndrew Rybchenko
60131bf5f03SAndrew Rybchenko fail2:
60231bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
60331bf5f03SAndrew Rybchenko fail1:
60431bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
60531bf5f03SAndrew Rybchenko
60631bf5f03SAndrew Rybchenko return (rc);
60731bf5f03SAndrew Rybchenko }
60831bf5f03SAndrew Rybchenko
60931bf5f03SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_alloc_vis(__in efx_nic_t * enp,__in uint32_t min_vi_count,__in uint32_t max_vi_count,__out uint32_t * vi_basep,__out uint32_t * vi_countp,__out uint32_t * vi_shiftp)61031bf5f03SAndrew Rybchenko efx_mcdi_alloc_vis(
61131bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
61231bf5f03SAndrew Rybchenko __in uint32_t min_vi_count,
61331bf5f03SAndrew Rybchenko __in uint32_t max_vi_count,
61431bf5f03SAndrew Rybchenko __out uint32_t *vi_basep,
61531bf5f03SAndrew Rybchenko __out uint32_t *vi_countp,
61631bf5f03SAndrew Rybchenko __out uint32_t *vi_shiftp)
61731bf5f03SAndrew Rybchenko {
61831bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
619315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ALLOC_VIS_IN_LEN,
620315bbbaaSAndrew Rybchenko MC_CMD_ALLOC_VIS_EXT_OUT_LEN);
62131bf5f03SAndrew Rybchenko efx_rc_t rc;
62231bf5f03SAndrew Rybchenko
62331bf5f03SAndrew Rybchenko if (vi_countp == NULL) {
62431bf5f03SAndrew Rybchenko rc = EINVAL;
62531bf5f03SAndrew Rybchenko goto fail1;
62631bf5f03SAndrew Rybchenko }
62731bf5f03SAndrew Rybchenko
62831bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_ALLOC_VIS;
62931bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
63031bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN;
63131bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
632454502b9SAndrew Rybchenko req.emr_out_length = MC_CMD_ALLOC_VIS_EXT_OUT_LEN;
63331bf5f03SAndrew Rybchenko
63431bf5f03SAndrew Rybchenko MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count);
63531bf5f03SAndrew Rybchenko MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count);
63631bf5f03SAndrew Rybchenko
63731bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
63831bf5f03SAndrew Rybchenko
63931bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
64031bf5f03SAndrew Rybchenko rc = req.emr_rc;
64131bf5f03SAndrew Rybchenko goto fail2;
64231bf5f03SAndrew Rybchenko }
64331bf5f03SAndrew Rybchenko
64431bf5f03SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) {
64531bf5f03SAndrew Rybchenko rc = EMSGSIZE;
64631bf5f03SAndrew Rybchenko goto fail3;
64731bf5f03SAndrew Rybchenko }
64831bf5f03SAndrew Rybchenko
64931bf5f03SAndrew Rybchenko *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE);
65031bf5f03SAndrew Rybchenko *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT);
65131bf5f03SAndrew Rybchenko
65231bf5f03SAndrew Rybchenko /* Report VI_SHIFT if available (always zero for Huntington) */
65331bf5f03SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_EXT_OUT_LEN)
65431bf5f03SAndrew Rybchenko *vi_shiftp = 0;
65531bf5f03SAndrew Rybchenko else
65631bf5f03SAndrew Rybchenko *vi_shiftp = MCDI_OUT_DWORD(req, ALLOC_VIS_EXT_OUT_VI_SHIFT);
65731bf5f03SAndrew Rybchenko
65831bf5f03SAndrew Rybchenko return (0);
65931bf5f03SAndrew Rybchenko
66031bf5f03SAndrew Rybchenko fail3:
66131bf5f03SAndrew Rybchenko EFSYS_PROBE(fail3);
66231bf5f03SAndrew Rybchenko fail2:
66331bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
66431bf5f03SAndrew Rybchenko fail1:
66531bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
66631bf5f03SAndrew Rybchenko
66731bf5f03SAndrew Rybchenko return (rc);
66831bf5f03SAndrew Rybchenko }
66931bf5f03SAndrew Rybchenko
67031bf5f03SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_free_vis(__in efx_nic_t * enp)67131bf5f03SAndrew Rybchenko efx_mcdi_free_vis(
67231bf5f03SAndrew Rybchenko __in efx_nic_t *enp)
67331bf5f03SAndrew Rybchenko {
67431bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
67531bf5f03SAndrew Rybchenko efx_rc_t rc;
67631bf5f03SAndrew Rybchenko
67731bf5f03SAndrew Rybchenko EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0);
67831bf5f03SAndrew Rybchenko EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0);
67931bf5f03SAndrew Rybchenko
68031bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_FREE_VIS;
68131bf5f03SAndrew Rybchenko req.emr_in_buf = NULL;
68231bf5f03SAndrew Rybchenko req.emr_in_length = 0;
68331bf5f03SAndrew Rybchenko req.emr_out_buf = NULL;
68431bf5f03SAndrew Rybchenko req.emr_out_length = 0;
68531bf5f03SAndrew Rybchenko
68631bf5f03SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
68731bf5f03SAndrew Rybchenko
68831bf5f03SAndrew Rybchenko /* Ignore ELREADY (no allocated VIs, so nothing to free) */
68931bf5f03SAndrew Rybchenko if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) {
69031bf5f03SAndrew Rybchenko rc = req.emr_rc;
69131bf5f03SAndrew Rybchenko goto fail1;
69231bf5f03SAndrew Rybchenko }
69331bf5f03SAndrew Rybchenko
69431bf5f03SAndrew Rybchenko return (0);
69531bf5f03SAndrew Rybchenko
69631bf5f03SAndrew Rybchenko fail1:
69731bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
69831bf5f03SAndrew Rybchenko
69931bf5f03SAndrew Rybchenko return (rc);
70031bf5f03SAndrew Rybchenko }
70131bf5f03SAndrew Rybchenko
70231bf5f03SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_alloc_piobuf(__in efx_nic_t * enp,__out efx_piobuf_handle_t * handlep)70331bf5f03SAndrew Rybchenko efx_mcdi_alloc_piobuf(
70431bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
70531bf5f03SAndrew Rybchenko __out efx_piobuf_handle_t *handlep)
70631bf5f03SAndrew Rybchenko {
70731bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
708315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ALLOC_PIOBUF_IN_LEN,
709315bbbaaSAndrew Rybchenko MC_CMD_ALLOC_PIOBUF_OUT_LEN);
71031bf5f03SAndrew Rybchenko efx_rc_t rc;
71131bf5f03SAndrew Rybchenko
71231bf5f03SAndrew Rybchenko if (handlep == NULL) {
71331bf5f03SAndrew Rybchenko rc = EINVAL;
71431bf5f03SAndrew Rybchenko goto fail1;
71531bf5f03SAndrew Rybchenko }
71631bf5f03SAndrew Rybchenko
71731bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_ALLOC_PIOBUF;
71831bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
71931bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN;
72031bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
72131bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN;
72231bf5f03SAndrew Rybchenko
72331bf5f03SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
72431bf5f03SAndrew Rybchenko
72531bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
72631bf5f03SAndrew Rybchenko rc = req.emr_rc;
72731bf5f03SAndrew Rybchenko goto fail2;
72831bf5f03SAndrew Rybchenko }
72931bf5f03SAndrew Rybchenko
73031bf5f03SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) {
73131bf5f03SAndrew Rybchenko rc = EMSGSIZE;
73231bf5f03SAndrew Rybchenko goto fail3;
73331bf5f03SAndrew Rybchenko }
73431bf5f03SAndrew Rybchenko
73531bf5f03SAndrew Rybchenko *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE);
73631bf5f03SAndrew Rybchenko
73731bf5f03SAndrew Rybchenko return (0);
73831bf5f03SAndrew Rybchenko
73931bf5f03SAndrew Rybchenko fail3:
74031bf5f03SAndrew Rybchenko EFSYS_PROBE(fail3);
74131bf5f03SAndrew Rybchenko fail2:
74231bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
74331bf5f03SAndrew Rybchenko fail1:
74431bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
74531bf5f03SAndrew Rybchenko
74631bf5f03SAndrew Rybchenko return (rc);
74731bf5f03SAndrew Rybchenko }
74831bf5f03SAndrew Rybchenko
74931bf5f03SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_free_piobuf(__in efx_nic_t * enp,__in efx_piobuf_handle_t handle)75031bf5f03SAndrew Rybchenko efx_mcdi_free_piobuf(
75131bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
75231bf5f03SAndrew Rybchenko __in efx_piobuf_handle_t handle)
75331bf5f03SAndrew Rybchenko {
75431bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
755315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FREE_PIOBUF_IN_LEN,
756315bbbaaSAndrew Rybchenko MC_CMD_FREE_PIOBUF_OUT_LEN);
75731bf5f03SAndrew Rybchenko efx_rc_t rc;
75831bf5f03SAndrew Rybchenko
75931bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_FREE_PIOBUF;
76031bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
76131bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN;
76231bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
76331bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN;
76431bf5f03SAndrew Rybchenko
76531bf5f03SAndrew Rybchenko MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle);
76631bf5f03SAndrew Rybchenko
76731bf5f03SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
76831bf5f03SAndrew Rybchenko
76931bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
77031bf5f03SAndrew Rybchenko rc = req.emr_rc;
77131bf5f03SAndrew Rybchenko goto fail1;
77231bf5f03SAndrew Rybchenko }
77331bf5f03SAndrew Rybchenko
77431bf5f03SAndrew Rybchenko return (0);
77531bf5f03SAndrew Rybchenko
77631bf5f03SAndrew Rybchenko fail1:
77731bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
77831bf5f03SAndrew Rybchenko
77931bf5f03SAndrew Rybchenko return (rc);
78031bf5f03SAndrew Rybchenko }
78131bf5f03SAndrew Rybchenko
78231bf5f03SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_link_piobuf(__in efx_nic_t * enp,__in uint32_t vi_index,__in efx_piobuf_handle_t handle)78331bf5f03SAndrew Rybchenko efx_mcdi_link_piobuf(
78431bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
78531bf5f03SAndrew Rybchenko __in uint32_t vi_index,
78631bf5f03SAndrew Rybchenko __in efx_piobuf_handle_t handle)
78731bf5f03SAndrew Rybchenko {
78831bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
789315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LINK_PIOBUF_IN_LEN,
790315bbbaaSAndrew Rybchenko MC_CMD_LINK_PIOBUF_OUT_LEN);
79131bf5f03SAndrew Rybchenko efx_rc_t rc;
79231bf5f03SAndrew Rybchenko
79331bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_LINK_PIOBUF;
79431bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
79531bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN;
79631bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
79731bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN;
79831bf5f03SAndrew Rybchenko
79931bf5f03SAndrew Rybchenko MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle);
80031bf5f03SAndrew Rybchenko MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
80131bf5f03SAndrew Rybchenko
80231bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
80331bf5f03SAndrew Rybchenko
80431bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
80531bf5f03SAndrew Rybchenko rc = req.emr_rc;
80631bf5f03SAndrew Rybchenko goto fail1;
80731bf5f03SAndrew Rybchenko }
80831bf5f03SAndrew Rybchenko
80931bf5f03SAndrew Rybchenko return (0);
81031bf5f03SAndrew Rybchenko
81131bf5f03SAndrew Rybchenko fail1:
81231bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
81331bf5f03SAndrew Rybchenko
81431bf5f03SAndrew Rybchenko return (rc);
81531bf5f03SAndrew Rybchenko }
81631bf5f03SAndrew Rybchenko
81731bf5f03SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_unlink_piobuf(__in efx_nic_t * enp,__in uint32_t vi_index)81831bf5f03SAndrew Rybchenko efx_mcdi_unlink_piobuf(
81931bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
82031bf5f03SAndrew Rybchenko __in uint32_t vi_index)
82131bf5f03SAndrew Rybchenko {
82231bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
823315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_UNLINK_PIOBUF_IN_LEN,
824315bbbaaSAndrew Rybchenko MC_CMD_UNLINK_PIOBUF_OUT_LEN);
82531bf5f03SAndrew Rybchenko efx_rc_t rc;
82631bf5f03SAndrew Rybchenko
82731bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_UNLINK_PIOBUF;
82831bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
82931bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN;
83031bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
83131bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN;
83231bf5f03SAndrew Rybchenko
83331bf5f03SAndrew Rybchenko MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
83431bf5f03SAndrew Rybchenko
835bba8dcbcSAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
83631bf5f03SAndrew Rybchenko
83731bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
83831bf5f03SAndrew Rybchenko rc = req.emr_rc;
83931bf5f03SAndrew Rybchenko goto fail1;
84031bf5f03SAndrew Rybchenko }
84131bf5f03SAndrew Rybchenko
84231bf5f03SAndrew Rybchenko return (0);
84331bf5f03SAndrew Rybchenko
84431bf5f03SAndrew Rybchenko fail1:
84531bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
84631bf5f03SAndrew Rybchenko
84731bf5f03SAndrew Rybchenko return (rc);
84831bf5f03SAndrew Rybchenko }
84931bf5f03SAndrew Rybchenko
85031bf5f03SAndrew Rybchenko static void
ef10_nic_alloc_piobufs(__in efx_nic_t * enp,__in uint32_t max_piobuf_count)85131bf5f03SAndrew Rybchenko ef10_nic_alloc_piobufs(
85231bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
85331bf5f03SAndrew Rybchenko __in uint32_t max_piobuf_count)
85431bf5f03SAndrew Rybchenko {
85531bf5f03SAndrew Rybchenko efx_piobuf_handle_t *handlep;
85631bf5f03SAndrew Rybchenko unsigned int i;
85731bf5f03SAndrew Rybchenko
85831bf5f03SAndrew Rybchenko EFSYS_ASSERT3U(max_piobuf_count, <=,
85931bf5f03SAndrew Rybchenko EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle));
86031bf5f03SAndrew Rybchenko
86131bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count = 0;
86231bf5f03SAndrew Rybchenko
86331bf5f03SAndrew Rybchenko for (i = 0; i < max_piobuf_count; i++) {
86431bf5f03SAndrew Rybchenko handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
86531bf5f03SAndrew Rybchenko
866647a7e8fSAndrew Rybchenko if (efx_mcdi_alloc_piobuf(enp, handlep) != 0)
86731bf5f03SAndrew Rybchenko goto fail1;
86831bf5f03SAndrew Rybchenko
86931bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_pio_alloc_map[i] = 0;
87031bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count++;
87131bf5f03SAndrew Rybchenko }
87231bf5f03SAndrew Rybchenko
87331bf5f03SAndrew Rybchenko return;
87431bf5f03SAndrew Rybchenko
87531bf5f03SAndrew Rybchenko fail1:
87631bf5f03SAndrew Rybchenko for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
87731bf5f03SAndrew Rybchenko handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
87831bf5f03SAndrew Rybchenko
879e4ddd4ccSAndrew Rybchenko (void) efx_mcdi_free_piobuf(enp, *handlep);
88031bf5f03SAndrew Rybchenko *handlep = EFX_PIOBUF_HANDLE_INVALID;
88131bf5f03SAndrew Rybchenko }
88231bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count = 0;
88331bf5f03SAndrew Rybchenko }
88431bf5f03SAndrew Rybchenko
88531bf5f03SAndrew Rybchenko static void
ef10_nic_free_piobufs(__in efx_nic_t * enp)88631bf5f03SAndrew Rybchenko ef10_nic_free_piobufs(
88731bf5f03SAndrew Rybchenko __in efx_nic_t *enp)
88831bf5f03SAndrew Rybchenko {
88931bf5f03SAndrew Rybchenko efx_piobuf_handle_t *handlep;
89031bf5f03SAndrew Rybchenko unsigned int i;
89131bf5f03SAndrew Rybchenko
89231bf5f03SAndrew Rybchenko for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
89331bf5f03SAndrew Rybchenko handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
89431bf5f03SAndrew Rybchenko
895e4ddd4ccSAndrew Rybchenko (void) efx_mcdi_free_piobuf(enp, *handlep);
89631bf5f03SAndrew Rybchenko *handlep = EFX_PIOBUF_HANDLE_INVALID;
89731bf5f03SAndrew Rybchenko }
89831bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count = 0;
89931bf5f03SAndrew Rybchenko }
90031bf5f03SAndrew Rybchenko
90131bf5f03SAndrew Rybchenko /* Sub-allocate a block from a piobuf */
90231bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_pio_alloc(__inout efx_nic_t * enp,__out uint32_t * bufnump,__out efx_piobuf_handle_t * handlep,__out uint32_t * blknump,__out uint32_t * offsetp,__out size_t * sizep)90331bf5f03SAndrew Rybchenko ef10_nic_pio_alloc(
90431bf5f03SAndrew Rybchenko __inout efx_nic_t *enp,
90531bf5f03SAndrew Rybchenko __out uint32_t *bufnump,
90631bf5f03SAndrew Rybchenko __out efx_piobuf_handle_t *handlep,
90731bf5f03SAndrew Rybchenko __out uint32_t *blknump,
90831bf5f03SAndrew Rybchenko __out uint32_t *offsetp,
90931bf5f03SAndrew Rybchenko __out size_t *sizep)
91031bf5f03SAndrew Rybchenko {
91131bf5f03SAndrew Rybchenko efx_nic_cfg_t *encp = &enp->en_nic_cfg;
91231bf5f03SAndrew Rybchenko efx_drv_cfg_t *edcp = &enp->en_drv_cfg;
91331bf5f03SAndrew Rybchenko uint32_t blk_per_buf;
91431bf5f03SAndrew Rybchenko uint32_t buf, blk;
91531bf5f03SAndrew Rybchenko efx_rc_t rc;
91631bf5f03SAndrew Rybchenko
91731bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
918ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
919ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
92031bf5f03SAndrew Rybchenko EFSYS_ASSERT(bufnump);
92131bf5f03SAndrew Rybchenko EFSYS_ASSERT(handlep);
92231bf5f03SAndrew Rybchenko EFSYS_ASSERT(blknump);
92331bf5f03SAndrew Rybchenko EFSYS_ASSERT(offsetp);
92431bf5f03SAndrew Rybchenko EFSYS_ASSERT(sizep);
92531bf5f03SAndrew Rybchenko
92631bf5f03SAndrew Rybchenko if ((edcp->edc_pio_alloc_size == 0) ||
92731bf5f03SAndrew Rybchenko (enp->en_arch.ef10.ena_piobuf_count == 0)) {
92831bf5f03SAndrew Rybchenko rc = ENOMEM;
92931bf5f03SAndrew Rybchenko goto fail1;
93031bf5f03SAndrew Rybchenko }
93131bf5f03SAndrew Rybchenko blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size;
93231bf5f03SAndrew Rybchenko
93331bf5f03SAndrew Rybchenko for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) {
93431bf5f03SAndrew Rybchenko uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf];
93531bf5f03SAndrew Rybchenko
93631bf5f03SAndrew Rybchenko if (~(*map) == 0)
93731bf5f03SAndrew Rybchenko continue;
93831bf5f03SAndrew Rybchenko
93931bf5f03SAndrew Rybchenko EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map)));
94031bf5f03SAndrew Rybchenko for (blk = 0; blk < blk_per_buf; blk++) {
94131bf5f03SAndrew Rybchenko if ((*map & (1u << blk)) == 0) {
94231bf5f03SAndrew Rybchenko *map |= (1u << blk);
94331bf5f03SAndrew Rybchenko goto done;
94431bf5f03SAndrew Rybchenko }
94531bf5f03SAndrew Rybchenko }
94631bf5f03SAndrew Rybchenko }
94731bf5f03SAndrew Rybchenko rc = ENOMEM;
94831bf5f03SAndrew Rybchenko goto fail2;
94931bf5f03SAndrew Rybchenko
95031bf5f03SAndrew Rybchenko done:
95131bf5f03SAndrew Rybchenko *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf];
95231bf5f03SAndrew Rybchenko *bufnump = buf;
95331bf5f03SAndrew Rybchenko *blknump = blk;
95431bf5f03SAndrew Rybchenko *sizep = edcp->edc_pio_alloc_size;
95531bf5f03SAndrew Rybchenko *offsetp = blk * (*sizep);
95631bf5f03SAndrew Rybchenko
95731bf5f03SAndrew Rybchenko return (0);
95831bf5f03SAndrew Rybchenko
95931bf5f03SAndrew Rybchenko fail2:
96031bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
96131bf5f03SAndrew Rybchenko fail1:
96231bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
96331bf5f03SAndrew Rybchenko
96431bf5f03SAndrew Rybchenko return (rc);
96531bf5f03SAndrew Rybchenko }
96631bf5f03SAndrew Rybchenko
96731bf5f03SAndrew Rybchenko /* Free a piobuf sub-allocated block */
96831bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_pio_free(__inout efx_nic_t * enp,__in uint32_t bufnum,__in uint32_t blknum)96931bf5f03SAndrew Rybchenko ef10_nic_pio_free(
97031bf5f03SAndrew Rybchenko __inout efx_nic_t *enp,
97131bf5f03SAndrew Rybchenko __in uint32_t bufnum,
97231bf5f03SAndrew Rybchenko __in uint32_t blknum)
97331bf5f03SAndrew Rybchenko {
97431bf5f03SAndrew Rybchenko uint32_t *map;
97531bf5f03SAndrew Rybchenko efx_rc_t rc;
97631bf5f03SAndrew Rybchenko
97731bf5f03SAndrew Rybchenko if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) ||
97831bf5f03SAndrew Rybchenko (blknum >= (8 * sizeof (*map)))) {
97931bf5f03SAndrew Rybchenko rc = EINVAL;
98031bf5f03SAndrew Rybchenko goto fail1;
98131bf5f03SAndrew Rybchenko }
98231bf5f03SAndrew Rybchenko
98331bf5f03SAndrew Rybchenko map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum];
98431bf5f03SAndrew Rybchenko if ((*map & (1u << blknum)) == 0) {
98531bf5f03SAndrew Rybchenko rc = ENOENT;
98631bf5f03SAndrew Rybchenko goto fail2;
98731bf5f03SAndrew Rybchenko }
98831bf5f03SAndrew Rybchenko *map &= ~(1u << blknum);
98931bf5f03SAndrew Rybchenko
99031bf5f03SAndrew Rybchenko return (0);
99131bf5f03SAndrew Rybchenko
99231bf5f03SAndrew Rybchenko fail2:
99331bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
99431bf5f03SAndrew Rybchenko fail1:
99531bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
99631bf5f03SAndrew Rybchenko
99731bf5f03SAndrew Rybchenko return (rc);
99831bf5f03SAndrew Rybchenko }
99931bf5f03SAndrew Rybchenko
100031bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_pio_link(__inout efx_nic_t * enp,__in uint32_t vi_index,__in efx_piobuf_handle_t handle)100131bf5f03SAndrew Rybchenko ef10_nic_pio_link(
100231bf5f03SAndrew Rybchenko __inout efx_nic_t *enp,
100331bf5f03SAndrew Rybchenko __in uint32_t vi_index,
100431bf5f03SAndrew Rybchenko __in efx_piobuf_handle_t handle)
100531bf5f03SAndrew Rybchenko {
100631bf5f03SAndrew Rybchenko return (efx_mcdi_link_piobuf(enp, vi_index, handle));
100731bf5f03SAndrew Rybchenko }
100831bf5f03SAndrew Rybchenko
100931bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_pio_unlink(__inout efx_nic_t * enp,__in uint32_t vi_index)101031bf5f03SAndrew Rybchenko ef10_nic_pio_unlink(
101131bf5f03SAndrew Rybchenko __inout efx_nic_t *enp,
101231bf5f03SAndrew Rybchenko __in uint32_t vi_index)
101331bf5f03SAndrew Rybchenko {
101431bf5f03SAndrew Rybchenko return (efx_mcdi_unlink_piobuf(enp, vi_index));
101531bf5f03SAndrew Rybchenko }
101631bf5f03SAndrew Rybchenko
1017b422f949SAndrew Rybchenko static __checkReturn efx_rc_t
ef10_mcdi_get_pf_count(__in efx_nic_t * enp,__out uint32_t * pf_countp)1018b422f949SAndrew Rybchenko ef10_mcdi_get_pf_count(
1019b422f949SAndrew Rybchenko __in efx_nic_t *enp,
1020b422f949SAndrew Rybchenko __out uint32_t *pf_countp)
1021b422f949SAndrew Rybchenko {
1022b422f949SAndrew Rybchenko efx_mcdi_req_t req;
1023315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PF_COUNT_IN_LEN,
1024315bbbaaSAndrew Rybchenko MC_CMD_GET_PF_COUNT_OUT_LEN);
1025b422f949SAndrew Rybchenko efx_rc_t rc;
1026b422f949SAndrew Rybchenko
1027b422f949SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_PF_COUNT;
1028b422f949SAndrew Rybchenko req.emr_in_buf = payload;
1029b422f949SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_PF_COUNT_IN_LEN;
1030b422f949SAndrew Rybchenko req.emr_out_buf = payload;
1031b422f949SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_PF_COUNT_OUT_LEN;
1032b422f949SAndrew Rybchenko
1033b422f949SAndrew Rybchenko efx_mcdi_execute(enp, &req);
1034b422f949SAndrew Rybchenko
1035b422f949SAndrew Rybchenko if (req.emr_rc != 0) {
1036b422f949SAndrew Rybchenko rc = req.emr_rc;
1037b422f949SAndrew Rybchenko goto fail1;
1038b422f949SAndrew Rybchenko }
1039b422f949SAndrew Rybchenko
1040b422f949SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_PF_COUNT_OUT_LEN) {
1041b422f949SAndrew Rybchenko rc = EMSGSIZE;
1042b422f949SAndrew Rybchenko goto fail2;
1043b422f949SAndrew Rybchenko }
1044b422f949SAndrew Rybchenko
1045b422f949SAndrew Rybchenko *pf_countp = *MCDI_OUT(req, uint8_t,
1046b422f949SAndrew Rybchenko MC_CMD_GET_PF_COUNT_OUT_PF_COUNT_OFST);
1047b422f949SAndrew Rybchenko
1048b422f949SAndrew Rybchenko EFSYS_ASSERT(*pf_countp != 0);
1049b422f949SAndrew Rybchenko
1050b422f949SAndrew Rybchenko return (0);
1051b422f949SAndrew Rybchenko
1052b422f949SAndrew Rybchenko fail2:
1053b422f949SAndrew Rybchenko EFSYS_PROBE(fail2);
1054b422f949SAndrew Rybchenko fail1:
1055b422f949SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1056b422f949SAndrew Rybchenko
1057b422f949SAndrew Rybchenko return (rc);
1058b422f949SAndrew Rybchenko }
1059b422f949SAndrew Rybchenko
1060deeaf87fSAndrew Rybchenko static __checkReturn efx_rc_t
ef10_get_datapath_caps(__in efx_nic_t * enp)106131bf5f03SAndrew Rybchenko ef10_get_datapath_caps(
106231bf5f03SAndrew Rybchenko __in efx_nic_t *enp)
106331bf5f03SAndrew Rybchenko {
106431bf5f03SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1065016941e3SAndrew Rybchenko efx_mcdi_req_t req;
1066315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CAPABILITIES_IN_LEN,
1067315bbbaaSAndrew Rybchenko MC_CMD_GET_CAPABILITIES_V5_OUT_LEN);
106831bf5f03SAndrew Rybchenko efx_rc_t rc;
106931bf5f03SAndrew Rybchenko
1070b422f949SAndrew Rybchenko if ((rc = ef10_mcdi_get_pf_count(enp, &encp->enc_hw_pf_count)) != 0)
1071b422f949SAndrew Rybchenko goto fail1;
1072b422f949SAndrew Rybchenko
1073016941e3SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_CAPABILITIES;
1074016941e3SAndrew Rybchenko req.emr_in_buf = payload;
1075016941e3SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN;
1076016941e3SAndrew Rybchenko req.emr_out_buf = payload;
10775c2f9d6aSAndrew Rybchenko req.emr_out_length = MC_CMD_GET_CAPABILITIES_V5_OUT_LEN;
1078016941e3SAndrew Rybchenko
1079016941e3SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
1080016941e3SAndrew Rybchenko
1081016941e3SAndrew Rybchenko if (req.emr_rc != 0) {
1082016941e3SAndrew Rybchenko rc = req.emr_rc;
1083016941e3SAndrew Rybchenko goto fail2;
1084016941e3SAndrew Rybchenko }
1085016941e3SAndrew Rybchenko
1086016941e3SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) {
1087016941e3SAndrew Rybchenko rc = EMSGSIZE;
1088016941e3SAndrew Rybchenko goto fail3;
1089016941e3SAndrew Rybchenko }
1090016941e3SAndrew Rybchenko
1091016941e3SAndrew Rybchenko #define CAP_FLAGS1(_req, _flag) \
1092016941e3SAndrew Rybchenko (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_OUT_FLAGS1) & \
1093016941e3SAndrew Rybchenko (1u << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## _flag ## _LBN)))
1094016941e3SAndrew Rybchenko
1095016941e3SAndrew Rybchenko #define CAP_FLAGS2(_req, _flag) \
1096016941e3SAndrew Rybchenko (((_req).emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) && \
1097016941e3SAndrew Rybchenko (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_V2_OUT_FLAGS2) & \
1098016941e3SAndrew Rybchenko (1u << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## _flag ## _LBN))))
109931bf5f03SAndrew Rybchenko
110031bf5f03SAndrew Rybchenko /*
110131bf5f03SAndrew Rybchenko * Huntington RXDP firmware inserts a 0 or 14 byte prefix.
110231bf5f03SAndrew Rybchenko * We only support the 14 byte prefix here.
110331bf5f03SAndrew Rybchenko */
1104016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, RX_PREFIX_LEN_14) == 0) {
110531bf5f03SAndrew Rybchenko rc = ENOTSUP;
1106016941e3SAndrew Rybchenko goto fail4;
110731bf5f03SAndrew Rybchenko }
110831bf5f03SAndrew Rybchenko encp->enc_rx_prefix_size = 14;
110931bf5f03SAndrew Rybchenko
11105a51b32eSAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
1111fd962dffSAndrew Rybchenko /* Check if the firmware supports additional RSS modes */
1112fd962dffSAndrew Rybchenko if (CAP_FLAGS1(req, ADDITIONAL_RSS_MODES))
1113fd962dffSAndrew Rybchenko encp->enc_rx_scale_additional_modes_supported = B_TRUE;
1114fd962dffSAndrew Rybchenko else
1115fd962dffSAndrew Rybchenko encp->enc_rx_scale_additional_modes_supported = B_FALSE;
11165a51b32eSAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
1117fd962dffSAndrew Rybchenko
111831bf5f03SAndrew Rybchenko /* Check if the firmware supports TSO */
1119016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, TX_TSO))
1120016941e3SAndrew Rybchenko encp->enc_fw_assisted_tso_enabled = B_TRUE;
1121016941e3SAndrew Rybchenko else
1122016941e3SAndrew Rybchenko encp->enc_fw_assisted_tso_enabled = B_FALSE;
112331bf5f03SAndrew Rybchenko
112431bf5f03SAndrew Rybchenko /* Check if the firmware supports FATSOv2 */
1125016941e3SAndrew Rybchenko if (CAP_FLAGS2(req, TX_TSO_V2)) {
1126016941e3SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_enabled = B_TRUE;
1127016941e3SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_n_contexts = MCDI_OUT_WORD(req,
1128016941e3SAndrew Rybchenko GET_CAPABILITIES_V2_OUT_TX_TSO_V2_N_CONTEXTS);
1129016941e3SAndrew Rybchenko } else {
1130016941e3SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
1131016941e3SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_n_contexts = 0;
1132016941e3SAndrew Rybchenko }
11339933eabbSAndrew Rybchenko
1134357c2ebbSAndrew Rybchenko /* Check if the firmware supports FATSOv2 encap */
1135357c2ebbSAndrew Rybchenko if (CAP_FLAGS2(req, TX_TSO_V2_ENCAP))
1136357c2ebbSAndrew Rybchenko encp->enc_fw_assisted_tso_v2_encap_enabled = B_TRUE;
1137357c2ebbSAndrew Rybchenko else
1138357c2ebbSAndrew Rybchenko encp->enc_fw_assisted_tso_v2_encap_enabled = B_FALSE;
1139357c2ebbSAndrew Rybchenko
114031bf5f03SAndrew Rybchenko /* Check if the firmware has vadapter/vport/vswitch support */
1141016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, EVB))
1142016941e3SAndrew Rybchenko encp->enc_datapath_cap_evb = B_TRUE;
1143016941e3SAndrew Rybchenko else
1144016941e3SAndrew Rybchenko encp->enc_datapath_cap_evb = B_FALSE;
114531bf5f03SAndrew Rybchenko
114631bf5f03SAndrew Rybchenko /* Check if the firmware supports VLAN insertion */
1147016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, TX_VLAN_INSERTION))
1148016941e3SAndrew Rybchenko encp->enc_hw_tx_insert_vlan_enabled = B_TRUE;
1149016941e3SAndrew Rybchenko else
1150016941e3SAndrew Rybchenko encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
115131bf5f03SAndrew Rybchenko
115231bf5f03SAndrew Rybchenko /* Check if the firmware supports RX event batching */
1153016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, RX_BATCHING))
1154016941e3SAndrew Rybchenko encp->enc_rx_batching_enabled = B_TRUE;
1155016941e3SAndrew Rybchenko else
1156016941e3SAndrew Rybchenko encp->enc_rx_batching_enabled = B_FALSE;
115731bf5f03SAndrew Rybchenko
1158095bde93SAndrew Rybchenko /*
1159095bde93SAndrew Rybchenko * Even if batching isn't reported as supported, we may still get
1160095bde93SAndrew Rybchenko * batched events.
1161095bde93SAndrew Rybchenko */
116231bf5f03SAndrew Rybchenko encp->enc_rx_batch_max = 16;
116331bf5f03SAndrew Rybchenko
116431bf5f03SAndrew Rybchenko /* Check if the firmware supports disabling scatter on RXQs */
1165016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, RX_DISABLE_SCATTER))
1166016941e3SAndrew Rybchenko encp->enc_rx_disable_scatter_supported = B_TRUE;
1167016941e3SAndrew Rybchenko else
1168016941e3SAndrew Rybchenko encp->enc_rx_disable_scatter_supported = B_FALSE;
116931bf5f03SAndrew Rybchenko
11708e0c4827SAndrew Rybchenko /* Check if the firmware supports packed stream mode */
1171016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, RX_PACKED_STREAM))
1172016941e3SAndrew Rybchenko encp->enc_rx_packed_stream_supported = B_TRUE;
1173016941e3SAndrew Rybchenko else
1174016941e3SAndrew Rybchenko encp->enc_rx_packed_stream_supported = B_FALSE;
11758e0c4827SAndrew Rybchenko
11768e0c4827SAndrew Rybchenko /*
11778e0c4827SAndrew Rybchenko * Check if the firmware supports configurable buffer sizes
11788e0c4827SAndrew Rybchenko * for packed stream mode (otherwise buffer size is 1Mbyte)
11798e0c4827SAndrew Rybchenko */
1180016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, RX_PACKED_STREAM_VAR_BUFFERS))
1181016941e3SAndrew Rybchenko encp->enc_rx_var_packed_stream_supported = B_TRUE;
1182016941e3SAndrew Rybchenko else
1183016941e3SAndrew Rybchenko encp->enc_rx_var_packed_stream_supported = B_FALSE;
11848e0c4827SAndrew Rybchenko
1185ceeff9b1SAndrew Rybchenko /* Check if the firmware supports equal stride super-buffer mode */
1186ceeff9b1SAndrew Rybchenko if (CAP_FLAGS2(req, EQUAL_STRIDE_SUPER_BUFFER))
1187ceeff9b1SAndrew Rybchenko encp->enc_rx_es_super_buffer_supported = B_TRUE;
1188ceeff9b1SAndrew Rybchenko else
1189ceeff9b1SAndrew Rybchenko encp->enc_rx_es_super_buffer_supported = B_FALSE;
1190ceeff9b1SAndrew Rybchenko
11913f8f5495SAndrew Rybchenko /* Check if the firmware supports FW subvariant w/o Tx checksumming */
11923f8f5495SAndrew Rybchenko if (CAP_FLAGS2(req, FW_SUBVARIANT_NO_TX_CSUM))
11933f8f5495SAndrew Rybchenko encp->enc_fw_subvariant_no_tx_csum_supported = B_TRUE;
11943f8f5495SAndrew Rybchenko else
11953f8f5495SAndrew Rybchenko encp->enc_fw_subvariant_no_tx_csum_supported = B_FALSE;
11963f8f5495SAndrew Rybchenko
119731bf5f03SAndrew Rybchenko /* Check if the firmware supports set mac with running filters */
1198016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED))
1199016941e3SAndrew Rybchenko encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
1200016941e3SAndrew Rybchenko else
1201016941e3SAndrew Rybchenko encp->enc_allow_set_mac_with_installed_filters = B_FALSE;
120231bf5f03SAndrew Rybchenko
120331bf5f03SAndrew Rybchenko /*
120431bf5f03SAndrew Rybchenko * Check if firmware supports the extended MC_CMD_SET_MAC, which allows
120531bf5f03SAndrew Rybchenko * specifying which parameters to configure.
120631bf5f03SAndrew Rybchenko */
1207016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, SET_MAC_ENHANCED))
1208016941e3SAndrew Rybchenko encp->enc_enhanced_set_mac_supported = B_TRUE;
1209016941e3SAndrew Rybchenko else
1210016941e3SAndrew Rybchenko encp->enc_enhanced_set_mac_supported = B_FALSE;
121131bf5f03SAndrew Rybchenko
1212995a3bf4SAndrew Rybchenko /*
1213995a3bf4SAndrew Rybchenko * Check if firmware supports version 2 of MC_CMD_INIT_EVQ, which allows
1214995a3bf4SAndrew Rybchenko * us to let the firmware choose the settings to use on an EVQ.
1215995a3bf4SAndrew Rybchenko */
1216016941e3SAndrew Rybchenko if (CAP_FLAGS2(req, INIT_EVQ_V2))
1217016941e3SAndrew Rybchenko encp->enc_init_evq_v2_supported = B_TRUE;
1218016941e3SAndrew Rybchenko else
1219016941e3SAndrew Rybchenko encp->enc_init_evq_v2_supported = B_FALSE;
1220995a3bf4SAndrew Rybchenko
122158a72cb2SAndrew Rybchenko /*
1222621cf621SAndrew Rybchenko * Check if firmware-verified NVRAM updates must be used.
1223621cf621SAndrew Rybchenko *
1224621cf621SAndrew Rybchenko * The firmware trusted installer requires all NVRAM updates to use
1225621cf621SAndrew Rybchenko * version 2 of MC_CMD_NVRAM_UPDATE_START (to enable verified update)
1226621cf621SAndrew Rybchenko * and version 2 of MC_CMD_NVRAM_UPDATE_FINISH (to verify the updated
1227621cf621SAndrew Rybchenko * partition and report the result).
1228621cf621SAndrew Rybchenko */
1229016941e3SAndrew Rybchenko if (CAP_FLAGS2(req, NVRAM_UPDATE_REPORT_VERIFY_RESULT))
1230016941e3SAndrew Rybchenko encp->enc_nvram_update_verify_result_supported = B_TRUE;
1231016941e3SAndrew Rybchenko else
1232016941e3SAndrew Rybchenko encp->enc_nvram_update_verify_result_supported = B_FALSE;
1233621cf621SAndrew Rybchenko
1234621cf621SAndrew Rybchenko /*
123558a72cb2SAndrew Rybchenko * Check if firmware provides packet memory and Rx datapath
123658a72cb2SAndrew Rybchenko * counters.
123758a72cb2SAndrew Rybchenko */
1238016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, PM_AND_RXDP_COUNTERS))
1239016941e3SAndrew Rybchenko encp->enc_pm_and_rxdp_counters = B_TRUE;
1240016941e3SAndrew Rybchenko else
1241016941e3SAndrew Rybchenko encp->enc_pm_and_rxdp_counters = B_FALSE;
124258a72cb2SAndrew Rybchenko
124358a72cb2SAndrew Rybchenko /*
124458a72cb2SAndrew Rybchenko * Check if the 40G MAC hardware is capable of reporting
124558a72cb2SAndrew Rybchenko * statistics for Tx size bins.
124658a72cb2SAndrew Rybchenko */
1247016941e3SAndrew Rybchenko if (CAP_FLAGS2(req, MAC_STATS_40G_TX_SIZE_BINS))
1248016941e3SAndrew Rybchenko encp->enc_mac_stats_40g_tx_size_bins = B_TRUE;
1249016941e3SAndrew Rybchenko else
1250016941e3SAndrew Rybchenko encp->enc_mac_stats_40g_tx_size_bins = B_FALSE;
125158a72cb2SAndrew Rybchenko
1252799fadbeSAndrew Rybchenko /*
1253799fadbeSAndrew Rybchenko * Check if firmware supports VXLAN and NVGRE tunnels.
1254799fadbeSAndrew Rybchenko * The capability indicates Geneve protocol support as well.
1255799fadbeSAndrew Rybchenko */
1256016941e3SAndrew Rybchenko if (CAP_FLAGS1(req, VXLAN_NVGRE)) {
1257799fadbeSAndrew Rybchenko encp->enc_tunnel_encapsulations_supported =
1258799fadbeSAndrew Rybchenko (1u << EFX_TUNNEL_PROTOCOL_VXLAN) |
1259799fadbeSAndrew Rybchenko (1u << EFX_TUNNEL_PROTOCOL_GENEVE) |
1260799fadbeSAndrew Rybchenko (1u << EFX_TUNNEL_PROTOCOL_NVGRE);
1261799fadbeSAndrew Rybchenko
1262fdbe38cfSAndrew Rybchenko EFX_STATIC_ASSERT(EFX_TUNNEL_MAXNENTRIES ==
1263fdbe38cfSAndrew Rybchenko MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES_MAXNUM);
1264fdbe38cfSAndrew Rybchenko encp->enc_tunnel_config_udp_entries_max =
1265fdbe38cfSAndrew Rybchenko EFX_TUNNEL_MAXNENTRIES;
1266fdbe38cfSAndrew Rybchenko } else {
1267fdbe38cfSAndrew Rybchenko encp->enc_tunnel_config_udp_entries_max = 0;
1268fdbe38cfSAndrew Rybchenko }
1269fdbe38cfSAndrew Rybchenko
127076ecd4a3SAndrew Rybchenko /*
127176ecd4a3SAndrew Rybchenko * Check if firmware reports the VI window mode.
127276ecd4a3SAndrew Rybchenko * Medford2 has a variable VI window size (8K, 16K or 64K).
127376ecd4a3SAndrew Rybchenko * Medford and Huntington have a fixed 8K VI window size.
127476ecd4a3SAndrew Rybchenko */
127576ecd4a3SAndrew Rybchenko if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V3_OUT_LEN) {
127676ecd4a3SAndrew Rybchenko uint8_t mode =
127776ecd4a3SAndrew Rybchenko MCDI_OUT_BYTE(req, GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE);
127876ecd4a3SAndrew Rybchenko
127976ecd4a3SAndrew Rybchenko switch (mode) {
128076ecd4a3SAndrew Rybchenko case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_8K:
128176ecd4a3SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_8K;
128276ecd4a3SAndrew Rybchenko break;
128376ecd4a3SAndrew Rybchenko case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_16K:
128476ecd4a3SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_16K;
128576ecd4a3SAndrew Rybchenko break;
128676ecd4a3SAndrew Rybchenko case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_64K:
128776ecd4a3SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_64K;
128876ecd4a3SAndrew Rybchenko break;
128976ecd4a3SAndrew Rybchenko default:
129076ecd4a3SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_INVALID;
129176ecd4a3SAndrew Rybchenko break;
129276ecd4a3SAndrew Rybchenko }
129376ecd4a3SAndrew Rybchenko } else if ((enp->en_family == EFX_FAMILY_HUNTINGTON) ||
129476ecd4a3SAndrew Rybchenko (enp->en_family == EFX_FAMILY_MEDFORD)) {
129576ecd4a3SAndrew Rybchenko /* Huntington and Medford have fixed 8K window size */
129676ecd4a3SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_8K;
129776ecd4a3SAndrew Rybchenko } else {
129876ecd4a3SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_INVALID;
129976ecd4a3SAndrew Rybchenko }
130076ecd4a3SAndrew Rybchenko
1301807145d9SAndrew Rybchenko /* Check if firmware supports extended MAC stats. */
1302807145d9SAndrew Rybchenko if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V4_OUT_LEN) {
1303807145d9SAndrew Rybchenko /* Extended stats buffer supported */
1304807145d9SAndrew Rybchenko encp->enc_mac_stats_nstats = MCDI_OUT_WORD(req,
1305807145d9SAndrew Rybchenko GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS);
1306807145d9SAndrew Rybchenko } else {
1307807145d9SAndrew Rybchenko /* Use Siena-compatible legacy MAC stats */
1308807145d9SAndrew Rybchenko encp->enc_mac_stats_nstats = MC_CMD_MAC_NSTATS;
1309807145d9SAndrew Rybchenko }
1310807145d9SAndrew Rybchenko
1311747819d2SAndrew Rybchenko if (encp->enc_mac_stats_nstats >= MC_CMD_MAC_NSTATS_V2)
1312747819d2SAndrew Rybchenko encp->enc_fec_counters = B_TRUE;
1313747819d2SAndrew Rybchenko else
1314747819d2SAndrew Rybchenko encp->enc_fec_counters = B_FALSE;
1315747819d2SAndrew Rybchenko
1316aea9d093SAndrew Rybchenko /* Check if the firmware provides head-of-line blocking counters */
1317aea9d093SAndrew Rybchenko if (CAP_FLAGS2(req, RXDP_HLB_IDLE))
1318aea9d093SAndrew Rybchenko encp->enc_hlb_counters = B_TRUE;
1319aea9d093SAndrew Rybchenko else
1320aea9d093SAndrew Rybchenko encp->enc_hlb_counters = B_FALSE;
1321aea9d093SAndrew Rybchenko
13225a51b32eSAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
1323fcfb73b8SAndrew Rybchenko if (CAP_FLAGS1(req, RX_RSS_LIMITED)) {
1324fcfb73b8SAndrew Rybchenko /* Only one exclusive RSS context is available per port. */
1325fcfb73b8SAndrew Rybchenko encp->enc_rx_scale_max_exclusive_contexts = 1;
1326fcfb73b8SAndrew Rybchenko
1327fcfb73b8SAndrew Rybchenko switch (enp->en_family) {
1328fcfb73b8SAndrew Rybchenko case EFX_FAMILY_MEDFORD2:
1329fcfb73b8SAndrew Rybchenko encp->enc_rx_scale_hash_alg_mask =
1330fcfb73b8SAndrew Rybchenko (1U << EFX_RX_HASHALG_TOEPLITZ);
1331fcfb73b8SAndrew Rybchenko break;
1332fcfb73b8SAndrew Rybchenko
1333fcfb73b8SAndrew Rybchenko case EFX_FAMILY_MEDFORD:
1334fcfb73b8SAndrew Rybchenko case EFX_FAMILY_HUNTINGTON:
1335fcfb73b8SAndrew Rybchenko /*
1336fcfb73b8SAndrew Rybchenko * Packed stream firmware variant maintains a
1337fcfb73b8SAndrew Rybchenko * non-standard algorithm for hash computation.
1338fcfb73b8SAndrew Rybchenko * It implies explicit XORing together
1339fcfb73b8SAndrew Rybchenko * source + destination IP addresses (or last
1340fcfb73b8SAndrew Rybchenko * four bytes in the case of IPv6) and using the
1341fcfb73b8SAndrew Rybchenko * resulting value as the input to a Toeplitz hash.
1342fcfb73b8SAndrew Rybchenko */
1343fcfb73b8SAndrew Rybchenko encp->enc_rx_scale_hash_alg_mask =
1344fcfb73b8SAndrew Rybchenko (1U << EFX_RX_HASHALG_PACKED_STREAM);
1345fcfb73b8SAndrew Rybchenko break;
1346fcfb73b8SAndrew Rybchenko
1347fcfb73b8SAndrew Rybchenko default:
1348fcfb73b8SAndrew Rybchenko rc = EINVAL;
1349fcfb73b8SAndrew Rybchenko goto fail5;
1350fcfb73b8SAndrew Rybchenko }
1351fcfb73b8SAndrew Rybchenko
1352fcfb73b8SAndrew Rybchenko /* Port numbers cannot contribute to the hash value */
1353fcfb73b8SAndrew Rybchenko encp->enc_rx_scale_l4_hash_supported = B_FALSE;
1354fcfb73b8SAndrew Rybchenko } else {
1355fcfb73b8SAndrew Rybchenko /*
1356fcfb73b8SAndrew Rybchenko * Maximum number of exclusive RSS contexts.
1357fcfb73b8SAndrew Rybchenko * EF10 hardware supports 64 in total, but 6 are reserved
1358fcfb73b8SAndrew Rybchenko * for shared contexts. They are a global resource so
1359fcfb73b8SAndrew Rybchenko * not all may be available.
1360fcfb73b8SAndrew Rybchenko */
1361fcfb73b8SAndrew Rybchenko encp->enc_rx_scale_max_exclusive_contexts = 64 - 6;
1362fcfb73b8SAndrew Rybchenko
1363fcfb73b8SAndrew Rybchenko encp->enc_rx_scale_hash_alg_mask =
1364fcfb73b8SAndrew Rybchenko (1U << EFX_RX_HASHALG_TOEPLITZ);
1365fcfb73b8SAndrew Rybchenko
1366fcfb73b8SAndrew Rybchenko /*
1367fcfb73b8SAndrew Rybchenko * It is possible to use port numbers as
1368fcfb73b8SAndrew Rybchenko * the input data for hash computation.
1369fcfb73b8SAndrew Rybchenko */
1370fcfb73b8SAndrew Rybchenko encp->enc_rx_scale_l4_hash_supported = B_TRUE;
1371fcfb73b8SAndrew Rybchenko }
13725a51b32eSAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
13735a51b32eSAndrew Rybchenko
13746e1ebbe9SAndrew Rybchenko /* Check if the firmware supports "FLAG" and "MARK" filter actions */
13756e1ebbe9SAndrew Rybchenko if (CAP_FLAGS2(req, FILTER_ACTION_FLAG))
13766e1ebbe9SAndrew Rybchenko encp->enc_filter_action_flag_supported = B_TRUE;
13776e1ebbe9SAndrew Rybchenko else
13786e1ebbe9SAndrew Rybchenko encp->enc_filter_action_flag_supported = B_FALSE;
13796e1ebbe9SAndrew Rybchenko
13806e1ebbe9SAndrew Rybchenko if (CAP_FLAGS2(req, FILTER_ACTION_MARK))
13816e1ebbe9SAndrew Rybchenko encp->enc_filter_action_mark_supported = B_TRUE;
13826e1ebbe9SAndrew Rybchenko else
13836e1ebbe9SAndrew Rybchenko encp->enc_filter_action_mark_supported = B_FALSE;
1384fcfb73b8SAndrew Rybchenko
13855c2f9d6aSAndrew Rybchenko /* Get maximum supported value for "MARK" filter action */
13865c2f9d6aSAndrew Rybchenko if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V5_OUT_LEN)
13875c2f9d6aSAndrew Rybchenko encp->enc_filter_action_mark_max = MCDI_OUT_DWORD(req,
13885c2f9d6aSAndrew Rybchenko GET_CAPABILITIES_V5_OUT_FILTER_ACTION_MARK_MAX);
13895c2f9d6aSAndrew Rybchenko else
13905c2f9d6aSAndrew Rybchenko encp->enc_filter_action_mark_max = 0;
13915c2f9d6aSAndrew Rybchenko
1392016941e3SAndrew Rybchenko #undef CAP_FLAGS1
1393016941e3SAndrew Rybchenko #undef CAP_FLAGS2
139431bf5f03SAndrew Rybchenko
139531bf5f03SAndrew Rybchenko return (0);
139631bf5f03SAndrew Rybchenko
13975a51b32eSAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
1398fcfb73b8SAndrew Rybchenko fail5:
1399fcfb73b8SAndrew Rybchenko EFSYS_PROBE(fail5);
14005a51b32eSAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
1401016941e3SAndrew Rybchenko fail4:
1402016941e3SAndrew Rybchenko EFSYS_PROBE(fail4);
1403016941e3SAndrew Rybchenko fail3:
1404016941e3SAndrew Rybchenko EFSYS_PROBE(fail3);
140531bf5f03SAndrew Rybchenko fail2:
140631bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
140731bf5f03SAndrew Rybchenko fail1:
140831bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
140931bf5f03SAndrew Rybchenko
141031bf5f03SAndrew Rybchenko return (rc);
141131bf5f03SAndrew Rybchenko }
141231bf5f03SAndrew Rybchenko
1413d5bd0d6bSAndrew Rybchenko #define EF10_LEGACY_PF_PRIVILEGE_MASK \
1414d5bd0d6bSAndrew Rybchenko (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN | \
1415d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK | \
1416d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD | \
1417d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP | \
1418d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS | \
1419d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING | \
1420d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST | \
1421d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST | \
1422d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST | \
1423d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST | \
1424d5bd0d6bSAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS)
1425d5bd0d6bSAndrew Rybchenko
1426d5bd0d6bSAndrew Rybchenko #define EF10_LEGACY_VF_PRIVILEGE_MASK 0
1427d5bd0d6bSAndrew Rybchenko
142831bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_get_privilege_mask(__in efx_nic_t * enp,__out uint32_t * maskp)142931bf5f03SAndrew Rybchenko ef10_get_privilege_mask(
143031bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
143131bf5f03SAndrew Rybchenko __out uint32_t *maskp)
143231bf5f03SAndrew Rybchenko {
143331bf5f03SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
143431bf5f03SAndrew Rybchenko uint32_t mask;
143531bf5f03SAndrew Rybchenko efx_rc_t rc;
143631bf5f03SAndrew Rybchenko
143731bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
143831bf5f03SAndrew Rybchenko &mask)) != 0) {
143931bf5f03SAndrew Rybchenko if (rc != ENOTSUP)
144031bf5f03SAndrew Rybchenko goto fail1;
144131bf5f03SAndrew Rybchenko
144231bf5f03SAndrew Rybchenko /* Fallback for old firmware without privilege mask support */
144331bf5f03SAndrew Rybchenko if (EFX_PCI_FUNCTION_IS_PF(encp)) {
144431bf5f03SAndrew Rybchenko /* Assume PF has admin privilege */
144531bf5f03SAndrew Rybchenko mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
144631bf5f03SAndrew Rybchenko } else {
144731bf5f03SAndrew Rybchenko /* VF is always unprivileged by default */
144831bf5f03SAndrew Rybchenko mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
144931bf5f03SAndrew Rybchenko }
145031bf5f03SAndrew Rybchenko }
145131bf5f03SAndrew Rybchenko
145231bf5f03SAndrew Rybchenko *maskp = mask;
145331bf5f03SAndrew Rybchenko
145431bf5f03SAndrew Rybchenko return (0);
145531bf5f03SAndrew Rybchenko
145631bf5f03SAndrew Rybchenko fail1:
145731bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
145831bf5f03SAndrew Rybchenko
145931bf5f03SAndrew Rybchenko return (rc);
146031bf5f03SAndrew Rybchenko }
146131bf5f03SAndrew Rybchenko
1462*f0a2945dSAndrew Rybchenko #define EFX_EXT_PORT_MAX 4
1463*f0a2945dSAndrew Rybchenko #define EFX_EXT_PORT_NA 0xFF
1464*f0a2945dSAndrew Rybchenko
146531bf5f03SAndrew Rybchenko /*
14668da3f86bSAndrew Rybchenko * Table of mapping schemes from port number to external number.
1467b36a7ad2SAndrew Rybchenko *
14688da3f86bSAndrew Rybchenko * Each port number ultimately corresponds to a connector: either as part of
14698da3f86bSAndrew Rybchenko * a cable assembly attached to a module inserted in an SFP+/QSFP+ cage on
14708da3f86bSAndrew Rybchenko * the board, or fixed to the board (e.g. 10GBASE-T magjack on SFN5121T
14718da3f86bSAndrew Rybchenko * "Salina"). In general:
14728da3f86bSAndrew Rybchenko *
14738da3f86bSAndrew Rybchenko * Port number (0-based)
14748da3f86bSAndrew Rybchenko * |
14758da3f86bSAndrew Rybchenko * port mapping (n:1)
14768da3f86bSAndrew Rybchenko * |
14778da3f86bSAndrew Rybchenko * v
1478*f0a2945dSAndrew Rybchenko * External port number (1-based)
14798da3f86bSAndrew Rybchenko * |
14808da3f86bSAndrew Rybchenko * fixed (1:1) or cable assembly (1:m)
14818da3f86bSAndrew Rybchenko * |
14828da3f86bSAndrew Rybchenko * v
14838da3f86bSAndrew Rybchenko * Connector
14848da3f86bSAndrew Rybchenko *
14858da3f86bSAndrew Rybchenko * The external numbering refers to the cages or magjacks on the board,
14868da3f86bSAndrew Rybchenko * as visibly annotated on the board or back panel. This table describes
14878da3f86bSAndrew Rybchenko * how to determine which external cage/magjack corresponds to the port
14888da3f86bSAndrew Rybchenko * numbers used by the driver.
14898da3f86bSAndrew Rybchenko *
1490*f0a2945dSAndrew Rybchenko * The count of consecutive port numbers that map to each external number,
1491*f0a2945dSAndrew Rybchenko * is determined by the chip family and the current port mode.
1492b36a7ad2SAndrew Rybchenko *
1493b36a7ad2SAndrew Rybchenko * For the Huntington family, the current port mode cannot be discovered,
14948da3f86bSAndrew Rybchenko * but a single mapping is used by all modes for a given chip variant,
1495b36a7ad2SAndrew Rybchenko * so the mapping used is instead the last match in the table to the full
1496b36a7ad2SAndrew Rybchenko * set of port modes to which the NIC can be configured. Therefore the
14978da3f86bSAndrew Rybchenko * ordering of entries in the mapping table is significant.
149831bf5f03SAndrew Rybchenko */
14998da3f86bSAndrew Rybchenko static struct ef10_external_port_map_s {
150031bf5f03SAndrew Rybchenko efx_family_t family;
150131bf5f03SAndrew Rybchenko uint32_t modes_mask;
1502*f0a2945dSAndrew Rybchenko uint8_t base_port[EFX_EXT_PORT_MAX];
150331bf5f03SAndrew Rybchenko } __ef10_external_port_mappings[] = {
15048da3f86bSAndrew Rybchenko /*
15058da3f86bSAndrew Rybchenko * Modes used by Huntington family controllers where each port
15068da3f86bSAndrew Rybchenko * number maps to a separate cage.
15078da3f86bSAndrew Rybchenko * SFN7x22F (Torino):
15088da3f86bSAndrew Rybchenko * port 0 -> cage 1
15098da3f86bSAndrew Rybchenko * port 1 -> cage 2
15108da3f86bSAndrew Rybchenko * SFN7xx4F (Pavia):
15118da3f86bSAndrew Rybchenko * port 0 -> cage 1
15128da3f86bSAndrew Rybchenko * port 1 -> cage 2
15138da3f86bSAndrew Rybchenko * port 2 -> cage 3
15148da3f86bSAndrew Rybchenko * port 3 -> cage 4
15158da3f86bSAndrew Rybchenko */
151631bf5f03SAndrew Rybchenko {
151731bf5f03SAndrew Rybchenko EFX_FAMILY_HUNTINGTON,
1518b14569a4SAndrew Rybchenko (1U << TLV_PORT_MODE_10G) | /* mode 0 */
1519b14569a4SAndrew Rybchenko (1U << TLV_PORT_MODE_10G_10G) | /* mode 2 */
1520b14569a4SAndrew Rybchenko (1U << TLV_PORT_MODE_10G_10G_10G_10G), /* mode 4 */
1521*f0a2945dSAndrew Rybchenko { 0, 1, 2, 3 }
152231bf5f03SAndrew Rybchenko },
15238da3f86bSAndrew Rybchenko /*
15248da3f86bSAndrew Rybchenko * Modes which for Huntington identify a chip variant where 2
15258da3f86bSAndrew Rybchenko * adjacent port numbers map to each cage.
15268da3f86bSAndrew Rybchenko * SFN7x42Q (Monza):
15278da3f86bSAndrew Rybchenko * port 0 -> cage 1
15288da3f86bSAndrew Rybchenko * port 1 -> cage 1
15298da3f86bSAndrew Rybchenko * port 2 -> cage 2
15308da3f86bSAndrew Rybchenko * port 3 -> cage 2
15318da3f86bSAndrew Rybchenko */
153231bf5f03SAndrew Rybchenko {
153331bf5f03SAndrew Rybchenko EFX_FAMILY_HUNTINGTON,
1534b14569a4SAndrew Rybchenko (1U << TLV_PORT_MODE_40G) | /* mode 1 */
1535b14569a4SAndrew Rybchenko (1U << TLV_PORT_MODE_40G_40G) | /* mode 3 */
1536b14569a4SAndrew Rybchenko (1U << TLV_PORT_MODE_40G_10G_10G) | /* mode 6 */
1537b14569a4SAndrew Rybchenko (1U << TLV_PORT_MODE_10G_10G_40G), /* mode 7 */
1538*f0a2945dSAndrew Rybchenko { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
153931bf5f03SAndrew Rybchenko },
15408da3f86bSAndrew Rybchenko /*
1541259a7b37SAndrew Rybchenko * Modes that on Medford allocate each port number to a separate
1542259a7b37SAndrew Rybchenko * cage.
1543259a7b37SAndrew Rybchenko * port 0 -> cage 1
1544259a7b37SAndrew Rybchenko * port 1 -> cage 2
1545259a7b37SAndrew Rybchenko * port 2 -> cage 3
1546259a7b37SAndrew Rybchenko * port 3 -> cage 4
1547259a7b37SAndrew Rybchenko */
1548259a7b37SAndrew Rybchenko {
1549259a7b37SAndrew Rybchenko EFX_FAMILY_MEDFORD,
1550e12a751bSAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_NA) | /* mode 0 */
1551e12a751bSAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_1x1), /* mode 2 */
1552*f0a2945dSAndrew Rybchenko { 0, 1, 2, 3 }
1553259a7b37SAndrew Rybchenko },
1554259a7b37SAndrew Rybchenko /*
15558da3f86bSAndrew Rybchenko * Modes that on Medford allocate 2 adjacent port numbers to each
15568da3f86bSAndrew Rybchenko * cage.
15578da3f86bSAndrew Rybchenko * port 0 -> cage 1
15588da3f86bSAndrew Rybchenko * port 1 -> cage 1
15598da3f86bSAndrew Rybchenko * port 2 -> cage 2
15608da3f86bSAndrew Rybchenko * port 3 -> cage 2
15618da3f86bSAndrew Rybchenko */
156231bf5f03SAndrew Rybchenko {
156331bf5f03SAndrew Rybchenko EFX_FAMILY_MEDFORD,
1564e12a751bSAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */
1565e12a751bSAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */
1566e12a751bSAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_2x1) | /* mode 6 */
1567e12a751bSAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_1x4) | /* mode 7 */
1568b14569a4SAndrew Rybchenko /* Do not use 10G_10G_10G_10G_Q1_Q2 (see bug63270) */
1569b14569a4SAndrew Rybchenko (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2), /* mode 9 */
1570*f0a2945dSAndrew Rybchenko { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
157131bf5f03SAndrew Rybchenko },
15728da3f86bSAndrew Rybchenko /*
15738da3f86bSAndrew Rybchenko * Modes that on Medford allocate 4 adjacent port numbers to each
15748da3f86bSAndrew Rybchenko * connector, starting on cage 1.
15758da3f86bSAndrew Rybchenko * port 0 -> cage 1
15768da3f86bSAndrew Rybchenko * port 1 -> cage 1
15778da3f86bSAndrew Rybchenko * port 2 -> cage 1
15788da3f86bSAndrew Rybchenko * port 3 -> cage 1
15798da3f86bSAndrew Rybchenko */
158031bf5f03SAndrew Rybchenko {
158131bf5f03SAndrew Rybchenko EFX_FAMILY_MEDFORD,
1582e12a751bSAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_2x1) | /* mode 5 */
1583b14569a4SAndrew Rybchenko /* Do not use 10G_10G_10G_10G_Q1 (see bug63270) */
1584e12a751bSAndrew Rybchenko (1U << TLV_PORT_MODE_4x1_NA), /* mode 4 */
1585*f0a2945dSAndrew Rybchenko { 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
1586b36a7ad2SAndrew Rybchenko },
15878da3f86bSAndrew Rybchenko /*
15888da3f86bSAndrew Rybchenko * Modes that on Medford allocate 4 adjacent port numbers to each
15898da3f86bSAndrew Rybchenko * connector, starting on cage 2.
15908da3f86bSAndrew Rybchenko * port 0 -> cage 2
15918da3f86bSAndrew Rybchenko * port 1 -> cage 2
15928da3f86bSAndrew Rybchenko * port 2 -> cage 2
15938da3f86bSAndrew Rybchenko * port 3 -> cage 2
15948da3f86bSAndrew Rybchenko */
1595b36a7ad2SAndrew Rybchenko {
1596b36a7ad2SAndrew Rybchenko EFX_FAMILY_MEDFORD,
1597e12a751bSAndrew Rybchenko (1U << TLV_PORT_MODE_NA_4x1), /* mode 8 */
1598*f0a2945dSAndrew Rybchenko { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
159931bf5f03SAndrew Rybchenko },
1600f83ec516SAndrew Rybchenko /*
1601f83ec516SAndrew Rybchenko * Modes that on Medford2 allocate each port number to a separate
1602f83ec516SAndrew Rybchenko * cage.
1603f83ec516SAndrew Rybchenko * port 0 -> cage 1
1604f83ec516SAndrew Rybchenko * port 1 -> cage 2
1605f83ec516SAndrew Rybchenko * port 2 -> cage 3
1606f83ec516SAndrew Rybchenko * port 3 -> cage 4
1607f83ec516SAndrew Rybchenko */
1608f83ec516SAndrew Rybchenko {
1609f83ec516SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
1610f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_NA) | /* mode 0 */
1611f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */
1612f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_1x1) | /* mode 2 */
1613f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_1x2_NA) | /* mode 10 */
1614f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_1x2_1x2) | /* mode 12 */
1615f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_1x2) | /* mode 15 */
1616f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_1x2_1x4), /* mode 16 */
1617*f0a2945dSAndrew Rybchenko { 0, 1, 2, 3 }
1618f83ec516SAndrew Rybchenko },
1619f83ec516SAndrew Rybchenko /*
1620*f0a2945dSAndrew Rybchenko * Modes that on Medford2 allocate 1 port to cage 1 and the rest
1621*f0a2945dSAndrew Rybchenko * to cage 2.
1622f83ec516SAndrew Rybchenko * port 0 -> cage 1
1623f83ec516SAndrew Rybchenko * port 1 -> cage 2
1624f83ec516SAndrew Rybchenko * port 2 -> cage 2
1625f83ec516SAndrew Rybchenko */
1626*f0a2945dSAndrew Rybchenko {
1627*f0a2945dSAndrew Rybchenko EFX_FAMILY_MEDFORD2,
1628*f0a2945dSAndrew Rybchenko (1U << TLV_PORT_MODE_1x2_2x1) | /* mode 17 */
1629*f0a2945dSAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_2x1), /* mode 6 */
1630*f0a2945dSAndrew Rybchenko { 0, 1, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
1631*f0a2945dSAndrew Rybchenko },
1632f83ec516SAndrew Rybchenko /*
1633f83ec516SAndrew Rybchenko * Modes that on Medford2 allocate 2 adjacent port numbers to each
1634f83ec516SAndrew Rybchenko * cage, starting on cage 1.
1635f83ec516SAndrew Rybchenko * port 0 -> cage 1
1636f83ec516SAndrew Rybchenko * port 1 -> cage 1
1637f83ec516SAndrew Rybchenko * port 2 -> cage 2
1638f83ec516SAndrew Rybchenko * port 3 -> cage 2
1639f83ec516SAndrew Rybchenko */
1640f83ec516SAndrew Rybchenko {
1641f83ec516SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
1642f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */
1643f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_2x1) | /* mode 4 */
1644f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_2x1) | /* mode 6 */
1645f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_1x4) | /* mode 7 */
1646f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_2x2_NA) | /* mode 13 */
1647f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_1x2), /* mode 18 */
1648*f0a2945dSAndrew Rybchenko { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
1649f83ec516SAndrew Rybchenko },
1650f83ec516SAndrew Rybchenko /*
1651f83ec516SAndrew Rybchenko * Modes that on Medford2 allocate 2 adjacent port numbers to each
1652f83ec516SAndrew Rybchenko * cage, starting on cage 2.
1653f83ec516SAndrew Rybchenko * port 0 -> cage 2
1654f83ec516SAndrew Rybchenko * port 1 -> cage 2
1655f83ec516SAndrew Rybchenko */
1656f83ec516SAndrew Rybchenko {
1657f83ec516SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
1658f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_NA_2x2), /* mode 14 */
1659*f0a2945dSAndrew Rybchenko { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
1660f83ec516SAndrew Rybchenko },
1661f83ec516SAndrew Rybchenko /*
1662f83ec516SAndrew Rybchenko * Modes that on Medford2 allocate 4 adjacent port numbers to each
1663f83ec516SAndrew Rybchenko * connector, starting on cage 1.
1664f83ec516SAndrew Rybchenko * port 0 -> cage 1
1665f83ec516SAndrew Rybchenko * port 1 -> cage 1
1666f83ec516SAndrew Rybchenko * port 2 -> cage 1
1667f83ec516SAndrew Rybchenko * port 3 -> cage 1
1668f83ec516SAndrew Rybchenko */
1669f83ec516SAndrew Rybchenko {
1670f83ec516SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
1671f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_4x1_NA), /* mode 5 */
1672*f0a2945dSAndrew Rybchenko { 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
1673f83ec516SAndrew Rybchenko },
1674f83ec516SAndrew Rybchenko /*
1675f83ec516SAndrew Rybchenko * Modes that on Medford2 allocate 4 adjacent port numbers to each
1676f83ec516SAndrew Rybchenko * connector, starting on cage 2.
1677f83ec516SAndrew Rybchenko * port 0 -> cage 2
1678f83ec516SAndrew Rybchenko * port 1 -> cage 2
1679f83ec516SAndrew Rybchenko * port 2 -> cage 2
1680f83ec516SAndrew Rybchenko * port 3 -> cage 2
1681f83ec516SAndrew Rybchenko */
1682f83ec516SAndrew Rybchenko {
1683f83ec516SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
1684f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_NA_4x1) | /* mode 8 */
1685f83ec516SAndrew Rybchenko (1U << TLV_PORT_MODE_NA_1x2), /* mode 11 */
1686*f0a2945dSAndrew Rybchenko { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
1687f83ec516SAndrew Rybchenko },
168831bf5f03SAndrew Rybchenko };
168931bf5f03SAndrew Rybchenko
169009eac957SAndrew Rybchenko static __checkReturn efx_rc_t
ef10_external_port_mapping(__in efx_nic_t * enp,__in uint32_t port,__out uint8_t * external_portp)169131bf5f03SAndrew Rybchenko ef10_external_port_mapping(
169231bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
169331bf5f03SAndrew Rybchenko __in uint32_t port,
169431bf5f03SAndrew Rybchenko __out uint8_t *external_portp)
169531bf5f03SAndrew Rybchenko {
169631bf5f03SAndrew Rybchenko efx_rc_t rc;
169731bf5f03SAndrew Rybchenko int i;
169831bf5f03SAndrew Rybchenko uint32_t port_modes;
169931bf5f03SAndrew Rybchenko uint32_t matches;
1700b36a7ad2SAndrew Rybchenko uint32_t current;
1701*f0a2945dSAndrew Rybchenko struct ef10_external_port_map_s *mapp = NULL;
1702*f0a2945dSAndrew Rybchenko int ext_index = port; /* Default 1-1 mapping */
170331bf5f03SAndrew Rybchenko
1704cd5e3371SAndrew Rybchenko if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, ¤t,
1705cd5e3371SAndrew Rybchenko NULL)) != 0) {
1706b36a7ad2SAndrew Rybchenko /*
17078da3f86bSAndrew Rybchenko * No current port mode information (i.e. Huntington)
1708b36a7ad2SAndrew Rybchenko * - infer mapping from available modes
1709b36a7ad2SAndrew Rybchenko */
1710b36a7ad2SAndrew Rybchenko if ((rc = efx_mcdi_get_port_modes(enp,
1711cd5e3371SAndrew Rybchenko &port_modes, NULL, NULL)) != 0) {
1712b36a7ad2SAndrew Rybchenko /*
1713b36a7ad2SAndrew Rybchenko * No port mode information available
1714b36a7ad2SAndrew Rybchenko * - use default mapping
1715b36a7ad2SAndrew Rybchenko */
171631bf5f03SAndrew Rybchenko goto out;
171731bf5f03SAndrew Rybchenko }
1718b36a7ad2SAndrew Rybchenko } else {
1719b36a7ad2SAndrew Rybchenko /* Only need to scan the current mode */
1720b36a7ad2SAndrew Rybchenko port_modes = 1 << current;
1721b36a7ad2SAndrew Rybchenko }
172231bf5f03SAndrew Rybchenko
172331bf5f03SAndrew Rybchenko /*
17248da3f86bSAndrew Rybchenko * Infer the internal port -> external number mapping from
172531bf5f03SAndrew Rybchenko * the possible port modes for this NIC.
172631bf5f03SAndrew Rybchenko */
172731bf5f03SAndrew Rybchenko for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
17288da3f86bSAndrew Rybchenko struct ef10_external_port_map_s *eepmp =
17298da3f86bSAndrew Rybchenko &__ef10_external_port_mappings[i];
17308da3f86bSAndrew Rybchenko if (eepmp->family != enp->en_family)
173131bf5f03SAndrew Rybchenko continue;
17328da3f86bSAndrew Rybchenko matches = (eepmp->modes_mask & port_modes);
173331bf5f03SAndrew Rybchenko if (matches != 0) {
17348da3f86bSAndrew Rybchenko /*
17358da3f86bSAndrew Rybchenko * Some modes match. For some Huntington boards
17368da3f86bSAndrew Rybchenko * there will be multiple matches. The mapping on the
17378da3f86bSAndrew Rybchenko * last match is used.
17388da3f86bSAndrew Rybchenko */
1739*f0a2945dSAndrew Rybchenko mapp = eepmp;
174031bf5f03SAndrew Rybchenko port_modes &= ~matches;
174131bf5f03SAndrew Rybchenko }
174231bf5f03SAndrew Rybchenko }
174331bf5f03SAndrew Rybchenko
174431bf5f03SAndrew Rybchenko if (port_modes != 0) {
174531bf5f03SAndrew Rybchenko /* Some advertised modes are not supported */
174631bf5f03SAndrew Rybchenko rc = ENOTSUP;
174731bf5f03SAndrew Rybchenko goto fail1;
174831bf5f03SAndrew Rybchenko }
174931bf5f03SAndrew Rybchenko
175031bf5f03SAndrew Rybchenko out:
1751*f0a2945dSAndrew Rybchenko if (mapp != NULL) {
175231bf5f03SAndrew Rybchenko /*
1753*f0a2945dSAndrew Rybchenko * External ports are assigned a sequence of consecutive
1754*f0a2945dSAndrew Rybchenko * port numbers, so find the one with the closest base_port.
175531bf5f03SAndrew Rybchenko */
1756*f0a2945dSAndrew Rybchenko uint32_t delta = EFX_EXT_PORT_NA;
1757*f0a2945dSAndrew Rybchenko
1758*f0a2945dSAndrew Rybchenko for (i = 0; i < EFX_EXT_PORT_MAX; i++) {
1759*f0a2945dSAndrew Rybchenko uint32_t base = mapp->base_port[i];
1760*f0a2945dSAndrew Rybchenko if ((base != EFX_EXT_PORT_NA) && (base <= port)) {
1761*f0a2945dSAndrew Rybchenko if ((port - base) < delta) {
1762*f0a2945dSAndrew Rybchenko delta = (port - base);
1763*f0a2945dSAndrew Rybchenko ext_index = i;
1764*f0a2945dSAndrew Rybchenko }
1765*f0a2945dSAndrew Rybchenko }
1766*f0a2945dSAndrew Rybchenko }
1767*f0a2945dSAndrew Rybchenko }
1768*f0a2945dSAndrew Rybchenko *external_portp = (uint8_t)(ext_index + 1);
1769*f0a2945dSAndrew Rybchenko
177031bf5f03SAndrew Rybchenko return (0);
177131bf5f03SAndrew Rybchenko
177231bf5f03SAndrew Rybchenko fail1:
177331bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
177431bf5f03SAndrew Rybchenko
177531bf5f03SAndrew Rybchenko return (rc);
177631bf5f03SAndrew Rybchenko }
177731bf5f03SAndrew Rybchenko
177848194339SAndrew Rybchenko static __checkReturn efx_rc_t
ef10_nic_board_cfg(__in efx_nic_t * enp)177948194339SAndrew Rybchenko ef10_nic_board_cfg(
178048194339SAndrew Rybchenko __in efx_nic_t *enp)
178148194339SAndrew Rybchenko {
178248194339SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
178309eac957SAndrew Rybchenko efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
178409eac957SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1785e5f6f32fSAndrew Rybchenko ef10_link_state_t els;
1786e5f6f32fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
1787233c1e5eSAndrew Rybchenko uint32_t board_type = 0;
178861e0c16dSAndrew Rybchenko uint32_t base, nvec;
178909eac957SAndrew Rybchenko uint32_t port;
179026fcca57SAndrew Rybchenko uint32_t mask;
179117f272e7SAndrew Rybchenko uint32_t pf;
179217f272e7SAndrew Rybchenko uint32_t vf;
1793d36ea92cSAndrew Rybchenko uint8_t mac_addr[6] = { 0 };
179448194339SAndrew Rybchenko efx_rc_t rc;
179548194339SAndrew Rybchenko
179609eac957SAndrew Rybchenko /* Get the (zero-based) MCDI port number */
179709eac957SAndrew Rybchenko if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0)
179809eac957SAndrew Rybchenko goto fail1;
179909eac957SAndrew Rybchenko
180009eac957SAndrew Rybchenko /* EFX MCDI interface uses one-based port numbers */
180109eac957SAndrew Rybchenko emip->emi_port = port + 1;
180209eac957SAndrew Rybchenko
180309eac957SAndrew Rybchenko if ((rc = ef10_external_port_mapping(enp, port,
180409eac957SAndrew Rybchenko &encp->enc_external_port)) != 0)
180509eac957SAndrew Rybchenko goto fail2;
180609eac957SAndrew Rybchenko
180717f272e7SAndrew Rybchenko /*
180817f272e7SAndrew Rybchenko * Get PCIe function number from firmware (used for
180917f272e7SAndrew Rybchenko * per-function privilege and dynamic config info).
181017f272e7SAndrew Rybchenko * - PCIe PF: pf = PF number, vf = 0xffff.
181117f272e7SAndrew Rybchenko * - PCIe VF: pf = parent PF, vf = VF number.
181217f272e7SAndrew Rybchenko */
181317f272e7SAndrew Rybchenko if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0)
181417f272e7SAndrew Rybchenko goto fail3;
181517f272e7SAndrew Rybchenko
181617f272e7SAndrew Rybchenko encp->enc_pf = pf;
181717f272e7SAndrew Rybchenko encp->enc_vf = vf;
181817f272e7SAndrew Rybchenko
1819d36ea92cSAndrew Rybchenko /* MAC address for this function */
1820d36ea92cSAndrew Rybchenko if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1821d36ea92cSAndrew Rybchenko rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
1822d36ea92cSAndrew Rybchenko #if EFSYS_OPT_ALLOW_UNCONFIGURED_NIC
1823d36ea92cSAndrew Rybchenko /*
1824d36ea92cSAndrew Rybchenko * Disable static config checking, ONLY for manufacturing test
1825d36ea92cSAndrew Rybchenko * and setup at the factory, to allow the static config to be
1826d36ea92cSAndrew Rybchenko * installed.
1827d36ea92cSAndrew Rybchenko */
1828d36ea92cSAndrew Rybchenko #else /* EFSYS_OPT_ALLOW_UNCONFIGURED_NIC */
1829d36ea92cSAndrew Rybchenko if ((rc == 0) && (mac_addr[0] & 0x02)) {
1830d36ea92cSAndrew Rybchenko /*
1831d36ea92cSAndrew Rybchenko * If the static config does not include a global MAC
1832d36ea92cSAndrew Rybchenko * address pool then the board may return a locally
1833d36ea92cSAndrew Rybchenko * administered MAC address (this should only happen on
1834d36ea92cSAndrew Rybchenko * incorrectly programmed boards).
1835d36ea92cSAndrew Rybchenko */
1836d36ea92cSAndrew Rybchenko rc = EINVAL;
1837d36ea92cSAndrew Rybchenko }
1838d36ea92cSAndrew Rybchenko #endif /* EFSYS_OPT_ALLOW_UNCONFIGURED_NIC */
1839d36ea92cSAndrew Rybchenko } else {
1840d36ea92cSAndrew Rybchenko rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
1841d36ea92cSAndrew Rybchenko }
1842d36ea92cSAndrew Rybchenko if (rc != 0)
1843d36ea92cSAndrew Rybchenko goto fail4;
1844d36ea92cSAndrew Rybchenko
1845d36ea92cSAndrew Rybchenko EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
1846d36ea92cSAndrew Rybchenko
1847233c1e5eSAndrew Rybchenko /* Board configuration (legacy) */
1848233c1e5eSAndrew Rybchenko rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL);
1849233c1e5eSAndrew Rybchenko if (rc != 0) {
1850233c1e5eSAndrew Rybchenko /* Unprivileged functions may not be able to read board cfg */
1851233c1e5eSAndrew Rybchenko if (rc == EACCES)
1852233c1e5eSAndrew Rybchenko board_type = 0;
1853233c1e5eSAndrew Rybchenko else
1854233c1e5eSAndrew Rybchenko goto fail5;
1855233c1e5eSAndrew Rybchenko }
1856233c1e5eSAndrew Rybchenko
1857233c1e5eSAndrew Rybchenko encp->enc_board_type = board_type;
1858233c1e5eSAndrew Rybchenko encp->enc_clk_mult = 1; /* not used for EF10 */
1859233c1e5eSAndrew Rybchenko
1860e5f6f32fSAndrew Rybchenko /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
1861e5f6f32fSAndrew Rybchenko if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
1862e5f6f32fSAndrew Rybchenko goto fail6;
1863e5f6f32fSAndrew Rybchenko
18643f3f5d85SAndrew Rybchenko /*
18653f3f5d85SAndrew Rybchenko * Firmware with support for *_FEC capability bits does not
18663f3f5d85SAndrew Rybchenko * report that the corresponding *_FEC_REQUESTED bits are supported.
18673f3f5d85SAndrew Rybchenko * Add them here so that drivers understand that they are supported.
18683f3f5d85SAndrew Rybchenko */
18693f3f5d85SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1u << EFX_PHY_CAP_BASER_FEC))
18703f3f5d85SAndrew Rybchenko epp->ep_phy_cap_mask |=
18713f3f5d85SAndrew Rybchenko (1u << EFX_PHY_CAP_BASER_FEC_REQUESTED);
18723f3f5d85SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1u << EFX_PHY_CAP_RS_FEC))
18733f3f5d85SAndrew Rybchenko epp->ep_phy_cap_mask |=
18743f3f5d85SAndrew Rybchenko (1u << EFX_PHY_CAP_RS_FEC_REQUESTED);
18753f3f5d85SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1u << EFX_PHY_CAP_25G_BASER_FEC))
18763f3f5d85SAndrew Rybchenko epp->ep_phy_cap_mask |=
18773f3f5d85SAndrew Rybchenko (1u << EFX_PHY_CAP_25G_BASER_FEC_REQUESTED);
18783f3f5d85SAndrew Rybchenko
1879e5f6f32fSAndrew Rybchenko /* Obtain the default PHY advertised capabilities */
1880e5f6f32fSAndrew Rybchenko if ((rc = ef10_phy_get_link(enp, &els)) != 0)
1881e5f6f32fSAndrew Rybchenko goto fail7;
1882cf94ca37SAndrew Rybchenko epp->ep_default_adv_cap_mask = els.epls.epls_adv_cap_mask;
1883cf94ca37SAndrew Rybchenko epp->ep_adv_cap_mask = els.epls.epls_adv_cap_mask;
1884e5f6f32fSAndrew Rybchenko
1885deeaf87fSAndrew Rybchenko /* Check capabilities of running datapath firmware */
1886deeaf87fSAndrew Rybchenko if ((rc = ef10_get_datapath_caps(enp)) != 0)
1887deeaf87fSAndrew Rybchenko goto fail8;
1888deeaf87fSAndrew Rybchenko
188969aff9bbSAndrew Rybchenko /* Alignment for WPTR updates */
189069aff9bbSAndrew Rybchenko encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
189169aff9bbSAndrew Rybchenko
189240f5e54cSAndrew Rybchenko encp->enc_tx_dma_desc_size_max = EFX_MASK32(ESF_DZ_RX_KER_BYTE_CNT);
189340f5e54cSAndrew Rybchenko /* No boundary crossing limits */
189440f5e54cSAndrew Rybchenko encp->enc_tx_dma_desc_boundary = 0;
189540f5e54cSAndrew Rybchenko
189640f5e54cSAndrew Rybchenko /*
189740f5e54cSAndrew Rybchenko * Maximum number of bytes into the frame the TCP header can start for
189840f5e54cSAndrew Rybchenko * firmware assisted TSO to work.
189940f5e54cSAndrew Rybchenko */
190040f5e54cSAndrew Rybchenko encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT;
190140f5e54cSAndrew Rybchenko
1902ff8ff866SAndrew Rybchenko /*
1903ff8ff866SAndrew Rybchenko * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
1904ff8ff866SAndrew Rybchenko * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
1905ff8ff866SAndrew Rybchenko * resources (allocated to this PCIe function), which is zero until
1906ff8ff866SAndrew Rybchenko * after we have allocated VIs.
1907ff8ff866SAndrew Rybchenko */
1908ff8ff866SAndrew Rybchenko encp->enc_evq_limit = 1024;
1909ff8ff866SAndrew Rybchenko encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
1910ff8ff866SAndrew Rybchenko encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
1911ff8ff866SAndrew Rybchenko
1912ff8ff866SAndrew Rybchenko encp->enc_buftbl_limit = 0xFFFFFFFF;
191369aff9bbSAndrew Rybchenko
191461e0c16dSAndrew Rybchenko /* Get interrupt vector limits */
191561e0c16dSAndrew Rybchenko if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
191661e0c16dSAndrew Rybchenko if (EFX_PCI_FUNCTION_IS_PF(encp))
191761e0c16dSAndrew Rybchenko goto fail9;
191861e0c16dSAndrew Rybchenko
191961e0c16dSAndrew Rybchenko /* Ignore error (cannot query vector limits from a VF). */
192061e0c16dSAndrew Rybchenko base = 0;
192161e0c16dSAndrew Rybchenko nvec = 1024;
192261e0c16dSAndrew Rybchenko }
192361e0c16dSAndrew Rybchenko encp->enc_intr_vec_base = base;
192461e0c16dSAndrew Rybchenko encp->enc_intr_limit = nvec;
192561e0c16dSAndrew Rybchenko
192626fcca57SAndrew Rybchenko /*
192726fcca57SAndrew Rybchenko * Get the current privilege mask. Note that this may be modified
192826fcca57SAndrew Rybchenko * dynamically, so this value is informational only. DO NOT use
192926fcca57SAndrew Rybchenko * the privilege mask to check for sufficient privileges, as that
193026fcca57SAndrew Rybchenko * can result in time-of-check/time-of-use bugs.
193126fcca57SAndrew Rybchenko */
193226fcca57SAndrew Rybchenko if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0)
193326fcca57SAndrew Rybchenko goto fail10;
193426fcca57SAndrew Rybchenko encp->enc_privilege_mask = mask;
193526fcca57SAndrew Rybchenko
193609eac957SAndrew Rybchenko /* Get remaining controller-specific board config */
193748194339SAndrew Rybchenko if ((rc = enop->eno_board_cfg(enp)) != 0)
193848194339SAndrew Rybchenko if (rc != EACCES)
193926fcca57SAndrew Rybchenko goto fail11;
194048194339SAndrew Rybchenko
194148194339SAndrew Rybchenko return (0);
194248194339SAndrew Rybchenko
194326fcca57SAndrew Rybchenko fail11:
194426fcca57SAndrew Rybchenko EFSYS_PROBE(fail11);
194561e0c16dSAndrew Rybchenko fail10:
194661e0c16dSAndrew Rybchenko EFSYS_PROBE(fail10);
1947deeaf87fSAndrew Rybchenko fail9:
1948deeaf87fSAndrew Rybchenko EFSYS_PROBE(fail9);
1949e5f6f32fSAndrew Rybchenko fail8:
1950e5f6f32fSAndrew Rybchenko EFSYS_PROBE(fail8);
1951e5f6f32fSAndrew Rybchenko fail7:
1952e5f6f32fSAndrew Rybchenko EFSYS_PROBE(fail7);
1953233c1e5eSAndrew Rybchenko fail6:
1954233c1e5eSAndrew Rybchenko EFSYS_PROBE(fail6);
1955d36ea92cSAndrew Rybchenko fail5:
1956d36ea92cSAndrew Rybchenko EFSYS_PROBE(fail5);
195717f272e7SAndrew Rybchenko fail4:
195817f272e7SAndrew Rybchenko EFSYS_PROBE(fail4);
195909eac957SAndrew Rybchenko fail3:
196009eac957SAndrew Rybchenko EFSYS_PROBE(fail3);
196109eac957SAndrew Rybchenko fail2:
196209eac957SAndrew Rybchenko EFSYS_PROBE(fail2);
196348194339SAndrew Rybchenko fail1:
196448194339SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
196548194339SAndrew Rybchenko
196648194339SAndrew Rybchenko return (rc);
196748194339SAndrew Rybchenko }
196831bf5f03SAndrew Rybchenko
196931bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_probe(__in efx_nic_t * enp)197031bf5f03SAndrew Rybchenko ef10_nic_probe(
197131bf5f03SAndrew Rybchenko __in efx_nic_t *enp)
197231bf5f03SAndrew Rybchenko {
197331bf5f03SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
197431bf5f03SAndrew Rybchenko efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
197531bf5f03SAndrew Rybchenko efx_rc_t rc;
197631bf5f03SAndrew Rybchenko
197731bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1978ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
1979ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
198031bf5f03SAndrew Rybchenko
198131bf5f03SAndrew Rybchenko /* Read and clear any assertion state */
198231bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_read_assertion(enp)) != 0)
198331bf5f03SAndrew Rybchenko goto fail1;
198431bf5f03SAndrew Rybchenko
198531bf5f03SAndrew Rybchenko /* Exit the assertion handler */
198631bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
198731bf5f03SAndrew Rybchenko if (rc != EACCES)
198831bf5f03SAndrew Rybchenko goto fail2;
198931bf5f03SAndrew Rybchenko
199031bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
199131bf5f03SAndrew Rybchenko goto fail3;
199231bf5f03SAndrew Rybchenko
199348194339SAndrew Rybchenko if ((rc = ef10_nic_board_cfg(enp)) != 0)
199431bf5f03SAndrew Rybchenko goto fail4;
199531bf5f03SAndrew Rybchenko
199631bf5f03SAndrew Rybchenko /*
199731bf5f03SAndrew Rybchenko * Set default driver config limits (based on board config).
199831bf5f03SAndrew Rybchenko *
199931bf5f03SAndrew Rybchenko * FIXME: For now allocate a fixed number of VIs which is likely to be
200031bf5f03SAndrew Rybchenko * sufficient and small enough to allow multiple functions on the same
200131bf5f03SAndrew Rybchenko * port.
200231bf5f03SAndrew Rybchenko */
200331bf5f03SAndrew Rybchenko edcp->edc_min_vi_count = edcp->edc_max_vi_count =
200431bf5f03SAndrew Rybchenko MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
200531bf5f03SAndrew Rybchenko
200631bf5f03SAndrew Rybchenko /* The client driver must configure and enable PIO buffer support */
200731bf5f03SAndrew Rybchenko edcp->edc_max_piobuf_count = 0;
200831bf5f03SAndrew Rybchenko edcp->edc_pio_alloc_size = 0;
200931bf5f03SAndrew Rybchenko
201031bf5f03SAndrew Rybchenko #if EFSYS_OPT_MAC_STATS
201131bf5f03SAndrew Rybchenko /* Wipe the MAC statistics */
201231bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
201331bf5f03SAndrew Rybchenko goto fail5;
201431bf5f03SAndrew Rybchenko #endif
201531bf5f03SAndrew Rybchenko
201631bf5f03SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
201731bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
201831bf5f03SAndrew Rybchenko goto fail6;
201931bf5f03SAndrew Rybchenko #endif
202031bf5f03SAndrew Rybchenko
202131bf5f03SAndrew Rybchenko #if EFSYS_OPT_MON_STATS
202231bf5f03SAndrew Rybchenko if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
202331bf5f03SAndrew Rybchenko /* Unprivileged functions do not have access to sensors */
202431bf5f03SAndrew Rybchenko if (rc != EACCES)
202531bf5f03SAndrew Rybchenko goto fail7;
202631bf5f03SAndrew Rybchenko }
202731bf5f03SAndrew Rybchenko #endif
202831bf5f03SAndrew Rybchenko
202931bf5f03SAndrew Rybchenko encp->enc_features = enp->en_features;
203031bf5f03SAndrew Rybchenko
203131bf5f03SAndrew Rybchenko return (0);
203231bf5f03SAndrew Rybchenko
203331bf5f03SAndrew Rybchenko #if EFSYS_OPT_MON_STATS
203431bf5f03SAndrew Rybchenko fail7:
203531bf5f03SAndrew Rybchenko EFSYS_PROBE(fail7);
203631bf5f03SAndrew Rybchenko #endif
203731bf5f03SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
203831bf5f03SAndrew Rybchenko fail6:
203931bf5f03SAndrew Rybchenko EFSYS_PROBE(fail6);
204031bf5f03SAndrew Rybchenko #endif
204131bf5f03SAndrew Rybchenko #if EFSYS_OPT_MAC_STATS
204231bf5f03SAndrew Rybchenko fail5:
204331bf5f03SAndrew Rybchenko EFSYS_PROBE(fail5);
204431bf5f03SAndrew Rybchenko #endif
204531bf5f03SAndrew Rybchenko fail4:
204631bf5f03SAndrew Rybchenko EFSYS_PROBE(fail4);
204731bf5f03SAndrew Rybchenko fail3:
204831bf5f03SAndrew Rybchenko EFSYS_PROBE(fail3);
204931bf5f03SAndrew Rybchenko fail2:
205031bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
205131bf5f03SAndrew Rybchenko fail1:
205231bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
205331bf5f03SAndrew Rybchenko
205431bf5f03SAndrew Rybchenko return (rc);
205531bf5f03SAndrew Rybchenko }
205631bf5f03SAndrew Rybchenko
205731bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_set_drv_limits(__inout efx_nic_t * enp,__in efx_drv_limits_t * edlp)205831bf5f03SAndrew Rybchenko ef10_nic_set_drv_limits(
205931bf5f03SAndrew Rybchenko __inout efx_nic_t *enp,
206031bf5f03SAndrew Rybchenko __in efx_drv_limits_t *edlp)
206131bf5f03SAndrew Rybchenko {
206231bf5f03SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
206331bf5f03SAndrew Rybchenko efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
206431bf5f03SAndrew Rybchenko uint32_t min_evq_count, max_evq_count;
206531bf5f03SAndrew Rybchenko uint32_t min_rxq_count, max_rxq_count;
206631bf5f03SAndrew Rybchenko uint32_t min_txq_count, max_txq_count;
206731bf5f03SAndrew Rybchenko efx_rc_t rc;
206831bf5f03SAndrew Rybchenko
206931bf5f03SAndrew Rybchenko if (edlp == NULL) {
207031bf5f03SAndrew Rybchenko rc = EINVAL;
207131bf5f03SAndrew Rybchenko goto fail1;
207231bf5f03SAndrew Rybchenko }
207331bf5f03SAndrew Rybchenko
207431bf5f03SAndrew Rybchenko /* Get minimum required and maximum usable VI limits */
207531bf5f03SAndrew Rybchenko min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
207631bf5f03SAndrew Rybchenko min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
207731bf5f03SAndrew Rybchenko min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
207831bf5f03SAndrew Rybchenko
207931bf5f03SAndrew Rybchenko edcp->edc_min_vi_count =
208031bf5f03SAndrew Rybchenko MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
208131bf5f03SAndrew Rybchenko
208231bf5f03SAndrew Rybchenko max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
208331bf5f03SAndrew Rybchenko max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
208431bf5f03SAndrew Rybchenko max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
208531bf5f03SAndrew Rybchenko
208631bf5f03SAndrew Rybchenko edcp->edc_max_vi_count =
208731bf5f03SAndrew Rybchenko MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
208831bf5f03SAndrew Rybchenko
208931bf5f03SAndrew Rybchenko /*
209031bf5f03SAndrew Rybchenko * Check limits for sub-allocated piobuf blocks.
209131bf5f03SAndrew Rybchenko * PIO is optional, so don't fail if the limits are incorrect.
209231bf5f03SAndrew Rybchenko */
209331bf5f03SAndrew Rybchenko if ((encp->enc_piobuf_size == 0) ||
209431bf5f03SAndrew Rybchenko (encp->enc_piobuf_limit == 0) ||
209531bf5f03SAndrew Rybchenko (edlp->edl_min_pio_alloc_size == 0) ||
209631bf5f03SAndrew Rybchenko (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
209731bf5f03SAndrew Rybchenko /* Disable PIO */
209831bf5f03SAndrew Rybchenko edcp->edc_max_piobuf_count = 0;
209931bf5f03SAndrew Rybchenko edcp->edc_pio_alloc_size = 0;
210031bf5f03SAndrew Rybchenko } else {
210131bf5f03SAndrew Rybchenko uint32_t blk_size, blk_count, blks_per_piobuf;
210231bf5f03SAndrew Rybchenko
210331bf5f03SAndrew Rybchenko blk_size =
210431bf5f03SAndrew Rybchenko MAX(edlp->edl_min_pio_alloc_size,
210531bf5f03SAndrew Rybchenko encp->enc_piobuf_min_alloc_size);
210631bf5f03SAndrew Rybchenko
210731bf5f03SAndrew Rybchenko blks_per_piobuf = encp->enc_piobuf_size / blk_size;
210831bf5f03SAndrew Rybchenko EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
210931bf5f03SAndrew Rybchenko
211031bf5f03SAndrew Rybchenko blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
211131bf5f03SAndrew Rybchenko
211231bf5f03SAndrew Rybchenko /* A zero max pio alloc count means unlimited */
211331bf5f03SAndrew Rybchenko if ((edlp->edl_max_pio_alloc_count > 0) &&
211431bf5f03SAndrew Rybchenko (edlp->edl_max_pio_alloc_count < blk_count)) {
211531bf5f03SAndrew Rybchenko blk_count = edlp->edl_max_pio_alloc_count;
211631bf5f03SAndrew Rybchenko }
211731bf5f03SAndrew Rybchenko
211831bf5f03SAndrew Rybchenko edcp->edc_pio_alloc_size = blk_size;
211931bf5f03SAndrew Rybchenko edcp->edc_max_piobuf_count =
212031bf5f03SAndrew Rybchenko (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
212131bf5f03SAndrew Rybchenko }
212231bf5f03SAndrew Rybchenko
212331bf5f03SAndrew Rybchenko return (0);
212431bf5f03SAndrew Rybchenko
212531bf5f03SAndrew Rybchenko fail1:
212631bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
212731bf5f03SAndrew Rybchenko
212831bf5f03SAndrew Rybchenko return (rc);
212931bf5f03SAndrew Rybchenko }
213031bf5f03SAndrew Rybchenko
213131bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_reset(__in efx_nic_t * enp)213231bf5f03SAndrew Rybchenko ef10_nic_reset(
213331bf5f03SAndrew Rybchenko __in efx_nic_t *enp)
213431bf5f03SAndrew Rybchenko {
213531bf5f03SAndrew Rybchenko efx_mcdi_req_t req;
2136315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ENTITY_RESET_IN_LEN,
2137315bbbaaSAndrew Rybchenko MC_CMD_ENTITY_RESET_OUT_LEN);
213831bf5f03SAndrew Rybchenko efx_rc_t rc;
213931bf5f03SAndrew Rybchenko
214031bf5f03SAndrew Rybchenko /* ef10_nic_reset() is called to recover from BADASSERT failures. */
214131bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_read_assertion(enp)) != 0)
214231bf5f03SAndrew Rybchenko goto fail1;
214331bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
214431bf5f03SAndrew Rybchenko goto fail2;
214531bf5f03SAndrew Rybchenko
214631bf5f03SAndrew Rybchenko req.emr_cmd = MC_CMD_ENTITY_RESET;
214731bf5f03SAndrew Rybchenko req.emr_in_buf = payload;
214831bf5f03SAndrew Rybchenko req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
214931bf5f03SAndrew Rybchenko req.emr_out_buf = payload;
215031bf5f03SAndrew Rybchenko req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
215131bf5f03SAndrew Rybchenko
215231bf5f03SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
215331bf5f03SAndrew Rybchenko ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
215431bf5f03SAndrew Rybchenko
215531bf5f03SAndrew Rybchenko efx_mcdi_execute(enp, &req);
215631bf5f03SAndrew Rybchenko
215731bf5f03SAndrew Rybchenko if (req.emr_rc != 0) {
215831bf5f03SAndrew Rybchenko rc = req.emr_rc;
215931bf5f03SAndrew Rybchenko goto fail3;
216031bf5f03SAndrew Rybchenko }
216131bf5f03SAndrew Rybchenko
216231bf5f03SAndrew Rybchenko /* Clear RX/TX DMA queue errors */
216331bf5f03SAndrew Rybchenko enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
216431bf5f03SAndrew Rybchenko
216531bf5f03SAndrew Rybchenko return (0);
216631bf5f03SAndrew Rybchenko
216731bf5f03SAndrew Rybchenko fail3:
216831bf5f03SAndrew Rybchenko EFSYS_PROBE(fail3);
216931bf5f03SAndrew Rybchenko fail2:
217031bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
217131bf5f03SAndrew Rybchenko fail1:
217231bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
217331bf5f03SAndrew Rybchenko
217431bf5f03SAndrew Rybchenko return (rc);
217531bf5f03SAndrew Rybchenko }
217631bf5f03SAndrew Rybchenko
217731bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_init(__in efx_nic_t * enp)217831bf5f03SAndrew Rybchenko ef10_nic_init(
217931bf5f03SAndrew Rybchenko __in efx_nic_t *enp)
218031bf5f03SAndrew Rybchenko {
218131bf5f03SAndrew Rybchenko efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
218231bf5f03SAndrew Rybchenko uint32_t min_vi_count, max_vi_count;
218331bf5f03SAndrew Rybchenko uint32_t vi_count, vi_base, vi_shift;
218431bf5f03SAndrew Rybchenko uint32_t i;
218531bf5f03SAndrew Rybchenko uint32_t retry;
218631bf5f03SAndrew Rybchenko uint32_t delay_us;
2187c63c8369SAndrew Rybchenko uint32_t vi_window_size;
218831bf5f03SAndrew Rybchenko efx_rc_t rc;
218931bf5f03SAndrew Rybchenko
219031bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
2191ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
2192ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
219331bf5f03SAndrew Rybchenko
219431bf5f03SAndrew Rybchenko /* Enable reporting of some events (e.g. link change) */
219531bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
219631bf5f03SAndrew Rybchenko goto fail1;
219731bf5f03SAndrew Rybchenko
219831bf5f03SAndrew Rybchenko /* Allocate (optional) on-chip PIO buffers */
219931bf5f03SAndrew Rybchenko ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
220031bf5f03SAndrew Rybchenko
220131bf5f03SAndrew Rybchenko /*
220231bf5f03SAndrew Rybchenko * For best performance, PIO writes should use a write-combined
220331bf5f03SAndrew Rybchenko * (WC) memory mapping. Using a separate WC mapping for the PIO
220431bf5f03SAndrew Rybchenko * aperture of each VI would be a burden to drivers (and not
220531bf5f03SAndrew Rybchenko * possible if the host page size is >4Kbyte).
220631bf5f03SAndrew Rybchenko *
220731bf5f03SAndrew Rybchenko * To avoid this we use a single uncached (UC) mapping for VI
220831bf5f03SAndrew Rybchenko * register access, and a single WC mapping for extra VIs used
220931bf5f03SAndrew Rybchenko * for PIO writes.
221031bf5f03SAndrew Rybchenko *
221131bf5f03SAndrew Rybchenko * Each piobuf must be linked to a VI in the WC mapping, and to
221231bf5f03SAndrew Rybchenko * each VI that is using a sub-allocated block from the piobuf.
221331bf5f03SAndrew Rybchenko */
221431bf5f03SAndrew Rybchenko min_vi_count = edcp->edc_min_vi_count;
221531bf5f03SAndrew Rybchenko max_vi_count =
221631bf5f03SAndrew Rybchenko edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
221731bf5f03SAndrew Rybchenko
221831bf5f03SAndrew Rybchenko /* Ensure that the previously attached driver's VIs are freed */
221931bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_free_vis(enp)) != 0)
222031bf5f03SAndrew Rybchenko goto fail2;
222131bf5f03SAndrew Rybchenko
222231bf5f03SAndrew Rybchenko /*
222331bf5f03SAndrew Rybchenko * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
222431bf5f03SAndrew Rybchenko * fails then retrying the request for fewer VI resources may succeed.
222531bf5f03SAndrew Rybchenko */
222631bf5f03SAndrew Rybchenko vi_count = 0;
222731bf5f03SAndrew Rybchenko if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
222831bf5f03SAndrew Rybchenko &vi_base, &vi_count, &vi_shift)) != 0)
222931bf5f03SAndrew Rybchenko goto fail3;
223031bf5f03SAndrew Rybchenko
223131bf5f03SAndrew Rybchenko EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
223231bf5f03SAndrew Rybchenko
223331bf5f03SAndrew Rybchenko if (vi_count < min_vi_count) {
223431bf5f03SAndrew Rybchenko rc = ENOMEM;
223531bf5f03SAndrew Rybchenko goto fail4;
223631bf5f03SAndrew Rybchenko }
223731bf5f03SAndrew Rybchenko
223831bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_vi_base = vi_base;
223931bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_vi_count = vi_count;
224031bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_vi_shift = vi_shift;
224131bf5f03SAndrew Rybchenko
224231bf5f03SAndrew Rybchenko if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
224331bf5f03SAndrew Rybchenko /* Not enough extra VIs to map piobufs */
224431bf5f03SAndrew Rybchenko ef10_nic_free_piobufs(enp);
224531bf5f03SAndrew Rybchenko }
224631bf5f03SAndrew Rybchenko
224731bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_pio_write_vi_base =
224831bf5f03SAndrew Rybchenko vi_count - enp->en_arch.ef10.ena_piobuf_count;
224931bf5f03SAndrew Rybchenko
2250c63c8369SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nic_cfg.enc_vi_window_shift, !=,
2251c63c8369SAndrew Rybchenko EFX_VI_WINDOW_SHIFT_INVALID);
2252c63c8369SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nic_cfg.enc_vi_window_shift, <=,
2253c63c8369SAndrew Rybchenko EFX_VI_WINDOW_SHIFT_64K);
2254c63c8369SAndrew Rybchenko vi_window_size = 1U << enp->en_nic_cfg.enc_vi_window_shift;
2255c63c8369SAndrew Rybchenko
225631bf5f03SAndrew Rybchenko /* Save UC memory mapping details */
225731bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
225831bf5f03SAndrew Rybchenko if (enp->en_arch.ef10.ena_piobuf_count > 0) {
225931bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_size =
2260c63c8369SAndrew Rybchenko (vi_window_size *
226131bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_pio_write_vi_base);
226231bf5f03SAndrew Rybchenko } else {
226331bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_size =
2264c63c8369SAndrew Rybchenko (vi_window_size *
226531bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_vi_count);
226631bf5f03SAndrew Rybchenko }
226731bf5f03SAndrew Rybchenko
226831bf5f03SAndrew Rybchenko /* Save WC memory mapping details */
226931bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_wc_mem_map_offset =
227031bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_offset +
227131bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_size;
227231bf5f03SAndrew Rybchenko
227331bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_wc_mem_map_size =
2274c63c8369SAndrew Rybchenko (vi_window_size *
227531bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count);
227631bf5f03SAndrew Rybchenko
227731bf5f03SAndrew Rybchenko /* Link piobufs to extra VIs in WC mapping */
227831bf5f03SAndrew Rybchenko if (enp->en_arch.ef10.ena_piobuf_count > 0) {
227931bf5f03SAndrew Rybchenko for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
228031bf5f03SAndrew Rybchenko rc = efx_mcdi_link_piobuf(enp,
228131bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_pio_write_vi_base + i,
228231bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_handle[i]);
228331bf5f03SAndrew Rybchenko if (rc != 0)
228431bf5f03SAndrew Rybchenko break;
228531bf5f03SAndrew Rybchenko }
228631bf5f03SAndrew Rybchenko }
228731bf5f03SAndrew Rybchenko
228831bf5f03SAndrew Rybchenko /*
228931bf5f03SAndrew Rybchenko * Allocate a vAdaptor attached to our upstream vPort/pPort.
229031bf5f03SAndrew Rybchenko *
229131bf5f03SAndrew Rybchenko * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
229231bf5f03SAndrew Rybchenko * driver has yet to bring up the EVB port. See bug 56147. In this case,
229331bf5f03SAndrew Rybchenko * retry the request several times after waiting a while. The wait time
229431bf5f03SAndrew Rybchenko * between retries starts small (10ms) and exponentially increases.
229531bf5f03SAndrew Rybchenko * Total wait time is a little over two seconds. Retry logic in the
229631bf5f03SAndrew Rybchenko * client driver may mean this whole loop is repeated if it continues to
229731bf5f03SAndrew Rybchenko * fail.
229831bf5f03SAndrew Rybchenko */
229931bf5f03SAndrew Rybchenko retry = 0;
230031bf5f03SAndrew Rybchenko delay_us = 10000;
230131bf5f03SAndrew Rybchenko while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
230231bf5f03SAndrew Rybchenko if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
230331bf5f03SAndrew Rybchenko (rc != ENOENT)) {
230431bf5f03SAndrew Rybchenko /*
230531bf5f03SAndrew Rybchenko * Do not retry alloc for PF, or for other errors on
230631bf5f03SAndrew Rybchenko * a VF.
230731bf5f03SAndrew Rybchenko */
230831bf5f03SAndrew Rybchenko goto fail5;
230931bf5f03SAndrew Rybchenko }
231031bf5f03SAndrew Rybchenko
231131bf5f03SAndrew Rybchenko /* VF startup before PF is ready. Retry allocation. */
231231bf5f03SAndrew Rybchenko if (retry > 5) {
231331bf5f03SAndrew Rybchenko /* Too many attempts */
231431bf5f03SAndrew Rybchenko rc = EINVAL;
231531bf5f03SAndrew Rybchenko goto fail6;
231631bf5f03SAndrew Rybchenko }
231731bf5f03SAndrew Rybchenko EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
231831bf5f03SAndrew Rybchenko EFSYS_SLEEP(delay_us);
231931bf5f03SAndrew Rybchenko retry++;
232031bf5f03SAndrew Rybchenko if (delay_us < 500000)
232131bf5f03SAndrew Rybchenko delay_us <<= 2;
232231bf5f03SAndrew Rybchenko }
232331bf5f03SAndrew Rybchenko
232431bf5f03SAndrew Rybchenko enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
232531bf5f03SAndrew Rybchenko enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
232631bf5f03SAndrew Rybchenko
232731bf5f03SAndrew Rybchenko return (0);
232831bf5f03SAndrew Rybchenko
232931bf5f03SAndrew Rybchenko fail6:
233031bf5f03SAndrew Rybchenko EFSYS_PROBE(fail6);
233131bf5f03SAndrew Rybchenko fail5:
233231bf5f03SAndrew Rybchenko EFSYS_PROBE(fail5);
233331bf5f03SAndrew Rybchenko fail4:
233431bf5f03SAndrew Rybchenko EFSYS_PROBE(fail4);
233531bf5f03SAndrew Rybchenko fail3:
233631bf5f03SAndrew Rybchenko EFSYS_PROBE(fail3);
233731bf5f03SAndrew Rybchenko fail2:
233831bf5f03SAndrew Rybchenko EFSYS_PROBE(fail2);
233931bf5f03SAndrew Rybchenko
234031bf5f03SAndrew Rybchenko ef10_nic_free_piobufs(enp);
234131bf5f03SAndrew Rybchenko
234231bf5f03SAndrew Rybchenko fail1:
234331bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
234431bf5f03SAndrew Rybchenko
234531bf5f03SAndrew Rybchenko return (rc);
234631bf5f03SAndrew Rybchenko }
234731bf5f03SAndrew Rybchenko
234831bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_get_vi_pool(__in efx_nic_t * enp,__out uint32_t * vi_countp)234931bf5f03SAndrew Rybchenko ef10_nic_get_vi_pool(
235031bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
235131bf5f03SAndrew Rybchenko __out uint32_t *vi_countp)
235231bf5f03SAndrew Rybchenko {
235331bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
2354ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
2355ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
235631bf5f03SAndrew Rybchenko
235731bf5f03SAndrew Rybchenko /*
235831bf5f03SAndrew Rybchenko * Report VIs that the client driver can use.
235931bf5f03SAndrew Rybchenko * Do not include VIs used for PIO buffer writes.
236031bf5f03SAndrew Rybchenko */
236131bf5f03SAndrew Rybchenko *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
236231bf5f03SAndrew Rybchenko
236331bf5f03SAndrew Rybchenko return (0);
236431bf5f03SAndrew Rybchenko }
236531bf5f03SAndrew Rybchenko
236631bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_get_bar_region(__in efx_nic_t * enp,__in efx_nic_region_t region,__out uint32_t * offsetp,__out size_t * sizep)236731bf5f03SAndrew Rybchenko ef10_nic_get_bar_region(
236831bf5f03SAndrew Rybchenko __in efx_nic_t *enp,
236931bf5f03SAndrew Rybchenko __in efx_nic_region_t region,
237031bf5f03SAndrew Rybchenko __out uint32_t *offsetp,
237131bf5f03SAndrew Rybchenko __out size_t *sizep)
237231bf5f03SAndrew Rybchenko {
237331bf5f03SAndrew Rybchenko efx_rc_t rc;
237431bf5f03SAndrew Rybchenko
237531bf5f03SAndrew Rybchenko EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
2376ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD ||
2377ae64ac93SAndrew Rybchenko enp->en_family == EFX_FAMILY_MEDFORD2);
237831bf5f03SAndrew Rybchenko
237931bf5f03SAndrew Rybchenko /*
238031bf5f03SAndrew Rybchenko * TODO: Specify host memory mapping alignment and granularity
238131bf5f03SAndrew Rybchenko * in efx_drv_limits_t so that they can be taken into account
238231bf5f03SAndrew Rybchenko * when allocating extra VIs for PIO writes.
238331bf5f03SAndrew Rybchenko */
238431bf5f03SAndrew Rybchenko switch (region) {
238531bf5f03SAndrew Rybchenko case EFX_REGION_VI:
238631bf5f03SAndrew Rybchenko /* UC mapped memory BAR region for VI registers */
238731bf5f03SAndrew Rybchenko *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
238831bf5f03SAndrew Rybchenko *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
238931bf5f03SAndrew Rybchenko break;
239031bf5f03SAndrew Rybchenko
239131bf5f03SAndrew Rybchenko case EFX_REGION_PIO_WRITE_VI:
239231bf5f03SAndrew Rybchenko /* WC mapped memory BAR region for piobuf writes */
239331bf5f03SAndrew Rybchenko *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
239431bf5f03SAndrew Rybchenko *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
239531bf5f03SAndrew Rybchenko break;
239631bf5f03SAndrew Rybchenko
239731bf5f03SAndrew Rybchenko default:
239831bf5f03SAndrew Rybchenko rc = EINVAL;
239931bf5f03SAndrew Rybchenko goto fail1;
240031bf5f03SAndrew Rybchenko }
240131bf5f03SAndrew Rybchenko
240231bf5f03SAndrew Rybchenko return (0);
240331bf5f03SAndrew Rybchenko
240431bf5f03SAndrew Rybchenko fail1:
240531bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
240631bf5f03SAndrew Rybchenko
240731bf5f03SAndrew Rybchenko return (rc);
240831bf5f03SAndrew Rybchenko }
240931bf5f03SAndrew Rybchenko
2410c6d5e85dSAndrew Rybchenko __checkReturn boolean_t
ef10_nic_hw_unavailable(__in efx_nic_t * enp)2411c6d5e85dSAndrew Rybchenko ef10_nic_hw_unavailable(
2412c6d5e85dSAndrew Rybchenko __in efx_nic_t *enp)
2413c6d5e85dSAndrew Rybchenko {
2414c6d5e85dSAndrew Rybchenko efx_dword_t dword;
2415c6d5e85dSAndrew Rybchenko
2416c6d5e85dSAndrew Rybchenko if (enp->en_reset_flags & EFX_RESET_HW_UNAVAIL)
2417c6d5e85dSAndrew Rybchenko return (B_TRUE);
2418c6d5e85dSAndrew Rybchenko
2419c6d5e85dSAndrew Rybchenko EFX_BAR_READD(enp, ER_DZ_BIU_MC_SFT_STATUS_REG, &dword, B_FALSE);
2420c6d5e85dSAndrew Rybchenko if (EFX_DWORD_FIELD(dword, EFX_DWORD_0) == 0xffffffff)
2421c6d5e85dSAndrew Rybchenko goto unavail;
2422c6d5e85dSAndrew Rybchenko
2423c6d5e85dSAndrew Rybchenko return (B_FALSE);
2424c6d5e85dSAndrew Rybchenko
2425c6d5e85dSAndrew Rybchenko unavail:
2426b2053d80SAndrew Rybchenko ef10_nic_set_hw_unavailable(enp);
2427c6d5e85dSAndrew Rybchenko
2428c6d5e85dSAndrew Rybchenko return (B_TRUE);
2429c6d5e85dSAndrew Rybchenko }
2430c6d5e85dSAndrew Rybchenko
243131bf5f03SAndrew Rybchenko void
ef10_nic_set_hw_unavailable(__in efx_nic_t * enp)2432b2053d80SAndrew Rybchenko ef10_nic_set_hw_unavailable(
2433b2053d80SAndrew Rybchenko __in efx_nic_t *enp)
2434b2053d80SAndrew Rybchenko {
2435b2053d80SAndrew Rybchenko EFSYS_PROBE(hw_unavail);
2436b2053d80SAndrew Rybchenko enp->en_reset_flags |= EFX_RESET_HW_UNAVAIL;
2437b2053d80SAndrew Rybchenko }
2438b2053d80SAndrew Rybchenko
2439b2053d80SAndrew Rybchenko void
ef10_nic_fini(__in efx_nic_t * enp)244031bf5f03SAndrew Rybchenko ef10_nic_fini(
244131bf5f03SAndrew Rybchenko __in efx_nic_t *enp)
244231bf5f03SAndrew Rybchenko {
244331bf5f03SAndrew Rybchenko uint32_t i;
244431bf5f03SAndrew Rybchenko efx_rc_t rc;
244531bf5f03SAndrew Rybchenko
244631bf5f03SAndrew Rybchenko (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
244731bf5f03SAndrew Rybchenko enp->en_vport_id = 0;
244831bf5f03SAndrew Rybchenko
244931bf5f03SAndrew Rybchenko /* Unlink piobufs from extra VIs in WC mapping */
245031bf5f03SAndrew Rybchenko if (enp->en_arch.ef10.ena_piobuf_count > 0) {
245131bf5f03SAndrew Rybchenko for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
245231bf5f03SAndrew Rybchenko rc = efx_mcdi_unlink_piobuf(enp,
245331bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_pio_write_vi_base + i);
245431bf5f03SAndrew Rybchenko if (rc != 0)
245531bf5f03SAndrew Rybchenko break;
245631bf5f03SAndrew Rybchenko }
245731bf5f03SAndrew Rybchenko }
245831bf5f03SAndrew Rybchenko
245931bf5f03SAndrew Rybchenko ef10_nic_free_piobufs(enp);
246031bf5f03SAndrew Rybchenko
246131bf5f03SAndrew Rybchenko (void) efx_mcdi_free_vis(enp);
246231bf5f03SAndrew Rybchenko enp->en_arch.ef10.ena_vi_count = 0;
246331bf5f03SAndrew Rybchenko }
246431bf5f03SAndrew Rybchenko
246531bf5f03SAndrew Rybchenko void
ef10_nic_unprobe(__in efx_nic_t * enp)246631bf5f03SAndrew Rybchenko ef10_nic_unprobe(
246731bf5f03SAndrew Rybchenko __in efx_nic_t *enp)
246831bf5f03SAndrew Rybchenko {
246931bf5f03SAndrew Rybchenko #if EFSYS_OPT_MON_STATS
247031bf5f03SAndrew Rybchenko mcdi_mon_cfg_free(enp);
247131bf5f03SAndrew Rybchenko #endif /* EFSYS_OPT_MON_STATS */
247231bf5f03SAndrew Rybchenko (void) efx_mcdi_drv_attach(enp, B_FALSE);
247331bf5f03SAndrew Rybchenko }
247431bf5f03SAndrew Rybchenko
247531bf5f03SAndrew Rybchenko #if EFSYS_OPT_DIAG
247631bf5f03SAndrew Rybchenko
247731bf5f03SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_register_test(__in efx_nic_t * enp)247831bf5f03SAndrew Rybchenko ef10_nic_register_test(
247931bf5f03SAndrew Rybchenko __in efx_nic_t *enp)
248031bf5f03SAndrew Rybchenko {
248131bf5f03SAndrew Rybchenko efx_rc_t rc;
248231bf5f03SAndrew Rybchenko
248331bf5f03SAndrew Rybchenko /* FIXME */
248431bf5f03SAndrew Rybchenko _NOTE(ARGUNUSED(enp))
24855e951ea7SAndrew Rybchenko _NOTE(CONSTANTCONDITION)
248631bf5f03SAndrew Rybchenko if (B_FALSE) {
248731bf5f03SAndrew Rybchenko rc = ENOTSUP;
248831bf5f03SAndrew Rybchenko goto fail1;
248931bf5f03SAndrew Rybchenko }
249031bf5f03SAndrew Rybchenko /* FIXME */
249131bf5f03SAndrew Rybchenko
249231bf5f03SAndrew Rybchenko return (0);
249331bf5f03SAndrew Rybchenko
249431bf5f03SAndrew Rybchenko fail1:
249531bf5f03SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
249631bf5f03SAndrew Rybchenko
249731bf5f03SAndrew Rybchenko return (rc);
249831bf5f03SAndrew Rybchenko }
249931bf5f03SAndrew Rybchenko
250031bf5f03SAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
250131bf5f03SAndrew Rybchenko
250217bcc056SAndrew Rybchenko #if EFSYS_OPT_FW_SUBVARIANT_AWARE
250317bcc056SAndrew Rybchenko
250417bcc056SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_nic_global(__in efx_nic_t * enp,__in uint32_t key,__out uint32_t * valuep)250517bcc056SAndrew Rybchenko efx_mcdi_get_nic_global(
250617bcc056SAndrew Rybchenko __in efx_nic_t *enp,
250717bcc056SAndrew Rybchenko __in uint32_t key,
250817bcc056SAndrew Rybchenko __out uint32_t *valuep)
250917bcc056SAndrew Rybchenko {
251017bcc056SAndrew Rybchenko efx_mcdi_req_t req;
2511315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_NIC_GLOBAL_IN_LEN,
2512315bbbaaSAndrew Rybchenko MC_CMD_GET_NIC_GLOBAL_OUT_LEN);
251317bcc056SAndrew Rybchenko efx_rc_t rc;
251417bcc056SAndrew Rybchenko
251517bcc056SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_NIC_GLOBAL;
251617bcc056SAndrew Rybchenko req.emr_in_buf = payload;
251717bcc056SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_NIC_GLOBAL_IN_LEN;
251817bcc056SAndrew Rybchenko req.emr_out_buf = payload;
251917bcc056SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_NIC_GLOBAL_OUT_LEN;
252017bcc056SAndrew Rybchenko
252117bcc056SAndrew Rybchenko MCDI_IN_SET_DWORD(req, GET_NIC_GLOBAL_IN_KEY, key);
252217bcc056SAndrew Rybchenko
252317bcc056SAndrew Rybchenko efx_mcdi_execute(enp, &req);
252417bcc056SAndrew Rybchenko
252517bcc056SAndrew Rybchenko if (req.emr_rc != 0) {
252617bcc056SAndrew Rybchenko rc = req.emr_rc;
252717bcc056SAndrew Rybchenko goto fail1;
252817bcc056SAndrew Rybchenko }
252917bcc056SAndrew Rybchenko
253017bcc056SAndrew Rybchenko if (req.emr_out_length_used != MC_CMD_GET_NIC_GLOBAL_OUT_LEN) {
253117bcc056SAndrew Rybchenko rc = EMSGSIZE;
253217bcc056SAndrew Rybchenko goto fail2;
253317bcc056SAndrew Rybchenko }
253417bcc056SAndrew Rybchenko
253517bcc056SAndrew Rybchenko *valuep = MCDI_OUT_DWORD(req, GET_NIC_GLOBAL_OUT_VALUE);
253617bcc056SAndrew Rybchenko
253717bcc056SAndrew Rybchenko return (0);
253817bcc056SAndrew Rybchenko
253917bcc056SAndrew Rybchenko fail2:
254017bcc056SAndrew Rybchenko EFSYS_PROBE(fail2);
254117bcc056SAndrew Rybchenko fail1:
254217bcc056SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
254317bcc056SAndrew Rybchenko
254417bcc056SAndrew Rybchenko return (rc);
254517bcc056SAndrew Rybchenko }
254617bcc056SAndrew Rybchenko
254717bcc056SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_set_nic_global(__in efx_nic_t * enp,__in uint32_t key,__in uint32_t value)254817bcc056SAndrew Rybchenko efx_mcdi_set_nic_global(
254917bcc056SAndrew Rybchenko __in efx_nic_t *enp,
255017bcc056SAndrew Rybchenko __in uint32_t key,
255117bcc056SAndrew Rybchenko __in uint32_t value)
255217bcc056SAndrew Rybchenko {
255317bcc056SAndrew Rybchenko efx_mcdi_req_t req;
2554315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SET_NIC_GLOBAL_IN_LEN, 0);
255517bcc056SAndrew Rybchenko efx_rc_t rc;
255617bcc056SAndrew Rybchenko
255717bcc056SAndrew Rybchenko req.emr_cmd = MC_CMD_SET_NIC_GLOBAL;
255817bcc056SAndrew Rybchenko req.emr_in_buf = payload;
255917bcc056SAndrew Rybchenko req.emr_in_length = MC_CMD_SET_NIC_GLOBAL_IN_LEN;
256017bcc056SAndrew Rybchenko req.emr_out_buf = NULL;
256117bcc056SAndrew Rybchenko req.emr_out_length = 0;
256217bcc056SAndrew Rybchenko
256317bcc056SAndrew Rybchenko MCDI_IN_SET_DWORD(req, SET_NIC_GLOBAL_IN_KEY, key);
256417bcc056SAndrew Rybchenko MCDI_IN_SET_DWORD(req, SET_NIC_GLOBAL_IN_VALUE, value);
256517bcc056SAndrew Rybchenko
256617bcc056SAndrew Rybchenko efx_mcdi_execute(enp, &req);
256717bcc056SAndrew Rybchenko
256817bcc056SAndrew Rybchenko if (req.emr_rc != 0) {
256917bcc056SAndrew Rybchenko rc = req.emr_rc;
257017bcc056SAndrew Rybchenko goto fail1;
257117bcc056SAndrew Rybchenko }
257217bcc056SAndrew Rybchenko
257317bcc056SAndrew Rybchenko return (0);
257417bcc056SAndrew Rybchenko
257517bcc056SAndrew Rybchenko fail1:
257617bcc056SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
257717bcc056SAndrew Rybchenko
257817bcc056SAndrew Rybchenko return (rc);
257917bcc056SAndrew Rybchenko }
258017bcc056SAndrew Rybchenko
258117bcc056SAndrew Rybchenko #endif /* EFSYS_OPT_FW_SUBVARIANT_AWARE */
258231bf5f03SAndrew Rybchenko
2583ae64ac93SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
2584