@@ -820,10 +820,10 @@ int efx_ethtool_get_rxnfc(struct net_device *net_dev,
820
820
return 0 ;
821
821
822
822
case ETHTOOL_GRXFH : {
823
- struct efx_rss_context * ctx = & efx -> rss_context ;
823
+ struct efx_rss_context_priv * ctx = & efx -> rss_context . priv ;
824
824
__u64 data ;
825
825
826
- mutex_lock (& efx -> rss_lock );
826
+ mutex_lock (& net_dev -> ethtool -> rss_lock );
827
827
if (info -> flow_type & FLOW_RSS && info -> rss_context ) {
828
828
ctx = efx_find_rss_context_entry (efx , info -> rss_context );
829
829
if (!ctx ) {
@@ -864,7 +864,7 @@ int efx_ethtool_get_rxnfc(struct net_device *net_dev,
864
864
out_setdata_unlock :
865
865
info -> data = data ;
866
866
out_unlock :
867
- mutex_unlock (& efx -> rss_lock );
867
+ mutex_unlock (& net_dev -> ethtool -> rss_lock );
868
868
return rc ;
869
869
}
870
870
@@ -1167,31 +1167,33 @@ static int efx_ethtool_get_rxfh_context(struct net_device *net_dev,
1167
1167
struct ethtool_rxfh_param * rxfh )
1168
1168
{
1169
1169
struct efx_nic * efx = efx_netdev_priv (net_dev );
1170
- struct efx_rss_context * ctx ;
1170
+ struct efx_rss_context_priv * ctx_priv ;
1171
+ struct efx_rss_context ctx ;
1171
1172
int rc = 0 ;
1172
1173
1173
1174
if (!efx -> type -> rx_pull_rss_context_config )
1174
1175
return - EOPNOTSUPP ;
1175
1176
1176
- mutex_lock (& efx -> rss_lock );
1177
- ctx = efx_find_rss_context_entry (efx , rxfh -> rss_context );
1178
- if (!ctx ) {
1177
+ mutex_lock (& net_dev -> ethtool -> rss_lock );
1178
+ ctx_priv = efx_find_rss_context_entry (efx , rxfh -> rss_context );
1179
+ if (!ctx_priv ) {
1179
1180
rc = - ENOENT ;
1180
1181
goto out_unlock ;
1181
1182
}
1182
- rc = efx -> type -> rx_pull_rss_context_config (efx , ctx );
1183
+ ctx .priv = * ctx_priv ;
1184
+ rc = efx -> type -> rx_pull_rss_context_config (efx , & ctx );
1183
1185
if (rc )
1184
1186
goto out_unlock ;
1185
1187
1186
1188
rxfh -> hfunc = ETH_RSS_HASH_TOP ;
1187
1189
if (rxfh -> indir )
1188
- memcpy (rxfh -> indir , ctx -> rx_indir_table ,
1189
- sizeof (ctx -> rx_indir_table ));
1190
+ memcpy (rxfh -> indir , ctx . rx_indir_table ,
1191
+ sizeof (ctx . rx_indir_table ));
1190
1192
if (rxfh -> key )
1191
- memcpy (rxfh -> key , ctx -> rx_hash_key ,
1193
+ memcpy (rxfh -> key , ctx . rx_hash_key ,
1192
1194
efx -> type -> rx_hash_key_size );
1193
1195
out_unlock :
1194
- mutex_unlock (& efx -> rss_lock );
1196
+ mutex_unlock (& net_dev -> ethtool -> rss_lock );
1195
1197
return rc ;
1196
1198
}
1197
1199
@@ -1218,68 +1220,85 @@ int efx_ethtool_get_rxfh(struct net_device *net_dev,
1218
1220
return 0 ;
1219
1221
}
1220
1222
1221
- static int efx_ethtool_set_rxfh_context (struct net_device * net_dev ,
1222
- struct ethtool_rxfh_param * rxfh ,
1223
- struct netlink_ext_ack * extack )
1223
+ int efx_ethtool_modify_rxfh_context (struct net_device * net_dev ,
1224
+ struct ethtool_rxfh_context * ctx ,
1225
+ const struct ethtool_rxfh_param * rxfh ,
1226
+ struct netlink_ext_ack * extack )
1224
1227
{
1225
1228
struct efx_nic * efx = efx_netdev_priv (net_dev );
1226
- u32 * rss_context = & rxfh -> rss_context ;
1227
- struct efx_rss_context * ctx ;
1228
- u32 * indir = rxfh -> indir ;
1229
- bool allocated = false;
1230
- u8 * key = rxfh -> key ;
1231
- int rc ;
1229
+ struct efx_rss_context_priv * priv ;
1230
+ const u32 * indir = rxfh -> indir ;
1231
+ const u8 * key = rxfh -> key ;
1232
1232
1233
- if (!efx -> type -> rx_push_rss_context_config )
1233
+ if (!efx -> type -> rx_push_rss_context_config ) {
1234
+ NL_SET_ERR_MSG_MOD (extack ,
1235
+ "NIC type does not support custom contexts" );
1234
1236
return - EOPNOTSUPP ;
1235
-
1236
- mutex_lock (& efx -> rss_lock );
1237
-
1238
- if (* rss_context == ETH_RXFH_CONTEXT_ALLOC ) {
1239
- if (rxfh -> rss_delete ) {
1240
- /* alloc + delete == Nothing to do */
1241
- rc = - EINVAL ;
1242
- goto out_unlock ;
1243
- }
1244
- ctx = efx_alloc_rss_context_entry (efx );
1245
- if (!ctx ) {
1246
- rc = - ENOMEM ;
1247
- goto out_unlock ;
1248
- }
1249
- ctx -> context_id = EFX_MCDI_RSS_CONTEXT_INVALID ;
1250
- /* Initialise indir table and key to defaults */
1251
- efx_set_default_rx_indir_table (efx , ctx );
1252
- netdev_rss_key_fill (ctx -> rx_hash_key , sizeof (ctx -> rx_hash_key ));
1253
- allocated = true;
1254
- } else {
1255
- ctx = efx_find_rss_context_entry (efx , * rss_context );
1256
- if (!ctx ) {
1257
- rc = - ENOENT ;
1258
- goto out_unlock ;
1259
- }
1260
1237
}
1261
-
1262
- if (rxfh -> rss_delete ) {
1263
- /* delete this context */
1264
- rc = efx -> type -> rx_push_rss_context_config (efx , ctx , NULL , NULL );
1265
- if (!rc )
1266
- efx_free_rss_context_entry (ctx );
1267
- goto out_unlock ;
1238
+ /* Hash function is Toeplitz, cannot be changed */
1239
+ if (rxfh -> hfunc != ETH_RSS_HASH_NO_CHANGE &&
1240
+ rxfh -> hfunc != ETH_RSS_HASH_TOP ) {
1241
+ NL_SET_ERR_MSG_MOD (extack , "Only Toeplitz hash is supported" );
1242
+ return - EOPNOTSUPP ;
1268
1243
}
1269
1244
1245
+ priv = ethtool_rxfh_context_priv (ctx );
1246
+
1270
1247
if (!key )
1271
- key = ctx -> rx_hash_key ;
1248
+ key = ethtool_rxfh_context_key ( ctx ) ;
1272
1249
if (!indir )
1273
- indir = ctx -> rx_indir_table ;
1250
+ indir = ethtool_rxfh_context_indir ( ctx ) ;
1274
1251
1275
- rc = efx -> type -> rx_push_rss_context_config (efx , ctx , indir , key );
1276
- if (rc && allocated )
1277
- efx_free_rss_context_entry (ctx );
1278
- else
1279
- * rss_context = ctx -> user_id ;
1280
- out_unlock :
1281
- mutex_unlock (& efx -> rss_lock );
1282
- return rc ;
1252
+ return efx -> type -> rx_push_rss_context_config (efx , priv , indir , key ,
1253
+ false);
1254
+ }
1255
+
1256
+ int efx_ethtool_create_rxfh_context (struct net_device * net_dev ,
1257
+ struct ethtool_rxfh_context * ctx ,
1258
+ const struct ethtool_rxfh_param * rxfh ,
1259
+ struct netlink_ext_ack * extack )
1260
+ {
1261
+ struct efx_nic * efx = efx_netdev_priv (net_dev );
1262
+ struct efx_rss_context_priv * priv ;
1263
+
1264
+ priv = ethtool_rxfh_context_priv (ctx );
1265
+
1266
+ priv -> context_id = EFX_MCDI_RSS_CONTEXT_INVALID ;
1267
+ priv -> rx_hash_udp_4tuple = false;
1268
+ /* Generate default indir table and/or key if not specified.
1269
+ * We use ctx as a place to store these; this is fine because
1270
+ * we're doing a create, so if we fail then the ctx will just
1271
+ * be deleted.
1272
+ */
1273
+ if (!rxfh -> indir )
1274
+ efx_set_default_rx_indir_table (efx , ethtool_rxfh_context_indir (ctx ));
1275
+ if (!rxfh -> key )
1276
+ netdev_rss_key_fill (ethtool_rxfh_context_key (ctx ),
1277
+ ctx -> key_size );
1278
+ if (rxfh -> hfunc == ETH_RSS_HASH_NO_CHANGE )
1279
+ ctx -> hfunc = ETH_RSS_HASH_TOP ;
1280
+ if (rxfh -> input_xfrm == RXH_XFRM_NO_CHANGE )
1281
+ ctx -> input_xfrm = 0 ;
1282
+ return efx_ethtool_modify_rxfh_context (net_dev , ctx , rxfh , extack );
1283
+ }
1284
+
1285
+ int efx_ethtool_remove_rxfh_context (struct net_device * net_dev ,
1286
+ struct ethtool_rxfh_context * ctx ,
1287
+ u32 rss_context ,
1288
+ struct netlink_ext_ack * extack )
1289
+ {
1290
+ struct efx_nic * efx = efx_netdev_priv (net_dev );
1291
+ struct efx_rss_context_priv * priv ;
1292
+
1293
+ if (!efx -> type -> rx_push_rss_context_config ) {
1294
+ NL_SET_ERR_MSG_MOD (extack ,
1295
+ "NIC type does not support custom contexts" );
1296
+ return - EOPNOTSUPP ;
1297
+ }
1298
+
1299
+ priv = ethtool_rxfh_context_priv (ctx );
1300
+ return efx -> type -> rx_push_rss_context_config (efx , priv , NULL , NULL ,
1301
+ true);
1283
1302
}
1284
1303
1285
1304
int efx_ethtool_set_rxfh (struct net_device * net_dev ,
@@ -1295,8 +1314,9 @@ int efx_ethtool_set_rxfh(struct net_device *net_dev,
1295
1314
rxfh -> hfunc != ETH_RSS_HASH_TOP )
1296
1315
return - EOPNOTSUPP ;
1297
1316
1298
- if (rxfh -> rss_context )
1299
- return efx_ethtool_set_rxfh_context (net_dev , rxfh , extack );
1317
+ /* Custom contexts should use new API */
1318
+ if (WARN_ON_ONCE (rxfh -> rss_context ))
1319
+ return - EIO ;
1300
1320
1301
1321
if (!indir && !key )
1302
1322
return 0 ;
0 commit comments