xref: /dpdk/drivers/common/sfc_efx/base/ef10_rx.c (revision bcdcec8cca8a2ea2b4962e7fda6d6d3c866ef760)
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 
105e111ed8SAndrew Rybchenko 
11b6b29352SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10()
125e111ed8SAndrew Rybchenko 
135e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
145e111ed8SAndrew Rybchenko static	__checkReturn	efx_rc_t
efx_mcdi_rss_context_alloc(__in efx_nic_t * enp,__in efx_rx_scale_context_type_t type,__in uint32_t num_queues,__in uint32_t table_nentries,__out uint32_t * rss_contextp)155e111ed8SAndrew Rybchenko efx_mcdi_rss_context_alloc(
165e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
175e111ed8SAndrew Rybchenko 	__in		efx_rx_scale_context_type_t type,
185e111ed8SAndrew Rybchenko 	__in		uint32_t num_queues,
19e7ea5f30SIvan Malov 	__in		uint32_t table_nentries,
205e111ed8SAndrew Rybchenko 	__out		uint32_t *rss_contextp)
215e111ed8SAndrew Rybchenko {
22777da150SIvan Malov 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
235e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
24e7ea5f30SIvan Malov 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_ALLOC_V2_IN_LEN,
255e111ed8SAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN);
26*bcdcec8cSIvan Malov 	uint32_t table_nentries_min;
27*bcdcec8cSIvan Malov 	uint32_t table_nentries_max;
28*bcdcec8cSIvan Malov 	uint32_t num_queues_max;
295e111ed8SAndrew Rybchenko 	uint32_t rss_context;
305e111ed8SAndrew Rybchenko 	uint32_t context_type;
315e111ed8SAndrew Rybchenko 	efx_rc_t rc;
325e111ed8SAndrew Rybchenko 
33*bcdcec8cSIvan Malov 	switch (type) {
34*bcdcec8cSIvan Malov 	case EFX_RX_SCALE_EXCLUSIVE:
35*bcdcec8cSIvan Malov 		context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE;
36*bcdcec8cSIvan Malov 		num_queues_max = encp->enc_rx_scale_indirection_max_nqueues;
37*bcdcec8cSIvan Malov 		table_nentries_min = encp->enc_rx_scale_tbl_min_nentries;
38*bcdcec8cSIvan Malov 		table_nentries_max = encp->enc_rx_scale_tbl_max_nentries;
39*bcdcec8cSIvan Malov 		break;
40*bcdcec8cSIvan Malov 	case EFX_RX_SCALE_SHARED:
41*bcdcec8cSIvan Malov 		context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_SHARED;
42*bcdcec8cSIvan Malov 		num_queues_max = encp->enc_rx_scale_indirection_max_nqueues;
43*bcdcec8cSIvan Malov 		table_nentries_min = encp->enc_rx_scale_tbl_min_nentries;
44*bcdcec8cSIvan Malov 		table_nentries_max = encp->enc_rx_scale_tbl_max_nentries;
45*bcdcec8cSIvan Malov 		break;
46*bcdcec8cSIvan Malov 	case EFX_RX_SCALE_EVEN_SPREAD:
47*bcdcec8cSIvan Malov 		context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EVEN_SPREADING;
48*bcdcec8cSIvan Malov 		num_queues_max = encp->enc_rx_scale_even_spread_max_nqueues;
49*bcdcec8cSIvan Malov 		table_nentries_min = 0;
50*bcdcec8cSIvan Malov 		table_nentries_max = 0;
51*bcdcec8cSIvan Malov 		break;
52*bcdcec8cSIvan Malov 	default:
535e111ed8SAndrew Rybchenko 		rc = EINVAL;
545e111ed8SAndrew Rybchenko 		goto fail1;
555e111ed8SAndrew Rybchenko 	}
565e111ed8SAndrew Rybchenko 
57*bcdcec8cSIvan Malov 	if (num_queues == 0 || num_queues > num_queues_max) {
58e7ea5f30SIvan Malov 		rc = EINVAL;
59e7ea5f30SIvan Malov 		goto fail2;
60e7ea5f30SIvan Malov 	}
61e7ea5f30SIvan Malov 
62*bcdcec8cSIvan Malov 	if (table_nentries < table_nentries_min ||
63*bcdcec8cSIvan Malov 	    table_nentries > table_nentries_max ||
64*bcdcec8cSIvan Malov 	    (table_nentries != 0 && !ISP2(table_nentries))) {
655e111ed8SAndrew Rybchenko 		rc = EINVAL;
66e7ea5f30SIvan Malov 		goto fail3;
675e111ed8SAndrew Rybchenko 	}
685e111ed8SAndrew Rybchenko 
695e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_ALLOC;
705e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
71e7ea5f30SIvan Malov 	req.emr_in_length =
72e7ea5f30SIvan Malov 	    (encp->enc_rx_scale_tbl_entry_count_is_selectable != B_FALSE) ?
73e7ea5f30SIvan Malov 	    MC_CMD_RSS_CONTEXT_ALLOC_V2_IN_LEN :
74e7ea5f30SIvan Malov 	    MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN;
755e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
765e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN;
775e111ed8SAndrew Rybchenko 
785e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID,
795e111ed8SAndrew Rybchenko 		enp->en_vport_id);
805e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_TYPE, context_type);
815e111ed8SAndrew Rybchenko 
825e111ed8SAndrew Rybchenko 	/*
835e111ed8SAndrew Rybchenko 	 * For exclusive contexts, NUM_QUEUES is only used to validate
845e111ed8SAndrew Rybchenko 	 * indirection table offsets.
855e111ed8SAndrew Rybchenko 	 * For shared contexts, the provided context will spread traffic over
865e111ed8SAndrew Rybchenko 	 * NUM_QUEUES many queues.
87*bcdcec8cSIvan Malov 	 * For the even spread contexts, the provided context will spread
88*bcdcec8cSIvan Malov 	 * traffic over NUM_QUEUES many queues, but that will not involve
89*bcdcec8cSIvan Malov 	 * the use of precious indirection table resources in the adapter.
905e111ed8SAndrew Rybchenko 	 */
915e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, num_queues);
925e111ed8SAndrew Rybchenko 
93e7ea5f30SIvan Malov 	if (encp->enc_rx_scale_tbl_entry_count_is_selectable != B_FALSE) {
94e7ea5f30SIvan Malov 		MCDI_IN_SET_DWORD(req,
95e7ea5f30SIvan Malov 		    RSS_CONTEXT_ALLOC_V2_IN_INDIRECTION_TABLE_SIZE,
96e7ea5f30SIvan Malov 		    table_nentries);
97e7ea5f30SIvan Malov 	}
98e7ea5f30SIvan Malov 
995e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
1005e111ed8SAndrew Rybchenko 
1015e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
1025e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
103e7ea5f30SIvan Malov 		goto fail4;
1045e111ed8SAndrew Rybchenko 	}
1055e111ed8SAndrew Rybchenko 
1065e111ed8SAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN) {
1075e111ed8SAndrew Rybchenko 		rc = EMSGSIZE;
108e7ea5f30SIvan Malov 		goto fail5;
1095e111ed8SAndrew Rybchenko 	}
1105e111ed8SAndrew Rybchenko 
1115e111ed8SAndrew Rybchenko 	rss_context = MCDI_OUT_DWORD(req, RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID);
1125e111ed8SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
1135e111ed8SAndrew Rybchenko 		rc = ENOENT;
114e7ea5f30SIvan Malov 		goto fail6;
1155e111ed8SAndrew Rybchenko 	}
1165e111ed8SAndrew Rybchenko 
1175e111ed8SAndrew Rybchenko 	*rss_contextp = rss_context;
1185e111ed8SAndrew Rybchenko 
1195e111ed8SAndrew Rybchenko 	return (0);
1205e111ed8SAndrew Rybchenko 
121e7ea5f30SIvan Malov fail6:
122e7ea5f30SIvan Malov 	EFSYS_PROBE(fail6);
1235e111ed8SAndrew Rybchenko fail5:
1245e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail5);
1255e111ed8SAndrew Rybchenko fail4:
1265e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail4);
1275e111ed8SAndrew Rybchenko fail3:
1285e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
1295e111ed8SAndrew Rybchenko fail2:
1305e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1315e111ed8SAndrew Rybchenko fail1:
1325e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1335e111ed8SAndrew Rybchenko 
1345e111ed8SAndrew Rybchenko 	return (rc);
1355e111ed8SAndrew Rybchenko }
1365e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
1375e111ed8SAndrew Rybchenko 
1385e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
1395e111ed8SAndrew Rybchenko static			efx_rc_t
efx_mcdi_rss_context_free(__in efx_nic_t * enp,__in uint32_t rss_context)1405e111ed8SAndrew Rybchenko efx_mcdi_rss_context_free(
1415e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
1425e111ed8SAndrew Rybchenko 	__in		uint32_t rss_context)
1435e111ed8SAndrew Rybchenko {
1445e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
1455e111ed8SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_FREE_IN_LEN,
1465e111ed8SAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_FREE_OUT_LEN);
1475e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1485e111ed8SAndrew Rybchenko 
1495e111ed8SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
1505e111ed8SAndrew Rybchenko 		rc = EINVAL;
1515e111ed8SAndrew Rybchenko 		goto fail1;
1525e111ed8SAndrew Rybchenko 	}
1535e111ed8SAndrew Rybchenko 
1545e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_FREE;
1555e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
1565e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_RSS_CONTEXT_FREE_IN_LEN;
1575e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
1585e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_FREE_OUT_LEN;
1595e111ed8SAndrew Rybchenko 
1605e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_FREE_IN_RSS_CONTEXT_ID, rss_context);
1615e111ed8SAndrew Rybchenko 
1625e111ed8SAndrew Rybchenko 	efx_mcdi_execute_quiet(enp, &req);
1635e111ed8SAndrew Rybchenko 
1645e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
1655e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
1665e111ed8SAndrew Rybchenko 		goto fail2;
1675e111ed8SAndrew Rybchenko 	}
1685e111ed8SAndrew Rybchenko 
1695e111ed8SAndrew Rybchenko 	return (0);
1705e111ed8SAndrew Rybchenko 
1715e111ed8SAndrew Rybchenko fail2:
1725e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1735e111ed8SAndrew Rybchenko fail1:
1745e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1755e111ed8SAndrew Rybchenko 
1765e111ed8SAndrew Rybchenko 	return (rc);
1775e111ed8SAndrew Rybchenko }
1785e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
1795e111ed8SAndrew Rybchenko 
1805e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
1815e111ed8SAndrew Rybchenko static			efx_rc_t
efx_mcdi_rss_context_set_flags(__in efx_nic_t * enp,__in uint32_t rss_context,__in efx_rx_hash_type_t type)1825e111ed8SAndrew Rybchenko efx_mcdi_rss_context_set_flags(
1835e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
1845e111ed8SAndrew Rybchenko 	__in		uint32_t rss_context,
1855e111ed8SAndrew Rybchenko 	__in		efx_rx_hash_type_t type)
1865e111ed8SAndrew Rybchenko {
1875e111ed8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &enp->en_nic_cfg;
1885e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
1895e111ed8SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN,
1905e111ed8SAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN);
1915e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1925e111ed8SAndrew Rybchenko 
1935e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_LBN ==
1945e111ed8SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_LBN);
1955e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_WIDTH ==
1965e111ed8SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_WIDTH);
1975e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_LBN ==
1985e111ed8SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_LBN);
1995e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_WIDTH ==
2005e111ed8SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_WIDTH);
2015e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_LBN ==
2025e111ed8SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_LBN);
2035e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_WIDTH ==
2045e111ed8SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_WIDTH);
2055e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_LBN ==
2065e111ed8SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_LBN);
2075e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_WIDTH ==
2085e111ed8SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_WIDTH);
2095e111ed8SAndrew Rybchenko 
2105e111ed8SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
2115e111ed8SAndrew Rybchenko 		rc = EINVAL;
2125e111ed8SAndrew Rybchenko 		goto fail1;
2135e111ed8SAndrew Rybchenko 	}
2145e111ed8SAndrew Rybchenko 
2155e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_FLAGS;
2165e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
2175e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN;
2185e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
2195e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN;
2205e111ed8SAndrew Rybchenko 
2215e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID,
2225e111ed8SAndrew Rybchenko 	    rss_context);
2235e111ed8SAndrew Rybchenko 
2245e111ed8SAndrew Rybchenko 	/*
2255e111ed8SAndrew Rybchenko 	 * If the firmware lacks support for additional modes, RSS_MODE
2265e111ed8SAndrew Rybchenko 	 * fields must contain zeros, otherwise the operation will fail.
2275e111ed8SAndrew Rybchenko 	 */
2285e111ed8SAndrew Rybchenko 	if (encp->enc_rx_scale_additional_modes_supported == B_FALSE)
2295e111ed8SAndrew Rybchenko 		type &= EFX_RX_HASH_LEGACY_MASK;
2305e111ed8SAndrew Rybchenko 
2315e111ed8SAndrew Rybchenko 	MCDI_IN_POPULATE_DWORD_10(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
2325e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN,
2335e111ed8SAndrew Rybchenko 	    (type & EFX_RX_HASH_IPV4) ? 1 : 0,
2345e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN,
2355e111ed8SAndrew Rybchenko 	    (type & EFX_RX_HASH_TCPIPV4) ? 1 : 0,
2365e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN,
2375e111ed8SAndrew Rybchenko 	    (type & EFX_RX_HASH_IPV6) ? 1 : 0,
2385e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN,
2395e111ed8SAndrew Rybchenko 	    (type & EFX_RX_HASH_TCPIPV6) ? 1 : 0,
2405e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE,
2415e111ed8SAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV4_TCP_LBN) &
2425e111ed8SAndrew Rybchenko 	    EFX_MASK32(EFX_RX_CLASS_IPV4_TCP),
2435e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV4_RSS_MODE,
2445e111ed8SAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV4_UDP_LBN) &
2455e111ed8SAndrew Rybchenko 	    EFX_MASK32(EFX_RX_CLASS_IPV4_UDP),
2465e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE,
2475e111ed8SAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV4_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV4),
2485e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE,
2495e111ed8SAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV6_TCP_LBN) &
2505e111ed8SAndrew Rybchenko 	    EFX_MASK32(EFX_RX_CLASS_IPV6_TCP),
2515e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV6_RSS_MODE,
2525e111ed8SAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV6_UDP_LBN) &
2535e111ed8SAndrew Rybchenko 	    EFX_MASK32(EFX_RX_CLASS_IPV6_UDP),
2545e111ed8SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE,
2555e111ed8SAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV6_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV6));
2565e111ed8SAndrew Rybchenko 
2575e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
2585e111ed8SAndrew Rybchenko 
2595e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
2605e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
2615e111ed8SAndrew Rybchenko 		goto fail2;
2625e111ed8SAndrew Rybchenko 	}
2635e111ed8SAndrew Rybchenko 
2645e111ed8SAndrew Rybchenko 	return (0);
2655e111ed8SAndrew Rybchenko 
2665e111ed8SAndrew Rybchenko fail2:
2675e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
2685e111ed8SAndrew Rybchenko fail1:
2695e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2705e111ed8SAndrew Rybchenko 
2715e111ed8SAndrew Rybchenko 	return (rc);
2725e111ed8SAndrew Rybchenko }
2735e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
2745e111ed8SAndrew Rybchenko 
2755e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
2765e111ed8SAndrew Rybchenko static			efx_rc_t
efx_mcdi_rss_context_set_key(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (n)uint8_t * key,__in size_t n)2775e111ed8SAndrew Rybchenko efx_mcdi_rss_context_set_key(
2785e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
2795e111ed8SAndrew Rybchenko 	__in		uint32_t rss_context,
2805e111ed8SAndrew Rybchenko 	__in_ecount(n)	uint8_t *key,
2815e111ed8SAndrew Rybchenko 	__in		size_t n)
2825e111ed8SAndrew Rybchenko {
2835e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
2845e111ed8SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN,
2855e111ed8SAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN);
2865e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2875e111ed8SAndrew Rybchenko 
2885e111ed8SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
2895e111ed8SAndrew Rybchenko 		rc = EINVAL;
2905e111ed8SAndrew Rybchenko 		goto fail1;
2915e111ed8SAndrew Rybchenko 	}
2925e111ed8SAndrew Rybchenko 
2935e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_KEY;
2945e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
2955e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN;
2965e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
2975e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN;
2985e111ed8SAndrew Rybchenko 
2995e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_KEY_IN_RSS_CONTEXT_ID,
3005e111ed8SAndrew Rybchenko 	    rss_context);
3015e111ed8SAndrew Rybchenko 
3025e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(n, ==, MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
3035e111ed8SAndrew Rybchenko 	if (n != MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN) {
3045e111ed8SAndrew Rybchenko 		rc = EINVAL;
3055e111ed8SAndrew Rybchenko 		goto fail2;
3065e111ed8SAndrew Rybchenko 	}
3075e111ed8SAndrew Rybchenko 
3085e111ed8SAndrew Rybchenko 	memcpy(MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY),
3095e111ed8SAndrew Rybchenko 	    key, n);
3105e111ed8SAndrew Rybchenko 
3115e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
3125e111ed8SAndrew Rybchenko 
3135e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
3145e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
3155e111ed8SAndrew Rybchenko 		goto fail3;
3165e111ed8SAndrew Rybchenko 	}
3175e111ed8SAndrew Rybchenko 
3185e111ed8SAndrew Rybchenko 	return (0);
3195e111ed8SAndrew Rybchenko 
3205e111ed8SAndrew Rybchenko fail3:
3215e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
3225e111ed8SAndrew Rybchenko fail2:
3235e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
3245e111ed8SAndrew Rybchenko fail1:
3255e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3265e111ed8SAndrew Rybchenko 
3275e111ed8SAndrew Rybchenko 	return (rc);
3285e111ed8SAndrew Rybchenko }
3295e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
3305e111ed8SAndrew Rybchenko 
3315e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
3325e111ed8SAndrew Rybchenko static				efx_rc_t
efx_mcdi_rss_context_set_table(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (nentries)unsigned int * table,__in size_t nentries)3335e111ed8SAndrew Rybchenko efx_mcdi_rss_context_set_table(
3345e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
3355e111ed8SAndrew Rybchenko 	__in			uint32_t rss_context,
3367a71c15dSIvan Malov 	__in_ecount(nentries)	unsigned int *table,
3377a71c15dSIvan Malov 	__in			size_t nentries)
3385e111ed8SAndrew Rybchenko {
3395e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
3405e111ed8SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN,
3415e111ed8SAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN);
3425e111ed8SAndrew Rybchenko 	uint8_t *req_table;
3435e111ed8SAndrew Rybchenko 	int i, rc;
3445e111ed8SAndrew Rybchenko 
3455e111ed8SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
3465e111ed8SAndrew Rybchenko 		rc = EINVAL;
3475e111ed8SAndrew Rybchenko 		goto fail1;
3485e111ed8SAndrew Rybchenko 	}
3495e111ed8SAndrew Rybchenko 
3505e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_TABLE;
3515e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
3525e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN;
3535e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
3545e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN;
3555e111ed8SAndrew Rybchenko 
3565e111ed8SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_TABLE_IN_RSS_CONTEXT_ID,
3575e111ed8SAndrew Rybchenko 	    rss_context);
3585e111ed8SAndrew Rybchenko 
3595e111ed8SAndrew Rybchenko 	req_table =
3605e111ed8SAndrew Rybchenko 	    MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE);
3615e111ed8SAndrew Rybchenko 
3625e111ed8SAndrew Rybchenko 	for (i = 0;
3635e111ed8SAndrew Rybchenko 	    i < MC_CMD_RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE_LEN;
3645e111ed8SAndrew Rybchenko 	    i++) {
3657a71c15dSIvan Malov 		req_table[i] = (nentries > 0) ?
3667a71c15dSIvan Malov 		    (uint8_t)table[i % nentries] : 0;
3675e111ed8SAndrew Rybchenko 	}
3685e111ed8SAndrew Rybchenko 
3695e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
3705e111ed8SAndrew Rybchenko 
3715e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
3725e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
3735e111ed8SAndrew Rybchenko 		goto fail2;
3745e111ed8SAndrew Rybchenko 	}
3755e111ed8SAndrew Rybchenko 
3765e111ed8SAndrew Rybchenko 	return (0);
3775e111ed8SAndrew Rybchenko 
3785e111ed8SAndrew Rybchenko fail2:
3795e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
3805e111ed8SAndrew Rybchenko fail1:
3815e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3825e111ed8SAndrew Rybchenko 
3835e111ed8SAndrew Rybchenko 	return (rc);
3845e111ed8SAndrew Rybchenko }
3855e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
3865e111ed8SAndrew Rybchenko 
387e7ea5f30SIvan Malov #if EFSYS_OPT_RX_SCALE
388e7ea5f30SIvan Malov static	__checkReturn		efx_rc_t
efx_mcdi_rss_context_write_table(__in efx_nic_t * enp,__in uint32_t context,__in unsigned int start_idx,__in_ecount (nentries)unsigned int * table,__in unsigned int nentries)389e7ea5f30SIvan Malov efx_mcdi_rss_context_write_table(
390e7ea5f30SIvan Malov 	__in			efx_nic_t *enp,
391e7ea5f30SIvan Malov 	__in			uint32_t context,
392e7ea5f30SIvan Malov 	__in			unsigned int start_idx,
393e7ea5f30SIvan Malov 	__in_ecount(nentries)	unsigned int *table,
394e7ea5f30SIvan Malov 	__in			unsigned int nentries)
395e7ea5f30SIvan Malov {
396e7ea5f30SIvan Malov 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
397e7ea5f30SIvan Malov 	efx_mcdi_req_t req;
398e7ea5f30SIvan Malov 	EFX_MCDI_DECLARE_BUF(payload,
399e7ea5f30SIvan Malov 	     MC_CMD_RSS_CONTEXT_WRITE_TABLE_IN_LENMAX_MCDI2,
400e7ea5f30SIvan Malov 	     MC_CMD_RSS_CONTEXT_WRITE_TABLE_OUT_LEN);
401e7ea5f30SIvan Malov 	unsigned int i;
402e7ea5f30SIvan Malov 	int rc;
403e7ea5f30SIvan Malov 
404e7ea5f30SIvan Malov 	if (nentries >
405e7ea5f30SIvan Malov 	    MC_CMD_RSS_CONTEXT_WRITE_TABLE_IN_ENTRIES_MAXNUM_MCDI2) {
406e7ea5f30SIvan Malov 		rc = EINVAL;
407e7ea5f30SIvan Malov 		goto fail1;
408e7ea5f30SIvan Malov 	}
409e7ea5f30SIvan Malov 
410e7ea5f30SIvan Malov 	if (start_idx + nentries >
411e7ea5f30SIvan Malov 	    encp->enc_rx_scale_tbl_max_nentries) {
412e7ea5f30SIvan Malov 		rc = EINVAL;
413e7ea5f30SIvan Malov 		goto fail2;
414e7ea5f30SIvan Malov 	}
415e7ea5f30SIvan Malov 
416e7ea5f30SIvan Malov 	req.emr_cmd = MC_CMD_RSS_CONTEXT_WRITE_TABLE;
417e7ea5f30SIvan Malov 	req.emr_in_buf = payload;
418e7ea5f30SIvan Malov 	req.emr_in_length = MC_CMD_RSS_CONTEXT_WRITE_TABLE_IN_LEN(nentries);
419e7ea5f30SIvan Malov 	req.emr_out_buf = payload;
420e7ea5f30SIvan Malov 	req.emr_out_length = MC_CMD_RSS_CONTEXT_WRITE_TABLE_OUT_LEN;
421e7ea5f30SIvan Malov 
422e7ea5f30SIvan Malov 	MCDI_IN_SET_DWORD(req,
423e7ea5f30SIvan Malov 	    RSS_CONTEXT_WRITE_TABLE_IN_RSS_CONTEXT_ID, context);
424e7ea5f30SIvan Malov 
425e7ea5f30SIvan Malov 	for (i = 0; i < nentries; ++i) {
426e7ea5f30SIvan Malov 		if (table[i] >= encp->enc_rx_scale_indirection_max_nqueues) {
427e7ea5f30SIvan Malov 			rc = EINVAL;
428e7ea5f30SIvan Malov 			goto fail3;
429e7ea5f30SIvan Malov 		}
430e7ea5f30SIvan Malov 
431e7ea5f30SIvan Malov 		MCDI_IN_POPULATE_INDEXED_DWORD_2(req,
432e7ea5f30SIvan Malov 		    RSS_CONTEXT_WRITE_TABLE_IN_ENTRIES, i,
433e7ea5f30SIvan Malov 		    RSS_CONTEXT_WRITE_TABLE_ENTRY_INDEX, start_idx + i,
434e7ea5f30SIvan Malov 		    RSS_CONTEXT_WRITE_TABLE_ENTRY_VALUE, table[i]);
435e7ea5f30SIvan Malov 	}
436e7ea5f30SIvan Malov 
437e7ea5f30SIvan Malov 	efx_mcdi_execute(enp, &req);
438e7ea5f30SIvan Malov 	if (req.emr_rc != 0) {
439e7ea5f30SIvan Malov 		rc = req.emr_rc;
440e7ea5f30SIvan Malov 		goto fail4;
441e7ea5f30SIvan Malov 	}
442e7ea5f30SIvan Malov 
443e7ea5f30SIvan Malov 	return (0);
444e7ea5f30SIvan Malov 
445e7ea5f30SIvan Malov fail4:
446e7ea5f30SIvan Malov 	EFSYS_PROBE(fail4);
447e7ea5f30SIvan Malov fail3:
448e7ea5f30SIvan Malov 	EFSYS_PROBE(fail3);
449e7ea5f30SIvan Malov fail2:
450e7ea5f30SIvan Malov 	EFSYS_PROBE(fail2);
451e7ea5f30SIvan Malov fail1:
452e7ea5f30SIvan Malov 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
453e7ea5f30SIvan Malov 	return (rc);
454e7ea5f30SIvan Malov }
455e7ea5f30SIvan Malov #endif /* EFSYS_OPT_RX_SCALE */
456e7ea5f30SIvan Malov 
4575e111ed8SAndrew Rybchenko 
4585e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_init(__in efx_nic_t * enp)4595e111ed8SAndrew Rybchenko ef10_rx_init(
4605e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
4615e111ed8SAndrew Rybchenko {
4625e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
4635e111ed8SAndrew Rybchenko 
4645e111ed8SAndrew Rybchenko 	if (efx_mcdi_rss_context_alloc(enp, EFX_RX_SCALE_EXCLUSIVE, EFX_MAXRSS,
465e7ea5f30SIvan Malov 		EFX_RSS_TBL_SIZE, &enp->en_rss_context) == 0) {
4665e111ed8SAndrew Rybchenko 		/*
4675e111ed8SAndrew Rybchenko 		 * Allocated an exclusive RSS context, which allows both the
4685e111ed8SAndrew Rybchenko 		 * indirection table and key to be modified.
4695e111ed8SAndrew Rybchenko 		 */
4705e111ed8SAndrew Rybchenko 		enp->en_rss_context_type = EFX_RX_SCALE_EXCLUSIVE;
4715e111ed8SAndrew Rybchenko 		enp->en_hash_support = EFX_RX_HASH_AVAILABLE;
4725e111ed8SAndrew Rybchenko 	} else {
4735e111ed8SAndrew Rybchenko 		/*
4745e111ed8SAndrew Rybchenko 		 * Failed to allocate an exclusive RSS context. Continue
4755e111ed8SAndrew Rybchenko 		 * operation without support for RSS. The pseudo-header in
4765e111ed8SAndrew Rybchenko 		 * received packets will not contain a Toeplitz hash value.
4775e111ed8SAndrew Rybchenko 		 */
4785e111ed8SAndrew Rybchenko 		enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
4795e111ed8SAndrew Rybchenko 		enp->en_hash_support = EFX_RX_HASH_UNAVAILABLE;
4805e111ed8SAndrew Rybchenko 	}
4815e111ed8SAndrew Rybchenko 
4825e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
4835e111ed8SAndrew Rybchenko 
4845e111ed8SAndrew Rybchenko 	return (0);
4855e111ed8SAndrew Rybchenko }
4865e111ed8SAndrew Rybchenko 
487b6b29352SAndrew Rybchenko #if EFX_OPTS_EF10()
488b6b29352SAndrew Rybchenko 
4895e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCATTER
4905e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scatter_enable(__in efx_nic_t * enp,__in unsigned int buf_size)4915e111ed8SAndrew Rybchenko ef10_rx_scatter_enable(
4925e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
4935e111ed8SAndrew Rybchenko 	__in		unsigned int buf_size)
4945e111ed8SAndrew Rybchenko {
4955e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp, buf_size))
4965e111ed8SAndrew Rybchenko 	return (0);
4975e111ed8SAndrew Rybchenko }
4985e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_RX_SCATTER */
4995e111ed8SAndrew Rybchenko 
500b6b29352SAndrew Rybchenko #endif	/* EFX_OPTS_EF10() */
501b6b29352SAndrew Rybchenko 
5025e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
5035e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scale_context_alloc(__in efx_nic_t * enp,__in efx_rx_scale_context_type_t type,__in uint32_t num_queues,__in uint32_t table_nentries,__out uint32_t * rss_contextp)5045e111ed8SAndrew Rybchenko ef10_rx_scale_context_alloc(
5055e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
5065e111ed8SAndrew Rybchenko 	__in		efx_rx_scale_context_type_t type,
5075e111ed8SAndrew Rybchenko 	__in		uint32_t num_queues,
508e7ea5f30SIvan Malov 	__in		uint32_t table_nentries,
5095e111ed8SAndrew Rybchenko 	__out		uint32_t *rss_contextp)
5105e111ed8SAndrew Rybchenko {
5115e111ed8SAndrew Rybchenko 	efx_rc_t rc;
5125e111ed8SAndrew Rybchenko 
513e7ea5f30SIvan Malov 	rc = efx_mcdi_rss_context_alloc(enp, type, num_queues, table_nentries,
514e7ea5f30SIvan Malov 					rss_contextp);
5155e111ed8SAndrew Rybchenko 	if (rc != 0)
5165e111ed8SAndrew Rybchenko 		goto fail1;
5175e111ed8SAndrew Rybchenko 
5185e111ed8SAndrew Rybchenko 	return (0);
5195e111ed8SAndrew Rybchenko 
5205e111ed8SAndrew Rybchenko fail1:
5215e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5225e111ed8SAndrew Rybchenko 	return (rc);
5235e111ed8SAndrew Rybchenko }
5245e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
5255e111ed8SAndrew Rybchenko 
5265e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
5275e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scale_context_free(__in efx_nic_t * enp,__in uint32_t rss_context)5285e111ed8SAndrew Rybchenko ef10_rx_scale_context_free(
5295e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
5305e111ed8SAndrew Rybchenko 	__in		uint32_t rss_context)
5315e111ed8SAndrew Rybchenko {
5325e111ed8SAndrew Rybchenko 	efx_rc_t rc;
5335e111ed8SAndrew Rybchenko 
5345e111ed8SAndrew Rybchenko 	rc = efx_mcdi_rss_context_free(enp, rss_context);
5355e111ed8SAndrew Rybchenko 	if (rc != 0)
5365e111ed8SAndrew Rybchenko 		goto fail1;
5375e111ed8SAndrew Rybchenko 
5385e111ed8SAndrew Rybchenko 	return (0);
5395e111ed8SAndrew Rybchenko 
5405e111ed8SAndrew Rybchenko fail1:
5415e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5425e111ed8SAndrew Rybchenko 	return (rc);
5435e111ed8SAndrew Rybchenko }
5445e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
5455e111ed8SAndrew Rybchenko 
5465e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
5475e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scale_mode_set(__in efx_nic_t * enp,__in uint32_t rss_context,__in efx_rx_hash_alg_t alg,__in efx_rx_hash_type_t type,__in boolean_t insert)5485e111ed8SAndrew Rybchenko ef10_rx_scale_mode_set(
5495e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
5505e111ed8SAndrew Rybchenko 	__in		uint32_t rss_context,
5515e111ed8SAndrew Rybchenko 	__in		efx_rx_hash_alg_t alg,
5525e111ed8SAndrew Rybchenko 	__in		efx_rx_hash_type_t type,
5535e111ed8SAndrew Rybchenko 	__in		boolean_t insert)
5545e111ed8SAndrew Rybchenko {
5555e111ed8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &enp->en_nic_cfg;
5565e111ed8SAndrew Rybchenko 	efx_rc_t rc;
5575e111ed8SAndrew Rybchenko 
5585e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(insert, ==, B_TRUE);
5595e111ed8SAndrew Rybchenko 
5605e111ed8SAndrew Rybchenko 	if ((encp->enc_rx_scale_hash_alg_mask & (1U << alg)) == 0 ||
5615e111ed8SAndrew Rybchenko 	    insert == B_FALSE) {
5625e111ed8SAndrew Rybchenko 		rc = EINVAL;
5635e111ed8SAndrew Rybchenko 		goto fail1;
5645e111ed8SAndrew Rybchenko 	}
5655e111ed8SAndrew Rybchenko 
5665e111ed8SAndrew Rybchenko 	if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
5675e111ed8SAndrew Rybchenko 		if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
5685e111ed8SAndrew Rybchenko 			rc = ENOTSUP;
5695e111ed8SAndrew Rybchenko 			goto fail2;
5705e111ed8SAndrew Rybchenko 		}
5715e111ed8SAndrew Rybchenko 		rss_context = enp->en_rss_context;
5725e111ed8SAndrew Rybchenko 	}
5735e111ed8SAndrew Rybchenko 
5745e111ed8SAndrew Rybchenko 	if ((rc = efx_mcdi_rss_context_set_flags(enp,
5755e111ed8SAndrew Rybchenko 		    rss_context, type)) != 0)
5765e111ed8SAndrew Rybchenko 		goto fail3;
5775e111ed8SAndrew Rybchenko 
5785e111ed8SAndrew Rybchenko 	return (0);
5795e111ed8SAndrew Rybchenko 
5805e111ed8SAndrew Rybchenko fail3:
5815e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
5825e111ed8SAndrew Rybchenko fail2:
5835e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
5845e111ed8SAndrew Rybchenko fail1:
5855e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5865e111ed8SAndrew Rybchenko 
5875e111ed8SAndrew Rybchenko 	return (rc);
5885e111ed8SAndrew Rybchenko }
5895e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
5905e111ed8SAndrew Rybchenko 
5915e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
5925e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scale_key_set(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (n)uint8_t * key,__in size_t n)5935e111ed8SAndrew Rybchenko ef10_rx_scale_key_set(
5945e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
5955e111ed8SAndrew Rybchenko 	__in		uint32_t rss_context,
5965e111ed8SAndrew Rybchenko 	__in_ecount(n)	uint8_t *key,
5975e111ed8SAndrew Rybchenko 	__in		size_t n)
5985e111ed8SAndrew Rybchenko {
5995e111ed8SAndrew Rybchenko 	efx_rc_t rc;
6005e111ed8SAndrew Rybchenko 
6015e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RSS_KEY_SIZE ==
6025e111ed8SAndrew Rybchenko 	    MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
6035e111ed8SAndrew Rybchenko 
6045e111ed8SAndrew Rybchenko 	if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
6055e111ed8SAndrew Rybchenko 		if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
6065e111ed8SAndrew Rybchenko 			rc = ENOTSUP;
6075e111ed8SAndrew Rybchenko 			goto fail1;
6085e111ed8SAndrew Rybchenko 		}
6095e111ed8SAndrew Rybchenko 		rss_context = enp->en_rss_context;
6105e111ed8SAndrew Rybchenko 	}
6115e111ed8SAndrew Rybchenko 
6125e111ed8SAndrew Rybchenko 	if ((rc = efx_mcdi_rss_context_set_key(enp, rss_context, key, n)) != 0)
6135e111ed8SAndrew Rybchenko 		goto fail2;
6145e111ed8SAndrew Rybchenko 
6155e111ed8SAndrew Rybchenko 	return (0);
6165e111ed8SAndrew Rybchenko 
6175e111ed8SAndrew Rybchenko fail2:
6185e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
6195e111ed8SAndrew Rybchenko fail1:
6205e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
6215e111ed8SAndrew Rybchenko 
6225e111ed8SAndrew Rybchenko 	return (rc);
6235e111ed8SAndrew Rybchenko }
6245e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
6255e111ed8SAndrew Rybchenko 
6265e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
6275e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
ef10_rx_scale_tbl_set(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (nentries)unsigned int * table,__in size_t nentries)6285e111ed8SAndrew Rybchenko ef10_rx_scale_tbl_set(
6295e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
6305e111ed8SAndrew Rybchenko 	__in			uint32_t rss_context,
6317a71c15dSIvan Malov 	__in_ecount(nentries)	unsigned int *table,
6327a71c15dSIvan Malov 	__in			size_t nentries)
6335e111ed8SAndrew Rybchenko {
634e7ea5f30SIvan Malov 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
6355e111ed8SAndrew Rybchenko 	efx_rc_t rc;
6365e111ed8SAndrew Rybchenko 
6375e111ed8SAndrew Rybchenko 
6385e111ed8SAndrew Rybchenko 	if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
6395e111ed8SAndrew Rybchenko 		if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
6405e111ed8SAndrew Rybchenko 			rc = ENOTSUP;
6415e111ed8SAndrew Rybchenko 			goto fail1;
6425e111ed8SAndrew Rybchenko 		}
6435e111ed8SAndrew Rybchenko 		rss_context = enp->en_rss_context;
6445e111ed8SAndrew Rybchenko 	}
6455e111ed8SAndrew Rybchenko 
646e7ea5f30SIvan Malov 	if (encp->enc_rx_scale_tbl_entry_count_is_selectable != B_FALSE) {
647e7ea5f30SIvan Malov 		uint32_t index, remain, batch;
648e7ea5f30SIvan Malov 
649e7ea5f30SIvan Malov 		batch = MC_CMD_RSS_CONTEXT_WRITE_TABLE_IN_ENTRIES_MAXNUM_MCDI2;
650e7ea5f30SIvan Malov 		index = 0;
651e7ea5f30SIvan Malov 
652e7ea5f30SIvan Malov 		for (remain = nentries; remain > 0; remain -= batch) {
653e7ea5f30SIvan Malov 			if (batch > remain)
654e7ea5f30SIvan Malov 				batch = remain;
655e7ea5f30SIvan Malov 
656e7ea5f30SIvan Malov 			rc = efx_mcdi_rss_context_write_table(enp, rss_context,
657e7ea5f30SIvan Malov 				    index, &table[index], batch);
658e7ea5f30SIvan Malov 			if (rc != 0)
6595e111ed8SAndrew Rybchenko 				goto fail2;
6605e111ed8SAndrew Rybchenko 
661e7ea5f30SIvan Malov 			index += batch;
662e7ea5f30SIvan Malov 		}
663e7ea5f30SIvan Malov 	} else {
664e7ea5f30SIvan Malov 		rc = efx_mcdi_rss_context_set_table(enp, rss_context, table,
665e7ea5f30SIvan Malov 			    nentries);
666e7ea5f30SIvan Malov 		if (rc != 0)
667e7ea5f30SIvan Malov 			goto fail3;
668e7ea5f30SIvan Malov 	}
669e7ea5f30SIvan Malov 
6705e111ed8SAndrew Rybchenko 	return (0);
6715e111ed8SAndrew Rybchenko 
672e7ea5f30SIvan Malov fail3:
673e7ea5f30SIvan Malov 	EFSYS_PROBE(fail3);
6745e111ed8SAndrew Rybchenko fail2:
6755e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
6765e111ed8SAndrew Rybchenko fail1:
6775e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
6785e111ed8SAndrew Rybchenko 
6795e111ed8SAndrew Rybchenko 	return (rc);
6805e111ed8SAndrew Rybchenko }
6815e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
6825e111ed8SAndrew Rybchenko 
683b6b29352SAndrew Rybchenko #if EFX_OPTS_EF10()
6845e111ed8SAndrew Rybchenko 
6855e111ed8SAndrew Rybchenko /*
6866bba823fSAndrew Rybchenko  * EF10 RX pseudo-header (aka Rx prefix)
6876bba823fSAndrew Rybchenko  * -------------------------------------
6885e111ed8SAndrew Rybchenko  *
6895e111ed8SAndrew Rybchenko  * Receive packets are prefixed by an (optional) 14 byte pseudo-header:
6905e111ed8SAndrew Rybchenko  *
6915e111ed8SAndrew Rybchenko  *  +00: Toeplitz hash value.
6925e111ed8SAndrew Rybchenko  *       (32bit little-endian)
6935e111ed8SAndrew Rybchenko  *  +04: Outer VLAN tag. Zero if the packet did not have an outer VLAN tag.
6945e111ed8SAndrew Rybchenko  *       (16bit big-endian)
6955e111ed8SAndrew Rybchenko  *  +06: Inner VLAN tag. Zero if the packet did not have an inner VLAN tag.
6965e111ed8SAndrew Rybchenko  *       (16bit big-endian)
6975e111ed8SAndrew Rybchenko  *  +08: Packet Length. Zero if the RX datapath was in cut-through mode.
6985e111ed8SAndrew Rybchenko  *       (16bit little-endian)
6995e111ed8SAndrew Rybchenko  *  +10: MAC timestamp. Zero if timestamping is not enabled.
7005e111ed8SAndrew Rybchenko  *       (32bit little-endian)
7015e111ed8SAndrew Rybchenko  *
7025e111ed8SAndrew Rybchenko  * See "The RX Pseudo-header" in SF-109306-TC.
7036bba823fSAndrew Rybchenko  *
7046bba823fSAndrew Rybchenko  * EF10 does not support Rx prefix choice using MC_CMD_GET_RX_PREFIX_ID
7056bba823fSAndrew Rybchenko  * and query its layout using MC_CMD_QUERY_RX_PREFIX_ID.
7065e111ed8SAndrew Rybchenko  */
7076bba823fSAndrew Rybchenko static const efx_rx_prefix_layout_t ef10_default_rx_prefix_layout = {
7086bba823fSAndrew Rybchenko 	.erpl_id	= 0,
7096bba823fSAndrew Rybchenko 	.erpl_length	= 14,
7106bba823fSAndrew Rybchenko 	.erpl_fields	= {
7116bba823fSAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_RSS_HASH]			=
7126bba823fSAndrew Rybchenko 		    { 0,  32, B_FALSE },
7136bba823fSAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_VLAN_STRIP_TCI]		=
7146bba823fSAndrew Rybchenko 		    { 32, 16, B_TRUE },
7156bba823fSAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_INNER_VLAN_STRIP_TCI]	=
7166bba823fSAndrew Rybchenko 		    { 48, 16, B_TRUE },
7176bba823fSAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_LENGTH]			=
7186bba823fSAndrew Rybchenko 		    { 64, 16, B_FALSE },
7196bba823fSAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_PARTIAL_TSTAMP]		=
7206bba823fSAndrew Rybchenko 		    { 80, 32, B_FALSE },
7216bba823fSAndrew Rybchenko 	}
7226bba823fSAndrew Rybchenko };
7236bba823fSAndrew Rybchenko 
7246bba823fSAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
7256bba823fSAndrew Rybchenko 
7266bba823fSAndrew Rybchenko /*
7276bba823fSAndrew Rybchenko  * EF10 packed stream Rx prefix layout.
7286bba823fSAndrew Rybchenko  *
7296bba823fSAndrew Rybchenko  * See SF-112241-TC Full speed capture for Huntington and Medford section 4.5.
7306bba823fSAndrew Rybchenko  */
7316bba823fSAndrew Rybchenko static const efx_rx_prefix_layout_t ef10_packed_stream_rx_prefix_layout = {
7326bba823fSAndrew Rybchenko 	.erpl_id	= 0,
7336bba823fSAndrew Rybchenko 	.erpl_length	= 8,
7346bba823fSAndrew Rybchenko 	.erpl_fields	= {
7356bba823fSAndrew Rybchenko #define	EF10_PS_RX_PREFIX_FIELD(_efx, _ef10) \
7366bba823fSAndrew Rybchenko 	EFX_RX_PREFIX_FIELD(_efx, ES_DZ_PS_RX_PREFIX_ ## _ef10, B_FALSE)
7376bba823fSAndrew Rybchenko 
7386bba823fSAndrew Rybchenko 		EF10_PS_RX_PREFIX_FIELD(PARTIAL_TSTAMP, TSTAMP),
7396bba823fSAndrew Rybchenko 		EF10_PS_RX_PREFIX_FIELD(LENGTH, CAP_LEN),
7406bba823fSAndrew Rybchenko 		EF10_PS_RX_PREFIX_FIELD(ORIG_LENGTH, ORIG_LEN),
7416bba823fSAndrew Rybchenko 
7426bba823fSAndrew Rybchenko #undef	EF10_PS_RX_PREFIX_FIELD
7436bba823fSAndrew Rybchenko 	}
7446bba823fSAndrew Rybchenko };
7456bba823fSAndrew Rybchenko 
7466bba823fSAndrew Rybchenko #endif /* EFSYS_OPT_RX_PACKED_STREAM */
7476bba823fSAndrew Rybchenko 
7486bba823fSAndrew Rybchenko #if EFSYS_OPT_RX_ES_SUPER_BUFFER
7496bba823fSAndrew Rybchenko 
7506bba823fSAndrew Rybchenko /*
7516bba823fSAndrew Rybchenko  * EF10 equal stride super-buffer Rx prefix layout.
7526bba823fSAndrew Rybchenko  *
7536bba823fSAndrew Rybchenko  * See SF-119419-TC DPDK Firmware Driver Interface section 3.4.
7546bba823fSAndrew Rybchenko  */
7556bba823fSAndrew Rybchenko static const efx_rx_prefix_layout_t ef10_essb_rx_prefix_layout = {
7566bba823fSAndrew Rybchenko 	.erpl_id	= 0,
7576bba823fSAndrew Rybchenko 	.erpl_length	= ES_EZ_ESSB_RX_PREFIX_LEN,
7586bba823fSAndrew Rybchenko 	.erpl_fields	= {
7596bba823fSAndrew Rybchenko #define	EF10_ESSB_RX_PREFIX_FIELD(_efx, _ef10) \
7606bba823fSAndrew Rybchenko 	EFX_RX_PREFIX_FIELD(_efx, ES_EZ_ESSB_RX_PREFIX_ ## _ef10, B_FALSE)
7616bba823fSAndrew Rybchenko 
7626bba823fSAndrew Rybchenko 		EF10_ESSB_RX_PREFIX_FIELD(LENGTH, DATA_LEN),
7636bba823fSAndrew Rybchenko 		EF10_ESSB_RX_PREFIX_FIELD(USER_MARK, MARK),
7646bba823fSAndrew Rybchenko 		EF10_ESSB_RX_PREFIX_FIELD(RSS_HASH_VALID, HASH_VALID),
7656bba823fSAndrew Rybchenko 		EF10_ESSB_RX_PREFIX_FIELD(USER_MARK_VALID, MARK_VALID),
7666bba823fSAndrew Rybchenko 		EF10_ESSB_RX_PREFIX_FIELD(USER_FLAG, MATCH_FLAG),
7676bba823fSAndrew Rybchenko 		EF10_ESSB_RX_PREFIX_FIELD(RSS_HASH, HASH),
7686bba823fSAndrew Rybchenko 
7696bba823fSAndrew Rybchenko #undef	EF10_ESSB_RX_PREFIX_FIELD
7706bba823fSAndrew Rybchenko 	}
7716bba823fSAndrew Rybchenko };
7726bba823fSAndrew Rybchenko 
7736bba823fSAndrew Rybchenko #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
7745e111ed8SAndrew Rybchenko 
7755e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_prefix_pktlen(__in efx_nic_t * enp,__in uint8_t * buffer,__out uint16_t * lengthp)7765e111ed8SAndrew Rybchenko ef10_rx_prefix_pktlen(
7775e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
7785e111ed8SAndrew Rybchenko 	__in		uint8_t *buffer,
7795e111ed8SAndrew Rybchenko 	__out		uint16_t *lengthp)
7805e111ed8SAndrew Rybchenko {
7815e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
7825e111ed8SAndrew Rybchenko 
7835e111ed8SAndrew Rybchenko 	/*
7845e111ed8SAndrew Rybchenko 	 * The RX pseudo-header contains the packet length, excluding the
7855e111ed8SAndrew Rybchenko 	 * pseudo-header. If the hardware receive datapath was operating in
7865e111ed8SAndrew Rybchenko 	 * cut-through mode then the length in the RX pseudo-header will be
7875e111ed8SAndrew Rybchenko 	 * zero, and the packet length must be obtained from the DMA length
7885e111ed8SAndrew Rybchenko 	 * reported in the RX event.
7895e111ed8SAndrew Rybchenko 	 */
7905e111ed8SAndrew Rybchenko 	*lengthp = buffer[8] | (buffer[9] << 8);
7915e111ed8SAndrew Rybchenko 	return (0);
7925e111ed8SAndrew Rybchenko }
7935e111ed8SAndrew Rybchenko 
7945e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
7955e111ed8SAndrew Rybchenko 	__checkReturn	uint32_t
ef10_rx_prefix_hash(__in efx_nic_t * enp,__in efx_rx_hash_alg_t func,__in uint8_t * buffer)7965e111ed8SAndrew Rybchenko ef10_rx_prefix_hash(
7975e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
7985e111ed8SAndrew Rybchenko 	__in		efx_rx_hash_alg_t func,
7995e111ed8SAndrew Rybchenko 	__in		uint8_t *buffer)
8005e111ed8SAndrew Rybchenko {
8015e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
8025e111ed8SAndrew Rybchenko 
8035e111ed8SAndrew Rybchenko 	switch (func) {
8045e111ed8SAndrew Rybchenko 	case EFX_RX_HASHALG_PACKED_STREAM:
8055e111ed8SAndrew Rybchenko 	case EFX_RX_HASHALG_TOEPLITZ:
8065e111ed8SAndrew Rybchenko 		return (buffer[0] |
8075e111ed8SAndrew Rybchenko 		    (buffer[1] << 8) |
8085e111ed8SAndrew Rybchenko 		    (buffer[2] << 16) |
8095e111ed8SAndrew Rybchenko 		    (buffer[3] << 24));
8105e111ed8SAndrew Rybchenko 
8115e111ed8SAndrew Rybchenko 	default:
8125e111ed8SAndrew Rybchenko 		EFSYS_ASSERT(0);
8135e111ed8SAndrew Rybchenko 		return (0);
8145e111ed8SAndrew Rybchenko 	}
8155e111ed8SAndrew Rybchenko }
8165e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
8175e111ed8SAndrew Rybchenko 
8185e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
8195e111ed8SAndrew Rybchenko /*
8205e111ed8SAndrew Rybchenko  * Fake length for RXQ descriptors in packed stream mode
8215e111ed8SAndrew Rybchenko  * to make hardware happy
8225e111ed8SAndrew Rybchenko  */
8235e111ed8SAndrew Rybchenko #define	EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE 32
8245e111ed8SAndrew Rybchenko #endif
8255e111ed8SAndrew Rybchenko 
8265e111ed8SAndrew Rybchenko 				void
ef10_rx_qpost(__in efx_rxq_t * erp,__in_ecount (ndescs)efsys_dma_addr_t * addrp,__in size_t size,__in unsigned int ndescs,__in unsigned int completed,__in unsigned int added)8275e111ed8SAndrew Rybchenko ef10_rx_qpost(
8285e111ed8SAndrew Rybchenko 	__in			efx_rxq_t *erp,
8295e111ed8SAndrew Rybchenko 	__in_ecount(ndescs)	efsys_dma_addr_t *addrp,
8305e111ed8SAndrew Rybchenko 	__in			size_t size,
8315e111ed8SAndrew Rybchenko 	__in			unsigned int ndescs,
8325e111ed8SAndrew Rybchenko 	__in			unsigned int completed,
8335e111ed8SAndrew Rybchenko 	__in			unsigned int added)
8345e111ed8SAndrew Rybchenko {
8355e111ed8SAndrew Rybchenko 	efx_qword_t qword;
8365e111ed8SAndrew Rybchenko 	unsigned int i;
8375e111ed8SAndrew Rybchenko 	unsigned int offset;
8385e111ed8SAndrew Rybchenko 	unsigned int id;
8395e111ed8SAndrew Rybchenko 
8405e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(completed))
8415e111ed8SAndrew Rybchenko 
8425e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
8435e111ed8SAndrew Rybchenko 	/*
8445e111ed8SAndrew Rybchenko 	 * Real size of the buffer does not fit into ESF_DZ_RX_KER_BYTE_CNT
8455e111ed8SAndrew Rybchenko 	 * and equal to 0 after applying mask. Hardware does not like it.
8465e111ed8SAndrew Rybchenko 	 */
8475e111ed8SAndrew Rybchenko 	if (erp->er_ev_qstate->eers_rx_packed_stream)
8485e111ed8SAndrew Rybchenko 		size = EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE;
8495e111ed8SAndrew Rybchenko #endif
8505e111ed8SAndrew Rybchenko 
8515e111ed8SAndrew Rybchenko 	/* The client driver must not overfill the queue */
8525e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(added - completed + ndescs, <=,
8535e111ed8SAndrew Rybchenko 	    EFX_RXQ_LIMIT(erp->er_mask + 1));
8545e111ed8SAndrew Rybchenko 
8555e111ed8SAndrew Rybchenko 	id = added & (erp->er_mask);
8565e111ed8SAndrew Rybchenko 	for (i = 0; i < ndescs; i++) {
8575e111ed8SAndrew Rybchenko 		EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
8585e111ed8SAndrew Rybchenko 		    unsigned int, id, efsys_dma_addr_t, addrp[i],
8595e111ed8SAndrew Rybchenko 		    size_t, size);
8605e111ed8SAndrew Rybchenko 
8615e111ed8SAndrew Rybchenko 		EFX_POPULATE_QWORD_3(qword,
8625e111ed8SAndrew Rybchenko 		    ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size),
8635e111ed8SAndrew Rybchenko 		    ESF_DZ_RX_KER_BUF_ADDR_DW0,
8645e111ed8SAndrew Rybchenko 		    (uint32_t)(addrp[i] & 0xffffffff),
8655e111ed8SAndrew Rybchenko 		    ESF_DZ_RX_KER_BUF_ADDR_DW1,
8665e111ed8SAndrew Rybchenko 		    (uint32_t)(addrp[i] >> 32));
8675e111ed8SAndrew Rybchenko 
8685e111ed8SAndrew Rybchenko 		offset = id * sizeof (efx_qword_t);
8695e111ed8SAndrew Rybchenko 		EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
8705e111ed8SAndrew Rybchenko 
8715e111ed8SAndrew Rybchenko 		id = (id + 1) & (erp->er_mask);
8725e111ed8SAndrew Rybchenko 	}
8735e111ed8SAndrew Rybchenko }
8745e111ed8SAndrew Rybchenko 
8755e111ed8SAndrew Rybchenko 			void
ef10_rx_qpush(__in efx_rxq_t * erp,__in unsigned int added,__inout unsigned int * pushedp)8765e111ed8SAndrew Rybchenko ef10_rx_qpush(
8775e111ed8SAndrew Rybchenko 	__in	efx_rxq_t *erp,
8785e111ed8SAndrew Rybchenko 	__in	unsigned int added,
8795e111ed8SAndrew Rybchenko 	__inout	unsigned int *pushedp)
8805e111ed8SAndrew Rybchenko {
8815e111ed8SAndrew Rybchenko 	efx_nic_t *enp = erp->er_enp;
8825e111ed8SAndrew Rybchenko 	unsigned int pushed = *pushedp;
8835e111ed8SAndrew Rybchenko 	uint32_t wptr;
8845e111ed8SAndrew Rybchenko 	efx_dword_t dword;
8855e111ed8SAndrew Rybchenko 
8865e111ed8SAndrew Rybchenko 	/* Hardware has alignment restriction for WPTR */
8875e111ed8SAndrew Rybchenko 	wptr = EFX_P2ALIGN(unsigned int, added, EF10_RX_WPTR_ALIGN);
8885e111ed8SAndrew Rybchenko 	if (pushed == wptr)
8895e111ed8SAndrew Rybchenko 		return;
8905e111ed8SAndrew Rybchenko 
8915e111ed8SAndrew Rybchenko 	*pushedp = wptr;
8925e111ed8SAndrew Rybchenko 
8935e111ed8SAndrew Rybchenko 	/* Push the populated descriptors out */
8945e111ed8SAndrew Rybchenko 	wptr &= erp->er_mask;
8955e111ed8SAndrew Rybchenko 
8965e111ed8SAndrew Rybchenko 	EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr);
8975e111ed8SAndrew Rybchenko 
8985e111ed8SAndrew Rybchenko 	/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
8995e111ed8SAndrew Rybchenko 	EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
90082192e22SAndrew Rybchenko 	    EF10_RXQ_DESC_SIZE, wptr, pushed & erp->er_mask);
9015e111ed8SAndrew Rybchenko 	EFSYS_PIO_WRITE_BARRIER();
9025e111ed8SAndrew Rybchenko 	EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
9035e111ed8SAndrew Rybchenko 	    erp->er_index, &dword, B_FALSE);
9045e111ed8SAndrew Rybchenko }
9055e111ed8SAndrew Rybchenko 
9065e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
9075e111ed8SAndrew Rybchenko 
9085e111ed8SAndrew Rybchenko 			void
ef10_rx_qpush_ps_credits(__in efx_rxq_t * erp)9095e111ed8SAndrew Rybchenko ef10_rx_qpush_ps_credits(
9105e111ed8SAndrew Rybchenko 	__in		efx_rxq_t *erp)
9115e111ed8SAndrew Rybchenko {
9125e111ed8SAndrew Rybchenko 	efx_nic_t *enp = erp->er_enp;
9135e111ed8SAndrew Rybchenko 	efx_dword_t dword;
9145e111ed8SAndrew Rybchenko 	efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
9155e111ed8SAndrew Rybchenko 	uint32_t credits;
9165e111ed8SAndrew Rybchenko 
9175e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
9185e111ed8SAndrew Rybchenko 
9195e111ed8SAndrew Rybchenko 	if (rxq_state->eers_rx_packed_stream_credits == 0)
9205e111ed8SAndrew Rybchenko 		return;
9215e111ed8SAndrew Rybchenko 
9225e111ed8SAndrew Rybchenko 	/*
9235e111ed8SAndrew Rybchenko 	 * It is a bug if we think that FW has utilized more
9245e111ed8SAndrew Rybchenko 	 * credits than it is allowed to have (maximum). However,
9255e111ed8SAndrew Rybchenko 	 * make sure that we do not credit more than maximum anyway.
9265e111ed8SAndrew Rybchenko 	 */
9275e111ed8SAndrew Rybchenko 	credits = MIN(rxq_state->eers_rx_packed_stream_credits,
9285e111ed8SAndrew Rybchenko 	    EFX_RX_PACKED_STREAM_MAX_CREDITS);
9295e111ed8SAndrew Rybchenko 	EFX_POPULATE_DWORD_3(dword,
9305e111ed8SAndrew Rybchenko 	    ERF_DZ_RX_DESC_MAGIC_DOORBELL, 1,
9315e111ed8SAndrew Rybchenko 	    ERF_DZ_RX_DESC_MAGIC_CMD,
9325e111ed8SAndrew Rybchenko 	    ERE_DZ_RX_DESC_MAGIC_CMD_PS_CREDITS,
9335e111ed8SAndrew Rybchenko 	    ERF_DZ_RX_DESC_MAGIC_DATA, credits);
9345e111ed8SAndrew Rybchenko 	EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
9355e111ed8SAndrew Rybchenko 	    erp->er_index, &dword, B_FALSE);
9365e111ed8SAndrew Rybchenko 
9375e111ed8SAndrew Rybchenko 	rxq_state->eers_rx_packed_stream_credits = 0;
9385e111ed8SAndrew Rybchenko }
9395e111ed8SAndrew Rybchenko 
9405e111ed8SAndrew Rybchenko /*
9415e111ed8SAndrew Rybchenko  * In accordance with SF-112241-TC the received data has the following layout:
9425e111ed8SAndrew Rybchenko  *  - 8 byte pseudo-header which consist of:
9435e111ed8SAndrew Rybchenko  *    - 4 byte little-endian timestamp
9445e111ed8SAndrew Rybchenko  *    - 2 byte little-endian captured length in bytes
9455e111ed8SAndrew Rybchenko  *    - 2 byte little-endian original packet length in bytes
9465e111ed8SAndrew Rybchenko  *  - captured packet bytes
9475e111ed8SAndrew Rybchenko  *  - optional padding to align to 64 bytes boundary
9485e111ed8SAndrew Rybchenko  *  - 64 bytes scratch space for the host software
9495e111ed8SAndrew Rybchenko  */
9505e111ed8SAndrew Rybchenko 	__checkReturn	uint8_t *
ef10_rx_qps_packet_info(__in efx_rxq_t * erp,__in uint8_t * buffer,__in uint32_t buffer_length,__in uint32_t current_offset,__out uint16_t * lengthp,__out uint32_t * next_offsetp,__out uint32_t * timestamp)9515e111ed8SAndrew Rybchenko ef10_rx_qps_packet_info(
9525e111ed8SAndrew Rybchenko 	__in		efx_rxq_t *erp,
9535e111ed8SAndrew Rybchenko 	__in		uint8_t *buffer,
9545e111ed8SAndrew Rybchenko 	__in		uint32_t buffer_length,
9555e111ed8SAndrew Rybchenko 	__in		uint32_t current_offset,
9565e111ed8SAndrew Rybchenko 	__out		uint16_t *lengthp,
9575e111ed8SAndrew Rybchenko 	__out		uint32_t *next_offsetp,
9585e111ed8SAndrew Rybchenko 	__out		uint32_t *timestamp)
9595e111ed8SAndrew Rybchenko {
9605e111ed8SAndrew Rybchenko 	uint16_t buf_len;
9615e111ed8SAndrew Rybchenko 	uint8_t *pkt_start;
9625e111ed8SAndrew Rybchenko 	efx_qword_t *qwordp;
9635e111ed8SAndrew Rybchenko 	efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
9645e111ed8SAndrew Rybchenko 
9655e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
9665e111ed8SAndrew Rybchenko 
9675e111ed8SAndrew Rybchenko 	buffer += current_offset;
9685e111ed8SAndrew Rybchenko 	pkt_start = buffer + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE;
9695e111ed8SAndrew Rybchenko 
9705e111ed8SAndrew Rybchenko 	qwordp = (efx_qword_t *)buffer;
9715e111ed8SAndrew Rybchenko 	*timestamp = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_TSTAMP);
9725e111ed8SAndrew Rybchenko 	*lengthp   = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_ORIG_LEN);
9735e111ed8SAndrew Rybchenko 	buf_len    = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_CAP_LEN);
9745e111ed8SAndrew Rybchenko 
9755e111ed8SAndrew Rybchenko 	buf_len = EFX_P2ROUNDUP(uint16_t,
9765e111ed8SAndrew Rybchenko 	    buf_len + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE,
9775e111ed8SAndrew Rybchenko 	    EFX_RX_PACKED_STREAM_ALIGNMENT);
9785e111ed8SAndrew Rybchenko 	*next_offsetp =
9795e111ed8SAndrew Rybchenko 	    current_offset + buf_len + EFX_RX_PACKED_STREAM_ALIGNMENT;
9805e111ed8SAndrew Rybchenko 
9815e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(*next_offsetp, <=, buffer_length);
9825e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(current_offset + *lengthp, <, *next_offsetp);
9835e111ed8SAndrew Rybchenko 
9845e111ed8SAndrew Rybchenko 	if ((*next_offsetp ^ current_offset) &
9855e111ed8SAndrew Rybchenko 	    EFX_RX_PACKED_STREAM_MEM_PER_CREDIT)
9865e111ed8SAndrew Rybchenko 		rxq_state->eers_rx_packed_stream_credits++;
9875e111ed8SAndrew Rybchenko 
9885e111ed8SAndrew Rybchenko 	return (pkt_start);
9895e111ed8SAndrew Rybchenko }
9905e111ed8SAndrew Rybchenko 
9915e111ed8SAndrew Rybchenko 
9925e111ed8SAndrew Rybchenko #endif
9935e111ed8SAndrew Rybchenko 
9945e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_qflush(__in efx_rxq_t * erp)9955e111ed8SAndrew Rybchenko ef10_rx_qflush(
9965e111ed8SAndrew Rybchenko 	__in	efx_rxq_t *erp)
9975e111ed8SAndrew Rybchenko {
9985e111ed8SAndrew Rybchenko 	efx_nic_t *enp = erp->er_enp;
9995e111ed8SAndrew Rybchenko 	efx_rc_t rc;
10005e111ed8SAndrew Rybchenko 
10015e111ed8SAndrew Rybchenko 	if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
10025e111ed8SAndrew Rybchenko 		goto fail1;
10035e111ed8SAndrew Rybchenko 
10045e111ed8SAndrew Rybchenko 	return (0);
10055e111ed8SAndrew Rybchenko 
10065e111ed8SAndrew Rybchenko fail1:
10075e111ed8SAndrew Rybchenko 	/*
10085e111ed8SAndrew Rybchenko 	 * EALREADY is not an error, but indicates that the MC has rebooted and
10095e111ed8SAndrew Rybchenko 	 * that the RXQ has already been destroyed. Callers need to know that
10105e111ed8SAndrew Rybchenko 	 * the RXQ flush has completed to avoid waiting until timeout for a
10115e111ed8SAndrew Rybchenko 	 * flush done event that will not be delivered.
10125e111ed8SAndrew Rybchenko 	 */
10135e111ed8SAndrew Rybchenko 	if (rc != EALREADY)
10145e111ed8SAndrew Rybchenko 		EFSYS_PROBE1(fail1, efx_rc_t, rc);
10155e111ed8SAndrew Rybchenko 
10165e111ed8SAndrew Rybchenko 	return (rc);
10175e111ed8SAndrew Rybchenko }
10185e111ed8SAndrew Rybchenko 
10195e111ed8SAndrew Rybchenko 		void
ef10_rx_qenable(__in efx_rxq_t * erp)10205e111ed8SAndrew Rybchenko ef10_rx_qenable(
10215e111ed8SAndrew Rybchenko 	__in	efx_rxq_t *erp)
10225e111ed8SAndrew Rybchenko {
10235e111ed8SAndrew Rybchenko 	/* FIXME */
10245e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(erp))
10255e111ed8SAndrew Rybchenko 	/* FIXME */
10265e111ed8SAndrew Rybchenko }
10275e111ed8SAndrew Rybchenko 
10285e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_qcreate(__in efx_nic_t * enp,__in unsigned int index,__in unsigned int label,__in efx_rxq_type_t type,__in_opt const efx_rxq_type_data_t * type_data,__in efsys_mem_t * esmp,__in size_t ndescs,__in uint32_t id,__in unsigned int flags,__in efx_evq_t * eep,__in efx_rxq_t * erp)10295e111ed8SAndrew Rybchenko ef10_rx_qcreate(
10305e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
10315e111ed8SAndrew Rybchenko 	__in		unsigned int index,
10325e111ed8SAndrew Rybchenko 	__in		unsigned int label,
10335e111ed8SAndrew Rybchenko 	__in		efx_rxq_type_t type,
10345e111ed8SAndrew Rybchenko 	__in_opt	const efx_rxq_type_data_t *type_data,
10355e111ed8SAndrew Rybchenko 	__in		efsys_mem_t *esmp,
10365e111ed8SAndrew Rybchenko 	__in		size_t ndescs,
10375e111ed8SAndrew Rybchenko 	__in		uint32_t id,
10385e111ed8SAndrew Rybchenko 	__in		unsigned int flags,
10395e111ed8SAndrew Rybchenko 	__in		efx_evq_t *eep,
10405e111ed8SAndrew Rybchenko 	__in		efx_rxq_t *erp)
10415e111ed8SAndrew Rybchenko {
10425e111ed8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
10437640543fSAndrew Rybchenko 	efx_mcdi_init_rxq_params_t params;
10446bba823fSAndrew Rybchenko 	const efx_rx_prefix_layout_t *erpl;
10455e111ed8SAndrew Rybchenko 	efx_rc_t rc;
10465e111ed8SAndrew Rybchenko 
10475e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(id, erp))
10485e111ed8SAndrew Rybchenko 
10495e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH));
10505e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
10515e111ed8SAndrew Rybchenko 
10527640543fSAndrew Rybchenko 	memset(&params, 0, sizeof (params));
10537640543fSAndrew Rybchenko 	params.buf_size = erp->er_buf_size;
10547640543fSAndrew Rybchenko 
10555e111ed8SAndrew Rybchenko 	switch (type) {
10565e111ed8SAndrew Rybchenko 	case EFX_RXQ_TYPE_DEFAULT:
10576bba823fSAndrew Rybchenko 		erpl = &ef10_default_rx_prefix_layout;
10585e111ed8SAndrew Rybchenko 		if (type_data == NULL) {
10595e111ed8SAndrew Rybchenko 			rc = EINVAL;
1060e9b9b2e5SAndrew Rybchenko 			goto fail1;
10615e111ed8SAndrew Rybchenko 		}
10625e111ed8SAndrew Rybchenko 		erp->er_buf_size = type_data->ertd_default.ed_buf_size;
1063c414c567SIgor Romanov 		if (flags & EFX_RXQ_FLAG_USER_MARK) {
1064c414c567SIgor Romanov 			rc = ENOTSUP;
1065c414c567SIgor Romanov 			goto fail2;
1066c414c567SIgor Romanov 		}
1067cdea571bSIvan Malov 		if (flags & EFX_RXQ_FLAG_USER_FLAG) {
1068cdea571bSIvan Malov 			rc = ENOTSUP;
1069cdea571bSIvan Malov 			goto fail3;
1070cdea571bSIvan Malov 		}
1071f784cdc5SAndrew Rybchenko 		/*
1072f784cdc5SAndrew Rybchenko 		 * Ignore EFX_RXQ_FLAG_RSS_HASH since if RSS hash is calculated
1073f784cdc5SAndrew Rybchenko 		 * it is always delivered from HW in the pseudo-header.
1074f784cdc5SAndrew Rybchenko 		 */
10755e111ed8SAndrew Rybchenko 		break;
10765e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
10775e111ed8SAndrew Rybchenko 	case EFX_RXQ_TYPE_PACKED_STREAM:
10786bba823fSAndrew Rybchenko 		erpl = &ef10_packed_stream_rx_prefix_layout;
10795e111ed8SAndrew Rybchenko 		if (type_data == NULL) {
10805e111ed8SAndrew Rybchenko 			rc = EINVAL;
1081cdea571bSIvan Malov 			goto fail4;
10825e111ed8SAndrew Rybchenko 		}
10835e111ed8SAndrew Rybchenko 		switch (type_data->ertd_packed_stream.eps_buf_size) {
10845e111ed8SAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_1M:
10857640543fSAndrew Rybchenko 			params.ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M;
10865e111ed8SAndrew Rybchenko 			break;
10875e111ed8SAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_512K:
10887640543fSAndrew Rybchenko 			params.ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_512K;
10895e111ed8SAndrew Rybchenko 			break;
10905e111ed8SAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_256K:
10917640543fSAndrew Rybchenko 			params.ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_256K;
10925e111ed8SAndrew Rybchenko 			break;
10935e111ed8SAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_128K:
10947640543fSAndrew Rybchenko 			params.ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_128K;
10955e111ed8SAndrew Rybchenko 			break;
10965e111ed8SAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_64K:
10977640543fSAndrew Rybchenko 			params.ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_64K;
10985e111ed8SAndrew Rybchenko 			break;
10995e111ed8SAndrew Rybchenko 		default:
11005e111ed8SAndrew Rybchenko 			rc = ENOTSUP;
1101cdea571bSIvan Malov 			goto fail5;
11025e111ed8SAndrew Rybchenko 		}
11035e111ed8SAndrew Rybchenko 		erp->er_buf_size = type_data->ertd_packed_stream.eps_buf_size;
1104f784cdc5SAndrew Rybchenko 		/* Packed stream pseudo header does not have RSS hash value */
1105f784cdc5SAndrew Rybchenko 		if (flags & EFX_RXQ_FLAG_RSS_HASH) {
1106f784cdc5SAndrew Rybchenko 			rc = ENOTSUP;
1107cdea571bSIvan Malov 			goto fail6;
1108c414c567SIgor Romanov 		}
1109c414c567SIgor Romanov 		if (flags & EFX_RXQ_FLAG_USER_MARK) {
1110c414c567SIgor Romanov 			rc = ENOTSUP;
1111cdea571bSIvan Malov 			goto fail7;
1112cdea571bSIvan Malov 		}
1113cdea571bSIvan Malov 		if (flags & EFX_RXQ_FLAG_USER_FLAG) {
1114cdea571bSIvan Malov 			rc = ENOTSUP;
1115cdea571bSIvan Malov 			goto fail8;
1116f784cdc5SAndrew Rybchenko 		}
11175e111ed8SAndrew Rybchenko 		break;
11185e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_PACKED_STREAM */
11195e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_ES_SUPER_BUFFER
11205e111ed8SAndrew Rybchenko 	case EFX_RXQ_TYPE_ES_SUPER_BUFFER:
11216bba823fSAndrew Rybchenko 		erpl = &ef10_essb_rx_prefix_layout;
11225e111ed8SAndrew Rybchenko 		if (type_data == NULL) {
11235e111ed8SAndrew Rybchenko 			rc = EINVAL;
1124cdea571bSIvan Malov 			goto fail9;
11255e111ed8SAndrew Rybchenko 		}
11267640543fSAndrew Rybchenko 		params.es_bufs_per_desc =
11275e111ed8SAndrew Rybchenko 		    type_data->ertd_es_super_buffer.eessb_bufs_per_desc;
11287640543fSAndrew Rybchenko 		params.es_max_dma_len =
11295e111ed8SAndrew Rybchenko 		    type_data->ertd_es_super_buffer.eessb_max_dma_len;
11307640543fSAndrew Rybchenko 		params.es_buf_stride =
11315e111ed8SAndrew Rybchenko 		    type_data->ertd_es_super_buffer.eessb_buf_stride;
11327640543fSAndrew Rybchenko 		params.hol_block_timeout =
11335e111ed8SAndrew Rybchenko 		    type_data->ertd_es_super_buffer.eessb_hol_block_timeout;
1134f784cdc5SAndrew Rybchenko 		/*
1135f784cdc5SAndrew Rybchenko 		 * Ignore EFX_RXQ_FLAG_RSS_HASH since if RSS hash is calculated
1136f784cdc5SAndrew Rybchenko 		 * it is always delivered from HW in the pseudo-header.
1137f784cdc5SAndrew Rybchenko 		 */
11385e111ed8SAndrew Rybchenko 		break;
11395e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
11405e111ed8SAndrew Rybchenko 	default:
11415e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
1142cdea571bSIvan Malov 		goto fail10;
11435e111ed8SAndrew Rybchenko 	}
11445e111ed8SAndrew Rybchenko 
11455e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
11467640543fSAndrew Rybchenko 	if (params.ps_buf_size != 0) {
11475e111ed8SAndrew Rybchenko 		/* Check if datapath firmware supports packed stream mode */
11485e111ed8SAndrew Rybchenko 		if (encp->enc_rx_packed_stream_supported == B_FALSE) {
11495e111ed8SAndrew Rybchenko 			rc = ENOTSUP;
1150cdea571bSIvan Malov 			goto fail11;
11515e111ed8SAndrew Rybchenko 		}
11525e111ed8SAndrew Rybchenko 		/* Check if packed stream allows configurable buffer sizes */
11537640543fSAndrew Rybchenko 		if ((params.ps_buf_size != MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M) &&
11545e111ed8SAndrew Rybchenko 		    (encp->enc_rx_var_packed_stream_supported == B_FALSE)) {
11555e111ed8SAndrew Rybchenko 			rc = ENOTSUP;
1156cdea571bSIvan Malov 			goto fail12;
11575e111ed8SAndrew Rybchenko 		}
11585e111ed8SAndrew Rybchenko 	}
11595e111ed8SAndrew Rybchenko #else /* EFSYS_OPT_RX_PACKED_STREAM */
11607640543fSAndrew Rybchenko 	EFSYS_ASSERT(params.ps_buf_size == 0);
11615e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_PACKED_STREAM */
11625e111ed8SAndrew Rybchenko 
11635e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_ES_SUPER_BUFFER
11647640543fSAndrew Rybchenko 	if (params.es_bufs_per_desc > 0) {
11655e111ed8SAndrew Rybchenko 		if (encp->enc_rx_es_super_buffer_supported == B_FALSE) {
11665e111ed8SAndrew Rybchenko 			rc = ENOTSUP;
1167cdea571bSIvan Malov 			goto fail13;
11685e111ed8SAndrew Rybchenko 		}
11697640543fSAndrew Rybchenko 		if (!EFX_IS_P2ALIGNED(uint32_t, params.es_max_dma_len,
11705e111ed8SAndrew Rybchenko 			    EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) {
11715e111ed8SAndrew Rybchenko 			rc = EINVAL;
1172cdea571bSIvan Malov 			goto fail14;
11735e111ed8SAndrew Rybchenko 		}
11747640543fSAndrew Rybchenko 		if (!EFX_IS_P2ALIGNED(uint32_t, params.es_buf_stride,
11755e111ed8SAndrew Rybchenko 			    EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) {
11765e111ed8SAndrew Rybchenko 			rc = EINVAL;
1177cdea571bSIvan Malov 			goto fail15;
11785e111ed8SAndrew Rybchenko 		}
11795e111ed8SAndrew Rybchenko 	}
11805e111ed8SAndrew Rybchenko #else /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
11817640543fSAndrew Rybchenko 	EFSYS_ASSERT(params.es_bufs_per_desc == 0);
11825e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
11835e111ed8SAndrew Rybchenko 
1184aa3e21f0SIgor Romanov 	if (flags & EFX_RXQ_FLAG_INGRESS_MPORT) {
1185aa3e21f0SIgor Romanov 		rc = ENOTSUP;
1186cdea571bSIvan Malov 		goto fail16;
1187aa3e21f0SIgor Romanov 	}
1188aa3e21f0SIgor Romanov 
11895e111ed8SAndrew Rybchenko 	/* Scatter can only be disabled if the firmware supports doing so */
11905e111ed8SAndrew Rybchenko 	if (flags & EFX_RXQ_FLAG_SCATTER)
11917640543fSAndrew Rybchenko 		params.disable_scatter = B_FALSE;
11925e111ed8SAndrew Rybchenko 	else
11937640543fSAndrew Rybchenko 		params.disable_scatter = encp->enc_rx_disable_scatter_supported;
11945e111ed8SAndrew Rybchenko 
11955e111ed8SAndrew Rybchenko 	if (flags & EFX_RXQ_FLAG_INNER_CLASSES)
11967640543fSAndrew Rybchenko 		params.want_inner_classes = B_TRUE;
11975e111ed8SAndrew Rybchenko 	else
11987640543fSAndrew Rybchenko 		params.want_inner_classes = B_FALSE;
11995e111ed8SAndrew Rybchenko 
12005e111ed8SAndrew Rybchenko 	if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep, label, index,
12017640543fSAndrew Rybchenko 		    esmp, &params)) != 0)
1202cdea571bSIvan Malov 		goto fail17;
12035e111ed8SAndrew Rybchenko 
12045e111ed8SAndrew Rybchenko 	erp->er_eep = eep;
12055e111ed8SAndrew Rybchenko 	erp->er_label = label;
12065e111ed8SAndrew Rybchenko 
12075e111ed8SAndrew Rybchenko 	ef10_ev_rxlabel_init(eep, erp, label, type);
12085e111ed8SAndrew Rybchenko 
12095e111ed8SAndrew Rybchenko 	erp->er_ev_qstate = &erp->er_eep->ee_rxq_state[label];
12105e111ed8SAndrew Rybchenko 
12116bba823fSAndrew Rybchenko 	erp->er_prefix_layout = *erpl;
12126bba823fSAndrew Rybchenko 
12135e111ed8SAndrew Rybchenko 	return (0);
12145e111ed8SAndrew Rybchenko 
1215cdea571bSIvan Malov fail17:
1216cdea571bSIvan Malov 	EFSYS_PROBE(fail15);
1217cdea571bSIvan Malov fail16:
1218cdea571bSIvan Malov 	EFSYS_PROBE(fail14);
1219cdea571bSIvan Malov #if EFSYS_OPT_RX_ES_SUPER_BUFFER
1220c414c567SIgor Romanov fail15:
1221c414c567SIgor Romanov 	EFSYS_PROBE(fail15);
1222c414c567SIgor Romanov fail14:
1223c414c567SIgor Romanov 	EFSYS_PROBE(fail14);
1224aa3e21f0SIgor Romanov fail13:
1225aa3e21f0SIgor Romanov 	EFSYS_PROBE(fail13);
1226cdea571bSIvan Malov #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
1227cdea571bSIvan Malov #if EFSYS_OPT_RX_PACKED_STREAM
1228f784cdc5SAndrew Rybchenko fail12:
1229f784cdc5SAndrew Rybchenko 	EFSYS_PROBE(fail12);
12305e111ed8SAndrew Rybchenko fail11:
12315e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail11);
1232cdea571bSIvan Malov #endif /* EFSYS_OPT_RX_PACKED_STREAM */
12335e111ed8SAndrew Rybchenko fail10:
12345e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail10);
1235cdea571bSIvan Malov #if EFSYS_OPT_RX_ES_SUPER_BUFFER
12365e111ed8SAndrew Rybchenko fail9:
12375e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail9);
1238e9b9b2e5SAndrew Rybchenko #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
1239e9b9b2e5SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
1240cdea571bSIvan Malov fail8:
1241cdea571bSIvan Malov 	EFSYS_PROBE(fail8);
1242cdea571bSIvan Malov fail7:
1243cdea571bSIvan Malov 	EFSYS_PROBE(fail7);
1244c414c567SIgor Romanov fail6:
1245c414c567SIgor Romanov 	EFSYS_PROBE(fail6);
1246c414c567SIgor Romanov fail5:
1247c414c567SIgor Romanov 	EFSYS_PROBE(fail5);
1248f784cdc5SAndrew Rybchenko fail4:
1249f784cdc5SAndrew Rybchenko 	EFSYS_PROBE(fail4);
1250cdea571bSIvan Malov #endif /* EFSYS_OPT_RX_PACKED_STREAM */
12515e111ed8SAndrew Rybchenko fail3:
12525e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
12535e111ed8SAndrew Rybchenko fail2:
12545e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
12555e111ed8SAndrew Rybchenko fail1:
12565e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
12575e111ed8SAndrew Rybchenko 
12585e111ed8SAndrew Rybchenko 	return (rc);
12595e111ed8SAndrew Rybchenko }
12605e111ed8SAndrew Rybchenko 
12615e111ed8SAndrew Rybchenko 		void
ef10_rx_qdestroy(__in efx_rxq_t * erp)12625e111ed8SAndrew Rybchenko ef10_rx_qdestroy(
12635e111ed8SAndrew Rybchenko 	__in	efx_rxq_t *erp)
12645e111ed8SAndrew Rybchenko {
12655e111ed8SAndrew Rybchenko 	efx_evq_t *eep = erp->er_eep;
12665e111ed8SAndrew Rybchenko 	unsigned int label = erp->er_label;
12675e111ed8SAndrew Rybchenko 
12685e111ed8SAndrew Rybchenko 	ef10_ev_rxlabel_fini(eep, label);
12695e111ed8SAndrew Rybchenko }
12705e111ed8SAndrew Rybchenko 
1271b6b29352SAndrew Rybchenko #endif /* EFX_OPTS_EF10() */
1272b6b29352SAndrew Rybchenko 
12735e111ed8SAndrew Rybchenko 		void
ef10_rx_fini(__in efx_nic_t * enp)12745e111ed8SAndrew Rybchenko ef10_rx_fini(
12755e111ed8SAndrew Rybchenko 	__in	efx_nic_t *enp)
12765e111ed8SAndrew Rybchenko {
12775e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
12785e111ed8SAndrew Rybchenko 	if (enp->en_rss_context_type != EFX_RX_SCALE_UNAVAILABLE)
12795e111ed8SAndrew Rybchenko 		(void) efx_mcdi_rss_context_free(enp, enp->en_rss_context);
12805e111ed8SAndrew Rybchenko 	enp->en_rss_context = 0;
12815e111ed8SAndrew Rybchenko 	enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
12825e111ed8SAndrew Rybchenko #else
12835e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
12845e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
12855e111ed8SAndrew Rybchenko }
12865e111ed8SAndrew Rybchenko 
1287b6b29352SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */
1288