diff options
author | Yevgeny Petrilin <yevgenyp@mellanox.co.il> | 2012-01-17 17:54:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-01-18 16:07:34 -0500 |
commit | 93d3e3678f23109363cd6f99f2944d2cda616b23 (patch) | |
tree | bb03e8801b25f03d3e658e9dc3108101f7e94fc1 /drivers/net/ethernet/mellanox | |
parent | d00a9dd21bdf7908b70866794c8313ee8a5abd5c (diff) |
mlx4_en: set number of rx rings used by RSS using ethtool
Value must be a power of 2 due to HW limitation.
Driver supports only 'equal' mode in ethtool and can't be set by using weights.
Signed-off-by: Amir Vadai <amirv@mellanox.co.il>
Reviewed-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 93 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_main.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_rx.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 2 |
4 files changed, 102 insertions, 7 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 7dbc6a230779..53c66869aecd 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | |||
@@ -479,6 +479,95 @@ static void mlx4_en_get_ringparam(struct net_device *dev, | |||
479 | param->tx_pending = priv->tx_ring[0].size; | 479 | param->tx_pending = priv->tx_ring[0].size; |
480 | } | 480 | } |
481 | 481 | ||
482 | static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev) | ||
483 | { | ||
484 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
485 | |||
486 | return priv->rx_ring_num; | ||
487 | } | ||
488 | |||
489 | static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index) | ||
490 | { | ||
491 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
492 | struct mlx4_en_rss_map *rss_map = &priv->rss_map; | ||
493 | int rss_rings; | ||
494 | size_t n = priv->rx_ring_num; | ||
495 | int err = 0; | ||
496 | |||
497 | rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num; | ||
498 | |||
499 | while (n--) { | ||
500 | ring_index[n] = rss_map->qps[n % rss_rings].qpn - | ||
501 | rss_map->base_qpn; | ||
502 | } | ||
503 | |||
504 | return err; | ||
505 | } | ||
506 | |||
507 | static int mlx4_en_set_rxfh_indir(struct net_device *dev, | ||
508 | const u32 *ring_index) | ||
509 | { | ||
510 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
511 | struct mlx4_en_dev *mdev = priv->mdev; | ||
512 | int port_up = 0; | ||
513 | int err = 0; | ||
514 | int i; | ||
515 | int rss_rings = 0; | ||
516 | |||
517 | /* Calculate RSS table size and make sure flows are spread evenly | ||
518 | * between rings | ||
519 | */ | ||
520 | for (i = 0; i < priv->rx_ring_num; i++) { | ||
521 | if (i > 0 && !ring_index[i] && !rss_rings) | ||
522 | rss_rings = i; | ||
523 | |||
524 | if (ring_index[i] != (i % (rss_rings ?: priv->rx_ring_num))) | ||
525 | return -EINVAL; | ||
526 | } | ||
527 | |||
528 | if (!rss_rings) | ||
529 | rss_rings = priv->rx_ring_num; | ||
530 | |||
531 | /* RSS table size must be an order of 2 */ | ||
532 | if (!is_power_of_2(rss_rings)) | ||
533 | return -EINVAL; | ||
534 | |||
535 | mutex_lock(&mdev->state_lock); | ||
536 | if (priv->port_up) { | ||
537 | port_up = 1; | ||
538 | mlx4_en_stop_port(dev); | ||
539 | } | ||
540 | |||
541 | priv->prof->rss_rings = rss_rings; | ||
542 | |||
543 | if (port_up) { | ||
544 | err = mlx4_en_start_port(dev); | ||
545 | if (err) | ||
546 | en_err(priv, "Failed starting port\n"); | ||
547 | } | ||
548 | |||
549 | mutex_unlock(&mdev->state_lock); | ||
550 | return err; | ||
551 | } | ||
552 | |||
553 | static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, | ||
554 | u32 *rule_locs) | ||
555 | { | ||
556 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
557 | int err = 0; | ||
558 | |||
559 | switch (cmd->cmd) { | ||
560 | case ETHTOOL_GRXRINGS: | ||
561 | cmd->data = priv->rx_ring_num; | ||
562 | break; | ||
563 | default: | ||
564 | err = -EOPNOTSUPP; | ||
565 | break; | ||
566 | } | ||
567 | |||
568 | return err; | ||
569 | } | ||
570 | |||
482 | const struct ethtool_ops mlx4_en_ethtool_ops = { | 571 | const struct ethtool_ops mlx4_en_ethtool_ops = { |
483 | .get_drvinfo = mlx4_en_get_drvinfo, | 572 | .get_drvinfo = mlx4_en_get_drvinfo, |
484 | .get_settings = mlx4_en_get_settings, | 573 | .get_settings = mlx4_en_get_settings, |
@@ -498,6 +587,10 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { | |||
498 | .set_pauseparam = mlx4_en_set_pauseparam, | 587 | .set_pauseparam = mlx4_en_set_pauseparam, |
499 | .get_ringparam = mlx4_en_get_ringparam, | 588 | .get_ringparam = mlx4_en_get_ringparam, |
500 | .set_ringparam = mlx4_en_set_ringparam, | 589 | .set_ringparam = mlx4_en_set_ringparam, |
590 | .get_rxnfc = mlx4_en_get_rxnfc, | ||
591 | .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size, | ||
592 | .get_rxfh_indir = mlx4_en_get_rxfh_indir, | ||
593 | .set_rxfh_indir = mlx4_en_set_rxfh_indir, | ||
501 | }; | 594 | }; |
502 | 595 | ||
503 | 596 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index a06096fcc0b8..2097a7d3c5b8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c | |||
@@ -62,10 +62,6 @@ static const char mlx4_en_version[] = | |||
62 | * Device scope module parameters | 62 | * Device scope module parameters |
63 | */ | 63 | */ |
64 | 64 | ||
65 | |||
66 | /* Enable RSS TCP traffic */ | ||
67 | MLX4_EN_PARM_INT(tcp_rss, 1, | ||
68 | "Enable RSS for incomming TCP traffic or disabled (0)"); | ||
69 | /* Enable RSS UDP traffic */ | 65 | /* Enable RSS UDP traffic */ |
70 | MLX4_EN_PARM_INT(udp_rss, 1, | 66 | MLX4_EN_PARM_INT(udp_rss, 1, |
71 | "Enable RSS for incomming UDP traffic or disabled (0)"); | 67 | "Enable RSS for incomming UDP traffic or disabled (0)"); |
@@ -104,7 +100,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) | |||
104 | struct mlx4_en_profile *params = &mdev->profile; | 100 | struct mlx4_en_profile *params = &mdev->profile; |
105 | int i; | 101 | int i; |
106 | 102 | ||
107 | params->tcp_rss = tcp_rss; | ||
108 | params->udp_rss = udp_rss; | 103 | params->udp_rss = udp_rss; |
109 | if (params->udp_rss && !(mdev->dev->caps.flags | 104 | if (params->udp_rss && !(mdev->dev->caps.flags |
110 | & MLX4_DEV_CAP_FLAG_UDP_RSS)) { | 105 | & MLX4_DEV_CAP_FLAG_UDP_RSS)) { |
@@ -120,6 +115,7 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) | |||
120 | params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; | 115 | params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; |
121 | params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS + | 116 | params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS + |
122 | (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS; | 117 | (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS; |
118 | params->prof[i].rss_rings = 0; | ||
123 | } | 119 | } |
124 | 120 | ||
125 | return 0; | 121 | return 0; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index e8d6ad2dce0a..971d4b6b8dfe 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c | |||
@@ -853,6 +853,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) | |||
853 | struct mlx4_en_rss_map *rss_map = &priv->rss_map; | 853 | struct mlx4_en_rss_map *rss_map = &priv->rss_map; |
854 | struct mlx4_qp_context context; | 854 | struct mlx4_qp_context context; |
855 | struct mlx4_rss_context *rss_context; | 855 | struct mlx4_rss_context *rss_context; |
856 | int rss_rings; | ||
856 | void *ptr; | 857 | void *ptr; |
857 | u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 | | 858 | u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 | |
858 | MLX4_RSS_TCP_IPV6); | 859 | MLX4_RSS_TCP_IPV6); |
@@ -893,10 +894,15 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) | |||
893 | mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn, | 894 | mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn, |
894 | priv->rx_ring[0].cqn, &context); | 895 | priv->rx_ring[0].cqn, &context); |
895 | 896 | ||
897 | if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num) | ||
898 | rss_rings = priv->rx_ring_num; | ||
899 | else | ||
900 | rss_rings = priv->prof->rss_rings; | ||
901 | |||
896 | ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path) | 902 | ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path) |
897 | + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH; | 903 | + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH; |
898 | rss_context = ptr; | 904 | rss_context = ptr; |
899 | rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 | | 905 | rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 | |
900 | (rss_map->base_qpn)); | 906 | (rss_map->base_qpn)); |
901 | rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn); | 907 | rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn); |
902 | if (priv->mdev->profile.udp_rss) { | 908 | if (priv->mdev->profile.udp_rss) { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index f2a8e65f5f88..f4d189a1290e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | |||
@@ -325,11 +325,11 @@ struct mlx4_en_port_profile { | |||
325 | u8 rx_ppp; | 325 | u8 rx_ppp; |
326 | u8 tx_pause; | 326 | u8 tx_pause; |
327 | u8 tx_ppp; | 327 | u8 tx_ppp; |
328 | int rss_rings; | ||
328 | }; | 329 | }; |
329 | 330 | ||
330 | struct mlx4_en_profile { | 331 | struct mlx4_en_profile { |
331 | int rss_xor; | 332 | int rss_xor; |
332 | int tcp_rss; | ||
333 | int udp_rss; | 333 | int udp_rss; |
334 | u8 rss_mask; | 334 | u8 rss_mask; |
335 | u32 active_ports; | 335 | u32 active_ports; |