Skip to content

Commit 8e6e596

Browse files
committed
Merge branch 'sfc-udp-rss'
Edward Cree says: ==================== sfc: enable 4-tuple UDP RSS hashing EF10 based NICs have configurable RSS hash fields, and can be made to take the ports into the hash on UDP (they already do so for TCP). This patch series enables this, in order to improve spreading of UDP traffic. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 04b206b + b718c88 commit 8e6e596

File tree

3 files changed

+94
-4
lines changed

3 files changed

+94
-4
lines changed

drivers/net/ethernet/sfc/ef10.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,6 +2245,86 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue)
22452245
}
22462246
}
22472247

2248+
#define RSS_MODE_HASH_ADDRS (1 << RSS_MODE_HASH_SRC_ADDR_LBN |\
2249+
1 << RSS_MODE_HASH_DST_ADDR_LBN)
2250+
#define RSS_MODE_HASH_PORTS (1 << RSS_MODE_HASH_SRC_PORT_LBN |\
2251+
1 << RSS_MODE_HASH_DST_PORT_LBN)
2252+
#define RSS_CONTEXT_FLAGS_DEFAULT (1 << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TOEPLITZ_IPV4_EN_LBN |\
2253+
1 << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TOEPLITZ_TCPV4_EN_LBN |\
2254+
1 << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TOEPLITZ_IPV6_EN_LBN |\
2255+
1 << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TOEPLITZ_TCPV6_EN_LBN |\
2256+
(RSS_MODE_HASH_ADDRS | RSS_MODE_HASH_PORTS) << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TCP_IPV4_RSS_MODE_LBN |\
2257+
RSS_MODE_HASH_ADDRS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_UDP_IPV4_RSS_MODE_LBN |\
2258+
RSS_MODE_HASH_ADDRS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_OTHER_IPV4_RSS_MODE_LBN |\
2259+
(RSS_MODE_HASH_ADDRS | RSS_MODE_HASH_PORTS) << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_TCP_IPV6_RSS_MODE_LBN |\
2260+
RSS_MODE_HASH_ADDRS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_UDP_IPV6_RSS_MODE_LBN |\
2261+
RSS_MODE_HASH_ADDRS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_OTHER_IPV6_RSS_MODE_LBN)
2262+
2263+
static int efx_ef10_get_rss_flags(struct efx_nic *efx, u32 context, u32 *flags)
2264+
{
2265+
/* Firmware had a bug (sfc bug 61952) where it would not actually
2266+
* fill in the flags field in the response to MC_CMD_RSS_CONTEXT_GET_FLAGS.
2267+
* This meant that it would always contain whatever was previously
2268+
* in the MCDI buffer. Fortunately, all firmware versions with
2269+
* this bug have the same default flags value for a newly-allocated
2270+
* RSS context, and the only time we want to get the flags is just
2271+
* after allocating. Moreover, the response has a 32-bit hole
2272+
* where the context ID would be in the request, so we can use an
2273+
* overlength buffer in the request and pre-fill the flags field
2274+
* with what we believe the default to be. Thus if the firmware
2275+
* has the bug, it will leave our pre-filled value in the flags
2276+
* field of the response, and we will get the right answer.
2277+
*
2278+
* However, this does mean that this function should NOT be used if
2279+
* the RSS context flags might not be their defaults - it is ONLY
2280+
* reliably correct for a newly-allocated RSS context.
2281+
*/
2282+
MCDI_DECLARE_BUF(inbuf, MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_LEN);
2283+
MCDI_DECLARE_BUF(outbuf, MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_LEN);
2284+
size_t outlen;
2285+
int rc;
2286+
2287+
/* Check we have a hole for the context ID */
2288+
BUILD_BUG_ON(MC_CMD_RSS_CONTEXT_GET_FLAGS_IN_LEN != MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_FLAGS_OFST);
2289+
MCDI_SET_DWORD(inbuf, RSS_CONTEXT_GET_FLAGS_IN_RSS_CONTEXT_ID, context);
2290+
MCDI_SET_DWORD(inbuf, RSS_CONTEXT_GET_FLAGS_OUT_FLAGS,
2291+
RSS_CONTEXT_FLAGS_DEFAULT);
2292+
rc = efx_mcdi_rpc(efx, MC_CMD_RSS_CONTEXT_GET_FLAGS, inbuf,
2293+
sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
2294+
if (rc == 0) {
2295+
if (outlen < MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_LEN)
2296+
rc = -EIO;
2297+
else
2298+
*flags = MCDI_DWORD(outbuf, RSS_CONTEXT_GET_FLAGS_OUT_FLAGS);
2299+
}
2300+
return rc;
2301+
}
2302+
2303+
/* Attempt to enable 4-tuple UDP hashing on the specified RSS context.
2304+
* If we fail, we just leave the RSS context at its default hash settings,
2305+
* which is safe but may slightly reduce performance.
2306+
* Defaults are 4-tuple for TCP and 2-tuple for UDP and other-IP, so we
2307+
* just need to set the UDP ports flags (for both IP versions).
2308+
*/
2309+
static void efx_ef10_set_rss_flags(struct efx_nic *efx, u32 context)
2310+
{
2311+
MCDI_DECLARE_BUF(inbuf, MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN);
2312+
u32 flags;
2313+
2314+
BUILD_BUG_ON(MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN != 0);
2315+
2316+
if (efx_ef10_get_rss_flags(efx, context, &flags) != 0)
2317+
return;
2318+
MCDI_SET_DWORD(inbuf, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID, context);
2319+
flags |= RSS_MODE_HASH_PORTS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_UDP_IPV4_RSS_MODE_LBN;
2320+
flags |= RSS_MODE_HASH_PORTS << MC_CMD_RSS_CONTEXT_GET_FLAGS_OUT_UDP_IPV6_RSS_MODE_LBN;
2321+
MCDI_SET_DWORD(inbuf, RSS_CONTEXT_SET_FLAGS_IN_FLAGS, flags);
2322+
if (!efx_mcdi_rpc(efx, MC_CMD_RSS_CONTEXT_SET_FLAGS, inbuf, sizeof(inbuf),
2323+
NULL, 0, NULL))
2324+
/* Succeeded, so UDP 4-tuple is now enabled */
2325+
efx->rx_hash_udp_4tuple = true;
2326+
}
2327+
22482328
static int efx_ef10_alloc_rss_context(struct efx_nic *efx, u32 *context,
22492329
bool exclusive, unsigned *context_size)
22502330
{
@@ -2290,6 +2370,10 @@ static int efx_ef10_alloc_rss_context(struct efx_nic *efx, u32 *context,
22902370
if (context_size)
22912371
*context_size = rss_spread;
22922372

2373+
if (nic_data->datapath_caps &
2374+
1 << MC_CMD_GET_CAPABILITIES_OUT_ADDITIONAL_RSS_MODES_LBN)
2375+
efx_ef10_set_rss_flags(efx, *context);
2376+
22932377
return 0;
22942378
}
22952379

drivers/net/ethernet/sfc/ethtool.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -968,20 +968,24 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev,
968968

969969
info->data = 0;
970970
switch (info->flow_type) {
971+
case UDP_V4_FLOW:
972+
if (efx->rx_hash_udp_4tuple)
973+
/* fall through */
971974
case TCP_V4_FLOW:
972-
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
975+
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
973976
/* fall through */
974-
case UDP_V4_FLOW:
975977
case SCTP_V4_FLOW:
976978
case AH_ESP_V4_FLOW:
977979
case IPV4_FLOW:
978980
info->data |= RXH_IP_SRC | RXH_IP_DST;
979981
min_revision = EFX_REV_FALCON_B0;
980982
break;
983+
case UDP_V6_FLOW:
984+
if (efx->rx_hash_udp_4tuple)
985+
/* fall through */
981986
case TCP_V6_FLOW:
982-
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
987+
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
983988
/* fall through */
984-
case UDP_V6_FLOW:
985989
case SCTP_V6_FLOW:
986990
case AH_ESP_V6_FLOW:
987991
case IPV6_FLOW:

drivers/net/ethernet/sfc/net_driver.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,7 @@ struct vfdi_status;
853853
* @rx_hash_key: Toeplitz hash key for RSS
854854
* @rx_indir_table: Indirection table for RSS
855855
* @rx_scatter: Scatter mode enabled for receives
856+
* @rx_hash_udp_4tuple: UDP 4-tuple hashing enabled
856857
* @int_error_count: Number of internal errors seen recently
857858
* @int_error_expire: Time at which error count will be expired
858859
* @irq_soft_enabled: Are IRQs soft-enabled? If not, IRQ handler will
@@ -990,6 +991,7 @@ struct efx_nic {
990991
u8 rx_hash_key[40];
991992
u32 rx_indir_table[128];
992993
bool rx_scatter;
994+
bool rx_hash_udp_4tuple;
993995

994996
unsigned int_error_count;
995997
unsigned long int_error_expire;

0 commit comments

Comments
 (0)