|
@@ -542,6 +542,146 @@ fltr_err:
|
|
|
|
|
|
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,
|
|
|
u32 *rule_locs)
|
|
@@ -550,6 +690,7 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
|
|
int rc = 0;
|
|
|
|
|
|
switch (cmd->cmd) {
|
|
|
+#ifdef CONFIG_RFS_ACCEL
|
|
|
case ETHTOOL_GRXRINGS:
|
|
|
cmd->data = bp->rx_nr_rings;
|
|
|
break;
|
|
@@ -566,6 +707,11 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
|
|
case ETHTOOL_GRXCLSRULE:
|
|
|
rc = bnxt_grxclsrule(bp, cmd);
|
|
|
break;
|
|
|
+#endif
|
|
|
+
|
|
|
+ case ETHTOOL_GRXFH:
|
|
|
+ rc = bnxt_grxfh(bp, cmd);
|
|
|
+ break;
|
|
|
|
|
|
default:
|
|
|
rc = -EOPNOTSUPP;
|
|
@@ -574,7 +720,23 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
|
|
|
|
|
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)
|
|
|
{
|
|
@@ -1885,9 +2047,8 @@ const struct ethtool_ops bnxt_ethtool_ops = {
|
|
|
.get_ringparam = bnxt_get_ringparam,
|
|
|
.get_channels = bnxt_get_channels,
|
|
|
.set_channels = bnxt_set_channels,
|
|
|
-#ifdef CONFIG_RFS_ACCEL
|
|
|
.get_rxnfc = bnxt_get_rxnfc,
|
|
|
-#endif
|
|
|
+ .set_rxnfc = bnxt_set_rxnfc,
|
|
|
.get_rxfh_indir_size = bnxt_get_rxfh_indir_size,
|
|
|
.get_rxfh_key_size = bnxt_get_rxfh_key_size,
|
|
|
.get_rxfh = bnxt_get_rxfh,
|