aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2011-12-15 08:55:01 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-16 13:52:47 -0500
commit7850f63f1620512631445b901ae11cd149e7375c (patch)
treed26a5f049dcf3634c4bf9e1b86915d201fab3836 /drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
parent14596f7006297b67516e2b6a2b26bcb11fe08fb3 (diff)
ethtool: Centralise validation of ETHTOOL_{G, S}RXFHINDIR parameters
Add a new ethtool operation (get_rxfh_indir_size) to get the indirectional table size. Use this to validate the user buffer size before calling get_rxfh_indir or set_rxfh_indir. Use get_rxnfc to get the number of RX rings, and validate the contents of the new indirection table before calling set_rxfh_indir. Remove this validation from drivers. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Acked-by: Dimitris Michailidis <dm@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c39
1 files changed, 14 insertions, 25 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 90d44af85600..a688b9d975a2 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -2302,18 +2302,20 @@ static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
2302 } 2302 }
2303} 2303}
2304 2304
2305static int bnx2x_get_rxfh_indir(struct net_device *dev, 2305static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev)
2306 struct ethtool_rxfh_indir *indir) 2306{
2307 struct bnx2x *bp = netdev_priv(dev);
2308
2309 return (bp->multi_mode == ETH_RSS_MODE_DISABLED ?
2310 0 : T_ETH_INDIRECTION_TABLE_SIZE);
2311}
2312
2313static int bnx2x_get_rxfh_indir(struct net_device *dev, u32 *indir)
2307{ 2314{
2308 struct bnx2x *bp = netdev_priv(dev); 2315 struct bnx2x *bp = netdev_priv(dev);
2309 size_t copy_size =
2310 min_t(size_t, indir->size, T_ETH_INDIRECTION_TABLE_SIZE);
2311 u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0}; 2316 u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
2312 size_t i; 2317 size_t i;
2313 2318
2314 if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
2315 return -EOPNOTSUPP;
2316
2317 /* Get the current configuration of the RSS indirection table */ 2319 /* Get the current configuration of the RSS indirection table */
2318 bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table); 2320 bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
2319 2321
@@ -2326,33 +2328,19 @@ static int bnx2x_get_rxfh_indir(struct net_device *dev,
2326 * align the returned table to the Client ID of the leading RSS 2328 * align the returned table to the Client ID of the leading RSS
2327 * queue. 2329 * queue.
2328 */ 2330 */
2329 for (i = 0; i < copy_size; i++) 2331 for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++)
2330 indir->ring_index[i] = ind_table[i] - bp->fp->cl_id; 2332 indir[i] = ind_table[i] - bp->fp->cl_id;
2331
2332 indir->size = T_ETH_INDIRECTION_TABLE_SIZE;
2333 2333
2334 return 0; 2334 return 0;
2335} 2335}
2336 2336
2337static int bnx2x_set_rxfh_indir(struct net_device *dev, 2337static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir)
2338 const struct ethtool_rxfh_indir *indir)
2339{ 2338{
2340 struct bnx2x *bp = netdev_priv(dev); 2339 struct bnx2x *bp = netdev_priv(dev);
2341 size_t i; 2340 size_t i;
2342 u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0}; 2341 u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
2343 u32 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
2344
2345 if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
2346 return -EOPNOTSUPP;
2347
2348 /* validate the size */
2349 if (indir->size != T_ETH_INDIRECTION_TABLE_SIZE)
2350 return -EINVAL;
2351 2342
2352 for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) { 2343 for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
2353 /* validate the indices */
2354 if (indir->ring_index[i] >= num_eth_queues)
2355 return -EINVAL;
2356 /* 2344 /*
2357 * The same as in bnx2x_get_rxfh_indir: we can't use a memcpy() 2345 * The same as in bnx2x_get_rxfh_indir: we can't use a memcpy()
2358 * as an internal storage of an indirection table is a u8 array 2346 * as an internal storage of an indirection table is a u8 array
@@ -2362,7 +2350,7 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev,
2362 * align the received table to the Client ID of the leading RSS 2350 * align the received table to the Client ID of the leading RSS
2363 * queue 2351 * queue
2364 */ 2352 */
2365 ind_table[i] = indir->ring_index[i] + bp->fp->cl_id; 2353 ind_table[i] = indir[i] + bp->fp->cl_id;
2366 } 2354 }
2367 2355
2368 return bnx2x_config_rss_pf(bp, ind_table, false); 2356 return bnx2x_config_rss_pf(bp, ind_table, false);
@@ -2395,6 +2383,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
2395 .set_phys_id = bnx2x_set_phys_id, 2383 .set_phys_id = bnx2x_set_phys_id,
2396 .get_ethtool_stats = bnx2x_get_ethtool_stats, 2384 .get_ethtool_stats = bnx2x_get_ethtool_stats,
2397 .get_rxnfc = bnx2x_get_rxnfc, 2385 .get_rxnfc = bnx2x_get_rxnfc,
2386 .get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
2398 .get_rxfh_indir = bnx2x_get_rxfh_indir, 2387 .get_rxfh_indir = bnx2x_get_rxfh_indir,
2399 .set_rxfh_indir = bnx2x_set_rxfh_indir, 2388 .set_rxfh_indir = bnx2x_set_rxfh_indir,
2400}; 2389};