diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2011-12-15 08:55:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-16 13:52:47 -0500 |
commit | 7850f63f1620512631445b901ae11cd149e7375c (patch) | |
tree | d26a5f049dcf3634c4bf9e1b86915d201fab3836 /drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | |
parent | 14596f7006297b67516e2b6a2b26bcb11fe08fb3 (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.c | 39 |
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 | ||
2305 | static int bnx2x_get_rxfh_indir(struct net_device *dev, | 2305 | static 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 | |||
2313 | static 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 | ||
2337 | static int bnx2x_set_rxfh_indir(struct net_device *dev, | 2337 | static 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 | }; |