mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
bnxt_en: Add ethtool -n|-N rx-flow-hash support.
To display and modify the RSS hash. Signed-off-by: Michael Chan <michael.chan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
87da7f796d
commit
a011952a1a
@ -542,6 +542,146 @@ fltr_err:
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static u64 get_ethtool_ipv4_rss(struct bnxt *bp)
|
||||||
|
{
|
||||||
|
if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4)
|
||||||
|
return RXH_IP_SRC | RXH_IP_DST;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 get_ethtool_ipv6_rss(struct bnxt *bp)
|
||||||
|
{
|
||||||
|
if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6)
|
||||||
|
return RXH_IP_SRC | RXH_IP_DST;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bnxt_grxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd)
|
||||||
|
{
|
||||||
|
cmd->data = 0;
|
||||||
|
switch (cmd->flow_type) {
|
||||||
|
case TCP_V4_FLOW:
|
||||||
|
if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4)
|
||||||
|
cmd->data |= RXH_IP_SRC | RXH_IP_DST |
|
||||||
|
RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||||
|
cmd->data |= get_ethtool_ipv4_rss(bp);
|
||||||
|
break;
|
||||||
|
case UDP_V4_FLOW:
|
||||||
|
if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4)
|
||||||
|
cmd->data |= RXH_IP_SRC | RXH_IP_DST |
|
||||||
|
RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||||
|
/* fall through */
|
||||||
|
case SCTP_V4_FLOW:
|
||||||
|
case AH_ESP_V4_FLOW:
|
||||||
|
case AH_V4_FLOW:
|
||||||
|
case ESP_V4_FLOW:
|
||||||
|
case IPV4_FLOW:
|
||||||
|
cmd->data |= get_ethtool_ipv4_rss(bp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_V6_FLOW:
|
||||||
|
if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6)
|
||||||
|
cmd->data |= RXH_IP_SRC | RXH_IP_DST |
|
||||||
|
RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||||
|
cmd->data |= get_ethtool_ipv6_rss(bp);
|
||||||
|
break;
|
||||||
|
case UDP_V6_FLOW:
|
||||||
|
if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6)
|
||||||
|
cmd->data |= RXH_IP_SRC | RXH_IP_DST |
|
||||||
|
RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||||
|
/* fall through */
|
||||||
|
case SCTP_V6_FLOW:
|
||||||
|
case AH_ESP_V6_FLOW:
|
||||||
|
case AH_V6_FLOW:
|
||||||
|
case ESP_V6_FLOW:
|
||||||
|
case IPV6_FLOW:
|
||||||
|
cmd->data |= get_ethtool_ipv6_rss(bp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RXH_4TUPLE (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)
|
||||||
|
#define RXH_2TUPLE (RXH_IP_SRC | RXH_IP_DST)
|
||||||
|
|
||||||
|
static int bnxt_srxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd)
|
||||||
|
{
|
||||||
|
u32 rss_hash_cfg = bp->rss_hash_cfg;
|
||||||
|
int tuple, rc = 0;
|
||||||
|
|
||||||
|
if (cmd->data == RXH_4TUPLE)
|
||||||
|
tuple = 4;
|
||||||
|
else if (cmd->data == RXH_2TUPLE)
|
||||||
|
tuple = 2;
|
||||||
|
else if (!cmd->data)
|
||||||
|
tuple = 0;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (cmd->flow_type == TCP_V4_FLOW) {
|
||||||
|
rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4;
|
||||||
|
if (tuple == 4)
|
||||||
|
rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4;
|
||||||
|
} else if (cmd->flow_type == UDP_V4_FLOW) {
|
||||||
|
if (tuple == 4 && !(bp->flags & BNXT_FLAG_UDP_RSS_CAP))
|
||||||
|
return -EINVAL;
|
||||||
|
rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4;
|
||||||
|
if (tuple == 4)
|
||||||
|
rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4;
|
||||||
|
} else if (cmd->flow_type == TCP_V6_FLOW) {
|
||||||
|
rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
|
||||||
|
if (tuple == 4)
|
||||||
|
rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
|
||||||
|
} else if (cmd->flow_type == UDP_V6_FLOW) {
|
||||||
|
if (tuple == 4 && !(bp->flags & BNXT_FLAG_UDP_RSS_CAP))
|
||||||
|
return -EINVAL;
|
||||||
|
rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
|
||||||
|
if (tuple == 4)
|
||||||
|
rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
|
||||||
|
} else if (tuple == 4) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cmd->flow_type) {
|
||||||
|
case TCP_V4_FLOW:
|
||||||
|
case UDP_V4_FLOW:
|
||||||
|
case SCTP_V4_FLOW:
|
||||||
|
case AH_ESP_V4_FLOW:
|
||||||
|
case AH_V4_FLOW:
|
||||||
|
case ESP_V4_FLOW:
|
||||||
|
case IPV4_FLOW:
|
||||||
|
if (tuple == 2)
|
||||||
|
rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4;
|
||||||
|
else if (!tuple)
|
||||||
|
rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_V6_FLOW:
|
||||||
|
case UDP_V6_FLOW:
|
||||||
|
case SCTP_V6_FLOW:
|
||||||
|
case AH_ESP_V6_FLOW:
|
||||||
|
case AH_V6_FLOW:
|
||||||
|
case ESP_V6_FLOW:
|
||||||
|
case IPV6_FLOW:
|
||||||
|
if (tuple == 2)
|
||||||
|
rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6;
|
||||||
|
else if (!tuple)
|
||||||
|
rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bp->rss_hash_cfg == rss_hash_cfg)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bp->rss_hash_cfg = rss_hash_cfg;
|
||||||
|
if (netif_running(bp->dev)) {
|
||||||
|
bnxt_close_nic(bp, false, false);
|
||||||
|
rc = bnxt_open_nic(bp, false, false);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
||||||
u32 *rule_locs)
|
u32 *rule_locs)
|
||||||
@ -550,6 +690,7 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
switch (cmd->cmd) {
|
switch (cmd->cmd) {
|
||||||
|
#ifdef CONFIG_RFS_ACCEL
|
||||||
case ETHTOOL_GRXRINGS:
|
case ETHTOOL_GRXRINGS:
|
||||||
cmd->data = bp->rx_nr_rings;
|
cmd->data = bp->rx_nr_rings;
|
||||||
break;
|
break;
|
||||||
@ -566,6 +707,11 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
|||||||
case ETHTOOL_GRXCLSRULE:
|
case ETHTOOL_GRXCLSRULE:
|
||||||
rc = bnxt_grxclsrule(bp, cmd);
|
rc = bnxt_grxclsrule(bp, cmd);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case ETHTOOL_GRXFH:
|
||||||
|
rc = bnxt_grxfh(bp, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
@ -574,7 +720,23 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
static int bnxt_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
|
||||||
|
{
|
||||||
|
struct bnxt *bp = netdev_priv(dev);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
switch (cmd->cmd) {
|
||||||
|
case ETHTOOL_SRXFH:
|
||||||
|
rc = bnxt_srxfh(bp, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static u32 bnxt_get_rxfh_indir_size(struct net_device *dev)
|
static u32 bnxt_get_rxfh_indir_size(struct net_device *dev)
|
||||||
{
|
{
|
||||||
@ -1885,9 +2047,8 @@ const struct ethtool_ops bnxt_ethtool_ops = {
|
|||||||
.get_ringparam = bnxt_get_ringparam,
|
.get_ringparam = bnxt_get_ringparam,
|
||||||
.get_channels = bnxt_get_channels,
|
.get_channels = bnxt_get_channels,
|
||||||
.set_channels = bnxt_set_channels,
|
.set_channels = bnxt_set_channels,
|
||||||
#ifdef CONFIG_RFS_ACCEL
|
|
||||||
.get_rxnfc = bnxt_get_rxnfc,
|
.get_rxnfc = bnxt_get_rxnfc,
|
||||||
#endif
|
.set_rxnfc = bnxt_set_rxnfc,
|
||||||
.get_rxfh_indir_size = bnxt_get_rxfh_indir_size,
|
.get_rxfh_indir_size = bnxt_get_rxfh_indir_size,
|
||||||
.get_rxfh_key_size = bnxt_get_rxfh_key_size,
|
.get_rxfh_key_size = bnxt_get_rxfh_key_size,
|
||||||
.get_rxfh = bnxt_get_rxfh,
|
.get_rxfh = bnxt_get_rxfh,
|
||||||
|
Loading…
Reference in New Issue
Block a user