@@ -1022,6 +1022,15 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
10221022 if (copy_from_user (& info , useraddr , info_size ))
10231023 return - EFAULT ;
10241024
1025+ /* If FLOW_RSS was requested then user-space must be using the
1026+ * new definition, as FLOW_RSS is newer.
1027+ */
1028+ if (cmd == ETHTOOL_GRXFH && info .flow_type & FLOW_RSS ) {
1029+ info_size = sizeof (info );
1030+ if (copy_from_user (& info , useraddr , info_size ))
1031+ return - EFAULT ;
1032+ }
1033+
10251034 if (info .cmd == ETHTOOL_GRXCLSRLALL ) {
10261035 if (info .rule_cnt > 0 ) {
10271036 if (info .rule_cnt <= KMALLOC_MAX_SIZE / sizeof (u32 ))
@@ -1251,9 +1260,11 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
12511260 user_key_size = rxfh .key_size ;
12521261
12531262 /* Check that reserved fields are 0 for now */
1254- if (rxfh .rss_context || rxfh .rsvd8 [0 ] || rxfh .rsvd8 [1 ] ||
1255- rxfh .rsvd8 [2 ] || rxfh .rsvd32 )
1263+ if (rxfh .rsvd8 [0 ] || rxfh .rsvd8 [1 ] || rxfh .rsvd8 [2 ] || rxfh .rsvd32 )
12561264 return - EINVAL ;
1265+ /* Most drivers don't handle rss_context, check it's 0 as well */
1266+ if (rxfh .rss_context && !ops -> get_rxfh_context )
1267+ return - EOPNOTSUPP ;
12571268
12581269 rxfh .indir_size = dev_indir_size ;
12591270 rxfh .key_size = dev_key_size ;
@@ -1276,7 +1287,12 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
12761287 if (user_key_size )
12771288 hkey = rss_config + indir_bytes ;
12781289
1279- ret = dev -> ethtool_ops -> get_rxfh (dev , indir , hkey , & dev_hfunc );
1290+ if (rxfh .rss_context )
1291+ ret = dev -> ethtool_ops -> get_rxfh_context (dev , indir , hkey ,
1292+ & dev_hfunc ,
1293+ rxfh .rss_context );
1294+ else
1295+ ret = dev -> ethtool_ops -> get_rxfh (dev , indir , hkey , & dev_hfunc );
12801296 if (ret )
12811297 goto out ;
12821298
@@ -1306,6 +1322,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
13061322 u8 * hkey = NULL ;
13071323 u8 * rss_config ;
13081324 u32 rss_cfg_offset = offsetof(struct ethtool_rxfh , rss_config [0 ]);
1325+ bool delete = false;
13091326
13101327 if (!ops -> get_rxnfc || !ops -> set_rxfh )
13111328 return - EOPNOTSUPP ;
@@ -1319,9 +1336,11 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
13191336 return - EFAULT ;
13201337
13211338 /* Check that reserved fields are 0 for now */
1322- if (rxfh .rss_context || rxfh .rsvd8 [0 ] || rxfh .rsvd8 [1 ] ||
1323- rxfh .rsvd8 [2 ] || rxfh .rsvd32 )
1339+ if (rxfh .rsvd8 [0 ] || rxfh .rsvd8 [1 ] || rxfh .rsvd8 [2 ] || rxfh .rsvd32 )
13241340 return - EINVAL ;
1341+ /* Most drivers don't handle rss_context, check it's 0 as well */
1342+ if (rxfh .rss_context && !ops -> set_rxfh_context )
1343+ return - EOPNOTSUPP ;
13251344
13261345 /* If either indir, hash key or function is valid, proceed further.
13271346 * Must request at least one change: indir size, hash key or function.
@@ -1346,7 +1365,8 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
13461365 if (ret )
13471366 goto out ;
13481367
1349- /* rxfh.indir_size == 0 means reset the indir table to default.
1368+ /* rxfh.indir_size == 0 means reset the indir table to default (master
1369+ * context) or delete the context (other RSS contexts).
13501370 * rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE means leave it unchanged.
13511371 */
13521372 if (rxfh .indir_size &&
@@ -1359,9 +1379,13 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
13591379 if (ret )
13601380 goto out ;
13611381 } else if (rxfh .indir_size == 0 ) {
1362- indir = (u32 * )rss_config ;
1363- for (i = 0 ; i < dev_indir_size ; i ++ )
1364- indir [i ] = ethtool_rxfh_indir_default (i , rx_rings .data );
1382+ if (rxfh .rss_context == 0 ) {
1383+ indir = (u32 * )rss_config ;
1384+ for (i = 0 ; i < dev_indir_size ; i ++ )
1385+ indir [i ] = ethtool_rxfh_indir_default (i , rx_rings .data );
1386+ } else {
1387+ delete = true;
1388+ }
13651389 }
13661390
13671391 if (rxfh .key_size ) {
@@ -1374,15 +1398,25 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
13741398 }
13751399 }
13761400
1377- ret = ops -> set_rxfh (dev , indir , hkey , rxfh .hfunc );
1401+ if (rxfh .rss_context )
1402+ ret = ops -> set_rxfh_context (dev , indir , hkey , rxfh .hfunc ,
1403+ & rxfh .rss_context , delete );
1404+ else
1405+ ret = ops -> set_rxfh (dev , indir , hkey , rxfh .hfunc );
13781406 if (ret )
13791407 goto out ;
13801408
1381- /* indicate whether rxfh was set to default */
1382- if (rxfh .indir_size == 0 )
1383- dev -> priv_flags &= ~IFF_RXFH_CONFIGURED ;
1384- else if (rxfh .indir_size != ETH_RXFH_INDIR_NO_CHANGE )
1385- dev -> priv_flags |= IFF_RXFH_CONFIGURED ;
1409+ if (copy_to_user (useraddr + offsetof(struct ethtool_rxfh , rss_context ),
1410+ & rxfh .rss_context , sizeof (rxfh .rss_context )))
1411+ ret = - EFAULT ;
1412+
1413+ if (!rxfh .rss_context ) {
1414+ /* indicate whether rxfh was set to default */
1415+ if (rxfh .indir_size == 0 )
1416+ dev -> priv_flags &= ~IFF_RXFH_CONFIGURED ;
1417+ else if (rxfh .indir_size != ETH_RXFH_INDIR_NO_CHANGE )
1418+ dev -> priv_flags |= IFF_RXFH_CONFIGURED ;
1419+ }
13861420
13871421out :
13881422 kfree (rss_config );
0 commit comments