提交 5d317c6a 编写于 作者: M Merav Sicron 提交者: David S. Miller

bnx2x: Add support for 4-tupple UDP RSS

This change enables to control via ethtool whether to do UDP RSS on 2-tupple
(IP source / destination only) or on 4-tupple (include UDP source / destination
port). It also enables to read back the RSS configuration.
Signed-off-by: NMerav Sicron <meravs@broadcom.com>
Signed-off-by: NEilon Greenstein <eilong@broadcom.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 cf2c1df6
...@@ -1666,14 +1666,13 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp) ...@@ -1666,14 +1666,13 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
static int bnx2x_init_rss_pf(struct bnx2x *bp) static int bnx2x_init_rss_pf(struct bnx2x *bp)
{ {
int i; int i;
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp); u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
/* Prepare the initial contents fo the indirection table if RSS is /* Prepare the initial contents fo the indirection table if RSS is
* enabled * enabled
*/ */
for (i = 0; i < sizeof(ind_table); i++) for (i = 0; i < sizeof(bp->rss_conf_obj.ind_table); i++)
ind_table[i] = bp->rss_conf_obj.ind_table[i] =
bp->fp->cl_id + bp->fp->cl_id +
ethtool_rxfh_indir_default(i, num_eth_queues); ethtool_rxfh_indir_default(i, num_eth_queues);
...@@ -1685,12 +1684,11 @@ static int bnx2x_init_rss_pf(struct bnx2x *bp) ...@@ -1685,12 +1684,11 @@ static int bnx2x_init_rss_pf(struct bnx2x *bp)
* For 57712 and newer on the other hand it's a per-function * For 57712 and newer on the other hand it's a per-function
* configuration. * configuration.
*/ */
return bnx2x_config_rss_eth(bp, ind_table, return bnx2x_config_rss_eth(bp, bp->port.pmf || !CHIP_IS_E1x(bp));
bp->port.pmf || !CHIP_IS_E1x(bp));
} }
int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
u8 *ind_table, bool config_hash) bool config_hash)
{ {
struct bnx2x_config_rss_params params = {NULL}; struct bnx2x_config_rss_params params = {NULL};
int i; int i;
...@@ -1713,11 +1711,15 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, ...@@ -1713,11 +1711,15 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
__set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags); __set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags);
__set_bit(BNX2X_RSS_IPV6, &params.rss_flags); __set_bit(BNX2X_RSS_IPV6, &params.rss_flags);
__set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags); __set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags);
if (rss_obj->udp_rss_v4)
__set_bit(BNX2X_RSS_IPV4_UDP, &params.rss_flags);
if (rss_obj->udp_rss_v6)
__set_bit(BNX2X_RSS_IPV6_UDP, &params.rss_flags);
/* Hash bits */ /* Hash bits */
params.rss_result_mask = MULTI_MASK; params.rss_result_mask = MULTI_MASK;
memcpy(params.ind_table, ind_table, sizeof(params.ind_table)); memcpy(params.ind_table, rss_obj->ind_table, sizeof(params.ind_table));
if (config_hash) { if (config_hash) {
/* RSS keys */ /* RSS keys */
......
...@@ -94,7 +94,7 @@ void bnx2x_send_unload_done(struct bnx2x *bp); ...@@ -94,7 +94,7 @@ void bnx2x_send_unload_done(struct bnx2x *bp);
* @config_hash: re-configure RSS hash keys configuration * @config_hash: re-configure RSS hash keys configuration
*/ */
int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
u8 *ind_table, bool config_hash); bool config_hash);
/** /**
* bnx2x__init_func_obj - init function object * bnx2x__init_func_obj - init function object
...@@ -865,11 +865,9 @@ static inline int func_by_vn(struct bnx2x *bp, int vn) ...@@ -865,11 +865,9 @@ static inline int func_by_vn(struct bnx2x *bp, int vn)
return 2 * vn + BP_PORT(bp); return 2 * vn + BP_PORT(bp);
} }
static inline int bnx2x_config_rss_eth(struct bnx2x *bp, u8 *ind_table, static inline int bnx2x_config_rss_eth(struct bnx2x *bp, bool config_hash)
bool config_hash)
{ {
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, ind_table, return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, config_hash);
config_hash);
} }
/** /**
......
...@@ -2600,6 +2600,41 @@ static int bnx2x_set_phys_id(struct net_device *dev, ...@@ -2600,6 +2600,41 @@ static int bnx2x_set_phys_id(struct net_device *dev,
return 0; return 0;
} }
static int bnx2x_get_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
{
switch (info->flow_type) {
case TCP_V4_FLOW:
case TCP_V6_FLOW:
info->data = RXH_IP_SRC | RXH_IP_DST |
RXH_L4_B_0_1 | RXH_L4_B_2_3;
break;
case UDP_V4_FLOW:
if (bp->rss_conf_obj.udp_rss_v4)
info->data = RXH_IP_SRC | RXH_IP_DST |
RXH_L4_B_0_1 | RXH_L4_B_2_3;
else
info->data = RXH_IP_SRC | RXH_IP_DST;
break;
case UDP_V6_FLOW:
if (bp->rss_conf_obj.udp_rss_v6)
info->data = RXH_IP_SRC | RXH_IP_DST |
RXH_L4_B_0_1 | RXH_L4_B_2_3;
else
info->data = RXH_IP_SRC | RXH_IP_DST;
break;
case IPV4_FLOW:
case IPV6_FLOW:
info->data = RXH_IP_SRC | RXH_IP_DST;
break;
default:
info->data = 0;
break;
}
return 0;
}
static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
u32 *rules __always_unused) u32 *rules __always_unused)
{ {
...@@ -2609,7 +2644,102 @@ static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, ...@@ -2609,7 +2644,102 @@ static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
case ETHTOOL_GRXRINGS: case ETHTOOL_GRXRINGS:
info->data = BNX2X_NUM_ETH_QUEUES(bp); info->data = BNX2X_NUM_ETH_QUEUES(bp);
return 0; return 0;
case ETHTOOL_GRXFH:
return bnx2x_get_rss_flags(bp, info);
default:
DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n");
return -EOPNOTSUPP;
}
}
static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
{
int udp_rss_requested;
DP(BNX2X_MSG_ETHTOOL,
"Set rss flags command parameters: flow type = %d, data = %llu\n",
info->flow_type, info->data);
switch (info->flow_type) {
case TCP_V4_FLOW:
case TCP_V6_FLOW:
/* For TCP only 4-tupple hash is supported */
if (info->data ^ (RXH_IP_SRC | RXH_IP_DST |
RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
DP(BNX2X_MSG_ETHTOOL,
"Command parameters not supported\n");
return -EINVAL;
} else {
return 0;
}
case UDP_V4_FLOW:
case UDP_V6_FLOW:
/* For UDP either 2-tupple hash or 4-tupple hash is supported */
if (info->data == (RXH_IP_SRC | RXH_IP_DST |
RXH_L4_B_0_1 | RXH_L4_B_2_3))
udp_rss_requested = 1;
else if (info->data == (RXH_IP_SRC | RXH_IP_DST))
udp_rss_requested = 0;
else
return -EINVAL;
if ((info->flow_type == UDP_V4_FLOW) &&
(bp->rss_conf_obj.udp_rss_v4 != udp_rss_requested)) {
bp->rss_conf_obj.udp_rss_v4 = udp_rss_requested;
DP(BNX2X_MSG_ETHTOOL,
"rss re-configured, UDP 4-tupple %s\n",
udp_rss_requested ? "enabled" : "disabled");
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
} else if ((info->flow_type == UDP_V6_FLOW) &&
(bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) {
bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested;
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
DP(BNX2X_MSG_ETHTOOL,
"rss re-configured, UDP 4-tupple %s\n",
udp_rss_requested ? "enabled" : "disabled");
} else {
return 0;
}
case IPV4_FLOW:
case IPV6_FLOW:
/* For IP only 2-tupple hash is supported */
if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) {
DP(BNX2X_MSG_ETHTOOL,
"Command parameters not supported\n");
return -EINVAL;
} else {
return 0;
}
case SCTP_V4_FLOW:
case AH_ESP_V4_FLOW:
case AH_V4_FLOW:
case ESP_V4_FLOW:
case SCTP_V6_FLOW:
case AH_ESP_V6_FLOW:
case AH_V6_FLOW:
case ESP_V6_FLOW:
case IP_USER_FLOW:
case ETHER_FLOW:
/* RSS is not supported for these protocols */
if (info->data) {
DP(BNX2X_MSG_ETHTOOL,
"Command parameters not supported\n");
return -EINVAL;
} else {
return 0;
}
default:
return -EINVAL;
}
}
static int bnx2x_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
{
struct bnx2x *bp = netdev_priv(dev);
switch (info->cmd) {
case ETHTOOL_SRXFH:
return bnx2x_set_rss_flags(bp, info);
default: default:
DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n"); DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n");
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -2649,7 +2779,6 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir) ...@@ -2649,7 +2779,6 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir)
{ {
struct bnx2x *bp = netdev_priv(dev); struct bnx2x *bp = netdev_priv(dev);
size_t i; size_t i;
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) { for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
/* /*
...@@ -2661,10 +2790,10 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir) ...@@ -2661,10 +2790,10 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir)
* align the received table to the Client ID of the leading RSS * align the received table to the Client ID of the leading RSS
* queue * queue
*/ */
ind_table[i] = indir[i] + bp->fp->cl_id; bp->rss_conf_obj.ind_table[i] = indir[i] + bp->fp->cl_id;
} }
return bnx2x_config_rss_eth(bp, ind_table, false); return bnx2x_config_rss_eth(bp, false);
} }
static const struct ethtool_ops bnx2x_ethtool_ops = { static const struct ethtool_ops bnx2x_ethtool_ops = {
...@@ -2694,6 +2823,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = { ...@@ -2694,6 +2823,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
.set_phys_id = bnx2x_set_phys_id, .set_phys_id = bnx2x_set_phys_id,
.get_ethtool_stats = bnx2x_get_ethtool_stats, .get_ethtool_stats = bnx2x_get_ethtool_stats,
.get_rxnfc = bnx2x_get_rxnfc, .get_rxnfc = bnx2x_get_rxnfc,
.set_rxnfc = bnx2x_set_rxnfc,
.get_rxfh_indir_size = bnx2x_get_rxfh_indir_size, .get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
.get_rxfh_indir = bnx2x_get_rxfh_indir, .get_rxfh_indir = bnx2x_get_rxfh_indir,
.set_rxfh_indir = bnx2x_set_rxfh_indir, .set_rxfh_indir = bnx2x_set_rxfh_indir,
......
...@@ -4107,6 +4107,10 @@ static int bnx2x_setup_rss(struct bnx2x *bp, ...@@ -4107,6 +4107,10 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
data->capabilities |= data->capabilities |=
ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY; ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
if (test_bit(BNX2X_RSS_IPV4_UDP, &p->rss_flags))
data->capabilities |=
ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY;
if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags)) if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags))
data->capabilities |= data->capabilities |=
ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY; ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
...@@ -4115,6 +4119,10 @@ static int bnx2x_setup_rss(struct bnx2x *bp, ...@@ -4115,6 +4119,10 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
data->capabilities |= data->capabilities |=
ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY; ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
if (test_bit(BNX2X_RSS_IPV6_UDP, &p->rss_flags))
data->capabilities |=
ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY;
/* Hashing mask */ /* Hashing mask */
data->rss_result_mask = p->rss_result_mask; data->rss_result_mask = p->rss_result_mask;
......
...@@ -694,8 +694,10 @@ enum { ...@@ -694,8 +694,10 @@ enum {
BNX2X_RSS_IPV4, BNX2X_RSS_IPV4,
BNX2X_RSS_IPV4_TCP, BNX2X_RSS_IPV4_TCP,
BNX2X_RSS_IPV4_UDP,
BNX2X_RSS_IPV6, BNX2X_RSS_IPV6,
BNX2X_RSS_IPV6_TCP, BNX2X_RSS_IPV6_TCP,
BNX2X_RSS_IPV6_UDP,
}; };
struct bnx2x_config_rss_params { struct bnx2x_config_rss_params {
...@@ -729,6 +731,10 @@ struct bnx2x_rss_config_obj { ...@@ -729,6 +731,10 @@ struct bnx2x_rss_config_obj {
/* Last configured indirection table */ /* Last configured indirection table */
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE]; u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
/* flags for enabling 4-tupple hash on UDP */
u8 udp_rss_v4;
u8 udp_rss_v6;
int (*config_rss)(struct bnx2x *bp, int (*config_rss)(struct bnx2x *bp,
struct bnx2x_config_rss_params *p); struct bnx2x_config_rss_params *p);
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册