@@ -808,7 +808,8 @@ static inline void ip6_fill_mask(__be32 *mask)
808
808
}
809
809
810
810
static int efx_ethtool_get_class_rule (struct efx_nic * efx ,
811
- struct ethtool_rx_flow_spec * rule )
811
+ struct ethtool_rx_flow_spec * rule ,
812
+ u32 * rss_context )
812
813
{
813
814
struct ethtool_tcpip4_spec * ip_entry = & rule -> h_u .tcp_ip4_spec ;
814
815
struct ethtool_tcpip4_spec * ip_mask = & rule -> m_u .tcp_ip4_spec ;
@@ -964,6 +965,11 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
964
965
rule -> m_ext .vlan_tci = htons (0xfff );
965
966
}
966
967
968
+ if (spec .flags & EFX_FILTER_FLAG_RX_RSS ) {
969
+ rule -> flow_type |= FLOW_RSS ;
970
+ * rss_context = spec .rss_context ;
971
+ }
972
+
967
973
return rc ;
968
974
}
969
975
@@ -972,19 +978,29 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev,
972
978
struct ethtool_rxnfc * info , u32 * rule_locs )
973
979
{
974
980
struct efx_nic * efx = netdev_priv (net_dev );
981
+ u32 rss_context = 0 ;
982
+ s32 rc ;
975
983
976
984
switch (info -> cmd ) {
977
985
case ETHTOOL_GRXRINGS :
978
986
info -> data = efx -> n_rx_channels ;
979
987
return 0 ;
980
988
981
989
case ETHTOOL_GRXFH : {
990
+ struct efx_rss_context * ctx = & efx -> rss_context ;
991
+
992
+ if (info -> flow_type & FLOW_RSS && info -> rss_context ) {
993
+ ctx = efx_find_rss_context_entry (info -> rss_context ,
994
+ & efx -> rss_context .list );
995
+ if (!ctx )
996
+ return - ENOENT ;
997
+ }
982
998
info -> data = 0 ;
983
- if (!efx -> rss_active ) /* No RSS */
999
+ if (!efx_rss_active ( ctx ) ) /* No RSS */
984
1000
return 0 ;
985
- switch (info -> flow_type ) {
1001
+ switch (info -> flow_type & ~ FLOW_RSS ) {
986
1002
case UDP_V4_FLOW :
987
- if (efx -> rx_hash_udp_4tuple )
1003
+ if (ctx -> rx_hash_udp_4tuple )
988
1004
/* fall through */
989
1005
case TCP_V4_FLOW :
990
1006
info -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 ;
@@ -995,7 +1011,7 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev,
995
1011
info -> data |= RXH_IP_SRC | RXH_IP_DST ;
996
1012
break ;
997
1013
case UDP_V6_FLOW :
998
- if (efx -> rx_hash_udp_4tuple )
1014
+ if (ctx -> rx_hash_udp_4tuple )
999
1015
/* fall through */
1000
1016
case TCP_V6_FLOW :
1001
1017
info -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 ;
@@ -1023,10 +1039,14 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev,
1023
1039
case ETHTOOL_GRXCLSRULE :
1024
1040
if (efx_filter_get_rx_id_limit (efx ) == 0 )
1025
1041
return - EOPNOTSUPP ;
1026
- return efx_ethtool_get_class_rule (efx , & info -> fs );
1042
+ rc = efx_ethtool_get_class_rule (efx , & info -> fs , & rss_context );
1043
+ if (rc < 0 )
1044
+ return rc ;
1045
+ if (info -> fs .flow_type & FLOW_RSS )
1046
+ info -> rss_context = rss_context ;
1047
+ return 0 ;
1027
1048
1028
- case ETHTOOL_GRXCLSRLALL : {
1029
- s32 rc ;
1049
+ case ETHTOOL_GRXCLSRLALL :
1030
1050
info -> data = efx_filter_get_rx_id_limit (efx );
1031
1051
if (info -> data == 0 )
1032
1052
return - EOPNOTSUPP ;
@@ -1036,7 +1056,6 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev,
1036
1056
return rc ;
1037
1057
info -> rule_cnt = rc ;
1038
1058
return 0 ;
1039
- }
1040
1059
1041
1060
default :
1042
1061
return - EOPNOTSUPP ;
@@ -1054,7 +1073,8 @@ static inline bool ip6_mask_is_empty(__be32 mask[4])
1054
1073
}
1055
1074
1056
1075
static int efx_ethtool_set_class_rule (struct efx_nic * efx ,
1057
- struct ethtool_rx_flow_spec * rule )
1076
+ struct ethtool_rx_flow_spec * rule ,
1077
+ u32 rss_context )
1058
1078
{
1059
1079
struct ethtool_tcpip4_spec * ip_entry = & rule -> h_u .tcp_ip4_spec ;
1060
1080
struct ethtool_tcpip4_spec * ip_mask = & rule -> m_u .tcp_ip4_spec ;
@@ -1066,6 +1086,7 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
1066
1086
struct ethtool_usrip6_spec * uip6_mask = & rule -> m_u .usr_ip6_spec ;
1067
1087
struct ethhdr * mac_entry = & rule -> h_u .ether_spec ;
1068
1088
struct ethhdr * mac_mask = & rule -> m_u .ether_spec ;
1089
+ enum efx_filter_flags flags = 0 ;
1069
1090
struct efx_filter_spec spec ;
1070
1091
int rc ;
1071
1092
@@ -1084,12 +1105,19 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
1084
1105
rule -> m_ext .data [1 ]))
1085
1106
return - EINVAL ;
1086
1107
1087
- efx_filter_init_rx (& spec , EFX_FILTER_PRI_MANUAL ,
1088
- efx -> rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0 ,
1108
+ if (efx -> rx_scatter )
1109
+ flags |= EFX_FILTER_FLAG_RX_SCATTER ;
1110
+ if (rule -> flow_type & FLOW_RSS )
1111
+ flags |= EFX_FILTER_FLAG_RX_RSS ;
1112
+
1113
+ efx_filter_init_rx (& spec , EFX_FILTER_PRI_MANUAL , flags ,
1089
1114
(rule -> ring_cookie == RX_CLS_FLOW_DISC ) ?
1090
1115
EFX_FILTER_RX_DMAQ_ID_DROP : rule -> ring_cookie );
1091
1116
1092
- switch (rule -> flow_type & ~FLOW_EXT ) {
1117
+ if (rule -> flow_type & FLOW_RSS )
1118
+ spec .rss_context = rss_context ;
1119
+
1120
+ switch (rule -> flow_type & ~(FLOW_EXT | FLOW_RSS )) {
1093
1121
case TCP_V4_FLOW :
1094
1122
case UDP_V4_FLOW :
1095
1123
spec .match_flags = (EFX_FILTER_MATCH_ETHER_TYPE |
@@ -1265,7 +1293,8 @@ static int efx_ethtool_set_rxnfc(struct net_device *net_dev,
1265
1293
1266
1294
switch (info -> cmd ) {
1267
1295
case ETHTOOL_SRXCLSRLINS :
1268
- return efx_ethtool_set_class_rule (efx , & info -> fs );
1296
+ return efx_ethtool_set_class_rule (efx , & info -> fs ,
1297
+ info -> rss_context );
1269
1298
1270
1299
case ETHTOOL_SRXCLSRLDEL :
1271
1300
return efx_filter_remove_id_safe (efx , EFX_FILTER_PRI_MANUAL ,
@@ -1280,7 +1309,9 @@ static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev)
1280
1309
{
1281
1310
struct efx_nic * efx = netdev_priv (net_dev );
1282
1311
1283
- return (efx -> n_rx_channels == 1 ) ? 0 : ARRAY_SIZE (efx -> rx_indir_table );
1312
+ if (efx -> n_rx_channels == 1 )
1313
+ return 0 ;
1314
+ return ARRAY_SIZE (efx -> rss_context .rx_indir_table );
1284
1315
}
1285
1316
1286
1317
static u32 efx_ethtool_get_rxfh_key_size (struct net_device * net_dev )
@@ -1303,9 +1334,11 @@ static int efx_ethtool_get_rxfh(struct net_device *net_dev, u32 *indir, u8 *key,
1303
1334
if (hfunc )
1304
1335
* hfunc = ETH_RSS_HASH_TOP ;
1305
1336
if (indir )
1306
- memcpy (indir , efx -> rx_indir_table , sizeof (efx -> rx_indir_table ));
1337
+ memcpy (indir , efx -> rss_context .rx_indir_table ,
1338
+ sizeof (efx -> rss_context .rx_indir_table ));
1307
1339
if (key )
1308
- memcpy (key , efx -> rx_hash_key , efx -> type -> rx_hash_key_size );
1340
+ memcpy (key , efx -> rss_context .rx_hash_key ,
1341
+ efx -> type -> rx_hash_key_size );
1309
1342
return 0 ;
1310
1343
}
1311
1344
@@ -1321,13 +1354,93 @@ static int efx_ethtool_set_rxfh(struct net_device *net_dev, const u32 *indir,
1321
1354
return 0 ;
1322
1355
1323
1356
if (!key )
1324
- key = efx -> rx_hash_key ;
1357
+ key = efx -> rss_context . rx_hash_key ;
1325
1358
if (!indir )
1326
- indir = efx -> rx_indir_table ;
1359
+ indir = efx -> rss_context . rx_indir_table ;
1327
1360
1328
1361
return efx -> type -> rx_push_rss_config (efx , true, indir , key );
1329
1362
}
1330
1363
1364
+ static int efx_ethtool_get_rxfh_context (struct net_device * net_dev , u32 * indir ,
1365
+ u8 * key , u8 * hfunc , u32 rss_context )
1366
+ {
1367
+ struct efx_nic * efx = netdev_priv (net_dev );
1368
+ struct efx_rss_context * ctx ;
1369
+ int rc ;
1370
+
1371
+ if (!efx -> type -> rx_pull_rss_context_config )
1372
+ return - EOPNOTSUPP ;
1373
+ ctx = efx_find_rss_context_entry (rss_context , & efx -> rss_context .list );
1374
+ if (!ctx )
1375
+ return - ENOENT ;
1376
+ rc = efx -> type -> rx_pull_rss_context_config (efx , ctx );
1377
+ if (rc )
1378
+ return rc ;
1379
+
1380
+ if (hfunc )
1381
+ * hfunc = ETH_RSS_HASH_TOP ;
1382
+ if (indir )
1383
+ memcpy (indir , ctx -> rx_indir_table , sizeof (ctx -> rx_indir_table ));
1384
+ if (key )
1385
+ memcpy (key , ctx -> rx_hash_key , efx -> type -> rx_hash_key_size );
1386
+ return 0 ;
1387
+ }
1388
+
1389
+ static int efx_ethtool_set_rxfh_context (struct net_device * net_dev ,
1390
+ const u32 * indir , const u8 * key ,
1391
+ const u8 hfunc , u32 * rss_context ,
1392
+ bool delete )
1393
+ {
1394
+ struct efx_nic * efx = netdev_priv (net_dev );
1395
+ struct efx_rss_context * ctx ;
1396
+ bool allocated = false;
1397
+ int rc ;
1398
+
1399
+ if (!efx -> type -> rx_push_rss_context_config )
1400
+ return - EOPNOTSUPP ;
1401
+ /* Hash function is Toeplitz, cannot be changed */
1402
+ if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP )
1403
+ return - EOPNOTSUPP ;
1404
+ if (* rss_context == ETH_RXFH_CONTEXT_ALLOC ) {
1405
+ if (delete )
1406
+ /* alloc + delete == Nothing to do */
1407
+ return - EINVAL ;
1408
+ ctx = efx_alloc_rss_context_entry (& efx -> rss_context .list );
1409
+ if (!ctx )
1410
+ return - ENOMEM ;
1411
+ ctx -> context_id = EFX_EF10_RSS_CONTEXT_INVALID ;
1412
+ /* Initialise indir table and key to defaults */
1413
+ efx_set_default_rx_indir_table (efx , ctx );
1414
+ netdev_rss_key_fill (ctx -> rx_hash_key , sizeof (ctx -> rx_hash_key ));
1415
+ allocated = true;
1416
+ } else {
1417
+ ctx = efx_find_rss_context_entry (* rss_context ,
1418
+ & efx -> rss_context .list );
1419
+ if (!ctx )
1420
+ return - ENOENT ;
1421
+ }
1422
+
1423
+ if (delete ) {
1424
+ /* delete this context */
1425
+ rc = efx -> type -> rx_push_rss_context_config (efx , ctx , NULL , NULL );
1426
+ if (!rc )
1427
+ efx_free_rss_context_entry (ctx );
1428
+ return rc ;
1429
+ }
1430
+
1431
+ if (!key )
1432
+ key = ctx -> rx_hash_key ;
1433
+ if (!indir )
1434
+ indir = ctx -> rx_indir_table ;
1435
+
1436
+ rc = efx -> type -> rx_push_rss_context_config (efx , ctx , indir , key );
1437
+ if (rc && allocated )
1438
+ efx_free_rss_context_entry (ctx );
1439
+ else
1440
+ * rss_context = ctx -> user_id ;
1441
+ return rc ;
1442
+ }
1443
+
1331
1444
static int efx_ethtool_get_ts_info (struct net_device * net_dev ,
1332
1445
struct ethtool_ts_info * ts_info )
1333
1446
{
@@ -1403,6 +1516,8 @@ const struct ethtool_ops efx_ethtool_ops = {
1403
1516
.get_rxfh_key_size = efx_ethtool_get_rxfh_key_size ,
1404
1517
.get_rxfh = efx_ethtool_get_rxfh ,
1405
1518
.set_rxfh = efx_ethtool_set_rxfh ,
1519
+ .get_rxfh_context = efx_ethtool_get_rxfh_context ,
1520
+ .set_rxfh_context = efx_ethtool_set_rxfh_context ,
1406
1521
.get_ts_info = efx_ethtool_get_ts_info ,
1407
1522
.get_module_info = efx_ethtool_get_module_info ,
1408
1523
.get_module_eeprom = efx_ethtool_get_module_eeprom ,
0 commit comments