15e111ed8SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
25e111ed8SAndrew Rybchenko *
3672386c1SAndrew Rybchenko * Copyright(c) 2019-2021 Xilinx, Inc.
45e111ed8SAndrew Rybchenko * Copyright(c) 2012-2019 Solarflare Communications Inc.
55e111ed8SAndrew Rybchenko */
65e111ed8SAndrew Rybchenko
75e111ed8SAndrew Rybchenko #include "efx.h"
85e111ed8SAndrew Rybchenko #include "efx_impl.h"
95e111ed8SAndrew Rybchenko #if EFSYS_OPT_MON_MCDI
105e111ed8SAndrew Rybchenko #include "mcdi_mon.h"
115e111ed8SAndrew Rybchenko #endif
125e111ed8SAndrew Rybchenko
133c1c5cc4SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10()
145e111ed8SAndrew Rybchenko
155e111ed8SAndrew Rybchenko #include "ef10_tlv_layout.h"
165e111ed8SAndrew Rybchenko
175e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_port_assignment(__in efx_nic_t * enp,__out uint32_t * portp)185e111ed8SAndrew Rybchenko efx_mcdi_get_port_assignment(
195e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
205e111ed8SAndrew Rybchenko __out uint32_t *portp)
215e111ed8SAndrew Rybchenko {
225e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
235e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN,
245e111ed8SAndrew Rybchenko MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
255e111ed8SAndrew Rybchenko efx_rc_t rc;
265e111ed8SAndrew Rybchenko
273c1c5cc4SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
285e111ed8SAndrew Rybchenko
295e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
305e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
315e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN;
325e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
335e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN;
345e111ed8SAndrew Rybchenko
355e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
365e111ed8SAndrew Rybchenko
375e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
385e111ed8SAndrew Rybchenko rc = req.emr_rc;
395e111ed8SAndrew Rybchenko goto fail1;
405e111ed8SAndrew Rybchenko }
415e111ed8SAndrew Rybchenko
425e111ed8SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN) {
435e111ed8SAndrew Rybchenko rc = EMSGSIZE;
445e111ed8SAndrew Rybchenko goto fail2;
455e111ed8SAndrew Rybchenko }
465e111ed8SAndrew Rybchenko
475e111ed8SAndrew Rybchenko *portp = MCDI_OUT_DWORD(req, GET_PORT_ASSIGNMENT_OUT_PORT);
485e111ed8SAndrew Rybchenko
495e111ed8SAndrew Rybchenko return (0);
505e111ed8SAndrew Rybchenko
515e111ed8SAndrew Rybchenko fail2:
525e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
535e111ed8SAndrew Rybchenko fail1:
545e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
555e111ed8SAndrew Rybchenko
565e111ed8SAndrew Rybchenko return (rc);
575e111ed8SAndrew Rybchenko }
585e111ed8SAndrew Rybchenko
595e111ed8SAndrew 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)605e111ed8SAndrew Rybchenko efx_mcdi_get_port_modes(
615e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
625e111ed8SAndrew Rybchenko __out uint32_t *modesp,
635e111ed8SAndrew Rybchenko __out_opt uint32_t *current_modep,
645e111ed8SAndrew Rybchenko __out_opt uint32_t *default_modep)
655e111ed8SAndrew Rybchenko {
665e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
675e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PORT_MODES_IN_LEN,
685e111ed8SAndrew Rybchenko MC_CMD_GET_PORT_MODES_OUT_LEN);
695e111ed8SAndrew Rybchenko efx_rc_t rc;
705e111ed8SAndrew Rybchenko
713c1c5cc4SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
725e111ed8SAndrew Rybchenko
735e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_PORT_MODES;
745e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
755e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN;
765e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
775e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_PORT_MODES_OUT_LEN;
785e111ed8SAndrew Rybchenko
795e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
805e111ed8SAndrew Rybchenko
815e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
825e111ed8SAndrew Rybchenko rc = req.emr_rc;
835e111ed8SAndrew Rybchenko goto fail1;
845e111ed8SAndrew Rybchenko }
855e111ed8SAndrew Rybchenko
865e111ed8SAndrew Rybchenko /*
875e111ed8SAndrew Rybchenko * Require only Modes and DefaultMode fields, unless the current mode
885e111ed8SAndrew Rybchenko * was requested (CurrentMode field was added for Medford).
895e111ed8SAndrew Rybchenko */
905e111ed8SAndrew Rybchenko if (req.emr_out_length_used <
915e111ed8SAndrew Rybchenko MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) {
925e111ed8SAndrew Rybchenko rc = EMSGSIZE;
935e111ed8SAndrew Rybchenko goto fail2;
945e111ed8SAndrew Rybchenko }
955e111ed8SAndrew Rybchenko if ((current_modep != NULL) && (req.emr_out_length_used <
965e111ed8SAndrew Rybchenko MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST + 4)) {
975e111ed8SAndrew Rybchenko rc = EMSGSIZE;
985e111ed8SAndrew Rybchenko goto fail3;
995e111ed8SAndrew Rybchenko }
1005e111ed8SAndrew Rybchenko
1015e111ed8SAndrew Rybchenko *modesp = MCDI_OUT_DWORD(req, GET_PORT_MODES_OUT_MODES);
1025e111ed8SAndrew Rybchenko
1035e111ed8SAndrew Rybchenko if (current_modep != NULL) {
1045e111ed8SAndrew Rybchenko *current_modep = MCDI_OUT_DWORD(req,
1055e111ed8SAndrew Rybchenko GET_PORT_MODES_OUT_CURRENT_MODE);
1065e111ed8SAndrew Rybchenko }
1075e111ed8SAndrew Rybchenko
1085e111ed8SAndrew Rybchenko if (default_modep != NULL) {
1095e111ed8SAndrew Rybchenko *default_modep = MCDI_OUT_DWORD(req,
1105e111ed8SAndrew Rybchenko GET_PORT_MODES_OUT_DEFAULT_MODE);
1115e111ed8SAndrew Rybchenko }
1125e111ed8SAndrew Rybchenko
1135e111ed8SAndrew Rybchenko return (0);
1145e111ed8SAndrew Rybchenko
1155e111ed8SAndrew Rybchenko fail3:
1165e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
1175e111ed8SAndrew Rybchenko fail2:
1185e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
1195e111ed8SAndrew Rybchenko fail1:
1205e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1215e111ed8SAndrew Rybchenko
1225e111ed8SAndrew Rybchenko return (rc);
1235e111ed8SAndrew Rybchenko }
1245e111ed8SAndrew Rybchenko
1255e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_get_port_mode_bandwidth(__in efx_nic_t * enp,__out uint32_t * bandwidth_mbpsp)1265e111ed8SAndrew Rybchenko ef10_nic_get_port_mode_bandwidth(
1275e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
1285e111ed8SAndrew Rybchenko __out uint32_t *bandwidth_mbpsp)
1295e111ed8SAndrew Rybchenko {
1305e111ed8SAndrew Rybchenko uint32_t port_modes;
1315e111ed8SAndrew Rybchenko uint32_t current_mode;
1325e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
1335e111ed8SAndrew Rybchenko
1345e111ed8SAndrew Rybchenko uint32_t single_lane;
1355e111ed8SAndrew Rybchenko uint32_t dual_lane;
1365e111ed8SAndrew Rybchenko uint32_t quad_lane;
1375e111ed8SAndrew Rybchenko uint32_t bandwidth;
1385e111ed8SAndrew Rybchenko efx_rc_t rc;
1395e111ed8SAndrew Rybchenko
1405e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_get_port_modes(enp, &port_modes,
1415e111ed8SAndrew Rybchenko ¤t_mode, NULL)) != 0) {
1425e111ed8SAndrew Rybchenko /* No port mode info available. */
1435e111ed8SAndrew Rybchenko goto fail1;
1445e111ed8SAndrew Rybchenko }
1455e111ed8SAndrew Rybchenko
1465e111ed8SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_25000FDX))
1475e111ed8SAndrew Rybchenko single_lane = 25000;
1485e111ed8SAndrew Rybchenko else
1495e111ed8SAndrew Rybchenko single_lane = 10000;
1505e111ed8SAndrew Rybchenko
1515e111ed8SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_50000FDX))
1525e111ed8SAndrew Rybchenko dual_lane = 50000;
1535e111ed8SAndrew Rybchenko else
1545e111ed8SAndrew Rybchenko dual_lane = 20000;
1555e111ed8SAndrew Rybchenko
1565e111ed8SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_100000FDX))
1575e111ed8SAndrew Rybchenko quad_lane = 100000;
1585e111ed8SAndrew Rybchenko else
1595e111ed8SAndrew Rybchenko quad_lane = 40000;
1605e111ed8SAndrew Rybchenko
1615e111ed8SAndrew Rybchenko switch (current_mode) {
1625e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x1_NA: /* mode 0 */
1635e111ed8SAndrew Rybchenko bandwidth = single_lane;
1645e111ed8SAndrew Rybchenko break;
1655e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x2_NA: /* mode 10 */
1665e111ed8SAndrew Rybchenko case TLV_PORT_MODE_NA_1x2: /* mode 11 */
1675e111ed8SAndrew Rybchenko bandwidth = dual_lane;
1685e111ed8SAndrew Rybchenko break;
1695e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x1_1x1: /* mode 2 */
1705e111ed8SAndrew Rybchenko bandwidth = single_lane + single_lane;
1715e111ed8SAndrew Rybchenko break;
1725e111ed8SAndrew Rybchenko case TLV_PORT_MODE_4x1_NA: /* mode 4 */
1735e111ed8SAndrew Rybchenko case TLV_PORT_MODE_NA_4x1: /* mode 8 */
1745e111ed8SAndrew Rybchenko bandwidth = 4 * single_lane;
1755e111ed8SAndrew Rybchenko break;
1765e111ed8SAndrew Rybchenko case TLV_PORT_MODE_2x1_2x1: /* mode 5 */
1775e111ed8SAndrew Rybchenko bandwidth = (2 * single_lane) + (2 * single_lane);
1785e111ed8SAndrew Rybchenko break;
1795e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x2_1x2: /* mode 12 */
1805e111ed8SAndrew Rybchenko bandwidth = dual_lane + dual_lane;
1815e111ed8SAndrew Rybchenko break;
1825e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x2_2x1: /* mode 17 */
1835e111ed8SAndrew Rybchenko case TLV_PORT_MODE_2x1_1x2: /* mode 18 */
1845e111ed8SAndrew Rybchenko bandwidth = dual_lane + (2 * single_lane);
1855e111ed8SAndrew Rybchenko break;
1865e111ed8SAndrew Rybchenko /* Legacy Medford-only mode. Do not use (see bug63270) */
1875e111ed8SAndrew Rybchenko case TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2: /* mode 9 */
1885e111ed8SAndrew Rybchenko bandwidth = 4 * single_lane;
1895e111ed8SAndrew Rybchenko break;
1905e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x4_NA: /* mode 1 */
1915e111ed8SAndrew Rybchenko case TLV_PORT_MODE_NA_1x4: /* mode 22 */
1925e111ed8SAndrew Rybchenko bandwidth = quad_lane;
1935e111ed8SAndrew Rybchenko break;
1945e111ed8SAndrew Rybchenko case TLV_PORT_MODE_2x2_NA: /* mode 13 */
1955e111ed8SAndrew Rybchenko case TLV_PORT_MODE_NA_2x2: /* mode 14 */
1965e111ed8SAndrew Rybchenko bandwidth = 2 * dual_lane;
1975e111ed8SAndrew Rybchenko break;
1985e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x4_2x1: /* mode 6 */
1995e111ed8SAndrew Rybchenko case TLV_PORT_MODE_2x1_1x4: /* mode 7 */
2005e111ed8SAndrew Rybchenko bandwidth = quad_lane + (2 * single_lane);
2015e111ed8SAndrew Rybchenko break;
2025e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x4_1x2: /* mode 15 */
2035e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x2_1x4: /* mode 16 */
2045e111ed8SAndrew Rybchenko bandwidth = quad_lane + dual_lane;
2055e111ed8SAndrew Rybchenko break;
2065e111ed8SAndrew Rybchenko case TLV_PORT_MODE_1x4_1x4: /* mode 3 */
2075e111ed8SAndrew Rybchenko bandwidth = quad_lane + quad_lane;
2085e111ed8SAndrew Rybchenko break;
2095e111ed8SAndrew Rybchenko default:
2105e111ed8SAndrew Rybchenko rc = EINVAL;
2115e111ed8SAndrew Rybchenko goto fail2;
2125e111ed8SAndrew Rybchenko }
2135e111ed8SAndrew Rybchenko
2145e111ed8SAndrew Rybchenko *bandwidth_mbpsp = bandwidth;
2155e111ed8SAndrew Rybchenko
2165e111ed8SAndrew Rybchenko return (0);
2175e111ed8SAndrew Rybchenko
2185e111ed8SAndrew Rybchenko fail2:
2195e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
2205e111ed8SAndrew Rybchenko fail1:
2215e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
2225e111ed8SAndrew Rybchenko
2235e111ed8SAndrew Rybchenko return (rc);
2245e111ed8SAndrew Rybchenko }
2255e111ed8SAndrew Rybchenko
2263c1c5cc4SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */
2273c1c5cc4SAndrew Rybchenko
2283c1c5cc4SAndrew Rybchenko #if EFX_OPTS_EF10()
2293c1c5cc4SAndrew Rybchenko
2305e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_vadaptor_alloc(__in efx_nic_t * enp,__in uint32_t port_id)2315e111ed8SAndrew Rybchenko efx_mcdi_vadaptor_alloc(
2325e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
2335e111ed8SAndrew Rybchenko __in uint32_t port_id)
2345e111ed8SAndrew Rybchenko {
2355e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
2365e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VADAPTOR_ALLOC_IN_LEN,
2375e111ed8SAndrew Rybchenko MC_CMD_VADAPTOR_ALLOC_OUT_LEN);
2385e111ed8SAndrew Rybchenko efx_rc_t rc;
2395e111ed8SAndrew Rybchenko
2405e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_VADAPTOR_ALLOC;
2415e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
2425e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN;
2435e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
2445e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_VADAPTOR_ALLOC_OUT_LEN;
2455e111ed8SAndrew Rybchenko
2465e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
2475e111ed8SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, VADAPTOR_ALLOC_IN_FLAGS,
2485e111ed8SAndrew Rybchenko VADAPTOR_ALLOC_IN_FLAG_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED,
2495e111ed8SAndrew Rybchenko enp->en_nic_cfg.enc_allow_set_mac_with_installed_filters ? 1 : 0);
2505e111ed8SAndrew Rybchenko
2515e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
2525e111ed8SAndrew Rybchenko
2535e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
2545e111ed8SAndrew Rybchenko rc = req.emr_rc;
2555e111ed8SAndrew Rybchenko goto fail1;
2565e111ed8SAndrew Rybchenko }
2575e111ed8SAndrew Rybchenko
2585e111ed8SAndrew Rybchenko return (0);
2595e111ed8SAndrew Rybchenko
2605e111ed8SAndrew Rybchenko fail1:
2615e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
2625e111ed8SAndrew Rybchenko
2635e111ed8SAndrew Rybchenko return (rc);
2645e111ed8SAndrew Rybchenko }
2655e111ed8SAndrew Rybchenko
2665e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_vadaptor_free(__in efx_nic_t * enp,__in uint32_t port_id)2675e111ed8SAndrew Rybchenko efx_mcdi_vadaptor_free(
2685e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
2695e111ed8SAndrew Rybchenko __in uint32_t port_id)
2705e111ed8SAndrew Rybchenko {
2715e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
2725e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VADAPTOR_FREE_IN_LEN,
2735e111ed8SAndrew Rybchenko MC_CMD_VADAPTOR_FREE_OUT_LEN);
2745e111ed8SAndrew Rybchenko efx_rc_t rc;
2755e111ed8SAndrew Rybchenko
2765e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_VADAPTOR_FREE;
2775e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
2785e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_VADAPTOR_FREE_IN_LEN;
2795e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
2805e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_VADAPTOR_FREE_OUT_LEN;
2815e111ed8SAndrew Rybchenko
2825e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
2835e111ed8SAndrew Rybchenko
2845e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
2855e111ed8SAndrew Rybchenko
2865e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
2875e111ed8SAndrew Rybchenko rc = req.emr_rc;
2885e111ed8SAndrew Rybchenko goto fail1;
2895e111ed8SAndrew Rybchenko }
2905e111ed8SAndrew Rybchenko
2915e111ed8SAndrew Rybchenko return (0);
2925e111ed8SAndrew Rybchenko
2935e111ed8SAndrew Rybchenko fail1:
2945e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
2955e111ed8SAndrew Rybchenko
2965e111ed8SAndrew Rybchenko return (rc);
2975e111ed8SAndrew Rybchenko }
2985e111ed8SAndrew Rybchenko
2993c1c5cc4SAndrew Rybchenko #endif /* EFX_OPTS_EF10() */
3003c1c5cc4SAndrew Rybchenko
3013c1c5cc4SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10()
3023c1c5cc4SAndrew Rybchenko
3035e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
3045e111ed8SAndrew Rybchenko efx_mcdi_get_mac_address_pf(
3055e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
3065e111ed8SAndrew Rybchenko __out_ecount_opt(6) uint8_t mac_addrp[6])
3075e111ed8SAndrew Rybchenko {
3085e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
3095e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_MAC_ADDRESSES_IN_LEN,
3105e111ed8SAndrew Rybchenko MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
3115e111ed8SAndrew Rybchenko efx_rc_t rc;
3125e111ed8SAndrew Rybchenko
3133c1c5cc4SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
3145e111ed8SAndrew Rybchenko
3155e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
3165e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
3175e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_MAC_ADDRESSES_IN_LEN;
3185e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
3195e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN;
3205e111ed8SAndrew Rybchenko
3215e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
3225e111ed8SAndrew Rybchenko
3235e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
3245e111ed8SAndrew Rybchenko rc = req.emr_rc;
3255e111ed8SAndrew Rybchenko goto fail1;
3265e111ed8SAndrew Rybchenko }
3275e111ed8SAndrew Rybchenko
3285e111ed8SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) {
3295e111ed8SAndrew Rybchenko rc = EMSGSIZE;
3305e111ed8SAndrew Rybchenko goto fail2;
3315e111ed8SAndrew Rybchenko }
3325e111ed8SAndrew Rybchenko
3335e111ed8SAndrew Rybchenko if (MCDI_OUT_DWORD(req, GET_MAC_ADDRESSES_OUT_MAC_COUNT) < 1) {
3345e111ed8SAndrew Rybchenko rc = ENOENT;
3355e111ed8SAndrew Rybchenko goto fail3;
3365e111ed8SAndrew Rybchenko }
3375e111ed8SAndrew Rybchenko
3385e111ed8SAndrew Rybchenko if (mac_addrp != NULL) {
3395e111ed8SAndrew Rybchenko uint8_t *addrp;
3405e111ed8SAndrew Rybchenko
3415e111ed8SAndrew Rybchenko addrp = MCDI_OUT2(req, uint8_t,
3425e111ed8SAndrew Rybchenko GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE);
3435e111ed8SAndrew Rybchenko
3445e111ed8SAndrew Rybchenko EFX_MAC_ADDR_COPY(mac_addrp, addrp);
3455e111ed8SAndrew Rybchenko }
3465e111ed8SAndrew Rybchenko
3475e111ed8SAndrew Rybchenko return (0);
3485e111ed8SAndrew Rybchenko
3495e111ed8SAndrew Rybchenko fail3:
3505e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
3515e111ed8SAndrew Rybchenko fail2:
3525e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
3535e111ed8SAndrew Rybchenko fail1:
3545e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
3555e111ed8SAndrew Rybchenko
3565e111ed8SAndrew Rybchenko return (rc);
3575e111ed8SAndrew Rybchenko }
3585e111ed8SAndrew Rybchenko
3595e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
3605e111ed8SAndrew Rybchenko efx_mcdi_get_mac_address_vf(
3615e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
3625e111ed8SAndrew Rybchenko __out_ecount_opt(6) uint8_t mac_addrp[6])
3635e111ed8SAndrew Rybchenko {
3645e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
3655e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN,
3665e111ed8SAndrew Rybchenko MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX);
3675e111ed8SAndrew Rybchenko efx_rc_t rc;
3685e111ed8SAndrew Rybchenko
3693c1c5cc4SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
3705e111ed8SAndrew Rybchenko
3715e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES;
3725e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
3735e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN;
3745e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
3755e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX;
3765e111ed8SAndrew Rybchenko
3775e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID,
3785e111ed8SAndrew Rybchenko EVB_PORT_ID_ASSIGNED);
3795e111ed8SAndrew Rybchenko
3805e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
3815e111ed8SAndrew Rybchenko
3825e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
3835e111ed8SAndrew Rybchenko rc = req.emr_rc;
3845e111ed8SAndrew Rybchenko goto fail1;
3855e111ed8SAndrew Rybchenko }
3865e111ed8SAndrew Rybchenko
3875e111ed8SAndrew Rybchenko if (req.emr_out_length_used <
3885e111ed8SAndrew Rybchenko MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN) {
3895e111ed8SAndrew Rybchenko rc = EMSGSIZE;
3905e111ed8SAndrew Rybchenko goto fail2;
3915e111ed8SAndrew Rybchenko }
3925e111ed8SAndrew Rybchenko
3935e111ed8SAndrew Rybchenko if (MCDI_OUT_DWORD(req,
3945e111ed8SAndrew Rybchenko VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT) < 1) {
3955e111ed8SAndrew Rybchenko rc = ENOENT;
3965e111ed8SAndrew Rybchenko goto fail3;
3975e111ed8SAndrew Rybchenko }
3985e111ed8SAndrew Rybchenko
3995e111ed8SAndrew Rybchenko if (mac_addrp != NULL) {
4005e111ed8SAndrew Rybchenko uint8_t *addrp;
4015e111ed8SAndrew Rybchenko
4025e111ed8SAndrew Rybchenko addrp = MCDI_OUT2(req, uint8_t,
4035e111ed8SAndrew Rybchenko VPORT_GET_MAC_ADDRESSES_OUT_MACADDR);
4045e111ed8SAndrew Rybchenko
4055e111ed8SAndrew Rybchenko EFX_MAC_ADDR_COPY(mac_addrp, addrp);
4065e111ed8SAndrew Rybchenko }
4075e111ed8SAndrew Rybchenko
4085e111ed8SAndrew Rybchenko return (0);
4095e111ed8SAndrew Rybchenko
4105e111ed8SAndrew Rybchenko fail3:
4115e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
4125e111ed8SAndrew Rybchenko fail2:
4135e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
4145e111ed8SAndrew Rybchenko fail1:
4155e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4165e111ed8SAndrew Rybchenko
4175e111ed8SAndrew Rybchenko return (rc);
4185e111ed8SAndrew Rybchenko }
4195e111ed8SAndrew Rybchenko
4205e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_clock(__in efx_nic_t * enp,__out uint32_t * sys_freqp,__out uint32_t * dpcpu_freqp)4215e111ed8SAndrew Rybchenko efx_mcdi_get_clock(
4225e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
4235e111ed8SAndrew Rybchenko __out uint32_t *sys_freqp,
4245e111ed8SAndrew Rybchenko __out uint32_t *dpcpu_freqp)
4255e111ed8SAndrew Rybchenko {
4265e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
4275e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CLOCK_IN_LEN,
4285e111ed8SAndrew Rybchenko MC_CMD_GET_CLOCK_OUT_LEN);
4295e111ed8SAndrew Rybchenko efx_rc_t rc;
4305e111ed8SAndrew Rybchenko
4313c1c5cc4SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
4325e111ed8SAndrew Rybchenko
4335e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_CLOCK;
4345e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
4355e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_CLOCK_IN_LEN;
4365e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
4375e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_CLOCK_OUT_LEN;
4385e111ed8SAndrew Rybchenko
4395e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
4405e111ed8SAndrew Rybchenko
4415e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
4425e111ed8SAndrew Rybchenko rc = req.emr_rc;
4435e111ed8SAndrew Rybchenko goto fail1;
4445e111ed8SAndrew Rybchenko }
4455e111ed8SAndrew Rybchenko
4465e111ed8SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_CLOCK_OUT_LEN) {
4475e111ed8SAndrew Rybchenko rc = EMSGSIZE;
4485e111ed8SAndrew Rybchenko goto fail2;
4495e111ed8SAndrew Rybchenko }
4505e111ed8SAndrew Rybchenko
4515e111ed8SAndrew Rybchenko *sys_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_SYS_FREQ);
4525e111ed8SAndrew Rybchenko if (*sys_freqp == 0) {
4535e111ed8SAndrew Rybchenko rc = EINVAL;
4545e111ed8SAndrew Rybchenko goto fail3;
4555e111ed8SAndrew Rybchenko }
4565e111ed8SAndrew Rybchenko *dpcpu_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_DPCPU_FREQ);
4575e111ed8SAndrew Rybchenko if (*dpcpu_freqp == 0) {
4585e111ed8SAndrew Rybchenko rc = EINVAL;
4595e111ed8SAndrew Rybchenko goto fail4;
4605e111ed8SAndrew Rybchenko }
4615e111ed8SAndrew Rybchenko
4625e111ed8SAndrew Rybchenko return (0);
4635e111ed8SAndrew Rybchenko
4645e111ed8SAndrew Rybchenko fail4:
4655e111ed8SAndrew Rybchenko EFSYS_PROBE(fail4);
4665e111ed8SAndrew Rybchenko fail3:
4675e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
4685e111ed8SAndrew Rybchenko fail2:
4695e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
4705e111ed8SAndrew Rybchenko fail1:
4715e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4725e111ed8SAndrew Rybchenko
4735e111ed8SAndrew Rybchenko return (rc);
4745e111ed8SAndrew Rybchenko }
4755e111ed8SAndrew Rybchenko
4765e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_rxdp_config(__in efx_nic_t * enp,__out uint32_t * end_paddingp)4775e111ed8SAndrew Rybchenko efx_mcdi_get_rxdp_config(
4785e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
4795e111ed8SAndrew Rybchenko __out uint32_t *end_paddingp)
4805e111ed8SAndrew Rybchenko {
4815e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
4825e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_RXDP_CONFIG_IN_LEN,
4835e111ed8SAndrew Rybchenko MC_CMD_GET_RXDP_CONFIG_OUT_LEN);
4845e111ed8SAndrew Rybchenko uint32_t end_padding;
4855e111ed8SAndrew Rybchenko efx_rc_t rc;
4865e111ed8SAndrew Rybchenko
4875e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_RXDP_CONFIG;
4885e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
4895e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_RXDP_CONFIG_IN_LEN;
4905e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
4915e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_RXDP_CONFIG_OUT_LEN;
4925e111ed8SAndrew Rybchenko
4935e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
494e27950a0SAndy Moreton
4955e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
4965e111ed8SAndrew Rybchenko rc = req.emr_rc;
4975e111ed8SAndrew Rybchenko goto fail1;
4985e111ed8SAndrew Rybchenko }
4995e111ed8SAndrew Rybchenko
500e27950a0SAndy Moreton if (req.emr_out_length_used < MC_CMD_GET_RXDP_CONFIG_OUT_LEN) {
501e27950a0SAndy Moreton rc = EMSGSIZE;
502e27950a0SAndy Moreton goto fail2;
503e27950a0SAndy Moreton }
504e27950a0SAndy Moreton
5055e111ed8SAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA,
5065e111ed8SAndrew Rybchenko GET_RXDP_CONFIG_OUT_PAD_HOST_DMA) == 0) {
5075e111ed8SAndrew Rybchenko /* RX DMA end padding is disabled */
5085e111ed8SAndrew Rybchenko end_padding = 0;
5095e111ed8SAndrew Rybchenko } else {
5105e111ed8SAndrew Rybchenko switch (MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA,
5115e111ed8SAndrew Rybchenko GET_RXDP_CONFIG_OUT_PAD_HOST_LEN)) {
5125e111ed8SAndrew Rybchenko case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_64:
5135e111ed8SAndrew Rybchenko end_padding = 64;
5145e111ed8SAndrew Rybchenko break;
5155e111ed8SAndrew Rybchenko case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_128:
5165e111ed8SAndrew Rybchenko end_padding = 128;
5175e111ed8SAndrew Rybchenko break;
5185e111ed8SAndrew Rybchenko case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_256:
5195e111ed8SAndrew Rybchenko end_padding = 256;
5205e111ed8SAndrew Rybchenko break;
5215e111ed8SAndrew Rybchenko default:
5225e111ed8SAndrew Rybchenko rc = ENOTSUP;
523e27950a0SAndy Moreton goto fail3;
5245e111ed8SAndrew Rybchenko }
5255e111ed8SAndrew Rybchenko }
5265e111ed8SAndrew Rybchenko
5275e111ed8SAndrew Rybchenko *end_paddingp = end_padding;
5285e111ed8SAndrew Rybchenko
5295e111ed8SAndrew Rybchenko return (0);
5305e111ed8SAndrew Rybchenko
531e27950a0SAndy Moreton fail3:
532e27950a0SAndy Moreton EFSYS_PROBE(fail3);
5335e111ed8SAndrew Rybchenko fail2:
5345e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
5355e111ed8SAndrew Rybchenko fail1:
5365e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5375e111ed8SAndrew Rybchenko
5385e111ed8SAndrew Rybchenko return (rc);
5395e111ed8SAndrew Rybchenko }
5405e111ed8SAndrew Rybchenko
5415e111ed8SAndrew 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)5425e111ed8SAndrew Rybchenko efx_mcdi_get_vector_cfg(
5435e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
5445e111ed8SAndrew Rybchenko __out_opt uint32_t *vec_basep,
5455e111ed8SAndrew Rybchenko __out_opt uint32_t *pf_nvecp,
5465e111ed8SAndrew Rybchenko __out_opt uint32_t *vf_nvecp)
5475e111ed8SAndrew Rybchenko {
5485e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
5495e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_VECTOR_CFG_IN_LEN,
5505e111ed8SAndrew Rybchenko MC_CMD_GET_VECTOR_CFG_OUT_LEN);
5515e111ed8SAndrew Rybchenko efx_rc_t rc;
5525e111ed8SAndrew Rybchenko
5535e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_VECTOR_CFG;
5545e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
5555e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_VECTOR_CFG_IN_LEN;
5565e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
5575e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_VECTOR_CFG_OUT_LEN;
5585e111ed8SAndrew Rybchenko
5595e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
5605e111ed8SAndrew Rybchenko
5615e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
5625e111ed8SAndrew Rybchenko rc = req.emr_rc;
5635e111ed8SAndrew Rybchenko goto fail1;
5645e111ed8SAndrew Rybchenko }
5655e111ed8SAndrew Rybchenko
5665e111ed8SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_VECTOR_CFG_OUT_LEN) {
5675e111ed8SAndrew Rybchenko rc = EMSGSIZE;
5685e111ed8SAndrew Rybchenko goto fail2;
5695e111ed8SAndrew Rybchenko }
5705e111ed8SAndrew Rybchenko
5715e111ed8SAndrew Rybchenko if (vec_basep != NULL)
5725e111ed8SAndrew Rybchenko *vec_basep = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VEC_BASE);
5735e111ed8SAndrew Rybchenko if (pf_nvecp != NULL)
5745e111ed8SAndrew Rybchenko *pf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_PF);
5755e111ed8SAndrew Rybchenko if (vf_nvecp != NULL)
5765e111ed8SAndrew Rybchenko *vf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_VF);
5775e111ed8SAndrew Rybchenko
5785e111ed8SAndrew Rybchenko return (0);
5795e111ed8SAndrew Rybchenko
5805e111ed8SAndrew Rybchenko fail2:
5815e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
5825e111ed8SAndrew Rybchenko fail1:
5835e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5845e111ed8SAndrew Rybchenko
5855e111ed8SAndrew Rybchenko return (rc);
5865e111ed8SAndrew Rybchenko }
5875e111ed8SAndrew Rybchenko
5883c1c5cc4SAndrew Rybchenko __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)5895e111ed8SAndrew Rybchenko efx_mcdi_alloc_vis(
5905e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
5915e111ed8SAndrew Rybchenko __in uint32_t min_vi_count,
5925e111ed8SAndrew Rybchenko __in uint32_t max_vi_count,
5935e111ed8SAndrew Rybchenko __out uint32_t *vi_basep,
5945e111ed8SAndrew Rybchenko __out uint32_t *vi_countp,
5955e111ed8SAndrew Rybchenko __out uint32_t *vi_shiftp)
5965e111ed8SAndrew Rybchenko {
5975e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
5985e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ALLOC_VIS_IN_LEN,
5995e111ed8SAndrew Rybchenko MC_CMD_ALLOC_VIS_EXT_OUT_LEN);
6005e111ed8SAndrew Rybchenko efx_rc_t rc;
6015e111ed8SAndrew Rybchenko
6025e111ed8SAndrew Rybchenko if (vi_countp == NULL) {
6035e111ed8SAndrew Rybchenko rc = EINVAL;
6045e111ed8SAndrew Rybchenko goto fail1;
6055e111ed8SAndrew Rybchenko }
6065e111ed8SAndrew Rybchenko
6075e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_ALLOC_VIS;
6085e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
6095e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN;
6105e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
6115e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_ALLOC_VIS_EXT_OUT_LEN;
6125e111ed8SAndrew Rybchenko
6135e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count);
6145e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count);
6155e111ed8SAndrew Rybchenko
6165e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
6175e111ed8SAndrew Rybchenko
6185e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
6195e111ed8SAndrew Rybchenko rc = req.emr_rc;
6205e111ed8SAndrew Rybchenko goto fail2;
6215e111ed8SAndrew Rybchenko }
6225e111ed8SAndrew Rybchenko
6235e111ed8SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) {
6245e111ed8SAndrew Rybchenko rc = EMSGSIZE;
6255e111ed8SAndrew Rybchenko goto fail3;
6265e111ed8SAndrew Rybchenko }
6275e111ed8SAndrew Rybchenko
6285e111ed8SAndrew Rybchenko *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE);
6295e111ed8SAndrew Rybchenko *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT);
6305e111ed8SAndrew Rybchenko
6315e111ed8SAndrew Rybchenko /* Report VI_SHIFT if available (always zero for Huntington) */
6325e111ed8SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_EXT_OUT_LEN)
6335e111ed8SAndrew Rybchenko *vi_shiftp = 0;
6345e111ed8SAndrew Rybchenko else
6355e111ed8SAndrew Rybchenko *vi_shiftp = MCDI_OUT_DWORD(req, ALLOC_VIS_EXT_OUT_VI_SHIFT);
6365e111ed8SAndrew Rybchenko
6375e111ed8SAndrew Rybchenko return (0);
6385e111ed8SAndrew Rybchenko
6395e111ed8SAndrew Rybchenko fail3:
6405e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
6415e111ed8SAndrew Rybchenko fail2:
6425e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
6435e111ed8SAndrew Rybchenko fail1:
6445e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
6455e111ed8SAndrew Rybchenko
6465e111ed8SAndrew Rybchenko return (rc);
6475e111ed8SAndrew Rybchenko }
6485e111ed8SAndrew Rybchenko
6495e111ed8SAndrew Rybchenko
6503c1c5cc4SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_free_vis(__in efx_nic_t * enp)6515e111ed8SAndrew Rybchenko efx_mcdi_free_vis(
6525e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
6535e111ed8SAndrew Rybchenko {
6545e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
6555e111ed8SAndrew Rybchenko efx_rc_t rc;
6565e111ed8SAndrew Rybchenko
6575e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0);
6585e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0);
6595e111ed8SAndrew Rybchenko
6605e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_FREE_VIS;
6615e111ed8SAndrew Rybchenko req.emr_in_buf = NULL;
6625e111ed8SAndrew Rybchenko req.emr_in_length = 0;
6635e111ed8SAndrew Rybchenko req.emr_out_buf = NULL;
6645e111ed8SAndrew Rybchenko req.emr_out_length = 0;
6655e111ed8SAndrew Rybchenko
6665e111ed8SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
6675e111ed8SAndrew Rybchenko
6685e111ed8SAndrew Rybchenko /* Ignore ELREADY (no allocated VIs, so nothing to free) */
6695e111ed8SAndrew Rybchenko if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) {
6705e111ed8SAndrew Rybchenko rc = req.emr_rc;
6715e111ed8SAndrew Rybchenko goto fail1;
6725e111ed8SAndrew Rybchenko }
6735e111ed8SAndrew Rybchenko
6745e111ed8SAndrew Rybchenko return (0);
6755e111ed8SAndrew Rybchenko
6765e111ed8SAndrew Rybchenko fail1:
6775e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
6785e111ed8SAndrew Rybchenko
6795e111ed8SAndrew Rybchenko return (rc);
6805e111ed8SAndrew Rybchenko }
6815e111ed8SAndrew Rybchenko
6823c1c5cc4SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */
6833c1c5cc4SAndrew Rybchenko
6843c1c5cc4SAndrew Rybchenko #if EFX_OPTS_EF10()
6855e111ed8SAndrew Rybchenko
6865e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_alloc_piobuf(__in efx_nic_t * enp,__out efx_piobuf_handle_t * handlep)6875e111ed8SAndrew Rybchenko efx_mcdi_alloc_piobuf(
6885e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
6895e111ed8SAndrew Rybchenko __out efx_piobuf_handle_t *handlep)
6905e111ed8SAndrew Rybchenko {
6915e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
6925e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ALLOC_PIOBUF_IN_LEN,
6935e111ed8SAndrew Rybchenko MC_CMD_ALLOC_PIOBUF_OUT_LEN);
6945e111ed8SAndrew Rybchenko efx_rc_t rc;
6955e111ed8SAndrew Rybchenko
6965e111ed8SAndrew Rybchenko if (handlep == NULL) {
6975e111ed8SAndrew Rybchenko rc = EINVAL;
6985e111ed8SAndrew Rybchenko goto fail1;
6995e111ed8SAndrew Rybchenko }
7005e111ed8SAndrew Rybchenko
7015e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_ALLOC_PIOBUF;
7025e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
7035e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN;
7045e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
7055e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN;
7065e111ed8SAndrew Rybchenko
7075e111ed8SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
7085e111ed8SAndrew Rybchenko
7095e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
7105e111ed8SAndrew Rybchenko rc = req.emr_rc;
7115e111ed8SAndrew Rybchenko goto fail2;
7125e111ed8SAndrew Rybchenko }
7135e111ed8SAndrew Rybchenko
7145e111ed8SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) {
7155e111ed8SAndrew Rybchenko rc = EMSGSIZE;
7165e111ed8SAndrew Rybchenko goto fail3;
7175e111ed8SAndrew Rybchenko }
7185e111ed8SAndrew Rybchenko
7195e111ed8SAndrew Rybchenko *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE);
7205e111ed8SAndrew Rybchenko
7215e111ed8SAndrew Rybchenko return (0);
7225e111ed8SAndrew Rybchenko
7235e111ed8SAndrew Rybchenko fail3:
7245e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
7255e111ed8SAndrew Rybchenko fail2:
7265e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
7275e111ed8SAndrew Rybchenko fail1:
7285e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
7295e111ed8SAndrew Rybchenko
7305e111ed8SAndrew Rybchenko return (rc);
7315e111ed8SAndrew Rybchenko }
7325e111ed8SAndrew Rybchenko
7335e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_free_piobuf(__in efx_nic_t * enp,__in efx_piobuf_handle_t handle)7345e111ed8SAndrew Rybchenko efx_mcdi_free_piobuf(
7355e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
7365e111ed8SAndrew Rybchenko __in efx_piobuf_handle_t handle)
7375e111ed8SAndrew Rybchenko {
7385e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
7395e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FREE_PIOBUF_IN_LEN,
7405e111ed8SAndrew Rybchenko MC_CMD_FREE_PIOBUF_OUT_LEN);
7415e111ed8SAndrew Rybchenko efx_rc_t rc;
7425e111ed8SAndrew Rybchenko
7435e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_FREE_PIOBUF;
7445e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
7455e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN;
7465e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
7475e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN;
7485e111ed8SAndrew Rybchenko
7495e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle);
7505e111ed8SAndrew Rybchenko
7515e111ed8SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
7525e111ed8SAndrew Rybchenko
7535e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
7545e111ed8SAndrew Rybchenko rc = req.emr_rc;
7555e111ed8SAndrew Rybchenko goto fail1;
7565e111ed8SAndrew Rybchenko }
7575e111ed8SAndrew Rybchenko
7585e111ed8SAndrew Rybchenko return (0);
7595e111ed8SAndrew Rybchenko
7605e111ed8SAndrew Rybchenko fail1:
7615e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
7625e111ed8SAndrew Rybchenko
7635e111ed8SAndrew Rybchenko return (rc);
7645e111ed8SAndrew Rybchenko }
7655e111ed8SAndrew Rybchenko
7665e111ed8SAndrew 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)7675e111ed8SAndrew Rybchenko efx_mcdi_link_piobuf(
7685e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
7695e111ed8SAndrew Rybchenko __in uint32_t vi_index,
7705e111ed8SAndrew Rybchenko __in efx_piobuf_handle_t handle)
7715e111ed8SAndrew Rybchenko {
7725e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
7735e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LINK_PIOBUF_IN_LEN,
7745e111ed8SAndrew Rybchenko MC_CMD_LINK_PIOBUF_OUT_LEN);
7755e111ed8SAndrew Rybchenko efx_rc_t rc;
7765e111ed8SAndrew Rybchenko
7775e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_LINK_PIOBUF;
7785e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
7795e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN;
7805e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
7815e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN;
7825e111ed8SAndrew Rybchenko
7835e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle);
7845e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
7855e111ed8SAndrew Rybchenko
7865e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
7875e111ed8SAndrew Rybchenko
7885e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
7895e111ed8SAndrew Rybchenko rc = req.emr_rc;
7905e111ed8SAndrew Rybchenko goto fail1;
7915e111ed8SAndrew Rybchenko }
7925e111ed8SAndrew Rybchenko
7935e111ed8SAndrew Rybchenko return (0);
7945e111ed8SAndrew Rybchenko
7955e111ed8SAndrew Rybchenko fail1:
7965e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
7975e111ed8SAndrew Rybchenko
7985e111ed8SAndrew Rybchenko return (rc);
7995e111ed8SAndrew Rybchenko }
8005e111ed8SAndrew Rybchenko
8015e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_unlink_piobuf(__in efx_nic_t * enp,__in uint32_t vi_index)8025e111ed8SAndrew Rybchenko efx_mcdi_unlink_piobuf(
8035e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
8045e111ed8SAndrew Rybchenko __in uint32_t vi_index)
8055e111ed8SAndrew Rybchenko {
8065e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
8075e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_UNLINK_PIOBUF_IN_LEN,
8085e111ed8SAndrew Rybchenko MC_CMD_UNLINK_PIOBUF_OUT_LEN);
8095e111ed8SAndrew Rybchenko efx_rc_t rc;
8105e111ed8SAndrew Rybchenko
8115e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_UNLINK_PIOBUF;
8125e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
8135e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN;
8145e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
8155e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN;
8165e111ed8SAndrew Rybchenko
8175e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
8185e111ed8SAndrew Rybchenko
8195e111ed8SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
8205e111ed8SAndrew Rybchenko
8215e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
8225e111ed8SAndrew Rybchenko rc = req.emr_rc;
8235e111ed8SAndrew Rybchenko goto fail1;
8245e111ed8SAndrew Rybchenko }
8255e111ed8SAndrew Rybchenko
8265e111ed8SAndrew Rybchenko return (0);
8275e111ed8SAndrew Rybchenko
8285e111ed8SAndrew Rybchenko fail1:
8295e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
8305e111ed8SAndrew Rybchenko
8315e111ed8SAndrew Rybchenko return (rc);
8325e111ed8SAndrew Rybchenko }
8335e111ed8SAndrew Rybchenko
8345e111ed8SAndrew Rybchenko static void
ef10_nic_alloc_piobufs(__in efx_nic_t * enp,__in uint32_t max_piobuf_count)8355e111ed8SAndrew Rybchenko ef10_nic_alloc_piobufs(
8365e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
8375e111ed8SAndrew Rybchenko __in uint32_t max_piobuf_count)
8385e111ed8SAndrew Rybchenko {
8395e111ed8SAndrew Rybchenko efx_piobuf_handle_t *handlep;
8405e111ed8SAndrew Rybchenko unsigned int i;
8415e111ed8SAndrew Rybchenko
8425e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(max_piobuf_count, <=,
8435e111ed8SAndrew Rybchenko EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle));
8445e111ed8SAndrew Rybchenko
8455e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count = 0;
8465e111ed8SAndrew Rybchenko
8475e111ed8SAndrew Rybchenko for (i = 0; i < max_piobuf_count; i++) {
8485e111ed8SAndrew Rybchenko handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
8495e111ed8SAndrew Rybchenko
8505e111ed8SAndrew Rybchenko if (efx_mcdi_alloc_piobuf(enp, handlep) != 0)
8515e111ed8SAndrew Rybchenko goto fail1;
8525e111ed8SAndrew Rybchenko
8535e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_pio_alloc_map[i] = 0;
8545e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count++;
8555e111ed8SAndrew Rybchenko }
8565e111ed8SAndrew Rybchenko
8575e111ed8SAndrew Rybchenko return;
8585e111ed8SAndrew Rybchenko
8595e111ed8SAndrew Rybchenko fail1:
8605e111ed8SAndrew Rybchenko for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
8615e111ed8SAndrew Rybchenko handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
8625e111ed8SAndrew Rybchenko
8635e111ed8SAndrew Rybchenko (void) efx_mcdi_free_piobuf(enp, *handlep);
8645e111ed8SAndrew Rybchenko *handlep = EFX_PIOBUF_HANDLE_INVALID;
8655e111ed8SAndrew Rybchenko }
8665e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count = 0;
8675e111ed8SAndrew Rybchenko }
8685e111ed8SAndrew Rybchenko
8695e111ed8SAndrew Rybchenko
8705e111ed8SAndrew Rybchenko static void
ef10_nic_free_piobufs(__in efx_nic_t * enp)8715e111ed8SAndrew Rybchenko ef10_nic_free_piobufs(
8725e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
8735e111ed8SAndrew Rybchenko {
8745e111ed8SAndrew Rybchenko efx_piobuf_handle_t *handlep;
8755e111ed8SAndrew Rybchenko unsigned int i;
8765e111ed8SAndrew Rybchenko
8775e111ed8SAndrew Rybchenko for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
8785e111ed8SAndrew Rybchenko handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
8795e111ed8SAndrew Rybchenko
8805e111ed8SAndrew Rybchenko (void) efx_mcdi_free_piobuf(enp, *handlep);
8815e111ed8SAndrew Rybchenko *handlep = EFX_PIOBUF_HANDLE_INVALID;
8825e111ed8SAndrew Rybchenko }
8835e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count = 0;
8845e111ed8SAndrew Rybchenko }
8855e111ed8SAndrew Rybchenko
8865e111ed8SAndrew Rybchenko /* Sub-allocate a block from a piobuf */
8875e111ed8SAndrew 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)8885e111ed8SAndrew Rybchenko ef10_nic_pio_alloc(
8895e111ed8SAndrew Rybchenko __inout efx_nic_t *enp,
8905e111ed8SAndrew Rybchenko __out uint32_t *bufnump,
8915e111ed8SAndrew Rybchenko __out efx_piobuf_handle_t *handlep,
8925e111ed8SAndrew Rybchenko __out uint32_t *blknump,
8935e111ed8SAndrew Rybchenko __out uint32_t *offsetp,
8945e111ed8SAndrew Rybchenko __out size_t *sizep)
8955e111ed8SAndrew Rybchenko {
8965e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &enp->en_nic_cfg;
8975e111ed8SAndrew Rybchenko efx_drv_cfg_t *edcp = &enp->en_drv_cfg;
8985e111ed8SAndrew Rybchenko uint32_t blk_per_buf;
8995e111ed8SAndrew Rybchenko uint32_t buf, blk;
9005e111ed8SAndrew Rybchenko efx_rc_t rc;
9015e111ed8SAndrew Rybchenko
9025e111ed8SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
9035e111ed8SAndrew Rybchenko EFSYS_ASSERT(bufnump);
9045e111ed8SAndrew Rybchenko EFSYS_ASSERT(handlep);
9055e111ed8SAndrew Rybchenko EFSYS_ASSERT(blknump);
9065e111ed8SAndrew Rybchenko EFSYS_ASSERT(offsetp);
9075e111ed8SAndrew Rybchenko EFSYS_ASSERT(sizep);
9085e111ed8SAndrew Rybchenko
9095e111ed8SAndrew Rybchenko if ((edcp->edc_pio_alloc_size == 0) ||
9105e111ed8SAndrew Rybchenko (enp->en_arch.ef10.ena_piobuf_count == 0)) {
9115e111ed8SAndrew Rybchenko rc = ENOMEM;
9125e111ed8SAndrew Rybchenko goto fail1;
9135e111ed8SAndrew Rybchenko }
9145e111ed8SAndrew Rybchenko blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size;
9155e111ed8SAndrew Rybchenko
9165e111ed8SAndrew Rybchenko for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) {
9175e111ed8SAndrew Rybchenko uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf];
9185e111ed8SAndrew Rybchenko
9195e111ed8SAndrew Rybchenko if (~(*map) == 0)
9205e111ed8SAndrew Rybchenko continue;
9215e111ed8SAndrew Rybchenko
9225e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map)));
9235e111ed8SAndrew Rybchenko for (blk = 0; blk < blk_per_buf; blk++) {
9245e111ed8SAndrew Rybchenko if ((*map & (1u << blk)) == 0) {
9255e111ed8SAndrew Rybchenko *map |= (1u << blk);
9265e111ed8SAndrew Rybchenko goto done;
9275e111ed8SAndrew Rybchenko }
9285e111ed8SAndrew Rybchenko }
9295e111ed8SAndrew Rybchenko }
9305e111ed8SAndrew Rybchenko rc = ENOMEM;
9315e111ed8SAndrew Rybchenko goto fail2;
9325e111ed8SAndrew Rybchenko
9335e111ed8SAndrew Rybchenko done:
9345e111ed8SAndrew Rybchenko *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf];
9355e111ed8SAndrew Rybchenko *bufnump = buf;
9365e111ed8SAndrew Rybchenko *blknump = blk;
9375e111ed8SAndrew Rybchenko *sizep = edcp->edc_pio_alloc_size;
9385e111ed8SAndrew Rybchenko *offsetp = blk * (*sizep);
9395e111ed8SAndrew Rybchenko
9405e111ed8SAndrew Rybchenko return (0);
9415e111ed8SAndrew Rybchenko
9425e111ed8SAndrew Rybchenko fail2:
9435e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
9445e111ed8SAndrew Rybchenko fail1:
9455e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
9465e111ed8SAndrew Rybchenko
9475e111ed8SAndrew Rybchenko return (rc);
9485e111ed8SAndrew Rybchenko }
9495e111ed8SAndrew Rybchenko
9505e111ed8SAndrew Rybchenko /* Free a piobuf sub-allocated block */
9515e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_pio_free(__inout efx_nic_t * enp,__in uint32_t bufnum,__in uint32_t blknum)9525e111ed8SAndrew Rybchenko ef10_nic_pio_free(
9535e111ed8SAndrew Rybchenko __inout efx_nic_t *enp,
9545e111ed8SAndrew Rybchenko __in uint32_t bufnum,
9555e111ed8SAndrew Rybchenko __in uint32_t blknum)
9565e111ed8SAndrew Rybchenko {
9575e111ed8SAndrew Rybchenko uint32_t *map;
9585e111ed8SAndrew Rybchenko efx_rc_t rc;
9595e111ed8SAndrew Rybchenko
9605e111ed8SAndrew Rybchenko if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) ||
9615e111ed8SAndrew Rybchenko (blknum >= (8 * sizeof (*map)))) {
9625e111ed8SAndrew Rybchenko rc = EINVAL;
9635e111ed8SAndrew Rybchenko goto fail1;
9645e111ed8SAndrew Rybchenko }
9655e111ed8SAndrew Rybchenko
9665e111ed8SAndrew Rybchenko map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum];
9675e111ed8SAndrew Rybchenko if ((*map & (1u << blknum)) == 0) {
9685e111ed8SAndrew Rybchenko rc = ENOENT;
9695e111ed8SAndrew Rybchenko goto fail2;
9705e111ed8SAndrew Rybchenko }
9715e111ed8SAndrew Rybchenko *map &= ~(1u << blknum);
9725e111ed8SAndrew Rybchenko
9735e111ed8SAndrew Rybchenko return (0);
9745e111ed8SAndrew Rybchenko
9755e111ed8SAndrew Rybchenko fail2:
9765e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
9775e111ed8SAndrew Rybchenko fail1:
9785e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
9795e111ed8SAndrew Rybchenko
9805e111ed8SAndrew Rybchenko return (rc);
9815e111ed8SAndrew Rybchenko }
9825e111ed8SAndrew Rybchenko
9835e111ed8SAndrew 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)9845e111ed8SAndrew Rybchenko ef10_nic_pio_link(
9855e111ed8SAndrew Rybchenko __inout efx_nic_t *enp,
9865e111ed8SAndrew Rybchenko __in uint32_t vi_index,
9875e111ed8SAndrew Rybchenko __in efx_piobuf_handle_t handle)
9885e111ed8SAndrew Rybchenko {
9895e111ed8SAndrew Rybchenko return (efx_mcdi_link_piobuf(enp, vi_index, handle));
9905e111ed8SAndrew Rybchenko }
9915e111ed8SAndrew Rybchenko
9925e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_pio_unlink(__inout efx_nic_t * enp,__in uint32_t vi_index)9935e111ed8SAndrew Rybchenko ef10_nic_pio_unlink(
9945e111ed8SAndrew Rybchenko __inout efx_nic_t *enp,
9955e111ed8SAndrew Rybchenko __in uint32_t vi_index)
9965e111ed8SAndrew Rybchenko {
9975e111ed8SAndrew Rybchenko return (efx_mcdi_unlink_piobuf(enp, vi_index));
9985e111ed8SAndrew Rybchenko }
9995e111ed8SAndrew Rybchenko
10003c1c5cc4SAndrew Rybchenko #endif /* EFX_OPTS_EF10() */
10013c1c5cc4SAndrew Rybchenko
10023c1c5cc4SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10()
10033c1c5cc4SAndrew Rybchenko
10045e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t
ef10_mcdi_get_pf_count(__in efx_nic_t * enp,__out uint32_t * pf_countp)10055e111ed8SAndrew Rybchenko ef10_mcdi_get_pf_count(
10065e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
10075e111ed8SAndrew Rybchenko __out uint32_t *pf_countp)
10085e111ed8SAndrew Rybchenko {
10095e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
10105e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PF_COUNT_IN_LEN,
10115e111ed8SAndrew Rybchenko MC_CMD_GET_PF_COUNT_OUT_LEN);
10125e111ed8SAndrew Rybchenko efx_rc_t rc;
10135e111ed8SAndrew Rybchenko
10145e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_PF_COUNT;
10155e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
10165e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_PF_COUNT_IN_LEN;
10175e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
10185e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_PF_COUNT_OUT_LEN;
10195e111ed8SAndrew Rybchenko
10205e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
10215e111ed8SAndrew Rybchenko
10225e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
10235e111ed8SAndrew Rybchenko rc = req.emr_rc;
10245e111ed8SAndrew Rybchenko goto fail1;
10255e111ed8SAndrew Rybchenko }
10265e111ed8SAndrew Rybchenko
10275e111ed8SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_PF_COUNT_OUT_LEN) {
10285e111ed8SAndrew Rybchenko rc = EMSGSIZE;
10295e111ed8SAndrew Rybchenko goto fail2;
10305e111ed8SAndrew Rybchenko }
10315e111ed8SAndrew Rybchenko
10325e111ed8SAndrew Rybchenko *pf_countp = *MCDI_OUT(req, uint8_t,
10335e111ed8SAndrew Rybchenko MC_CMD_GET_PF_COUNT_OUT_PF_COUNT_OFST);
10345e111ed8SAndrew Rybchenko
10355e111ed8SAndrew Rybchenko EFSYS_ASSERT(*pf_countp != 0);
10365e111ed8SAndrew Rybchenko
10375e111ed8SAndrew Rybchenko return (0);
10385e111ed8SAndrew Rybchenko
10395e111ed8SAndrew Rybchenko fail2:
10405e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
10415e111ed8SAndrew Rybchenko fail1:
10425e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
10435e111ed8SAndrew Rybchenko
10445e111ed8SAndrew Rybchenko return (rc);
10455e111ed8SAndrew Rybchenko }
10465e111ed8SAndrew Rybchenko
10475e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t
ef10_nic_get_physical_port_usage(__in efx_nic_t * enp,__in_ecount (pfs_to_ports_size)uint8_t * pfs_to_ports,__in size_t pfs_to_ports_size,__out efx_port_usage_t * port_usagep)104894626988SSandilya Bhagi ef10_nic_get_physical_port_usage(
104994626988SSandilya Bhagi __in efx_nic_t *enp,
105094626988SSandilya Bhagi __in_ecount(pfs_to_ports_size) uint8_t *pfs_to_ports,
105194626988SSandilya Bhagi __in size_t pfs_to_ports_size,
105294626988SSandilya Bhagi __out efx_port_usage_t *port_usagep)
105394626988SSandilya Bhagi {
105494626988SSandilya Bhagi efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
105594626988SSandilya Bhagi efx_port_usage_t port_usage;
105694626988SSandilya Bhagi uint8_t phy_port;
105794626988SSandilya Bhagi efx_rc_t rc;
105894626988SSandilya Bhagi size_t pf;
105994626988SSandilya Bhagi
106094626988SSandilya Bhagi /*
106194626988SSandilya Bhagi * The sharing of physical ports between functions are determined
106294626988SSandilya Bhagi * in the following way.
106394626988SSandilya Bhagi * 1. If VFs are enabled then the physical port is shared.
106494626988SSandilya Bhagi * 2. Retrieve PFs to ports assignment.
106594626988SSandilya Bhagi * 3. If PF 0 assignment cannot be retrieved(ACCESS_DENIED), it
106694626988SSandilya Bhagi * implies this is an unprivileged function. An unprivileged
106794626988SSandilya Bhagi * function indicates the physical port must be shared with
106894626988SSandilya Bhagi * another privileged function.
106994626988SSandilya Bhagi * 4. If PF 0 assignment can be retrieved, it indicates this
107094626988SSandilya Bhagi * function is privileged. Now, read all other PF's physical
107194626988SSandilya Bhagi * port number assignment and check if the current PF's physical
107294626988SSandilya Bhagi * port is shared with any other PF's physical port.
107394626988SSandilya Bhagi * NOTE: PF 0 is always privileged function.
107494626988SSandilya Bhagi */
107594626988SSandilya Bhagi
107694626988SSandilya Bhagi if (EFX_PCI_FUNCTION_IS_VF(encp)) {
107794626988SSandilya Bhagi port_usage = EFX_PORT_USAGE_SHARED;
107894626988SSandilya Bhagi goto out;
107994626988SSandilya Bhagi }
108094626988SSandilya Bhagi
108194626988SSandilya Bhagi if (pfs_to_ports[0] ==
108294626988SSandilya Bhagi MC_CMD_GET_CAPABILITIES_V2_OUT_ACCESS_NOT_PERMITTED) {
108394626988SSandilya Bhagi /*
108494626988SSandilya Bhagi * This is unprivileged function as it do not have sufficient
108594626988SSandilya Bhagi * privileges to read the value, this implies the physical port
108694626988SSandilya Bhagi * is shared between this function and another privileged
108794626988SSandilya Bhagi * function
108894626988SSandilya Bhagi */
108994626988SSandilya Bhagi port_usage = EFX_PORT_USAGE_SHARED;
109094626988SSandilya Bhagi goto out;
109194626988SSandilya Bhagi }
109294626988SSandilya Bhagi
109394626988SSandilya Bhagi if (encp->enc_pf >= pfs_to_ports_size) {
109494626988SSandilya Bhagi rc = EINVAL;
109594626988SSandilya Bhagi goto fail1;
109694626988SSandilya Bhagi }
109794626988SSandilya Bhagi phy_port = pfs_to_ports[encp->enc_pf];
109894626988SSandilya Bhagi
109994626988SSandilya Bhagi /*
110094626988SSandilya Bhagi * This is privileged function as it is able read the value of
110194626988SSandilya Bhagi * PF 0. Now, check if any other function share the same physical
110294626988SSandilya Bhagi * port number as this function.
110394626988SSandilya Bhagi */
110494626988SSandilya Bhagi for (pf = 0; pf < pfs_to_ports_size; pf++) {
110594626988SSandilya Bhagi if ((encp->enc_pf != pf) && (phy_port == pfs_to_ports[pf])) {
110694626988SSandilya Bhagi /* Found match, PFs share the same physical port */
110794626988SSandilya Bhagi port_usage = EFX_PORT_USAGE_SHARED;
110894626988SSandilya Bhagi goto out;
110994626988SSandilya Bhagi }
111094626988SSandilya Bhagi }
111194626988SSandilya Bhagi
111294626988SSandilya Bhagi port_usage = EFX_PORT_USAGE_EXCLUSIVE;
111394626988SSandilya Bhagi
111494626988SSandilya Bhagi out:
111594626988SSandilya Bhagi *port_usagep = port_usage;
111694626988SSandilya Bhagi return (0);
111794626988SSandilya Bhagi
111894626988SSandilya Bhagi fail1:
111994626988SSandilya Bhagi EFSYS_PROBE1(fail1, efx_rc_t, rc);
112094626988SSandilya Bhagi
112194626988SSandilya Bhagi return (rc);
112294626988SSandilya Bhagi }
112394626988SSandilya Bhagi
112494626988SSandilya Bhagi static __checkReturn efx_rc_t
ef10_get_datapath_caps(__in efx_nic_t * enp)11255e111ed8SAndrew Rybchenko ef10_get_datapath_caps(
11265e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
11275e111ed8SAndrew Rybchenko {
11285e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
11295e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
11305e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CAPABILITIES_IN_LEN,
1131777da150SIvan Malov MC_CMD_GET_CAPABILITIES_V9_OUT_LEN);
11325e111ed8SAndrew Rybchenko efx_rc_t rc;
11335e111ed8SAndrew Rybchenko
11345e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_CAPABILITIES;
11355e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
11365e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN;
11375e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
1138777da150SIvan Malov req.emr_out_length = MC_CMD_GET_CAPABILITIES_V9_OUT_LEN;
11395e111ed8SAndrew Rybchenko
11405e111ed8SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
11415e111ed8SAndrew Rybchenko
11425e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
11435e111ed8SAndrew Rybchenko rc = req.emr_rc;
1144495c8fefSAndrew Rybchenko goto fail1;
11455e111ed8SAndrew Rybchenko }
11465e111ed8SAndrew Rybchenko
11475e111ed8SAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) {
11485e111ed8SAndrew Rybchenko rc = EMSGSIZE;
1149495c8fefSAndrew Rybchenko goto fail2;
11505e111ed8SAndrew Rybchenko }
11515e111ed8SAndrew Rybchenko
11525e111ed8SAndrew Rybchenko #define CAP_FLAGS1(_req, _flag) \
11535e111ed8SAndrew Rybchenko (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_OUT_FLAGS1) & \
11545e111ed8SAndrew Rybchenko (1u << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## _flag ## _LBN)))
11555e111ed8SAndrew Rybchenko
11565e111ed8SAndrew Rybchenko #define CAP_FLAGS2(_req, _flag) \
11575e111ed8SAndrew Rybchenko (((_req).emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) && \
11585e111ed8SAndrew Rybchenko (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_V2_OUT_FLAGS2) & \
11595e111ed8SAndrew Rybchenko (1u << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## _flag ## _LBN))))
11605e111ed8SAndrew Rybchenko
1161f8a60f76SAndy Moreton #define CAP_FLAGS3(_req, _flag) \
1162f8a60f76SAndy Moreton (((_req).emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V7_OUT_LEN) && \
1163f8a60f76SAndy Moreton (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_V7_OUT_FLAGS3) & \
1164f8a60f76SAndy Moreton (1u << (MC_CMD_GET_CAPABILITIES_V7_OUT_ ## _flag ## _LBN))))
1165f8a60f76SAndy Moreton
1166d9d41eeaSAndrew Rybchenko /* Check if RXDP firmware inserts 14 byte prefix */
1167d9d41eeaSAndrew Rybchenko if (CAP_FLAGS1(req, RX_PREFIX_LEN_14))
11685e111ed8SAndrew Rybchenko encp->enc_rx_prefix_size = 14;
1169d9d41eeaSAndrew Rybchenko else
1170d9d41eeaSAndrew Rybchenko encp->enc_rx_prefix_size = 0;
11715e111ed8SAndrew Rybchenko
11725e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
11735e111ed8SAndrew Rybchenko /* Check if the firmware supports additional RSS modes */
11745e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, ADDITIONAL_RSS_MODES))
11755e111ed8SAndrew Rybchenko encp->enc_rx_scale_additional_modes_supported = B_TRUE;
11765e111ed8SAndrew Rybchenko else
11775e111ed8SAndrew Rybchenko encp->enc_rx_scale_additional_modes_supported = B_FALSE;
11785e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
11795e111ed8SAndrew Rybchenko
11805e111ed8SAndrew Rybchenko /* Check if the firmware supports TSO */
11815e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, TX_TSO))
11825e111ed8SAndrew Rybchenko encp->enc_fw_assisted_tso_enabled = B_TRUE;
11835e111ed8SAndrew Rybchenko else
11845e111ed8SAndrew Rybchenko encp->enc_fw_assisted_tso_enabled = B_FALSE;
11855e111ed8SAndrew Rybchenko
11865e111ed8SAndrew Rybchenko /* Check if the firmware supports FATSOv2 */
11875e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, TX_TSO_V2)) {
11885e111ed8SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_enabled = B_TRUE;
11895e111ed8SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_n_contexts = MCDI_OUT_WORD(req,
11905e111ed8SAndrew Rybchenko GET_CAPABILITIES_V2_OUT_TX_TSO_V2_N_CONTEXTS);
11915e111ed8SAndrew Rybchenko } else {
11925e111ed8SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
11935e111ed8SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_n_contexts = 0;
11945e111ed8SAndrew Rybchenko }
11955e111ed8SAndrew Rybchenko
11965e111ed8SAndrew Rybchenko /* Check if the firmware supports FATSOv2 encap */
11975e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, TX_TSO_V2_ENCAP))
11985e111ed8SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_encap_enabled = B_TRUE;
11995e111ed8SAndrew Rybchenko else
12005e111ed8SAndrew Rybchenko encp->enc_fw_assisted_tso_v2_encap_enabled = B_FALSE;
12015e111ed8SAndrew Rybchenko
12021306effbSIvan Malov /* Check if TSOv3 is supported */
12031306effbSIvan Malov if (CAP_FLAGS2(req, TX_TSO_V3))
12041306effbSIvan Malov encp->enc_tso_v3_enabled = B_TRUE;
12051306effbSIvan Malov else
12061306effbSIvan Malov encp->enc_tso_v3_enabled = B_FALSE;
12071306effbSIvan Malov
12085e111ed8SAndrew Rybchenko /* Check if the firmware has vadapter/vport/vswitch support */
12095e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, EVB))
12105e111ed8SAndrew Rybchenko encp->enc_datapath_cap_evb = B_TRUE;
12115e111ed8SAndrew Rybchenko else
12125e111ed8SAndrew Rybchenko encp->enc_datapath_cap_evb = B_FALSE;
12135e111ed8SAndrew Rybchenko
12145e111ed8SAndrew Rybchenko /* Check if the firmware supports vport reconfiguration */
12155e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, VPORT_RECONFIGURE))
12165e111ed8SAndrew Rybchenko encp->enc_vport_reconfigure_supported = B_TRUE;
12175e111ed8SAndrew Rybchenko else
12185e111ed8SAndrew Rybchenko encp->enc_vport_reconfigure_supported = B_FALSE;
12195e111ed8SAndrew Rybchenko
12205e111ed8SAndrew Rybchenko /* Check if the firmware supports VLAN insertion */
12215e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, TX_VLAN_INSERTION))
12225e111ed8SAndrew Rybchenko encp->enc_hw_tx_insert_vlan_enabled = B_TRUE;
12235e111ed8SAndrew Rybchenko else
12245e111ed8SAndrew Rybchenko encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
12255e111ed8SAndrew Rybchenko
1226*bf10e750SArtemii Morozov /* Check if firmware supports VLAN stripping. */
1227*bf10e750SArtemii Morozov if (CAP_FLAGS1(req, RX_VLAN_STRIPPING))
1228*bf10e750SArtemii Morozov encp->enc_rx_vlan_stripping_supported = B_TRUE;
1229*bf10e750SArtemii Morozov else
1230*bf10e750SArtemii Morozov encp->enc_rx_vlan_stripping_supported = B_FALSE;
1231*bf10e750SArtemii Morozov
12325e111ed8SAndrew Rybchenko /* Check if the firmware supports RX event batching */
12335e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, RX_BATCHING))
12345e111ed8SAndrew Rybchenko encp->enc_rx_batching_enabled = B_TRUE;
12355e111ed8SAndrew Rybchenko else
12365e111ed8SAndrew Rybchenko encp->enc_rx_batching_enabled = B_FALSE;
12375e111ed8SAndrew Rybchenko
12385e111ed8SAndrew Rybchenko /*
12395e111ed8SAndrew Rybchenko * Even if batching isn't reported as supported, we may still get
12405e111ed8SAndrew Rybchenko * batched events (see bug61153).
12415e111ed8SAndrew Rybchenko */
12425e111ed8SAndrew Rybchenko encp->enc_rx_batch_max = 16;
12435e111ed8SAndrew Rybchenko
12445e111ed8SAndrew Rybchenko /* Check if the firmware supports disabling scatter on RXQs */
12455e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, RX_DISABLE_SCATTER))
12465e111ed8SAndrew Rybchenko encp->enc_rx_disable_scatter_supported = B_TRUE;
12475e111ed8SAndrew Rybchenko else
12485e111ed8SAndrew Rybchenko encp->enc_rx_disable_scatter_supported = B_FALSE;
12495e111ed8SAndrew Rybchenko
1250abd9dc47SAndrew Rybchenko /* No limit on maximum number of Rx scatter elements per packet. */
1251abd9dc47SAndrew Rybchenko encp->enc_rx_scatter_max = -1;
1252abd9dc47SAndrew Rybchenko
1253d23d5966SRoman Zhukov /* Check if the firmware supports include FCS on RX */
1254d23d5966SRoman Zhukov if (CAP_FLAGS1(req, RX_INCLUDE_FCS))
1255d23d5966SRoman Zhukov encp->enc_rx_include_fcs_supported = B_TRUE;
1256d23d5966SRoman Zhukov else
1257d23d5966SRoman Zhukov encp->enc_rx_include_fcs_supported = B_FALSE;
1258d23d5966SRoman Zhukov
12595e111ed8SAndrew Rybchenko /* Check if the firmware supports packed stream mode */
12605e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, RX_PACKED_STREAM))
12615e111ed8SAndrew Rybchenko encp->enc_rx_packed_stream_supported = B_TRUE;
12625e111ed8SAndrew Rybchenko else
12635e111ed8SAndrew Rybchenko encp->enc_rx_packed_stream_supported = B_FALSE;
12645e111ed8SAndrew Rybchenko
12655e111ed8SAndrew Rybchenko /*
12665e111ed8SAndrew Rybchenko * Check if the firmware supports configurable buffer sizes
12675e111ed8SAndrew Rybchenko * for packed stream mode (otherwise buffer size is 1Mbyte)
12685e111ed8SAndrew Rybchenko */
12695e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, RX_PACKED_STREAM_VAR_BUFFERS))
12705e111ed8SAndrew Rybchenko encp->enc_rx_var_packed_stream_supported = B_TRUE;
12715e111ed8SAndrew Rybchenko else
12725e111ed8SAndrew Rybchenko encp->enc_rx_var_packed_stream_supported = B_FALSE;
12735e111ed8SAndrew Rybchenko
12745e111ed8SAndrew Rybchenko /* Check if the firmware supports equal stride super-buffer mode */
12755e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, EQUAL_STRIDE_SUPER_BUFFER))
12765e111ed8SAndrew Rybchenko encp->enc_rx_es_super_buffer_supported = B_TRUE;
12775e111ed8SAndrew Rybchenko else
12785e111ed8SAndrew Rybchenko encp->enc_rx_es_super_buffer_supported = B_FALSE;
12795e111ed8SAndrew Rybchenko
12805e111ed8SAndrew Rybchenko /* Check if the firmware supports FW subvariant w/o Tx checksumming */
12815e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, FW_SUBVARIANT_NO_TX_CSUM))
12825e111ed8SAndrew Rybchenko encp->enc_fw_subvariant_no_tx_csum_supported = B_TRUE;
12835e111ed8SAndrew Rybchenko else
12845e111ed8SAndrew Rybchenko encp->enc_fw_subvariant_no_tx_csum_supported = B_FALSE;
12855e111ed8SAndrew Rybchenko
12865e111ed8SAndrew Rybchenko /* Check if the firmware supports set mac with running filters */
12875e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED))
12885e111ed8SAndrew Rybchenko encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
12895e111ed8SAndrew Rybchenko else
12905e111ed8SAndrew Rybchenko encp->enc_allow_set_mac_with_installed_filters = B_FALSE;
12915e111ed8SAndrew Rybchenko
12925e111ed8SAndrew Rybchenko /*
12935e111ed8SAndrew Rybchenko * Check if firmware supports the extended MC_CMD_SET_MAC, which allows
12945e111ed8SAndrew Rybchenko * specifying which parameters to configure.
12955e111ed8SAndrew Rybchenko */
12965e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, SET_MAC_ENHANCED))
12975e111ed8SAndrew Rybchenko encp->enc_enhanced_set_mac_supported = B_TRUE;
12985e111ed8SAndrew Rybchenko else
12995e111ed8SAndrew Rybchenko encp->enc_enhanced_set_mac_supported = B_FALSE;
13005e111ed8SAndrew Rybchenko
13015e111ed8SAndrew Rybchenko /*
13025e111ed8SAndrew Rybchenko * Check if firmware supports version 2 of MC_CMD_INIT_EVQ, which allows
13035e111ed8SAndrew Rybchenko * us to let the firmware choose the settings to use on an EVQ.
13045e111ed8SAndrew Rybchenko */
13055e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, INIT_EVQ_V2))
13065e111ed8SAndrew Rybchenko encp->enc_init_evq_v2_supported = B_TRUE;
13075e111ed8SAndrew Rybchenko else
13085e111ed8SAndrew Rybchenko encp->enc_init_evq_v2_supported = B_FALSE;
13095e111ed8SAndrew Rybchenko
13105e111ed8SAndrew Rybchenko /*
1311f8a60f76SAndy Moreton * Check if firmware supports extended width event queues, which have
1312f8a60f76SAndy Moreton * a different event descriptor layout.
1313f8a60f76SAndy Moreton */
1314f8a60f76SAndy Moreton if (CAP_FLAGS3(req, EXTENDED_WIDTH_EVQS_SUPPORTED))
1315f8a60f76SAndy Moreton encp->enc_init_evq_extended_width_supported = B_TRUE;
1316f8a60f76SAndy Moreton else
1317f8a60f76SAndy Moreton encp->enc_init_evq_extended_width_supported = B_FALSE;
1318f8a60f76SAndy Moreton
1319f8a60f76SAndy Moreton /*
13205e111ed8SAndrew Rybchenko * Check if the NO_CONT_EV mode for RX events is supported.
13215e111ed8SAndrew Rybchenko */
13225e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, INIT_RXQ_NO_CONT_EV))
13235e111ed8SAndrew Rybchenko encp->enc_no_cont_ev_mode_supported = B_TRUE;
13245e111ed8SAndrew Rybchenko else
13255e111ed8SAndrew Rybchenko encp->enc_no_cont_ev_mode_supported = B_FALSE;
13265e111ed8SAndrew Rybchenko
13275e111ed8SAndrew Rybchenko /*
13285e111ed8SAndrew Rybchenko * Check if buffer size may and must be specified on INIT_RXQ.
13295e111ed8SAndrew Rybchenko * It may be always specified to efx_rx_qcreate(), but will be
13305e111ed8SAndrew Rybchenko * just kept libefx internal if MCDI does not support it.
13315e111ed8SAndrew Rybchenko */
13325e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, INIT_RXQ_WITH_BUFFER_SIZE))
13335e111ed8SAndrew Rybchenko encp->enc_init_rxq_with_buffer_size = B_TRUE;
13345e111ed8SAndrew Rybchenko else
13355e111ed8SAndrew Rybchenko encp->enc_init_rxq_with_buffer_size = B_FALSE;
13365e111ed8SAndrew Rybchenko
13375e111ed8SAndrew Rybchenko /*
13385e111ed8SAndrew Rybchenko * Check if firmware-verified NVRAM updates must be used.
13395e111ed8SAndrew Rybchenko *
13405e111ed8SAndrew Rybchenko * The firmware trusted installer requires all NVRAM updates to use
13415e111ed8SAndrew Rybchenko * version 2 of MC_CMD_NVRAM_UPDATE_START (to enable verified update)
13425e111ed8SAndrew Rybchenko * and version 2 of MC_CMD_NVRAM_UPDATE_FINISH (to verify the updated
13435e111ed8SAndrew Rybchenko * partition and report the result).
13445e111ed8SAndrew Rybchenko */
13455e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, NVRAM_UPDATE_REPORT_VERIFY_RESULT))
13465e111ed8SAndrew Rybchenko encp->enc_nvram_update_verify_result_supported = B_TRUE;
13475e111ed8SAndrew Rybchenko else
13485e111ed8SAndrew Rybchenko encp->enc_nvram_update_verify_result_supported = B_FALSE;
13495e111ed8SAndrew Rybchenko
13505e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, NVRAM_UPDATE_POLL_VERIFY_RESULT))
13515e111ed8SAndrew Rybchenko encp->enc_nvram_update_poll_verify_result_supported = B_TRUE;
13525e111ed8SAndrew Rybchenko else
13535e111ed8SAndrew Rybchenko encp->enc_nvram_update_poll_verify_result_supported = B_FALSE;
13545e111ed8SAndrew Rybchenko
13555e111ed8SAndrew Rybchenko /*
13565e111ed8SAndrew Rybchenko * Check if firmware update via the BUNDLE partition is supported
13575e111ed8SAndrew Rybchenko */
13585e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, BUNDLE_UPDATE))
13595e111ed8SAndrew Rybchenko encp->enc_nvram_bundle_update_supported = B_TRUE;
13605e111ed8SAndrew Rybchenko else
13615e111ed8SAndrew Rybchenko encp->enc_nvram_bundle_update_supported = B_FALSE;
13625e111ed8SAndrew Rybchenko
13635e111ed8SAndrew Rybchenko /*
13645e111ed8SAndrew Rybchenko * Check if firmware provides packet memory and Rx datapath
13655e111ed8SAndrew Rybchenko * counters.
13665e111ed8SAndrew Rybchenko */
13675e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, PM_AND_RXDP_COUNTERS))
13685e111ed8SAndrew Rybchenko encp->enc_pm_and_rxdp_counters = B_TRUE;
13695e111ed8SAndrew Rybchenko else
13705e111ed8SAndrew Rybchenko encp->enc_pm_and_rxdp_counters = B_FALSE;
13715e111ed8SAndrew Rybchenko
13725e111ed8SAndrew Rybchenko /*
13735e111ed8SAndrew Rybchenko * Check if the 40G MAC hardware is capable of reporting
13745e111ed8SAndrew Rybchenko * statistics for Tx size bins.
13755e111ed8SAndrew Rybchenko */
13765e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, MAC_STATS_40G_TX_SIZE_BINS))
13775e111ed8SAndrew Rybchenko encp->enc_mac_stats_40g_tx_size_bins = B_TRUE;
13785e111ed8SAndrew Rybchenko else
13795e111ed8SAndrew Rybchenko encp->enc_mac_stats_40g_tx_size_bins = B_FALSE;
13805e111ed8SAndrew Rybchenko
13815e111ed8SAndrew Rybchenko /*
13825e111ed8SAndrew Rybchenko * Check if firmware supports VXLAN and NVGRE tunnels.
13835e111ed8SAndrew Rybchenko * The capability indicates Geneve protocol support as well.
13845e111ed8SAndrew Rybchenko */
13855e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, VXLAN_NVGRE)) {
13865e111ed8SAndrew Rybchenko encp->enc_tunnel_encapsulations_supported =
13875e111ed8SAndrew Rybchenko (1u << EFX_TUNNEL_PROTOCOL_VXLAN) |
13885e111ed8SAndrew Rybchenko (1u << EFX_TUNNEL_PROTOCOL_GENEVE) |
13895e111ed8SAndrew Rybchenko (1u << EFX_TUNNEL_PROTOCOL_NVGRE);
13905e111ed8SAndrew Rybchenko
13915e111ed8SAndrew Rybchenko EFX_STATIC_ASSERT(EFX_TUNNEL_MAXNENTRIES ==
13925e111ed8SAndrew Rybchenko MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES_MAXNUM);
13935e111ed8SAndrew Rybchenko encp->enc_tunnel_config_udp_entries_max =
13945e111ed8SAndrew Rybchenko EFX_TUNNEL_MAXNENTRIES;
13955e111ed8SAndrew Rybchenko } else {
13965e111ed8SAndrew Rybchenko encp->enc_tunnel_config_udp_entries_max = 0;
13975e111ed8SAndrew Rybchenko }
13985e111ed8SAndrew Rybchenko
139994626988SSandilya Bhagi #define CAP_PFS_TO_PORTS(_n) \
140094626988SSandilya Bhagi (MC_CMD_GET_CAPABILITIES_V2_OUT_PFS_TO_PORTS_ASSIGNMENT_ ## _n)
140194626988SSandilya Bhagi
140294626988SSandilya Bhagi encp->enc_port_usage = EFX_PORT_USAGE_UNKNOWN;
140394626988SSandilya Bhagi
140494626988SSandilya Bhagi if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) {
140594626988SSandilya Bhagi /* PFs to ports assignment */
140694626988SSandilya Bhagi uint8_t pfs_to_ports[CAP_PFS_TO_PORTS(NUM)];
140794626988SSandilya Bhagi
140894626988SSandilya Bhagi EFX_STATIC_ASSERT((CAP_PFS_TO_PORTS(NUM) * CAP_PFS_TO_PORTS(LEN)) ==
140994626988SSandilya Bhagi EFX_ARRAY_SIZE(pfs_to_ports));
141094626988SSandilya Bhagi
141194626988SSandilya Bhagi memcpy(pfs_to_ports, MCDI_OUT(req, efx_byte_t, CAP_PFS_TO_PORTS(OFST)),
141294626988SSandilya Bhagi EFX_ARRAY_SIZE(pfs_to_ports));
141394626988SSandilya Bhagi
141494626988SSandilya Bhagi rc = ef10_nic_get_physical_port_usage(enp, pfs_to_ports,
141594626988SSandilya Bhagi EFX_ARRAY_SIZE(pfs_to_ports), &encp->enc_port_usage);
141694626988SSandilya Bhagi if (rc != 0) {
141794626988SSandilya Bhagi /* PF to port mapping lookup failed */
141894626988SSandilya Bhagi encp->enc_port_usage = EFX_PORT_USAGE_UNKNOWN;
141994626988SSandilya Bhagi }
142094626988SSandilya Bhagi }
142194626988SSandilya Bhagi #undef CAP_PFS_TO_PORTS
142294626988SSandilya Bhagi
14235e111ed8SAndrew Rybchenko /*
14245e111ed8SAndrew Rybchenko * Check if firmware reports the VI window mode.
14255e111ed8SAndrew Rybchenko * Medford2 has a variable VI window size (8K, 16K or 64K).
14265e111ed8SAndrew Rybchenko * Medford and Huntington have a fixed 8K VI window size.
14275e111ed8SAndrew Rybchenko */
14285e111ed8SAndrew Rybchenko if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V3_OUT_LEN) {
14295e111ed8SAndrew Rybchenko uint8_t mode =
14305e111ed8SAndrew Rybchenko MCDI_OUT_BYTE(req, GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE);
14315e111ed8SAndrew Rybchenko
14325e111ed8SAndrew Rybchenko switch (mode) {
14335e111ed8SAndrew Rybchenko case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_8K:
14345e111ed8SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_8K;
14355e111ed8SAndrew Rybchenko break;
14365e111ed8SAndrew Rybchenko case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_16K:
14375e111ed8SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_16K;
14385e111ed8SAndrew Rybchenko break;
14395e111ed8SAndrew Rybchenko case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_64K:
14405e111ed8SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_64K;
14415e111ed8SAndrew Rybchenko break;
14425e111ed8SAndrew Rybchenko default:
14435e111ed8SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_INVALID;
14445e111ed8SAndrew Rybchenko break;
14455e111ed8SAndrew Rybchenko }
14465e111ed8SAndrew Rybchenko } else if ((enp->en_family == EFX_FAMILY_HUNTINGTON) ||
14475e111ed8SAndrew Rybchenko (enp->en_family == EFX_FAMILY_MEDFORD)) {
14485e111ed8SAndrew Rybchenko /* Huntington and Medford have fixed 8K window size */
14495e111ed8SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_8K;
14505e111ed8SAndrew Rybchenko } else {
14515e111ed8SAndrew Rybchenko encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_INVALID;
14525e111ed8SAndrew Rybchenko }
14535e111ed8SAndrew Rybchenko
14545e111ed8SAndrew Rybchenko /* Check if firmware supports extended MAC stats. */
14555e111ed8SAndrew Rybchenko if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V4_OUT_LEN) {
14565e111ed8SAndrew Rybchenko /* Extended stats buffer supported */
14575e111ed8SAndrew Rybchenko encp->enc_mac_stats_nstats = MCDI_OUT_WORD(req,
14585e111ed8SAndrew Rybchenko GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS);
14595e111ed8SAndrew Rybchenko } else {
14605e111ed8SAndrew Rybchenko /* Use Siena-compatible legacy MAC stats */
14615e111ed8SAndrew Rybchenko encp->enc_mac_stats_nstats = MC_CMD_MAC_NSTATS;
14625e111ed8SAndrew Rybchenko }
14635e111ed8SAndrew Rybchenko
14645e111ed8SAndrew Rybchenko if (encp->enc_mac_stats_nstats >= MC_CMD_MAC_NSTATS_V2)
14655e111ed8SAndrew Rybchenko encp->enc_fec_counters = B_TRUE;
14665e111ed8SAndrew Rybchenko else
14675e111ed8SAndrew Rybchenko encp->enc_fec_counters = B_FALSE;
14685e111ed8SAndrew Rybchenko
14695e111ed8SAndrew Rybchenko /* Check if the firmware provides head-of-line blocking counters */
14705e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, RXDP_HLB_IDLE))
14715e111ed8SAndrew Rybchenko encp->enc_hlb_counters = B_TRUE;
14725e111ed8SAndrew Rybchenko else
14735e111ed8SAndrew Rybchenko encp->enc_hlb_counters = B_FALSE;
14745e111ed8SAndrew Rybchenko
14755e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
14765e111ed8SAndrew Rybchenko if (CAP_FLAGS1(req, RX_RSS_LIMITED)) {
14775e111ed8SAndrew Rybchenko /* Only one exclusive RSS context is available per port. */
14785e111ed8SAndrew Rybchenko encp->enc_rx_scale_max_exclusive_contexts = 1;
14795e111ed8SAndrew Rybchenko
14805e111ed8SAndrew Rybchenko switch (enp->en_family) {
14815e111ed8SAndrew Rybchenko case EFX_FAMILY_MEDFORD2:
14825e111ed8SAndrew Rybchenko encp->enc_rx_scale_hash_alg_mask =
14835e111ed8SAndrew Rybchenko (1U << EFX_RX_HASHALG_TOEPLITZ);
14845e111ed8SAndrew Rybchenko break;
14855e111ed8SAndrew Rybchenko
14865e111ed8SAndrew Rybchenko case EFX_FAMILY_MEDFORD:
14875e111ed8SAndrew Rybchenko case EFX_FAMILY_HUNTINGTON:
14885e111ed8SAndrew Rybchenko /*
14895e111ed8SAndrew Rybchenko * Packed stream firmware variant maintains a
14905e111ed8SAndrew Rybchenko * non-standard algorithm for hash computation.
14915e111ed8SAndrew Rybchenko * It implies explicit XORing together
14925e111ed8SAndrew Rybchenko * source + destination IP addresses (or last
14935e111ed8SAndrew Rybchenko * four bytes in the case of IPv6) and using the
14945e111ed8SAndrew Rybchenko * resulting value as the input to a Toeplitz hash.
14955e111ed8SAndrew Rybchenko */
14965e111ed8SAndrew Rybchenko encp->enc_rx_scale_hash_alg_mask =
14975e111ed8SAndrew Rybchenko (1U << EFX_RX_HASHALG_PACKED_STREAM);
14985e111ed8SAndrew Rybchenko break;
14995e111ed8SAndrew Rybchenko
15005e111ed8SAndrew Rybchenko default:
15015e111ed8SAndrew Rybchenko rc = EINVAL;
1502495c8fefSAndrew Rybchenko goto fail3;
15035e111ed8SAndrew Rybchenko }
15045e111ed8SAndrew Rybchenko
15055e111ed8SAndrew Rybchenko /* Port numbers cannot contribute to the hash value */
15065e111ed8SAndrew Rybchenko encp->enc_rx_scale_l4_hash_supported = B_FALSE;
15075e111ed8SAndrew Rybchenko } else {
15085e111ed8SAndrew Rybchenko /*
15095e111ed8SAndrew Rybchenko * Maximum number of exclusive RSS contexts.
15105e111ed8SAndrew Rybchenko * EF10 hardware supports 64 in total, but 6 are reserved
15115e111ed8SAndrew Rybchenko * for shared contexts. They are a global resource so
15125e111ed8SAndrew Rybchenko * not all may be available.
15135e111ed8SAndrew Rybchenko */
15145e111ed8SAndrew Rybchenko encp->enc_rx_scale_max_exclusive_contexts = 64 - 6;
15155e111ed8SAndrew Rybchenko
15165e111ed8SAndrew Rybchenko encp->enc_rx_scale_hash_alg_mask =
15175e111ed8SAndrew Rybchenko (1U << EFX_RX_HASHALG_TOEPLITZ);
15185e111ed8SAndrew Rybchenko
15195e111ed8SAndrew Rybchenko /*
15205e111ed8SAndrew Rybchenko * It is possible to use port numbers as
15215e111ed8SAndrew Rybchenko * the input data for hash computation.
15225e111ed8SAndrew Rybchenko */
15235e111ed8SAndrew Rybchenko encp->enc_rx_scale_l4_hash_supported = B_TRUE;
15245e111ed8SAndrew Rybchenko }
1525e7ea5f30SIvan Malov
1526e7ea5f30SIvan Malov if (CAP_FLAGS3(req, RSS_SELECTABLE_TABLE_SIZE))
1527e7ea5f30SIvan Malov encp->enc_rx_scale_tbl_entry_count_is_selectable = B_TRUE;
1528e7ea5f30SIvan Malov else
1529e7ea5f30SIvan Malov encp->enc_rx_scale_tbl_entry_count_is_selectable = B_FALSE;
15305e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
15315e111ed8SAndrew Rybchenko
15325e111ed8SAndrew Rybchenko /* Check if the firmware supports "FLAG" and "MARK" filter actions */
15335e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, FILTER_ACTION_FLAG))
15345e111ed8SAndrew Rybchenko encp->enc_filter_action_flag_supported = B_TRUE;
15355e111ed8SAndrew Rybchenko else
15365e111ed8SAndrew Rybchenko encp->enc_filter_action_flag_supported = B_FALSE;
15375e111ed8SAndrew Rybchenko
15385e111ed8SAndrew Rybchenko if (CAP_FLAGS2(req, FILTER_ACTION_MARK))
15395e111ed8SAndrew Rybchenko encp->enc_filter_action_mark_supported = B_TRUE;
15405e111ed8SAndrew Rybchenko else
15415e111ed8SAndrew Rybchenko encp->enc_filter_action_mark_supported = B_FALSE;
15425e111ed8SAndrew Rybchenko
15435e111ed8SAndrew Rybchenko /* Get maximum supported value for "MARK" filter action */
15445e111ed8SAndrew Rybchenko if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V5_OUT_LEN)
15455e111ed8SAndrew Rybchenko encp->enc_filter_action_mark_max = MCDI_OUT_DWORD(req,
15465e111ed8SAndrew Rybchenko GET_CAPABILITIES_V5_OUT_FILTER_ACTION_MARK_MAX);
15475e111ed8SAndrew Rybchenko else
15485e111ed8SAndrew Rybchenko encp->enc_filter_action_mark_max = 0;
15495e111ed8SAndrew Rybchenko
1550eb4e8008SIvan Malov #if EFSYS_OPT_MAE
1551eb4e8008SIvan Malov /*
1552be2f2be7SIvan Malov * Check support for EF100 Match Action Engine (MAE).
1553be2f2be7SIvan Malov * MAE hardware is present on Riverhead boards (from R2),
1554be2f2be7SIvan Malov * and on Keystone, and requires support in firmware.
1555be2f2be7SIvan Malov *
1556be2f2be7SIvan Malov * MAE control operations require MAE control privilege,
1557be2f2be7SIvan Malov * which is not available for VFs.
1558be2f2be7SIvan Malov *
1559be2f2be7SIvan Malov * Privileges can change dynamically at runtime: we assume
1560be2f2be7SIvan Malov * MAE support requires the privilege is granted initially,
1561be2f2be7SIvan Malov * and ignore later dynamic changes.
1562eb4e8008SIvan Malov */
156340ccb311SViacheslav Galaktionov if (CAP_FLAGS3(req, MAE_SUPPORTED)) {
1564eb4e8008SIvan Malov encp->enc_mae_supported = B_TRUE;
156540ccb311SViacheslav Galaktionov if (EFX_MCDI_HAVE_PRIVILEGE(encp->enc_privilege_mask, MAE))
156640ccb311SViacheslav Galaktionov encp->enc_mae_admin = B_TRUE;
1567eb4e8008SIvan Malov else
156840ccb311SViacheslav Galaktionov encp->enc_mae_admin = B_FALSE;
156940ccb311SViacheslav Galaktionov } else {
1570eb4e8008SIvan Malov encp->enc_mae_supported = B_FALSE;
157140ccb311SViacheslav Galaktionov encp->enc_mae_admin = B_FALSE;
157240ccb311SViacheslav Galaktionov }
1573c6e3e6c4SIvan Malov
1574c6e3e6c4SIvan Malov /*
1575c6e3e6c4SIvan Malov * Check support for MAE action set v2 features.
1576c6e3e6c4SIvan Malov * These provide support for packet edits.
1577c6e3e6c4SIvan Malov */
1578c6e3e6c4SIvan Malov if (CAP_FLAGS3(req, MAE_ACTION_SET_ALLOC_V2_SUPPORTED))
1579c6e3e6c4SIvan Malov encp->enc_mae_aset_v2_supported = B_TRUE;
1580c6e3e6c4SIvan Malov else
1581c6e3e6c4SIvan Malov encp->enc_mae_aset_v2_supported = B_FALSE;
1582eb4e8008SIvan Malov #else
1583eb4e8008SIvan Malov encp->enc_mae_supported = B_FALSE;
158440ccb311SViacheslav Galaktionov encp->enc_mae_admin = B_FALSE;
1585eb4e8008SIvan Malov #endif /* EFSYS_OPT_MAE */
1586eb4e8008SIvan Malov
1587777da150SIvan Malov #if EFSYS_OPT_RX_SCALE
1588777da150SIvan Malov if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V9_OUT_LEN) {
1589777da150SIvan Malov encp->enc_rx_scale_indirection_max_nqueues =
1590777da150SIvan Malov MCDI_OUT_DWORD(req,
1591777da150SIvan Malov GET_CAPABILITIES_V9_OUT_RSS_MAX_INDIRECTION_QUEUES);
1592e7ea5f30SIvan Malov encp->enc_rx_scale_tbl_min_nentries =
1593e7ea5f30SIvan Malov MCDI_OUT_DWORD(req,
1594e7ea5f30SIvan Malov GET_CAPABILITIES_V9_OUT_RSS_MIN_INDIRECTION_TABLE_SIZE);
1595e7ea5f30SIvan Malov encp->enc_rx_scale_tbl_max_nentries =
1596e7ea5f30SIvan Malov MCDI_OUT_DWORD(req,
1597e7ea5f30SIvan Malov GET_CAPABILITIES_V9_OUT_RSS_MAX_INDIRECTION_TABLE_SIZE);
1598bcdcec8cSIvan Malov
1599bcdcec8cSIvan Malov if (CAP_FLAGS3(req, RSS_EVEN_SPREADING)) {
1600bcdcec8cSIvan Malov #define RSS_MAX_EVEN_SPREADING_QUEUES \
1601bcdcec8cSIvan Malov GET_CAPABILITIES_V9_OUT_RSS_MAX_EVEN_SPREADING_QUEUES
1602bcdcec8cSIvan Malov /*
1603bcdcec8cSIvan Malov * The even spreading mode distributes traffic across
1604bcdcec8cSIvan Malov * the specified number of queues without the need to
1605bcdcec8cSIvan Malov * allocate precious indirection entry pool resources.
1606bcdcec8cSIvan Malov */
1607bcdcec8cSIvan Malov encp->enc_rx_scale_even_spread_max_nqueues =
1608bcdcec8cSIvan Malov MCDI_OUT_DWORD(req, RSS_MAX_EVEN_SPREADING_QUEUES);
1609bcdcec8cSIvan Malov #undef RSS_MAX_EVEN_SPREADING_QUEUES
1610bcdcec8cSIvan Malov } else {
1611bcdcec8cSIvan Malov /* There is no support for the even spread contexts. */
1612bcdcec8cSIvan Malov encp->enc_rx_scale_even_spread_max_nqueues = 0;
1613bcdcec8cSIvan Malov }
1614777da150SIvan Malov } else {
1615777da150SIvan Malov encp->enc_rx_scale_indirection_max_nqueues = EFX_MAXRSS;
1616e7ea5f30SIvan Malov encp->enc_rx_scale_tbl_min_nentries = EFX_RSS_TBL_SIZE;
1617e7ea5f30SIvan Malov encp->enc_rx_scale_tbl_max_nentries = EFX_RSS_TBL_SIZE;
1618bcdcec8cSIvan Malov
1619bcdcec8cSIvan Malov /*
1620bcdcec8cSIvan Malov * Assume that there is no support
1621bcdcec8cSIvan Malov * for the even spread contexts.
1622bcdcec8cSIvan Malov */
1623bcdcec8cSIvan Malov encp->enc_rx_scale_even_spread_max_nqueues = 0;
1624777da150SIvan Malov }
1625777da150SIvan Malov #endif /* EFSYS_OPT_RX_SCALE */
1626777da150SIvan Malov
16275e111ed8SAndrew Rybchenko #undef CAP_FLAGS1
16285e111ed8SAndrew Rybchenko #undef CAP_FLAGS2
1629eb4e8008SIvan Malov #undef CAP_FLAGS3
16305e111ed8SAndrew Rybchenko
16315e111ed8SAndrew Rybchenko return (0);
16325e111ed8SAndrew Rybchenko
16335e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
16345e111ed8SAndrew Rybchenko fail3:
16355e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
1636495c8fefSAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
16375e111ed8SAndrew Rybchenko fail2:
16385e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
16395e111ed8SAndrew Rybchenko fail1:
16405e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
16415e111ed8SAndrew Rybchenko
16425e111ed8SAndrew Rybchenko return (rc);
16435e111ed8SAndrew Rybchenko }
16445e111ed8SAndrew Rybchenko
16455e111ed8SAndrew Rybchenko
16465e111ed8SAndrew Rybchenko #define EF10_LEGACY_PF_PRIVILEGE_MASK \
16475e111ed8SAndrew Rybchenko (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN | \
16485e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK | \
16495e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD | \
16505e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP | \
16515e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS | \
16525e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING | \
16535e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST | \
16545e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST | \
16555e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST | \
16565e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST | \
16575e111ed8SAndrew Rybchenko MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS)
16585e111ed8SAndrew Rybchenko
16595e111ed8SAndrew Rybchenko #define EF10_LEGACY_VF_PRIVILEGE_MASK 0
16605e111ed8SAndrew Rybchenko
16615e111ed8SAndrew Rybchenko
16625e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_get_privilege_mask(__in efx_nic_t * enp,__out uint32_t * maskp)16635e111ed8SAndrew Rybchenko ef10_get_privilege_mask(
16645e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
16655e111ed8SAndrew Rybchenko __out uint32_t *maskp)
16665e111ed8SAndrew Rybchenko {
16675e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
16685e111ed8SAndrew Rybchenko uint32_t mask;
16695e111ed8SAndrew Rybchenko efx_rc_t rc;
16705e111ed8SAndrew Rybchenko
16715e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
16725e111ed8SAndrew Rybchenko &mask)) != 0) {
16735e111ed8SAndrew Rybchenko if (rc != ENOTSUP)
16745e111ed8SAndrew Rybchenko goto fail1;
16755e111ed8SAndrew Rybchenko
16765e111ed8SAndrew Rybchenko /* Fallback for old firmware without privilege mask support */
16775e111ed8SAndrew Rybchenko if (EFX_PCI_FUNCTION_IS_PF(encp)) {
16785e111ed8SAndrew Rybchenko /* Assume PF has admin privilege */
16795e111ed8SAndrew Rybchenko mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
16805e111ed8SAndrew Rybchenko } else {
16815e111ed8SAndrew Rybchenko /* VF is always unprivileged by default */
16825e111ed8SAndrew Rybchenko mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
16835e111ed8SAndrew Rybchenko }
16845e111ed8SAndrew Rybchenko }
16855e111ed8SAndrew Rybchenko
16865e111ed8SAndrew Rybchenko *maskp = mask;
16875e111ed8SAndrew Rybchenko
16885e111ed8SAndrew Rybchenko return (0);
16895e111ed8SAndrew Rybchenko
16905e111ed8SAndrew Rybchenko fail1:
16915e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
16925e111ed8SAndrew Rybchenko
16935e111ed8SAndrew Rybchenko return (rc);
16945e111ed8SAndrew Rybchenko }
16955e111ed8SAndrew Rybchenko
16965e111ed8SAndrew Rybchenko
16975e111ed8SAndrew Rybchenko #define EFX_EXT_PORT_MAX 4
16985e111ed8SAndrew Rybchenko #define EFX_EXT_PORT_NA 0xFF
16995e111ed8SAndrew Rybchenko
17005e111ed8SAndrew Rybchenko /*
17015e111ed8SAndrew Rybchenko * Table of mapping schemes from port number to external number.
17025e111ed8SAndrew Rybchenko *
17035e111ed8SAndrew Rybchenko * Each port number ultimately corresponds to a connector: either as part of
17045e111ed8SAndrew Rybchenko * a cable assembly attached to a module inserted in an SFP+/QSFP+ cage on
17055e111ed8SAndrew Rybchenko * the board, or fixed to the board (e.g. 10GBASE-T magjack on SFN5121T
17065e111ed8SAndrew Rybchenko * "Salina"). In general:
17075e111ed8SAndrew Rybchenko *
17085e111ed8SAndrew Rybchenko * Port number (0-based)
17095e111ed8SAndrew Rybchenko * |
17105e111ed8SAndrew Rybchenko * port mapping (n:1)
17115e111ed8SAndrew Rybchenko * |
17125e111ed8SAndrew Rybchenko * v
17135e111ed8SAndrew Rybchenko * External port number (1-based)
17145e111ed8SAndrew Rybchenko * |
17155e111ed8SAndrew Rybchenko * fixed (1:1) or cable assembly (1:m)
17165e111ed8SAndrew Rybchenko * |
17175e111ed8SAndrew Rybchenko * v
17185e111ed8SAndrew Rybchenko * Connector
17195e111ed8SAndrew Rybchenko *
17205e111ed8SAndrew Rybchenko * The external numbering refers to the cages or magjacks on the board,
17215e111ed8SAndrew Rybchenko * as visibly annotated on the board or back panel. This table describes
17225e111ed8SAndrew Rybchenko * how to determine which external cage/magjack corresponds to the port
17235e111ed8SAndrew Rybchenko * numbers used by the driver.
17245e111ed8SAndrew Rybchenko *
17255e111ed8SAndrew Rybchenko * The count of consecutive port numbers that map to each external number,
17265e111ed8SAndrew Rybchenko * is determined by the chip family and the current port mode.
17275e111ed8SAndrew Rybchenko *
17285e111ed8SAndrew Rybchenko * For the Huntington family, the current port mode cannot be discovered,
17295e111ed8SAndrew Rybchenko * but a single mapping is used by all modes for a given chip variant,
17305e111ed8SAndrew Rybchenko * so the mapping used is instead the last match in the table to the full
17315e111ed8SAndrew Rybchenko * set of port modes to which the NIC can be configured. Therefore the
17325e111ed8SAndrew Rybchenko * ordering of entries in the mapping table is significant.
17335e111ed8SAndrew Rybchenko */
17345e111ed8SAndrew Rybchenko static struct ef10_external_port_map_s {
17355e111ed8SAndrew Rybchenko efx_family_t family;
17365e111ed8SAndrew Rybchenko uint32_t modes_mask;
17375e111ed8SAndrew Rybchenko uint8_t base_port[EFX_EXT_PORT_MAX];
17385e111ed8SAndrew Rybchenko } __ef10_external_port_mappings[] = {
17395e111ed8SAndrew Rybchenko /*
17405e111ed8SAndrew Rybchenko * Modes used by Huntington family controllers where each port
17415e111ed8SAndrew Rybchenko * number maps to a separate cage.
17425e111ed8SAndrew Rybchenko * SFN7x22F (Torino):
17435e111ed8SAndrew Rybchenko * port 0 -> cage 1
17445e111ed8SAndrew Rybchenko * port 1 -> cage 2
17455e111ed8SAndrew Rybchenko * SFN7xx4F (Pavia):
17465e111ed8SAndrew Rybchenko * port 0 -> cage 1
17475e111ed8SAndrew Rybchenko * port 1 -> cage 2
17485e111ed8SAndrew Rybchenko * port 2 -> cage 3
17495e111ed8SAndrew Rybchenko * port 3 -> cage 4
17505e111ed8SAndrew Rybchenko */
17515e111ed8SAndrew Rybchenko {
17525e111ed8SAndrew Rybchenko EFX_FAMILY_HUNTINGTON,
17535e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_10G) | /* mode 0 */
17545e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_10G_10G) | /* mode 2 */
17555e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_10G_10G_10G_10G), /* mode 4 */
17565e111ed8SAndrew Rybchenko { 0, 1, 2, 3 }
17575e111ed8SAndrew Rybchenko },
17585e111ed8SAndrew Rybchenko /*
17595e111ed8SAndrew Rybchenko * Modes which for Huntington identify a chip variant where 2
17605e111ed8SAndrew Rybchenko * adjacent port numbers map to each cage.
17615e111ed8SAndrew Rybchenko * SFN7x42Q (Monza):
17625e111ed8SAndrew Rybchenko * port 0 -> cage 1
17635e111ed8SAndrew Rybchenko * port 1 -> cage 1
17645e111ed8SAndrew Rybchenko * port 2 -> cage 2
17655e111ed8SAndrew Rybchenko * port 3 -> cage 2
17665e111ed8SAndrew Rybchenko */
17675e111ed8SAndrew Rybchenko {
17685e111ed8SAndrew Rybchenko EFX_FAMILY_HUNTINGTON,
17695e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_40G) | /* mode 1 */
17705e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_40G_40G) | /* mode 3 */
17715e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_40G_10G_10G) | /* mode 6 */
17725e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_10G_10G_40G), /* mode 7 */
17735e111ed8SAndrew Rybchenko { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
17745e111ed8SAndrew Rybchenko },
17755e111ed8SAndrew Rybchenko /*
17765e111ed8SAndrew Rybchenko * Modes that on Medford allocate each port number to a separate
17775e111ed8SAndrew Rybchenko * cage.
17785e111ed8SAndrew Rybchenko * port 0 -> cage 1
17795e111ed8SAndrew Rybchenko * port 1 -> cage 2
17805e111ed8SAndrew Rybchenko * port 2 -> cage 3
17815e111ed8SAndrew Rybchenko * port 3 -> cage 4
17825e111ed8SAndrew Rybchenko */
17835e111ed8SAndrew Rybchenko {
17845e111ed8SAndrew Rybchenko EFX_FAMILY_MEDFORD,
17855e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_NA) | /* mode 0 */
17865e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */
17875e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_1x1), /* mode 2 */
17885e111ed8SAndrew Rybchenko { 0, 1, 2, 3 }
17895e111ed8SAndrew Rybchenko },
17905e111ed8SAndrew Rybchenko /*
17915e111ed8SAndrew Rybchenko * Modes that on Medford allocate 2 adjacent port numbers to each
17925e111ed8SAndrew Rybchenko * cage.
17935e111ed8SAndrew Rybchenko * port 0 -> cage 1
17945e111ed8SAndrew Rybchenko * port 1 -> cage 1
17955e111ed8SAndrew Rybchenko * port 2 -> cage 2
17965e111ed8SAndrew Rybchenko * port 3 -> cage 2
17975e111ed8SAndrew Rybchenko */
17985e111ed8SAndrew Rybchenko {
17995e111ed8SAndrew Rybchenko EFX_FAMILY_MEDFORD,
18005e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */
18015e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_2x1) | /* mode 5 */
18025e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_2x1) | /* mode 6 */
18035e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_1x4) | /* mode 7 */
18045e111ed8SAndrew Rybchenko /* Do not use 10G_10G_10G_10G_Q1_Q2 (see bug63270) */
18055e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2), /* mode 9 */
18065e111ed8SAndrew Rybchenko { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
18075e111ed8SAndrew Rybchenko },
18085e111ed8SAndrew Rybchenko /*
18095e111ed8SAndrew Rybchenko * Modes that on Medford allocate 4 adjacent port numbers to
18105e111ed8SAndrew Rybchenko * cage 1.
18115e111ed8SAndrew Rybchenko * port 0 -> cage 1
18125e111ed8SAndrew Rybchenko * port 1 -> cage 1
18135e111ed8SAndrew Rybchenko * port 2 -> cage 1
18145e111ed8SAndrew Rybchenko * port 3 -> cage 1
18155e111ed8SAndrew Rybchenko */
18165e111ed8SAndrew Rybchenko {
18175e111ed8SAndrew Rybchenko EFX_FAMILY_MEDFORD,
18185e111ed8SAndrew Rybchenko /* Do not use 10G_10G_10G_10G_Q1 (see bug63270) */
18195e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_4x1_NA), /* mode 4 */
18205e111ed8SAndrew Rybchenko { 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
18215e111ed8SAndrew Rybchenko },
18225e111ed8SAndrew Rybchenko /*
18235e111ed8SAndrew Rybchenko * Modes that on Medford allocate 4 adjacent port numbers to
18245e111ed8SAndrew Rybchenko * cage 2.
18255e111ed8SAndrew Rybchenko * port 0 -> cage 2
18265e111ed8SAndrew Rybchenko * port 1 -> cage 2
18275e111ed8SAndrew Rybchenko * port 2 -> cage 2
18285e111ed8SAndrew Rybchenko * port 3 -> cage 2
18295e111ed8SAndrew Rybchenko */
18305e111ed8SAndrew Rybchenko {
18315e111ed8SAndrew Rybchenko EFX_FAMILY_MEDFORD,
18325e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_NA_4x1), /* mode 8 */
18335e111ed8SAndrew Rybchenko { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
18345e111ed8SAndrew Rybchenko },
18355e111ed8SAndrew Rybchenko /*
18365e111ed8SAndrew Rybchenko * Modes that on Medford2 allocate each port number to a separate
18375e111ed8SAndrew Rybchenko * cage.
18385e111ed8SAndrew Rybchenko * port 0 -> cage 1
18395e111ed8SAndrew Rybchenko * port 1 -> cage 2
18405e111ed8SAndrew Rybchenko * port 2 -> cage 3
18415e111ed8SAndrew Rybchenko * port 3 -> cage 4
18425e111ed8SAndrew Rybchenko */
18435e111ed8SAndrew Rybchenko {
18445e111ed8SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
18455e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_NA) | /* mode 0 */
18465e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */
18475e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_1x1) | /* mode 2 */
18485e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */
18495e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x2_NA) | /* mode 10 */
18505e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x2_1x2) | /* mode 12 */
18515e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_1x2) | /* mode 15 */
18525e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x2_1x4), /* mode 16 */
18535e111ed8SAndrew Rybchenko { 0, 1, 2, 3 }
18545e111ed8SAndrew Rybchenko },
18555e111ed8SAndrew Rybchenko /*
18565e111ed8SAndrew Rybchenko * Modes that on Medford2 allocate 1 port to cage 1 and the rest
18575e111ed8SAndrew Rybchenko * to cage 2.
18585e111ed8SAndrew Rybchenko * port 0 -> cage 1
18595e111ed8SAndrew Rybchenko * port 1 -> cage 2
18605e111ed8SAndrew Rybchenko * port 2 -> cage 2
18615e111ed8SAndrew Rybchenko */
18625e111ed8SAndrew Rybchenko {
18635e111ed8SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
18645e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x2_2x1) | /* mode 17 */
18655e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_2x1), /* mode 6 */
18665e111ed8SAndrew Rybchenko { 0, 1, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
18675e111ed8SAndrew Rybchenko },
18685e111ed8SAndrew Rybchenko /*
18695e111ed8SAndrew Rybchenko * Modes that on Medford2 allocate 2 adjacent port numbers to cage 1
18705e111ed8SAndrew Rybchenko * and the rest to cage 2.
18715e111ed8SAndrew Rybchenko * port 0 -> cage 1
18725e111ed8SAndrew Rybchenko * port 1 -> cage 1
18735e111ed8SAndrew Rybchenko * port 2 -> cage 2
18745e111ed8SAndrew Rybchenko * port 3 -> cage 2
18755e111ed8SAndrew Rybchenko */
18765e111ed8SAndrew Rybchenko {
18775e111ed8SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
18785e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_2x1) | /* mode 4 */
18795e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_1x4) | /* mode 7 */
18805e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_2x2_NA) | /* mode 13 */
18815e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_2x1_1x2), /* mode 18 */
18825e111ed8SAndrew Rybchenko { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
18835e111ed8SAndrew Rybchenko },
18845e111ed8SAndrew Rybchenko /*
18855e111ed8SAndrew Rybchenko * Modes that on Medford2 allocate up to 4 adjacent port numbers
18865e111ed8SAndrew Rybchenko * to cage 1.
18875e111ed8SAndrew Rybchenko * port 0 -> cage 1
18885e111ed8SAndrew Rybchenko * port 1 -> cage 1
18895e111ed8SAndrew Rybchenko * port 2 -> cage 1
18905e111ed8SAndrew Rybchenko * port 3 -> cage 1
18915e111ed8SAndrew Rybchenko */
18925e111ed8SAndrew Rybchenko {
18935e111ed8SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
18945e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_4x1_NA), /* mode 5 */
18955e111ed8SAndrew Rybchenko { 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
18965e111ed8SAndrew Rybchenko },
18975e111ed8SAndrew Rybchenko /*
18985e111ed8SAndrew Rybchenko * Modes that on Medford2 allocate up to 4 adjacent port numbers
18995e111ed8SAndrew Rybchenko * to cage 2.
19005e111ed8SAndrew Rybchenko * port 0 -> cage 2
19015e111ed8SAndrew Rybchenko * port 1 -> cage 2
19025e111ed8SAndrew Rybchenko * port 2 -> cage 2
19035e111ed8SAndrew Rybchenko * port 3 -> cage 2
19045e111ed8SAndrew Rybchenko */
19055e111ed8SAndrew Rybchenko {
19065e111ed8SAndrew Rybchenko EFX_FAMILY_MEDFORD2,
19075e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_NA_4x1) | /* mode 8 */
19085e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_NA_1x2) | /* mode 11 */
19095e111ed8SAndrew Rybchenko (1U << TLV_PORT_MODE_NA_2x2), /* mode 14 */
19105e111ed8SAndrew Rybchenko { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
19115e111ed8SAndrew Rybchenko },
19123c1c5cc4SAndrew Rybchenko /*
19133c1c5cc4SAndrew Rybchenko * Modes that on Riverhead allocate each port number to a separate
19143c1c5cc4SAndrew Rybchenko * cage.
19153c1c5cc4SAndrew Rybchenko * port 0 -> cage 1
19163c1c5cc4SAndrew Rybchenko * port 1 -> cage 2
19173c1c5cc4SAndrew Rybchenko */
19183c1c5cc4SAndrew Rybchenko {
19193c1c5cc4SAndrew Rybchenko EFX_FAMILY_RIVERHEAD,
19203c1c5cc4SAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_NA) | /* mode 0 */
19213c1c5cc4SAndrew Rybchenko (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */
19223c1c5cc4SAndrew Rybchenko (1U << TLV_PORT_MODE_1x1_1x1), /* mode 2 */
19233c1c5cc4SAndrew Rybchenko { 0, 1, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
19243c1c5cc4SAndrew Rybchenko },
19255e111ed8SAndrew Rybchenko };
19265e111ed8SAndrew Rybchenko
19275e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t
ef10_external_port_mapping(__in efx_nic_t * enp,__in uint32_t port,__out uint8_t * external_portp)19285e111ed8SAndrew Rybchenko ef10_external_port_mapping(
19295e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
19305e111ed8SAndrew Rybchenko __in uint32_t port,
19315e111ed8SAndrew Rybchenko __out uint8_t *external_portp)
19325e111ed8SAndrew Rybchenko {
19335e111ed8SAndrew Rybchenko efx_rc_t rc;
19345e111ed8SAndrew Rybchenko int i;
19355e111ed8SAndrew Rybchenko uint32_t port_modes;
19365e111ed8SAndrew Rybchenko uint32_t matches;
19375e111ed8SAndrew Rybchenko uint32_t current;
19385e111ed8SAndrew Rybchenko struct ef10_external_port_map_s *mapp = NULL;
19395e111ed8SAndrew Rybchenko int ext_index = port; /* Default 1-1 mapping */
19405e111ed8SAndrew Rybchenko
19415e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, ¤t,
19425e111ed8SAndrew Rybchenko NULL)) != 0) {
19435e111ed8SAndrew Rybchenko /*
19445e111ed8SAndrew Rybchenko * No current port mode information (i.e. Huntington)
19455e111ed8SAndrew Rybchenko * - infer mapping from available modes
19465e111ed8SAndrew Rybchenko */
19475e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_get_port_modes(enp,
19485e111ed8SAndrew Rybchenko &port_modes, NULL, NULL)) != 0) {
19495e111ed8SAndrew Rybchenko /*
19505e111ed8SAndrew Rybchenko * No port mode information available
19515e111ed8SAndrew Rybchenko * - use default mapping
19525e111ed8SAndrew Rybchenko */
19535e111ed8SAndrew Rybchenko goto out;
19545e111ed8SAndrew Rybchenko }
19555e111ed8SAndrew Rybchenko } else {
19565e111ed8SAndrew Rybchenko /* Only need to scan the current mode */
19575e111ed8SAndrew Rybchenko port_modes = 1 << current;
19585e111ed8SAndrew Rybchenko }
19595e111ed8SAndrew Rybchenko
19605e111ed8SAndrew Rybchenko /*
19615e111ed8SAndrew Rybchenko * Infer the internal port -> external number mapping from
19625e111ed8SAndrew Rybchenko * the possible port modes for this NIC.
19635e111ed8SAndrew Rybchenko */
19645e111ed8SAndrew Rybchenko for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
19655e111ed8SAndrew Rybchenko struct ef10_external_port_map_s *eepmp =
19665e111ed8SAndrew Rybchenko &__ef10_external_port_mappings[i];
19675e111ed8SAndrew Rybchenko if (eepmp->family != enp->en_family)
19685e111ed8SAndrew Rybchenko continue;
19695e111ed8SAndrew Rybchenko matches = (eepmp->modes_mask & port_modes);
19705e111ed8SAndrew Rybchenko if (matches != 0) {
19715e111ed8SAndrew Rybchenko /*
19725e111ed8SAndrew Rybchenko * Some modes match. For some Huntington boards
19735e111ed8SAndrew Rybchenko * there will be multiple matches. The mapping on the
19745e111ed8SAndrew Rybchenko * last match is used.
19755e111ed8SAndrew Rybchenko */
19765e111ed8SAndrew Rybchenko mapp = eepmp;
19775e111ed8SAndrew Rybchenko port_modes &= ~matches;
19785e111ed8SAndrew Rybchenko }
19795e111ed8SAndrew Rybchenko }
19805e111ed8SAndrew Rybchenko
19815e111ed8SAndrew Rybchenko if (port_modes != 0) {
19825e111ed8SAndrew Rybchenko /* Some advertised modes are not supported */
19835e111ed8SAndrew Rybchenko rc = ENOTSUP;
19845e111ed8SAndrew Rybchenko goto fail1;
19855e111ed8SAndrew Rybchenko }
19865e111ed8SAndrew Rybchenko
19875e111ed8SAndrew Rybchenko out:
19885e111ed8SAndrew Rybchenko if (mapp != NULL) {
19895e111ed8SAndrew Rybchenko /*
19905e111ed8SAndrew Rybchenko * External ports are assigned a sequence of consecutive
19915e111ed8SAndrew Rybchenko * port numbers, so find the one with the closest base_port.
19925e111ed8SAndrew Rybchenko */
19935e111ed8SAndrew Rybchenko uint32_t delta = EFX_EXT_PORT_NA;
19945e111ed8SAndrew Rybchenko
19955e111ed8SAndrew Rybchenko for (i = 0; i < EFX_EXT_PORT_MAX; i++) {
19965e111ed8SAndrew Rybchenko uint32_t base = mapp->base_port[i];
19975e111ed8SAndrew Rybchenko if ((base != EFX_EXT_PORT_NA) && (base <= port)) {
19985e111ed8SAndrew Rybchenko if ((port - base) < delta) {
19995e111ed8SAndrew Rybchenko delta = (port - base);
20005e111ed8SAndrew Rybchenko ext_index = i;
20015e111ed8SAndrew Rybchenko }
20025e111ed8SAndrew Rybchenko }
20035e111ed8SAndrew Rybchenko }
20045e111ed8SAndrew Rybchenko }
20055e111ed8SAndrew Rybchenko *external_portp = (uint8_t)(ext_index + 1);
20065e111ed8SAndrew Rybchenko
20075e111ed8SAndrew Rybchenko return (0);
20085e111ed8SAndrew Rybchenko
20095e111ed8SAndrew Rybchenko fail1:
20105e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
20115e111ed8SAndrew Rybchenko
20125e111ed8SAndrew Rybchenko return (rc);
20135e111ed8SAndrew Rybchenko }
20145e111ed8SAndrew Rybchenko
201560fb370cSAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_get_nic_addr_caps(__in efx_nic_t * enp)201660fb370cSAndrew Rybchenko efx_mcdi_get_nic_addr_caps(
201760fb370cSAndrew Rybchenko __in efx_nic_t *enp)
201860fb370cSAndrew Rybchenko {
201960fb370cSAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
202060fb370cSAndrew Rybchenko uint32_t mapping_type;
202160fb370cSAndrew Rybchenko efx_rc_t rc;
202260fb370cSAndrew Rybchenko
202360fb370cSAndrew Rybchenko rc = efx_mcdi_get_nic_addr_info(enp, &mapping_type);
202460fb370cSAndrew Rybchenko if (rc != 0) {
202560fb370cSAndrew Rybchenko if (rc == ENOTSUP) {
202660fb370cSAndrew Rybchenko encp->enc_dma_mapping = EFX_NIC_DMA_MAPPING_FLAT;
202760fb370cSAndrew Rybchenko goto out;
202860fb370cSAndrew Rybchenko }
202960fb370cSAndrew Rybchenko goto fail1;
203060fb370cSAndrew Rybchenko }
203160fb370cSAndrew Rybchenko
203260fb370cSAndrew Rybchenko switch (mapping_type) {
203360fb370cSAndrew Rybchenko case MC_CMD_GET_DESC_ADDR_INFO_OUT_MAPPING_FLAT:
203460fb370cSAndrew Rybchenko encp->enc_dma_mapping = EFX_NIC_DMA_MAPPING_FLAT;
203560fb370cSAndrew Rybchenko break;
203660fb370cSAndrew Rybchenko case MC_CMD_GET_DESC_ADDR_INFO_OUT_MAPPING_REGIONED:
203760fb370cSAndrew Rybchenko encp->enc_dma_mapping = EFX_NIC_DMA_MAPPING_REGIONED;
203860fb370cSAndrew Rybchenko rc = efx_mcdi_get_nic_addr_regions(enp,
203960fb370cSAndrew Rybchenko &enp->en_dma.end_u.endu_region_info);
204060fb370cSAndrew Rybchenko if (rc != 0)
204160fb370cSAndrew Rybchenko goto fail2;
204260fb370cSAndrew Rybchenko break;
204360fb370cSAndrew Rybchenko default:
204460fb370cSAndrew Rybchenko goto fail3;
204560fb370cSAndrew Rybchenko }
204660fb370cSAndrew Rybchenko
204760fb370cSAndrew Rybchenko out:
204860fb370cSAndrew Rybchenko return (0);
204960fb370cSAndrew Rybchenko
205060fb370cSAndrew Rybchenko fail3:
205160fb370cSAndrew Rybchenko EFSYS_PROBE(fail3);
205260fb370cSAndrew Rybchenko fail2:
205360fb370cSAndrew Rybchenko EFSYS_PROBE(fail2);
205460fb370cSAndrew Rybchenko fail1:
205560fb370cSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
205660fb370cSAndrew Rybchenko
205760fb370cSAndrew Rybchenko return (rc);
205860fb370cSAndrew Rybchenko }
205960fb370cSAndrew Rybchenko
20603c1c5cc4SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_nic_board_cfg(__in efx_nic_t * enp)206134add036SAndrew Rybchenko efx_mcdi_nic_board_cfg(
20625e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
20635e111ed8SAndrew Rybchenko {
20645e111ed8SAndrew Rybchenko efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
20655e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
20665e111ed8SAndrew Rybchenko ef10_link_state_t els;
20675e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
20687d104a8dSViacheslav Galaktionov efx_pcie_interface_t intf;
20695e111ed8SAndrew Rybchenko uint32_t board_type = 0;
20705e111ed8SAndrew Rybchenko uint32_t base, nvec;
20715e111ed8SAndrew Rybchenko uint32_t port;
20725e111ed8SAndrew Rybchenko uint32_t mask;
20735e111ed8SAndrew Rybchenko uint32_t pf;
20745e111ed8SAndrew Rybchenko uint32_t vf;
20755e111ed8SAndrew Rybchenko uint8_t mac_addr[6] = { 0 };
20765e111ed8SAndrew Rybchenko efx_rc_t rc;
20775e111ed8SAndrew Rybchenko
20785e111ed8SAndrew Rybchenko /* Get the (zero-based) MCDI port number */
20795e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0)
20805e111ed8SAndrew Rybchenko goto fail1;
20815e111ed8SAndrew Rybchenko
20825e111ed8SAndrew Rybchenko /* EFX MCDI interface uses one-based port numbers */
20835e111ed8SAndrew Rybchenko emip->emi_port = port + 1;
20845e111ed8SAndrew Rybchenko
20855e111ed8SAndrew Rybchenko encp->enc_assigned_port = port;
20865e111ed8SAndrew Rybchenko
20875e111ed8SAndrew Rybchenko if ((rc = ef10_external_port_mapping(enp, port,
20885e111ed8SAndrew Rybchenko &encp->enc_external_port)) != 0)
20895e111ed8SAndrew Rybchenko goto fail2;
20905e111ed8SAndrew Rybchenko
20915e111ed8SAndrew Rybchenko /*
20925e111ed8SAndrew Rybchenko * Get PCIe function number from firmware (used for
20935e111ed8SAndrew Rybchenko * per-function privilege and dynamic config info).
20945e111ed8SAndrew Rybchenko * - PCIe PF: pf = PF number, vf = 0xffff.
20955e111ed8SAndrew Rybchenko * - PCIe VF: pf = parent PF, vf = VF number.
20965e111ed8SAndrew Rybchenko */
20977d104a8dSViacheslav Galaktionov if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf, &intf)) != 0)
20985e111ed8SAndrew Rybchenko goto fail3;
20995e111ed8SAndrew Rybchenko
21005e111ed8SAndrew Rybchenko encp->enc_pf = pf;
21015e111ed8SAndrew Rybchenko encp->enc_vf = vf;
21027d104a8dSViacheslav Galaktionov encp->enc_intf = intf;
21035e111ed8SAndrew Rybchenko
2104495c8fefSAndrew Rybchenko if ((rc = ef10_mcdi_get_pf_count(enp, &encp->enc_hw_pf_count)) != 0)
2105495c8fefSAndrew Rybchenko goto fail4;
2106495c8fefSAndrew Rybchenko
210778b82063SIvan Malov rc = efx_mcdi_client_mac_addr_get(enp, CLIENT_HANDLE_SELF, mac_addr);
210878b82063SIvan Malov if ((rc != 0) && EFX_PCI_FUNCTION_IS_PF(encp)) {
210978b82063SIvan Malov /* Fallback for legacy MAC address get approach (PF) */
21105e111ed8SAndrew Rybchenko rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
21115e111ed8SAndrew Rybchenko #if EFSYS_OPT_ALLOW_UNCONFIGURED_NIC
21125e111ed8SAndrew Rybchenko /*
21135e111ed8SAndrew Rybchenko * Disable static config checking, ONLY for manufacturing test
21145e111ed8SAndrew Rybchenko * and setup at the factory, to allow the static config to be
21155e111ed8SAndrew Rybchenko * installed.
21165e111ed8SAndrew Rybchenko */
21175e111ed8SAndrew Rybchenko #else /* EFSYS_OPT_ALLOW_UNCONFIGURED_NIC */
21185e111ed8SAndrew Rybchenko if ((rc == 0) && (mac_addr[0] & 0x02)) {
21195e111ed8SAndrew Rybchenko /*
21205e111ed8SAndrew Rybchenko * If the static config does not include a global MAC
21215e111ed8SAndrew Rybchenko * address pool then the board may return a locally
21225e111ed8SAndrew Rybchenko * administered MAC address (this should only happen on
21235e111ed8SAndrew Rybchenko * incorrectly programmed boards).
21245e111ed8SAndrew Rybchenko */
21255e111ed8SAndrew Rybchenko rc = EINVAL;
21265e111ed8SAndrew Rybchenko }
21275e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_ALLOW_UNCONFIGURED_NIC */
212878b82063SIvan Malov } else if (rc != 0) {
212978b82063SIvan Malov /* Fallback for legacy MAC address get approach (VF) */
21305e111ed8SAndrew Rybchenko rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
21315e111ed8SAndrew Rybchenko }
213278b82063SIvan Malov
21335e111ed8SAndrew Rybchenko if (rc != 0)
2134495c8fefSAndrew Rybchenko goto fail5;
21355e111ed8SAndrew Rybchenko
21365e111ed8SAndrew Rybchenko EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
21375e111ed8SAndrew Rybchenko
2138be2f2be7SIvan Malov /*
2139be2f2be7SIvan Malov * Get the current privilege mask. Note that this may be modified
2140be2f2be7SIvan Malov * dynamically, so for most cases the value is informational only.
2141be2f2be7SIvan Malov * If the privilege being discovered can't be granted dynamically,
2142be2f2be7SIvan Malov * it's fine to rely on the value. In all other cases, DO NOT use
2143be2f2be7SIvan Malov * the privilege mask to check for sufficient privileges, as that
2144be2f2be7SIvan Malov * can result in time-of-check/time-of-use bugs.
2145be2f2be7SIvan Malov */
2146be2f2be7SIvan Malov if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0)
2147be2f2be7SIvan Malov goto fail6;
2148be2f2be7SIvan Malov encp->enc_privilege_mask = mask;
2149be2f2be7SIvan Malov
21505e111ed8SAndrew Rybchenko /* Board configuration (legacy) */
21515e111ed8SAndrew Rybchenko rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL);
21525e111ed8SAndrew Rybchenko if (rc != 0) {
21535e111ed8SAndrew Rybchenko /* Unprivileged functions may not be able to read board cfg */
21545e111ed8SAndrew Rybchenko if (rc == EACCES)
21555e111ed8SAndrew Rybchenko board_type = 0;
21565e111ed8SAndrew Rybchenko else
2157be2f2be7SIvan Malov goto fail7;
21585e111ed8SAndrew Rybchenko }
21595e111ed8SAndrew Rybchenko
21605e111ed8SAndrew Rybchenko encp->enc_board_type = board_type;
21615e111ed8SAndrew Rybchenko
21625e111ed8SAndrew Rybchenko /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
21635e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
2164be2f2be7SIvan Malov goto fail8;
21655e111ed8SAndrew Rybchenko
21665e111ed8SAndrew Rybchenko /*
21675e111ed8SAndrew Rybchenko * Firmware with support for *_FEC capability bits does not
21685e111ed8SAndrew Rybchenko * report that the corresponding *_FEC_REQUESTED bits are supported.
21695e111ed8SAndrew Rybchenko * Add them here so that drivers understand that they are supported.
21705e111ed8SAndrew Rybchenko */
21715e111ed8SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1u << EFX_PHY_CAP_BASER_FEC))
21725e111ed8SAndrew Rybchenko epp->ep_phy_cap_mask |=
21735e111ed8SAndrew Rybchenko (1u << EFX_PHY_CAP_BASER_FEC_REQUESTED);
21745e111ed8SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1u << EFX_PHY_CAP_RS_FEC))
21755e111ed8SAndrew Rybchenko epp->ep_phy_cap_mask |=
21765e111ed8SAndrew Rybchenko (1u << EFX_PHY_CAP_RS_FEC_REQUESTED);
21775e111ed8SAndrew Rybchenko if (epp->ep_phy_cap_mask & (1u << EFX_PHY_CAP_25G_BASER_FEC))
21785e111ed8SAndrew Rybchenko epp->ep_phy_cap_mask |=
21795e111ed8SAndrew Rybchenko (1u << EFX_PHY_CAP_25G_BASER_FEC_REQUESTED);
21805e111ed8SAndrew Rybchenko
21815e111ed8SAndrew Rybchenko /* Obtain the default PHY advertised capabilities */
21825e111ed8SAndrew Rybchenko if ((rc = ef10_phy_get_link(enp, &els)) != 0)
2183be2f2be7SIvan Malov goto fail9;
21845e111ed8SAndrew Rybchenko epp->ep_default_adv_cap_mask = els.epls.epls_adv_cap_mask;
21855e111ed8SAndrew Rybchenko epp->ep_adv_cap_mask = els.epls.epls_adv_cap_mask;
21865e111ed8SAndrew Rybchenko
21875e111ed8SAndrew Rybchenko /* Check capabilities of running datapath firmware */
21885e111ed8SAndrew Rybchenko if ((rc = ef10_get_datapath_caps(enp)) != 0)
2189be2f2be7SIvan Malov goto fail10;
21905e111ed8SAndrew Rybchenko
219134add036SAndrew Rybchenko /* Get interrupt vector limits */
219234add036SAndrew Rybchenko if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
219334add036SAndrew Rybchenko if (EFX_PCI_FUNCTION_IS_PF(encp))
2194be2f2be7SIvan Malov goto fail11;
219534add036SAndrew Rybchenko
219634add036SAndrew Rybchenko /* Ignore error (cannot query vector limits from a VF). */
219734add036SAndrew Rybchenko base = 0;
219834add036SAndrew Rybchenko nvec = 1024;
219934add036SAndrew Rybchenko }
220034add036SAndrew Rybchenko encp->enc_intr_vec_base = base;
220134add036SAndrew Rybchenko encp->enc_intr_limit = nvec;
220234add036SAndrew Rybchenko
220360fb370cSAndrew Rybchenko rc = efx_mcdi_get_nic_addr_caps(enp);
220460fb370cSAndrew Rybchenko if (rc != 0)
220560fb370cSAndrew Rybchenko goto fail12;
220660fb370cSAndrew Rybchenko
220734add036SAndrew Rybchenko return (0);
220834add036SAndrew Rybchenko
220960fb370cSAndrew Rybchenko fail12:
221060fb370cSAndrew Rybchenko EFSYS_PROBE(fail12);
221134add036SAndrew Rybchenko fail11:
221234add036SAndrew Rybchenko EFSYS_PROBE(fail11);
221334add036SAndrew Rybchenko fail10:
221434add036SAndrew Rybchenko EFSYS_PROBE(fail10);
221534add036SAndrew Rybchenko fail9:
221634add036SAndrew Rybchenko EFSYS_PROBE(fail9);
221734add036SAndrew Rybchenko fail8:
221834add036SAndrew Rybchenko EFSYS_PROBE(fail8);
221934add036SAndrew Rybchenko fail7:
222034add036SAndrew Rybchenko EFSYS_PROBE(fail7);
222134add036SAndrew Rybchenko fail6:
222234add036SAndrew Rybchenko EFSYS_PROBE(fail6);
222334add036SAndrew Rybchenko fail5:
222434add036SAndrew Rybchenko EFSYS_PROBE(fail5);
222534add036SAndrew Rybchenko fail4:
222634add036SAndrew Rybchenko EFSYS_PROBE(fail4);
222734add036SAndrew Rybchenko fail3:
222834add036SAndrew Rybchenko EFSYS_PROBE(fail3);
222934add036SAndrew Rybchenko fail2:
223034add036SAndrew Rybchenko EFSYS_PROBE(fail2);
223134add036SAndrew Rybchenko fail1:
223234add036SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
223334add036SAndrew Rybchenko
223434add036SAndrew Rybchenko return (rc);
223534add036SAndrew Rybchenko }
223634add036SAndrew Rybchenko
22373c1c5cc4SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_entity_reset(__in efx_nic_t * enp)22384d0af0dbSAndrew Rybchenko efx_mcdi_entity_reset(
22394d0af0dbSAndrew Rybchenko __in efx_nic_t *enp)
22404d0af0dbSAndrew Rybchenko {
22414d0af0dbSAndrew Rybchenko efx_mcdi_req_t req;
22424d0af0dbSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ENTITY_RESET_IN_LEN,
22434d0af0dbSAndrew Rybchenko MC_CMD_ENTITY_RESET_OUT_LEN);
22444d0af0dbSAndrew Rybchenko efx_rc_t rc;
22454d0af0dbSAndrew Rybchenko
22464d0af0dbSAndrew Rybchenko req.emr_cmd = MC_CMD_ENTITY_RESET;
22474d0af0dbSAndrew Rybchenko req.emr_in_buf = payload;
22484d0af0dbSAndrew Rybchenko req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
22494d0af0dbSAndrew Rybchenko req.emr_out_buf = payload;
22504d0af0dbSAndrew Rybchenko req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
22514d0af0dbSAndrew Rybchenko
22524d0af0dbSAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
22534d0af0dbSAndrew Rybchenko ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
22544d0af0dbSAndrew Rybchenko
22554d0af0dbSAndrew Rybchenko efx_mcdi_execute(enp, &req);
22564d0af0dbSAndrew Rybchenko
22574d0af0dbSAndrew Rybchenko if (req.emr_rc != 0) {
22584d0af0dbSAndrew Rybchenko rc = req.emr_rc;
22594d0af0dbSAndrew Rybchenko goto fail1;
22604d0af0dbSAndrew Rybchenko }
22614d0af0dbSAndrew Rybchenko
22624d0af0dbSAndrew Rybchenko return (0);
22634d0af0dbSAndrew Rybchenko
22644d0af0dbSAndrew Rybchenko fail1:
22654d0af0dbSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
22664d0af0dbSAndrew Rybchenko
22674d0af0dbSAndrew Rybchenko return (rc);
22684d0af0dbSAndrew Rybchenko }
22694d0af0dbSAndrew Rybchenko
22703c1c5cc4SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */
22713c1c5cc4SAndrew Rybchenko
22723c1c5cc4SAndrew Rybchenko #if EFX_OPTS_EF10()
22733c1c5cc4SAndrew Rybchenko
22744d0af0dbSAndrew Rybchenko static __checkReturn efx_rc_t
ef10_set_workaround_bug26807(__in efx_nic_t * enp)227534add036SAndrew Rybchenko ef10_set_workaround_bug26807(
227634add036SAndrew Rybchenko __in efx_nic_t *enp)
227734add036SAndrew Rybchenko {
227834add036SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
227934add036SAndrew Rybchenko uint32_t flags;
228034add036SAndrew Rybchenko efx_rc_t rc;
228134add036SAndrew Rybchenko
228234add036SAndrew Rybchenko /*
228334add036SAndrew Rybchenko * If the bug26807 workaround is enabled, then firmware has enabled
228434add036SAndrew Rybchenko * support for chained multicast filters. Firmware will reset (FLR)
228534add036SAndrew Rybchenko * functions which have filters in the hardware filter table when the
228634add036SAndrew Rybchenko * workaround is enabled/disabled.
228734add036SAndrew Rybchenko *
228834add036SAndrew Rybchenko * We must recheck if the workaround is enabled after inserting the
228934add036SAndrew Rybchenko * first hardware filter, in case it has been changed since this check.
229034add036SAndrew Rybchenko */
229134add036SAndrew Rybchenko rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807,
229234add036SAndrew Rybchenko B_TRUE, &flags);
229334add036SAndrew Rybchenko if (rc == 0) {
229434add036SAndrew Rybchenko encp->enc_bug26807_workaround = B_TRUE;
229534add036SAndrew Rybchenko if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) {
229634add036SAndrew Rybchenko /*
229734add036SAndrew Rybchenko * Other functions had installed filters before the
229834add036SAndrew Rybchenko * workaround was enabled, and they have been reset
229934add036SAndrew Rybchenko * by firmware.
230034add036SAndrew Rybchenko */
230134add036SAndrew Rybchenko EFSYS_PROBE(bug26807_workaround_flr_done);
230234add036SAndrew Rybchenko /* FIXME: bump MC warm boot count ? */
230334add036SAndrew Rybchenko }
230434add036SAndrew Rybchenko } else if (rc == EACCES) {
230534add036SAndrew Rybchenko /*
230634add036SAndrew Rybchenko * Unprivileged functions cannot enable the workaround in older
230734add036SAndrew Rybchenko * firmware.
230834add036SAndrew Rybchenko */
230934add036SAndrew Rybchenko encp->enc_bug26807_workaround = B_FALSE;
231034add036SAndrew Rybchenko } else if ((rc == ENOTSUP) || (rc == ENOENT)) {
231134add036SAndrew Rybchenko encp->enc_bug26807_workaround = B_FALSE;
231234add036SAndrew Rybchenko } else {
231334add036SAndrew Rybchenko goto fail1;
231434add036SAndrew Rybchenko }
231534add036SAndrew Rybchenko
231634add036SAndrew Rybchenko return (0);
231734add036SAndrew Rybchenko
231834add036SAndrew Rybchenko fail1:
231934add036SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
232034add036SAndrew Rybchenko
232134add036SAndrew Rybchenko return (rc);
232234add036SAndrew Rybchenko }
232334add036SAndrew Rybchenko
232434add036SAndrew Rybchenko static __checkReturn efx_rc_t
ef10_nic_board_cfg(__in efx_nic_t * enp)232534add036SAndrew Rybchenko ef10_nic_board_cfg(
232634add036SAndrew Rybchenko __in efx_nic_t *enp)
232734add036SAndrew Rybchenko {
232834add036SAndrew Rybchenko const efx_nic_ops_t *enop = enp->en_enop;
232934add036SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
233034add036SAndrew Rybchenko efx_rc_t rc;
233134add036SAndrew Rybchenko
233234add036SAndrew Rybchenko if ((rc = efx_mcdi_nic_board_cfg(enp)) != 0)
233334add036SAndrew Rybchenko goto fail1;
233434add036SAndrew Rybchenko
2335d9d41eeaSAndrew Rybchenko /*
2336d9d41eeaSAndrew Rybchenko * Huntington RXDP firmware inserts a 0 or 14 byte prefix.
2337d9d41eeaSAndrew Rybchenko * We only support the 14 byte prefix here.
2338d9d41eeaSAndrew Rybchenko */
2339d9d41eeaSAndrew Rybchenko if (encp->enc_rx_prefix_size != 14) {
2340d9d41eeaSAndrew Rybchenko rc = ENOTSUP;
234134add036SAndrew Rybchenko goto fail2;
2342d9d41eeaSAndrew Rybchenko }
2343d9d41eeaSAndrew Rybchenko
234434add036SAndrew Rybchenko encp->enc_clk_mult = 1; /* not used for EF10 */
234534add036SAndrew Rybchenko
23465e111ed8SAndrew Rybchenko /* Alignment for WPTR updates */
23475e111ed8SAndrew Rybchenko encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
23485e111ed8SAndrew Rybchenko
234961b3e9e7SIvan Malov encp->enc_rx_dma_desc_size_max = EFX_MASK32(ESF_DZ_RX_KER_BYTE_CNT);
235079b0c192SIvan Malov encp->enc_tx_dma_desc_size_max = EFX_MASK32(ESF_DZ_TX_KER_BYTE_CNT);
23515e111ed8SAndrew Rybchenko /* No boundary crossing limits */
23525e111ed8SAndrew Rybchenko encp->enc_tx_dma_desc_boundary = 0;
23535e111ed8SAndrew Rybchenko
23545e111ed8SAndrew Rybchenko /*
23555e111ed8SAndrew Rybchenko * Maximum number of bytes into the frame the TCP header can start for
23565e111ed8SAndrew Rybchenko * firmware assisted TSO to work.
23575e111ed8SAndrew Rybchenko */
23585e111ed8SAndrew Rybchenko encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT;
23595e111ed8SAndrew Rybchenko
23607ed3ac82SIvan Malov /* EF10 TSO engine demands that packet header be contiguous. */
23617ed3ac82SIvan Malov encp->enc_tx_tso_max_header_ndescs = 1;
23627ed3ac82SIvan Malov
23637ed3ac82SIvan Malov /* The overall TSO header length is not limited. */
23647ed3ac82SIvan Malov encp->enc_tx_tso_max_header_length = UINT32_MAX;
23657ed3ac82SIvan Malov
23667ed3ac82SIvan Malov /*
23677ed3ac82SIvan Malov * There are no specific limitations on the number of
23687ed3ac82SIvan Malov * TSO payload descriptors.
23697ed3ac82SIvan Malov */
23707ed3ac82SIvan Malov encp->enc_tx_tso_max_payload_ndescs = UINT32_MAX;
23717ed3ac82SIvan Malov
23727ed3ac82SIvan Malov /* TSO superframe payload length is not limited. */
23737ed3ac82SIvan Malov encp->enc_tx_tso_max_payload_length = UINT32_MAX;
23747ed3ac82SIvan Malov
23757ed3ac82SIvan Malov /*
23767ed3ac82SIvan Malov * Limitation on the maximum number of outgoing packets per
23777ed3ac82SIvan Malov * TSO transaction described in SF-108452-SW.
23787ed3ac82SIvan Malov */
23797ed3ac82SIvan Malov encp->enc_tx_tso_max_nframes = 32767;
23807ed3ac82SIvan Malov
23815e111ed8SAndrew Rybchenko /*
23825e111ed8SAndrew Rybchenko * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
23835e111ed8SAndrew Rybchenko * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
23845e111ed8SAndrew Rybchenko * resources (allocated to this PCIe function), which is zero until
23855e111ed8SAndrew Rybchenko * after we have allocated VIs.
23865e111ed8SAndrew Rybchenko */
23875e111ed8SAndrew Rybchenko encp->enc_evq_limit = 1024;
23885e111ed8SAndrew Rybchenko encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
23895e111ed8SAndrew Rybchenko encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
23905e111ed8SAndrew Rybchenko
23915e111ed8SAndrew Rybchenko encp->enc_buftbl_limit = UINT32_MAX;
23925e111ed8SAndrew Rybchenko
23935e111ed8SAndrew Rybchenko if ((rc = ef10_set_workaround_bug26807(enp)) != 0)
239434add036SAndrew Rybchenko goto fail3;
23955e111ed8SAndrew Rybchenko
23965e111ed8SAndrew Rybchenko /* Get remaining controller-specific board config */
23975e111ed8SAndrew Rybchenko if ((rc = enop->eno_board_cfg(enp)) != 0)
23985e111ed8SAndrew Rybchenko if (rc != EACCES)
239934add036SAndrew Rybchenko goto fail4;
24005e111ed8SAndrew Rybchenko
24015e111ed8SAndrew Rybchenko return (0);
24025e111ed8SAndrew Rybchenko
24035e111ed8SAndrew Rybchenko fail4:
24045e111ed8SAndrew Rybchenko EFSYS_PROBE(fail4);
24055e111ed8SAndrew Rybchenko fail3:
24065e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
24075e111ed8SAndrew Rybchenko fail2:
24085e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
24095e111ed8SAndrew Rybchenko fail1:
24105e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
24115e111ed8SAndrew Rybchenko
24125e111ed8SAndrew Rybchenko return (rc);
24135e111ed8SAndrew Rybchenko }
24145e111ed8SAndrew Rybchenko
24155e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_probe(__in efx_nic_t * enp)24165e111ed8SAndrew Rybchenko ef10_nic_probe(
24175e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
24185e111ed8SAndrew Rybchenko {
24195e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
24205e111ed8SAndrew Rybchenko efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
24215e111ed8SAndrew Rybchenko efx_rc_t rc;
24225e111ed8SAndrew Rybchenko
24235e111ed8SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
24245e111ed8SAndrew Rybchenko
24255e111ed8SAndrew Rybchenko /* Read and clear any assertion state */
24265e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_read_assertion(enp)) != 0)
24275e111ed8SAndrew Rybchenko goto fail1;
24285e111ed8SAndrew Rybchenko
24295e111ed8SAndrew Rybchenko /* Exit the assertion handler */
24305e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
24315e111ed8SAndrew Rybchenko if (rc != EACCES)
24325e111ed8SAndrew Rybchenko goto fail2;
24335e111ed8SAndrew Rybchenko
24345e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
24355e111ed8SAndrew Rybchenko goto fail3;
24365e111ed8SAndrew Rybchenko
24375e111ed8SAndrew Rybchenko if ((rc = ef10_nic_board_cfg(enp)) != 0)
24385e111ed8SAndrew Rybchenko goto fail4;
24395e111ed8SAndrew Rybchenko
24405e111ed8SAndrew Rybchenko /*
24415e111ed8SAndrew Rybchenko * Set default driver config limits (based on board config).
24425e111ed8SAndrew Rybchenko *
24435e111ed8SAndrew Rybchenko * FIXME: For now allocate a fixed number of VIs which is likely to be
24445e111ed8SAndrew Rybchenko * sufficient and small enough to allow multiple functions on the same
24455e111ed8SAndrew Rybchenko * port.
24465e111ed8SAndrew Rybchenko */
24475e111ed8SAndrew Rybchenko edcp->edc_min_vi_count = edcp->edc_max_vi_count =
24485e111ed8SAndrew Rybchenko MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
24495e111ed8SAndrew Rybchenko
24505e111ed8SAndrew Rybchenko /* The client driver must configure and enable PIO buffer support */
24515e111ed8SAndrew Rybchenko edcp->edc_max_piobuf_count = 0;
24525e111ed8SAndrew Rybchenko edcp->edc_pio_alloc_size = 0;
24535e111ed8SAndrew Rybchenko
24545e111ed8SAndrew Rybchenko #if EFSYS_OPT_MAC_STATS
24555e111ed8SAndrew Rybchenko /* Wipe the MAC statistics */
24565e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
24575e111ed8SAndrew Rybchenko goto fail5;
24585e111ed8SAndrew Rybchenko #endif
24595e111ed8SAndrew Rybchenko
24605e111ed8SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
24615e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
24625e111ed8SAndrew Rybchenko goto fail6;
24635e111ed8SAndrew Rybchenko #endif
24645e111ed8SAndrew Rybchenko
24655e111ed8SAndrew Rybchenko #if EFSYS_OPT_MON_STATS
24665e111ed8SAndrew Rybchenko if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
24675e111ed8SAndrew Rybchenko /* Unprivileged functions do not have access to sensors */
24685e111ed8SAndrew Rybchenko if (rc != EACCES)
24695e111ed8SAndrew Rybchenko goto fail7;
24705e111ed8SAndrew Rybchenko }
24715e111ed8SAndrew Rybchenko #endif
24725e111ed8SAndrew Rybchenko
24735e111ed8SAndrew Rybchenko return (0);
24745e111ed8SAndrew Rybchenko
24755e111ed8SAndrew Rybchenko #if EFSYS_OPT_MON_STATS
24765e111ed8SAndrew Rybchenko fail7:
24775e111ed8SAndrew Rybchenko EFSYS_PROBE(fail7);
24785e111ed8SAndrew Rybchenko #endif
24795e111ed8SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
24805e111ed8SAndrew Rybchenko fail6:
24815e111ed8SAndrew Rybchenko EFSYS_PROBE(fail6);
24825e111ed8SAndrew Rybchenko #endif
24835e111ed8SAndrew Rybchenko #if EFSYS_OPT_MAC_STATS
24845e111ed8SAndrew Rybchenko fail5:
24855e111ed8SAndrew Rybchenko EFSYS_PROBE(fail5);
24865e111ed8SAndrew Rybchenko #endif
24875e111ed8SAndrew Rybchenko fail4:
24885e111ed8SAndrew Rybchenko EFSYS_PROBE(fail4);
24895e111ed8SAndrew Rybchenko fail3:
24905e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
24915e111ed8SAndrew Rybchenko fail2:
24925e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
24935e111ed8SAndrew Rybchenko fail1:
24945e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
24955e111ed8SAndrew Rybchenko
24965e111ed8SAndrew Rybchenko return (rc);
24975e111ed8SAndrew Rybchenko }
24985e111ed8SAndrew Rybchenko
24995e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_set_drv_limits(__inout efx_nic_t * enp,__in efx_drv_limits_t * edlp)25005e111ed8SAndrew Rybchenko ef10_nic_set_drv_limits(
25015e111ed8SAndrew Rybchenko __inout efx_nic_t *enp,
25025e111ed8SAndrew Rybchenko __in efx_drv_limits_t *edlp)
25035e111ed8SAndrew Rybchenko {
25045e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
25055e111ed8SAndrew Rybchenko efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
25065e111ed8SAndrew Rybchenko uint32_t min_evq_count, max_evq_count;
25075e111ed8SAndrew Rybchenko uint32_t min_rxq_count, max_rxq_count;
25085e111ed8SAndrew Rybchenko uint32_t min_txq_count, max_txq_count;
25095e111ed8SAndrew Rybchenko efx_rc_t rc;
25105e111ed8SAndrew Rybchenko
25115e111ed8SAndrew Rybchenko if (edlp == NULL) {
25125e111ed8SAndrew Rybchenko rc = EINVAL;
25135e111ed8SAndrew Rybchenko goto fail1;
25145e111ed8SAndrew Rybchenko }
25155e111ed8SAndrew Rybchenko
25165e111ed8SAndrew Rybchenko /* Get minimum required and maximum usable VI limits */
25175e111ed8SAndrew Rybchenko min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
25185e111ed8SAndrew Rybchenko min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
25195e111ed8SAndrew Rybchenko min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
25205e111ed8SAndrew Rybchenko
25215e111ed8SAndrew Rybchenko edcp->edc_min_vi_count =
25225e111ed8SAndrew Rybchenko MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
25235e111ed8SAndrew Rybchenko
25245e111ed8SAndrew Rybchenko max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
25255e111ed8SAndrew Rybchenko max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
25265e111ed8SAndrew Rybchenko max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
25275e111ed8SAndrew Rybchenko
25285e111ed8SAndrew Rybchenko edcp->edc_max_vi_count =
25295e111ed8SAndrew Rybchenko MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
25305e111ed8SAndrew Rybchenko
25315e111ed8SAndrew Rybchenko /*
25325e111ed8SAndrew Rybchenko * Check limits for sub-allocated piobuf blocks.
25335e111ed8SAndrew Rybchenko * PIO is optional, so don't fail if the limits are incorrect.
25345e111ed8SAndrew Rybchenko */
25355e111ed8SAndrew Rybchenko if ((encp->enc_piobuf_size == 0) ||
25365e111ed8SAndrew Rybchenko (encp->enc_piobuf_limit == 0) ||
25375e111ed8SAndrew Rybchenko (edlp->edl_min_pio_alloc_size == 0) ||
25385e111ed8SAndrew Rybchenko (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
25395e111ed8SAndrew Rybchenko /* Disable PIO */
25405e111ed8SAndrew Rybchenko edcp->edc_max_piobuf_count = 0;
25415e111ed8SAndrew Rybchenko edcp->edc_pio_alloc_size = 0;
25425e111ed8SAndrew Rybchenko } else {
25435e111ed8SAndrew Rybchenko uint32_t blk_size, blk_count, blks_per_piobuf;
25445e111ed8SAndrew Rybchenko
25455e111ed8SAndrew Rybchenko blk_size =
25465e111ed8SAndrew Rybchenko MAX(edlp->edl_min_pio_alloc_size,
25475e111ed8SAndrew Rybchenko encp->enc_piobuf_min_alloc_size);
25485e111ed8SAndrew Rybchenko
25495e111ed8SAndrew Rybchenko blks_per_piobuf = encp->enc_piobuf_size / blk_size;
25505e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
25515e111ed8SAndrew Rybchenko
25525e111ed8SAndrew Rybchenko blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
25535e111ed8SAndrew Rybchenko
25545e111ed8SAndrew Rybchenko /* A zero max pio alloc count means unlimited */
25555e111ed8SAndrew Rybchenko if ((edlp->edl_max_pio_alloc_count > 0) &&
25565e111ed8SAndrew Rybchenko (edlp->edl_max_pio_alloc_count < blk_count)) {
25575e111ed8SAndrew Rybchenko blk_count = edlp->edl_max_pio_alloc_count;
25585e111ed8SAndrew Rybchenko }
25595e111ed8SAndrew Rybchenko
25605e111ed8SAndrew Rybchenko edcp->edc_pio_alloc_size = blk_size;
25615e111ed8SAndrew Rybchenko edcp->edc_max_piobuf_count =
25625e111ed8SAndrew Rybchenko (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
25635e111ed8SAndrew Rybchenko }
25645e111ed8SAndrew Rybchenko
25655e111ed8SAndrew Rybchenko return (0);
25665e111ed8SAndrew Rybchenko
25675e111ed8SAndrew Rybchenko fail1:
25685e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
25695e111ed8SAndrew Rybchenko
25705e111ed8SAndrew Rybchenko return (rc);
25715e111ed8SAndrew Rybchenko }
25725e111ed8SAndrew Rybchenko
25735e111ed8SAndrew Rybchenko
25745e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_reset(__in efx_nic_t * enp)25755e111ed8SAndrew Rybchenko ef10_nic_reset(
25765e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
25775e111ed8SAndrew Rybchenko {
25785e111ed8SAndrew Rybchenko efx_rc_t rc;
25795e111ed8SAndrew Rybchenko
25805e111ed8SAndrew Rybchenko /* ef10_nic_reset() is called to recover from BADASSERT failures. */
25815e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_read_assertion(enp)) != 0)
25825e111ed8SAndrew Rybchenko goto fail1;
25835e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
25845e111ed8SAndrew Rybchenko goto fail2;
25855e111ed8SAndrew Rybchenko
25864d0af0dbSAndrew Rybchenko if ((rc = efx_mcdi_entity_reset(enp)) != 0)
25875e111ed8SAndrew Rybchenko goto fail3;
25885e111ed8SAndrew Rybchenko
25895e111ed8SAndrew Rybchenko /* Clear RX/TX DMA queue errors */
25905e111ed8SAndrew Rybchenko enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
25915e111ed8SAndrew Rybchenko
25925e111ed8SAndrew Rybchenko return (0);
25935e111ed8SAndrew Rybchenko
25945e111ed8SAndrew Rybchenko fail3:
25955e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
25965e111ed8SAndrew Rybchenko fail2:
25975e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
25985e111ed8SAndrew Rybchenko fail1:
25995e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
26005e111ed8SAndrew Rybchenko
26015e111ed8SAndrew Rybchenko return (rc);
26025e111ed8SAndrew Rybchenko }
26035e111ed8SAndrew Rybchenko
260479867285SAndrew Rybchenko #endif /* EFX_OPTS_EF10() */
260579867285SAndrew Rybchenko
260679867285SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10()
260779867285SAndrew Rybchenko
260879867285SAndrew Rybchenko __checkReturn efx_rc_t
ef10_upstream_port_vadaptor_alloc(__in efx_nic_t * enp)26095e111ed8SAndrew Rybchenko ef10_upstream_port_vadaptor_alloc(
26105e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
26115e111ed8SAndrew Rybchenko {
26125e111ed8SAndrew Rybchenko uint32_t retry;
26135e111ed8SAndrew Rybchenko uint32_t delay_us;
26145e111ed8SAndrew Rybchenko efx_rc_t rc;
26155e111ed8SAndrew Rybchenko
26165e111ed8SAndrew Rybchenko /*
26175e111ed8SAndrew Rybchenko * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
26185e111ed8SAndrew Rybchenko * driver has yet to bring up the EVB port. See bug 56147. In this case,
26195e111ed8SAndrew Rybchenko * retry the request several times after waiting a while. The wait time
26205e111ed8SAndrew Rybchenko * between retries starts small (10ms) and exponentially increases.
26215e111ed8SAndrew Rybchenko * Total wait time is a little over two seconds. Retry logic in the
26225e111ed8SAndrew Rybchenko * client driver may mean this whole loop is repeated if it continues to
26235e111ed8SAndrew Rybchenko * fail.
26245e111ed8SAndrew Rybchenko */
26255e111ed8SAndrew Rybchenko retry = 0;
26265e111ed8SAndrew Rybchenko delay_us = 10000;
26275e111ed8SAndrew Rybchenko while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
26285e111ed8SAndrew Rybchenko if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
26295e111ed8SAndrew Rybchenko (rc != ENOENT)) {
26305e111ed8SAndrew Rybchenko /*
26315e111ed8SAndrew Rybchenko * Do not retry alloc for PF, or for other errors on
26325e111ed8SAndrew Rybchenko * a VF.
26335e111ed8SAndrew Rybchenko */
26345e111ed8SAndrew Rybchenko goto fail1;
26355e111ed8SAndrew Rybchenko }
26365e111ed8SAndrew Rybchenko
26375e111ed8SAndrew Rybchenko /* VF startup before PF is ready. Retry allocation. */
26385e111ed8SAndrew Rybchenko if (retry > 5) {
26395e111ed8SAndrew Rybchenko /* Too many attempts */
26405e111ed8SAndrew Rybchenko rc = EINVAL;
26415e111ed8SAndrew Rybchenko goto fail2;
26425e111ed8SAndrew Rybchenko }
26435e111ed8SAndrew Rybchenko EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
26445e111ed8SAndrew Rybchenko EFSYS_SLEEP(delay_us);
26455e111ed8SAndrew Rybchenko retry++;
26465e111ed8SAndrew Rybchenko if (delay_us < 500000)
26475e111ed8SAndrew Rybchenko delay_us <<= 2;
26485e111ed8SAndrew Rybchenko }
26495e111ed8SAndrew Rybchenko
26505e111ed8SAndrew Rybchenko return (0);
26515e111ed8SAndrew Rybchenko
26525e111ed8SAndrew Rybchenko fail2:
26535e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
26545e111ed8SAndrew Rybchenko fail1:
26555e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
26565e111ed8SAndrew Rybchenko
26575e111ed8SAndrew Rybchenko return (rc);
26585e111ed8SAndrew Rybchenko }
26595e111ed8SAndrew Rybchenko
266079867285SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */
266179867285SAndrew Rybchenko
266279867285SAndrew Rybchenko #if EFX_OPTS_EF10()
266379867285SAndrew Rybchenko
26645e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_init(__in efx_nic_t * enp)26655e111ed8SAndrew Rybchenko ef10_nic_init(
26665e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
26675e111ed8SAndrew Rybchenko {
26685e111ed8SAndrew Rybchenko efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
26695e111ed8SAndrew Rybchenko uint32_t min_vi_count, max_vi_count;
26705e111ed8SAndrew Rybchenko uint32_t vi_count, vi_base, vi_shift;
26715e111ed8SAndrew Rybchenko uint32_t i;
26725e111ed8SAndrew Rybchenko uint32_t vi_window_size;
26735e111ed8SAndrew Rybchenko efx_rc_t rc;
26745e111ed8SAndrew Rybchenko boolean_t alloc_vadaptor = B_TRUE;
26755e111ed8SAndrew Rybchenko
26765e111ed8SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
26775e111ed8SAndrew Rybchenko
26785e111ed8SAndrew Rybchenko /* Enable reporting of some events (e.g. link change) */
26795e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
26805e111ed8SAndrew Rybchenko goto fail1;
26815e111ed8SAndrew Rybchenko
26825e111ed8SAndrew Rybchenko /* Allocate (optional) on-chip PIO buffers */
26835e111ed8SAndrew Rybchenko ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
26845e111ed8SAndrew Rybchenko
26855e111ed8SAndrew Rybchenko /*
26865e111ed8SAndrew Rybchenko * For best performance, PIO writes should use a write-combined
26875e111ed8SAndrew Rybchenko * (WC) memory mapping. Using a separate WC mapping for the PIO
26885e111ed8SAndrew Rybchenko * aperture of each VI would be a burden to drivers (and not
26895e111ed8SAndrew Rybchenko * possible if the host page size is >4Kbyte).
26905e111ed8SAndrew Rybchenko *
26915e111ed8SAndrew Rybchenko * To avoid this we use a single uncached (UC) mapping for VI
26925e111ed8SAndrew Rybchenko * register access, and a single WC mapping for extra VIs used
26935e111ed8SAndrew Rybchenko * for PIO writes.
26945e111ed8SAndrew Rybchenko *
26955e111ed8SAndrew Rybchenko * Each piobuf must be linked to a VI in the WC mapping, and to
26965e111ed8SAndrew Rybchenko * each VI that is using a sub-allocated block from the piobuf.
26975e111ed8SAndrew Rybchenko */
26985e111ed8SAndrew Rybchenko min_vi_count = edcp->edc_min_vi_count;
26995e111ed8SAndrew Rybchenko max_vi_count =
27005e111ed8SAndrew Rybchenko edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
27015e111ed8SAndrew Rybchenko
27025e111ed8SAndrew Rybchenko /* Ensure that the previously attached driver's VIs are freed */
27035e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_free_vis(enp)) != 0)
27045e111ed8SAndrew Rybchenko goto fail2;
27055e111ed8SAndrew Rybchenko
27065e111ed8SAndrew Rybchenko /*
27075e111ed8SAndrew Rybchenko * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
27085e111ed8SAndrew Rybchenko * fails then retrying the request for fewer VI resources may succeed.
27095e111ed8SAndrew Rybchenko */
27105e111ed8SAndrew Rybchenko vi_count = 0;
27115e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
27125e111ed8SAndrew Rybchenko &vi_base, &vi_count, &vi_shift)) != 0)
27135e111ed8SAndrew Rybchenko goto fail3;
27145e111ed8SAndrew Rybchenko
27155e111ed8SAndrew Rybchenko EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
27165e111ed8SAndrew Rybchenko
27175e111ed8SAndrew Rybchenko if (vi_count < min_vi_count) {
27185e111ed8SAndrew Rybchenko rc = ENOMEM;
27195e111ed8SAndrew Rybchenko goto fail4;
27205e111ed8SAndrew Rybchenko }
27215e111ed8SAndrew Rybchenko
27225e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_vi_base = vi_base;
27235e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_vi_count = vi_count;
27245e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_vi_shift = vi_shift;
27255e111ed8SAndrew Rybchenko
27265e111ed8SAndrew Rybchenko if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
27275e111ed8SAndrew Rybchenko /* Not enough extra VIs to map piobufs */
27285e111ed8SAndrew Rybchenko ef10_nic_free_piobufs(enp);
27295e111ed8SAndrew Rybchenko }
27305e111ed8SAndrew Rybchenko
27315e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_pio_write_vi_base =
27325e111ed8SAndrew Rybchenko vi_count - enp->en_arch.ef10.ena_piobuf_count;
27335e111ed8SAndrew Rybchenko
27345e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nic_cfg.enc_vi_window_shift, !=,
27355e111ed8SAndrew Rybchenko EFX_VI_WINDOW_SHIFT_INVALID);
27365e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nic_cfg.enc_vi_window_shift, <=,
27375e111ed8SAndrew Rybchenko EFX_VI_WINDOW_SHIFT_64K);
27385e111ed8SAndrew Rybchenko vi_window_size = 1U << enp->en_nic_cfg.enc_vi_window_shift;
27395e111ed8SAndrew Rybchenko
27405e111ed8SAndrew Rybchenko /* Save UC memory mapping details */
27415e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
27425e111ed8SAndrew Rybchenko if (enp->en_arch.ef10.ena_piobuf_count > 0) {
27435e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_size =
27445e111ed8SAndrew Rybchenko (vi_window_size *
27455e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_pio_write_vi_base);
27465e111ed8SAndrew Rybchenko } else {
27475e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_size =
27485e111ed8SAndrew Rybchenko (vi_window_size *
27495e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_vi_count);
27505e111ed8SAndrew Rybchenko }
27515e111ed8SAndrew Rybchenko
27525e111ed8SAndrew Rybchenko /* Save WC memory mapping details */
27535e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_wc_mem_map_offset =
27545e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_offset +
27555e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_uc_mem_map_size;
27565e111ed8SAndrew Rybchenko
27575e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_wc_mem_map_size =
27585e111ed8SAndrew Rybchenko (vi_window_size *
27595e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_count);
27605e111ed8SAndrew Rybchenko
27615e111ed8SAndrew Rybchenko /* Link piobufs to extra VIs in WC mapping */
27625e111ed8SAndrew Rybchenko if (enp->en_arch.ef10.ena_piobuf_count > 0) {
27635e111ed8SAndrew Rybchenko for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
27645e111ed8SAndrew Rybchenko rc = efx_mcdi_link_piobuf(enp,
27655e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_pio_write_vi_base + i,
27665e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_piobuf_handle[i]);
27675e111ed8SAndrew Rybchenko if (rc != 0)
27685e111ed8SAndrew Rybchenko break;
27695e111ed8SAndrew Rybchenko }
27705e111ed8SAndrew Rybchenko }
27715e111ed8SAndrew Rybchenko
27725e111ed8SAndrew Rybchenko /*
27735e111ed8SAndrew Rybchenko * For SR-IOV use case, vAdaptor is allocated for PF and associated VFs
27745e111ed8SAndrew Rybchenko * during NIC initialization when vSwitch is created and vports are
27755e111ed8SAndrew Rybchenko * allocated. Hence, skip vAdaptor allocation for EVB and update vport
27765e111ed8SAndrew Rybchenko * id in NIC structure with the one allocated for PF.
27775e111ed8SAndrew Rybchenko */
27785e111ed8SAndrew Rybchenko
27795e111ed8SAndrew Rybchenko enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
27805e111ed8SAndrew Rybchenko #if EFSYS_OPT_EVB
27815e111ed8SAndrew Rybchenko if ((enp->en_vswitchp != NULL) && (enp->en_vswitchp->ev_evcp != NULL)) {
27825e111ed8SAndrew Rybchenko /* For EVB use vport allocated on vswitch */
27835e111ed8SAndrew Rybchenko enp->en_vport_id = enp->en_vswitchp->ev_evcp->evc_vport_id;
27845e111ed8SAndrew Rybchenko alloc_vadaptor = B_FALSE;
27855e111ed8SAndrew Rybchenko }
27865e111ed8SAndrew Rybchenko #endif
27875e111ed8SAndrew Rybchenko if (alloc_vadaptor != B_FALSE) {
27885e111ed8SAndrew Rybchenko /* Allocate a vAdaptor attached to our upstream vPort/pPort */
27895e111ed8SAndrew Rybchenko if ((rc = ef10_upstream_port_vadaptor_alloc(enp)) != 0)
27905e111ed8SAndrew Rybchenko goto fail5;
27915e111ed8SAndrew Rybchenko }
27925e111ed8SAndrew Rybchenko enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
27935e111ed8SAndrew Rybchenko
27945e111ed8SAndrew Rybchenko return (0);
27955e111ed8SAndrew Rybchenko
27965e111ed8SAndrew Rybchenko fail5:
27975e111ed8SAndrew Rybchenko EFSYS_PROBE(fail5);
27985e111ed8SAndrew Rybchenko fail4:
27995e111ed8SAndrew Rybchenko EFSYS_PROBE(fail4);
28005e111ed8SAndrew Rybchenko fail3:
28015e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3);
28025e111ed8SAndrew Rybchenko fail2:
28035e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
28045e111ed8SAndrew Rybchenko
28055e111ed8SAndrew Rybchenko ef10_nic_free_piobufs(enp);
28065e111ed8SAndrew Rybchenko
28075e111ed8SAndrew Rybchenko fail1:
28085e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
28095e111ed8SAndrew Rybchenko
28105e111ed8SAndrew Rybchenko return (rc);
28115e111ed8SAndrew Rybchenko }
28125e111ed8SAndrew Rybchenko
28135e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_get_vi_pool(__in efx_nic_t * enp,__out uint32_t * vi_countp)28145e111ed8SAndrew Rybchenko ef10_nic_get_vi_pool(
28155e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
28165e111ed8SAndrew Rybchenko __out uint32_t *vi_countp)
28175e111ed8SAndrew Rybchenko {
28185e111ed8SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
28195e111ed8SAndrew Rybchenko
28205e111ed8SAndrew Rybchenko /*
28215e111ed8SAndrew Rybchenko * Report VIs that the client driver can use.
28225e111ed8SAndrew Rybchenko * Do not include VIs used for PIO buffer writes.
28235e111ed8SAndrew Rybchenko */
28245e111ed8SAndrew Rybchenko *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
28255e111ed8SAndrew Rybchenko
28265e111ed8SAndrew Rybchenko return (0);
28275e111ed8SAndrew Rybchenko }
28285e111ed8SAndrew Rybchenko
28295e111ed8SAndrew 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)28305e111ed8SAndrew Rybchenko ef10_nic_get_bar_region(
28315e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
28325e111ed8SAndrew Rybchenko __in efx_nic_region_t region,
28335e111ed8SAndrew Rybchenko __out uint32_t *offsetp,
28345e111ed8SAndrew Rybchenko __out size_t *sizep)
28355e111ed8SAndrew Rybchenko {
28365e111ed8SAndrew Rybchenko efx_rc_t rc;
28375e111ed8SAndrew Rybchenko
28385e111ed8SAndrew Rybchenko EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
28395e111ed8SAndrew Rybchenko
28405e111ed8SAndrew Rybchenko /*
28415e111ed8SAndrew Rybchenko * TODO: Specify host memory mapping alignment and granularity
28425e111ed8SAndrew Rybchenko * in efx_drv_limits_t so that they can be taken into account
28435e111ed8SAndrew Rybchenko * when allocating extra VIs for PIO writes.
28445e111ed8SAndrew Rybchenko */
28455e111ed8SAndrew Rybchenko switch (region) {
28465e111ed8SAndrew Rybchenko case EFX_REGION_VI:
28475e111ed8SAndrew Rybchenko /* UC mapped memory BAR region for VI registers */
28485e111ed8SAndrew Rybchenko *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
28495e111ed8SAndrew Rybchenko *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
28505e111ed8SAndrew Rybchenko break;
28515e111ed8SAndrew Rybchenko
28525e111ed8SAndrew Rybchenko case EFX_REGION_PIO_WRITE_VI:
28535e111ed8SAndrew Rybchenko /* WC mapped memory BAR region for piobuf writes */
28545e111ed8SAndrew Rybchenko *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
28555e111ed8SAndrew Rybchenko *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
28565e111ed8SAndrew Rybchenko break;
28575e111ed8SAndrew Rybchenko
28585e111ed8SAndrew Rybchenko default:
28595e111ed8SAndrew Rybchenko rc = EINVAL;
28605e111ed8SAndrew Rybchenko goto fail1;
28615e111ed8SAndrew Rybchenko }
28625e111ed8SAndrew Rybchenko
28635e111ed8SAndrew Rybchenko return (0);
28645e111ed8SAndrew Rybchenko
28655e111ed8SAndrew Rybchenko fail1:
28665e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
28675e111ed8SAndrew Rybchenko
28685e111ed8SAndrew Rybchenko return (rc);
28695e111ed8SAndrew Rybchenko }
28705e111ed8SAndrew Rybchenko
28715e111ed8SAndrew Rybchenko __checkReturn boolean_t
ef10_nic_hw_unavailable(__in efx_nic_t * enp)28725e111ed8SAndrew Rybchenko ef10_nic_hw_unavailable(
28735e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
28745e111ed8SAndrew Rybchenko {
28755e111ed8SAndrew Rybchenko efx_dword_t dword;
28765e111ed8SAndrew Rybchenko
28775e111ed8SAndrew Rybchenko if (enp->en_reset_flags & EFX_RESET_HW_UNAVAIL)
28785e111ed8SAndrew Rybchenko return (B_TRUE);
28795e111ed8SAndrew Rybchenko
28805e111ed8SAndrew Rybchenko EFX_BAR_READD(enp, ER_DZ_BIU_MC_SFT_STATUS_REG, &dword, B_FALSE);
28815e111ed8SAndrew Rybchenko if (EFX_DWORD_FIELD(dword, EFX_DWORD_0) == 0xffffffff)
28825e111ed8SAndrew Rybchenko goto unavail;
28835e111ed8SAndrew Rybchenko
28845e111ed8SAndrew Rybchenko return (B_FALSE);
28855e111ed8SAndrew Rybchenko
28865e111ed8SAndrew Rybchenko unavail:
28875e111ed8SAndrew Rybchenko ef10_nic_set_hw_unavailable(enp);
28885e111ed8SAndrew Rybchenko
28895e111ed8SAndrew Rybchenko return (B_TRUE);
28905e111ed8SAndrew Rybchenko }
28915e111ed8SAndrew Rybchenko
28925e111ed8SAndrew Rybchenko void
ef10_nic_set_hw_unavailable(__in efx_nic_t * enp)28935e111ed8SAndrew Rybchenko ef10_nic_set_hw_unavailable(
28945e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
28955e111ed8SAndrew Rybchenko {
28965e111ed8SAndrew Rybchenko EFSYS_PROBE(hw_unavail);
28975e111ed8SAndrew Rybchenko enp->en_reset_flags |= EFX_RESET_HW_UNAVAIL;
28985e111ed8SAndrew Rybchenko }
28995e111ed8SAndrew Rybchenko
29005e111ed8SAndrew Rybchenko
29015e111ed8SAndrew Rybchenko void
ef10_nic_fini(__in efx_nic_t * enp)29025e111ed8SAndrew Rybchenko ef10_nic_fini(
29035e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
29045e111ed8SAndrew Rybchenko {
29055e111ed8SAndrew Rybchenko uint32_t i;
29065e111ed8SAndrew Rybchenko efx_rc_t rc;
29075e111ed8SAndrew Rybchenko boolean_t do_vadaptor_free = B_TRUE;
29085e111ed8SAndrew Rybchenko
29095e111ed8SAndrew Rybchenko #if EFSYS_OPT_EVB
29105e111ed8SAndrew Rybchenko if (enp->en_vswitchp != NULL) {
29115e111ed8SAndrew Rybchenko /*
29125e111ed8SAndrew Rybchenko * For SR-IOV the vAdaptor is freed with the vswitch,
29135e111ed8SAndrew Rybchenko * so do not free it here.
29145e111ed8SAndrew Rybchenko */
29155e111ed8SAndrew Rybchenko do_vadaptor_free = B_FALSE;
29165e111ed8SAndrew Rybchenko }
29175e111ed8SAndrew Rybchenko #endif
29185e111ed8SAndrew Rybchenko if (do_vadaptor_free != B_FALSE) {
29195e111ed8SAndrew Rybchenko (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
29205e111ed8SAndrew Rybchenko enp->en_vport_id = EVB_PORT_ID_NULL;
29215e111ed8SAndrew Rybchenko }
29225e111ed8SAndrew Rybchenko
29235e111ed8SAndrew Rybchenko /* Unlink piobufs from extra VIs in WC mapping */
29245e111ed8SAndrew Rybchenko if (enp->en_arch.ef10.ena_piobuf_count > 0) {
29255e111ed8SAndrew Rybchenko for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
29265e111ed8SAndrew Rybchenko rc = efx_mcdi_unlink_piobuf(enp,
29275e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_pio_write_vi_base + i);
29285e111ed8SAndrew Rybchenko if (rc != 0)
29295e111ed8SAndrew Rybchenko break;
29305e111ed8SAndrew Rybchenko }
29315e111ed8SAndrew Rybchenko }
29325e111ed8SAndrew Rybchenko
29335e111ed8SAndrew Rybchenko ef10_nic_free_piobufs(enp);
29345e111ed8SAndrew Rybchenko
29355e111ed8SAndrew Rybchenko (void) efx_mcdi_free_vis(enp);
29365e111ed8SAndrew Rybchenko enp->en_arch.ef10.ena_vi_count = 0;
29375e111ed8SAndrew Rybchenko }
29385e111ed8SAndrew Rybchenko
29395e111ed8SAndrew Rybchenko void
ef10_nic_unprobe(__in efx_nic_t * enp)29405e111ed8SAndrew Rybchenko ef10_nic_unprobe(
29415e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
29425e111ed8SAndrew Rybchenko {
29435e111ed8SAndrew Rybchenko #if EFSYS_OPT_MON_STATS
29445e111ed8SAndrew Rybchenko mcdi_mon_cfg_free(enp);
29455e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MON_STATS */
29465e111ed8SAndrew Rybchenko (void) efx_mcdi_drv_attach(enp, B_FALSE);
29475e111ed8SAndrew Rybchenko }
29485e111ed8SAndrew Rybchenko
29495e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
29505e111ed8SAndrew Rybchenko
29515e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
ef10_nic_register_test(__in efx_nic_t * enp)29525e111ed8SAndrew Rybchenko ef10_nic_register_test(
29535e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
29545e111ed8SAndrew Rybchenko {
29555e111ed8SAndrew Rybchenko efx_rc_t rc;
29565e111ed8SAndrew Rybchenko
29575e111ed8SAndrew Rybchenko /* FIXME */
29585e111ed8SAndrew Rybchenko _NOTE(ARGUNUSED(enp))
29595e111ed8SAndrew Rybchenko _NOTE(CONSTANTCONDITION)
29605e111ed8SAndrew Rybchenko if (B_FALSE) {
29615e111ed8SAndrew Rybchenko rc = ENOTSUP;
29625e111ed8SAndrew Rybchenko goto fail1;
29635e111ed8SAndrew Rybchenko }
29645e111ed8SAndrew Rybchenko /* FIXME */
29655e111ed8SAndrew Rybchenko
29665e111ed8SAndrew Rybchenko return (0);
29675e111ed8SAndrew Rybchenko
29685e111ed8SAndrew Rybchenko fail1:
29695e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
29705e111ed8SAndrew Rybchenko
29715e111ed8SAndrew Rybchenko return (rc);
29725e111ed8SAndrew Rybchenko }
29735e111ed8SAndrew Rybchenko
29745e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
29755e111ed8SAndrew Rybchenko
29765e111ed8SAndrew Rybchenko #if EFSYS_OPT_FW_SUBVARIANT_AWARE
29775e111ed8SAndrew Rybchenko
29785e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_get_nic_global(__in efx_nic_t * enp,__in uint32_t key,__out uint32_t * valuep)29795e111ed8SAndrew Rybchenko efx_mcdi_get_nic_global(
29805e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
29815e111ed8SAndrew Rybchenko __in uint32_t key,
29825e111ed8SAndrew Rybchenko __out uint32_t *valuep)
29835e111ed8SAndrew Rybchenko {
29845e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
29855e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_NIC_GLOBAL_IN_LEN,
29865e111ed8SAndrew Rybchenko MC_CMD_GET_NIC_GLOBAL_OUT_LEN);
29875e111ed8SAndrew Rybchenko efx_rc_t rc;
29885e111ed8SAndrew Rybchenko
29895e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_GET_NIC_GLOBAL;
29905e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
29915e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_GET_NIC_GLOBAL_IN_LEN;
29925e111ed8SAndrew Rybchenko req.emr_out_buf = payload;
29935e111ed8SAndrew Rybchenko req.emr_out_length = MC_CMD_GET_NIC_GLOBAL_OUT_LEN;
29945e111ed8SAndrew Rybchenko
29955e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, GET_NIC_GLOBAL_IN_KEY, key);
29965e111ed8SAndrew Rybchenko
29975e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
29985e111ed8SAndrew Rybchenko
29995e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
30005e111ed8SAndrew Rybchenko rc = req.emr_rc;
30015e111ed8SAndrew Rybchenko goto fail1;
30025e111ed8SAndrew Rybchenko }
30035e111ed8SAndrew Rybchenko
30045e111ed8SAndrew Rybchenko if (req.emr_out_length_used != MC_CMD_GET_NIC_GLOBAL_OUT_LEN) {
30055e111ed8SAndrew Rybchenko rc = EMSGSIZE;
30065e111ed8SAndrew Rybchenko goto fail2;
30075e111ed8SAndrew Rybchenko }
30085e111ed8SAndrew Rybchenko
30095e111ed8SAndrew Rybchenko *valuep = MCDI_OUT_DWORD(req, GET_NIC_GLOBAL_OUT_VALUE);
30105e111ed8SAndrew Rybchenko
30115e111ed8SAndrew Rybchenko return (0);
30125e111ed8SAndrew Rybchenko
30135e111ed8SAndrew Rybchenko fail2:
30145e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
30155e111ed8SAndrew Rybchenko fail1:
30165e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
30175e111ed8SAndrew Rybchenko
30185e111ed8SAndrew Rybchenko return (rc);
30195e111ed8SAndrew Rybchenko }
30205e111ed8SAndrew Rybchenko
30215e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_set_nic_global(__in efx_nic_t * enp,__in uint32_t key,__in uint32_t value)30225e111ed8SAndrew Rybchenko efx_mcdi_set_nic_global(
30235e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
30245e111ed8SAndrew Rybchenko __in uint32_t key,
30255e111ed8SAndrew Rybchenko __in uint32_t value)
30265e111ed8SAndrew Rybchenko {
30275e111ed8SAndrew Rybchenko efx_mcdi_req_t req;
30285e111ed8SAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SET_NIC_GLOBAL_IN_LEN, 0);
30295e111ed8SAndrew Rybchenko efx_rc_t rc;
30305e111ed8SAndrew Rybchenko
30315e111ed8SAndrew Rybchenko req.emr_cmd = MC_CMD_SET_NIC_GLOBAL;
30325e111ed8SAndrew Rybchenko req.emr_in_buf = payload;
30335e111ed8SAndrew Rybchenko req.emr_in_length = MC_CMD_SET_NIC_GLOBAL_IN_LEN;
30345e111ed8SAndrew Rybchenko req.emr_out_buf = NULL;
30355e111ed8SAndrew Rybchenko req.emr_out_length = 0;
30365e111ed8SAndrew Rybchenko
30375e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, SET_NIC_GLOBAL_IN_KEY, key);
30385e111ed8SAndrew Rybchenko MCDI_IN_SET_DWORD(req, SET_NIC_GLOBAL_IN_VALUE, value);
30395e111ed8SAndrew Rybchenko
30405e111ed8SAndrew Rybchenko efx_mcdi_execute(enp, &req);
30415e111ed8SAndrew Rybchenko
30425e111ed8SAndrew Rybchenko if (req.emr_rc != 0) {
30435e111ed8SAndrew Rybchenko rc = req.emr_rc;
30445e111ed8SAndrew Rybchenko goto fail1;
30455e111ed8SAndrew Rybchenko }
30465e111ed8SAndrew Rybchenko
30475e111ed8SAndrew Rybchenko return (0);
30485e111ed8SAndrew Rybchenko
30495e111ed8SAndrew Rybchenko fail1:
30505e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
30515e111ed8SAndrew Rybchenko
30525e111ed8SAndrew Rybchenko return (rc);
30535e111ed8SAndrew Rybchenko }
30545e111ed8SAndrew Rybchenko
30555e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_FW_SUBVARIANT_AWARE */
30565e111ed8SAndrew Rybchenko
30575e111ed8SAndrew Rybchenko #endif /* EFX_OPTS_EF10() */
3058