@@ -2245,6 +2245,86 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue)
2245
2245
}
2246
2246
}
2247
2247
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
+
2248
2328
static int efx_ef10_alloc_rss_context (struct efx_nic * efx , u32 * context ,
2249
2329
bool exclusive , unsigned * context_size )
2250
2330
{
@@ -2290,6 +2370,10 @@ static int efx_ef10_alloc_rss_context(struct efx_nic *efx, u32 *context,
2290
2370
if (context_size )
2291
2371
* context_size = rss_spread ;
2292
2372
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
+
2293
2377
return 0 ;
2294
2378
}
2295
2379
0 commit comments