@@ -1208,18 +1208,41 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
12081208 return 0 ;
12091209}
12101210
1211+ static noinline_for_stack int ethtool_get_rxrings (struct net_device * dev ,
1212+ u32 cmd ,
1213+ void __user * useraddr )
1214+ {
1215+ struct ethtool_rxnfc info ;
1216+ size_t info_size ;
1217+ int ret ;
1218+
1219+ info_size = sizeof (info );
1220+ ret = ethtool_rxnfc_copy_struct (cmd , & info , & info_size , useraddr );
1221+ if (ret )
1222+ return ret ;
1223+
1224+ ret = ethtool_get_rx_ring_count (dev );
1225+ if (ret < 0 )
1226+ return ret ;
1227+
1228+ info .data = ret ;
1229+
1230+ return ethtool_rxnfc_copy_to_user (useraddr , & info , info_size , NULL );
1231+ }
1232+
12111233static noinline_for_stack int ethtool_get_rxnfc (struct net_device * dev ,
12121234 u32 cmd , void __user * useraddr )
12131235{
1214- struct ethtool_rxnfc info ;
1215- size_t info_size = sizeof (info );
12161236 const struct ethtool_ops * ops = dev -> ethtool_ops ;
1217- int ret ;
1237+ struct ethtool_rxnfc info ;
12181238 void * rule_buf = NULL ;
1239+ size_t info_size ;
1240+ int ret ;
12191241
12201242 if (!ops -> get_rxnfc )
12211243 return - EOPNOTSUPP ;
12221244
1245+ info_size = sizeof (info );
12231246 ret = ethtool_rxnfc_copy_struct (cmd , & info , & info_size , useraddr );
12241247 if (ret )
12251248 return ret ;
@@ -1246,8 +1269,8 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
12461269}
12471270
12481271static int ethtool_copy_validate_indir (u32 * indir , void __user * useraddr ,
1249- struct ethtool_rxnfc * rx_rings ,
1250- u32 size )
1272+ int num_rx_rings ,
1273+ u32 size )
12511274{
12521275 int i ;
12531276
@@ -1256,7 +1279,7 @@ static int ethtool_copy_validate_indir(u32 *indir, void __user *useraddr,
12561279
12571280 /* Validate ring indices */
12581281 for (i = 0 ; i < size ; i ++ )
1259- if (indir [i ] >= rx_rings -> data )
1282+ if (indir [i ] >= num_rx_rings )
12601283 return - EINVAL ;
12611284
12621285 return 0 ;
@@ -1327,13 +1350,12 @@ static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
13271350 const struct ethtool_ops * ops = dev -> ethtool_ops ;
13281351 struct ethtool_rxfh_param rxfh_dev = {};
13291352 struct netlink_ext_ack * extack = NULL ;
1330- struct ethtool_rxnfc rx_rings ;
1353+ int num_rx_rings ;
13311354 u32 user_size , i ;
13321355 int ret ;
13331356 u32 ringidx_offset = offsetof(struct ethtool_rxfh_indir , ring_index [0 ]);
13341357
1335- if (!ops -> get_rxfh_indir_size || !ops -> set_rxfh ||
1336- !ops -> get_rxnfc )
1358+ if (!ops -> get_rxfh_indir_size || !ops -> set_rxfh )
13371359 return - EOPNOTSUPP ;
13381360
13391361 rxfh_dev .indir_size = ops -> get_rxfh_indir_size (dev );
@@ -1353,20 +1375,21 @@ static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
13531375 if (!rxfh_dev .indir )
13541376 return - ENOMEM ;
13551377
1356- rx_rings . cmd = ETHTOOL_GRXRINGS ;
1357- ret = ops -> get_rxnfc ( dev , & rx_rings , NULL );
1358- if ( ret )
1378+ num_rx_rings = ethtool_get_rx_ring_count ( dev ) ;
1379+ if ( num_rx_rings < 0 ) {
1380+ ret = num_rx_rings ;
13591381 goto out ;
1382+ }
13601383
13611384 if (user_size == 0 ) {
13621385 u32 * indir = rxfh_dev .indir ;
13631386
13641387 for (i = 0 ; i < rxfh_dev .indir_size ; i ++ )
1365- indir [i ] = ethtool_rxfh_indir_default (i , rx_rings . data );
1388+ indir [i ] = ethtool_rxfh_indir_default (i , num_rx_rings );
13661389 } else {
13671390 ret = ethtool_copy_validate_indir (rxfh_dev .indir ,
13681391 useraddr + ringidx_offset ,
1369- & rx_rings ,
1392+ num_rx_rings ,
13701393 rxfh_dev .indir_size );
13711394 if (ret )
13721395 goto out ;
@@ -1508,14 +1531,14 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
15081531 struct ethtool_rxfh_param rxfh_dev = {};
15091532 struct ethtool_rxfh_context * ctx = NULL ;
15101533 struct netlink_ext_ack * extack = NULL ;
1511- struct ethtool_rxnfc rx_rings ;
15121534 struct ethtool_rxfh rxfh ;
15131535 bool create = false;
1536+ int num_rx_rings ;
15141537 u8 * rss_config ;
15151538 int ntf = 0 ;
15161539 int ret ;
15171540
1518- if (!ops -> get_rxnfc || ! ops -> set_rxfh )
1541+ if (!ops -> set_rxfh )
15191542 return - EOPNOTSUPP ;
15201543
15211544 if (ops -> get_rxfh_indir_size )
@@ -1571,10 +1594,11 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
15711594 if (!rss_config )
15721595 return - ENOMEM ;
15731596
1574- rx_rings . cmd = ETHTOOL_GRXRINGS ;
1575- ret = ops -> get_rxnfc ( dev , & rx_rings , NULL );
1576- if ( ret )
1597+ num_rx_rings = ethtool_get_rx_ring_count ( dev ) ;
1598+ if ( num_rx_rings < 0 ) {
1599+ ret = num_rx_rings ;
15771600 goto out_free ;
1601+ }
15781602
15791603 /* rxfh.indir_size == 0 means reset the indir table to default (master
15801604 * context) or delete the context (other RSS contexts).
@@ -1587,7 +1611,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
15871611 rxfh_dev .indir_size = dev_indir_size ;
15881612 ret = ethtool_copy_validate_indir (rxfh_dev .indir ,
15891613 useraddr + rss_cfg_offset ,
1590- & rx_rings ,
1614+ num_rx_rings ,
15911615 rxfh .indir_size );
15921616 if (ret )
15931617 goto out_free ;
@@ -1599,7 +1623,8 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
15991623 rxfh_dev .indir_size = dev_indir_size ;
16001624 indir = rxfh_dev .indir ;
16011625 for (i = 0 ; i < dev_indir_size ; i ++ )
1602- indir [i ] = ethtool_rxfh_indir_default (i , rx_rings .data );
1626+ indir [i ] =
1627+ ethtool_rxfh_indir_default (i , num_rx_rings );
16031628 } else {
16041629 rxfh_dev .rss_delete = true;
16051630 }
@@ -3377,6 +3402,8 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr,
33773402 rc = ethtool_set_rxfh_fields (dev , ethcmd , useraddr );
33783403 break ;
33793404 case ETHTOOL_GRXRINGS :
3405+ rc = ethtool_get_rxrings (dev , ethcmd , useraddr );
3406+ break ;
33803407 case ETHTOOL_GRXCLSRLCNT :
33813408 case ETHTOOL_GRXCLSRULE :
33823409 case ETHTOOL_GRXCLSRLALL :
0 commit comments