|
@@ -399,6 +399,117 @@ static void dpaa_get_strings(struct net_device *net_dev, u32 stringset,
|
|
|
memcpy(strings, dpaa_stats_global, size);
|
|
|
}
|
|
|
|
|
|
+static int dpaa_get_hash_opts(struct net_device *dev,
|
|
|
+ struct ethtool_rxnfc *cmd)
|
|
|
+{
|
|
|
+ cmd->data = 0;
|
|
|
+
|
|
|
+ switch (cmd->flow_type) {
|
|
|
+ case TCP_V4_FLOW:
|
|
|
+ case TCP_V6_FLOW:
|
|
|
+ case UDP_V4_FLOW:
|
|
|
+ case UDP_V6_FLOW:
|
|
|
+ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
|
|
+ /* Fall through */
|
|
|
+ case IPV4_FLOW:
|
|
|
+ case IPV6_FLOW:
|
|
|
+ case SCTP_V4_FLOW:
|
|
|
+ case SCTP_V6_FLOW:
|
|
|
+ case AH_ESP_V4_FLOW:
|
|
|
+ case AH_ESP_V6_FLOW:
|
|
|
+ case AH_V4_FLOW:
|
|
|
+ case AH_V6_FLOW:
|
|
|
+ case ESP_V4_FLOW:
|
|
|
+ case ESP_V6_FLOW:
|
|
|
+ cmd->data |= RXH_IP_SRC | RXH_IP_DST;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ cmd->data = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int dpaa_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
|
|
+ u32 *unused)
|
|
|
+{
|
|
|
+ int ret = -EOPNOTSUPP;
|
|
|
+
|
|
|
+ switch (cmd->cmd) {
|
|
|
+ case ETHTOOL_GRXFH:
|
|
|
+ ret = dpaa_get_hash_opts(dev, cmd);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void dpaa_set_hash(struct net_device *net_dev, bool enable)
|
|
|
+{
|
|
|
+ struct mac_device *mac_dev;
|
|
|
+ struct fman_port *rxport;
|
|
|
+ struct dpaa_priv *priv;
|
|
|
+
|
|
|
+ priv = netdev_priv(net_dev);
|
|
|
+ mac_dev = priv->mac_dev;
|
|
|
+ rxport = mac_dev->port[0];
|
|
|
+
|
|
|
+ fman_port_use_kg_hash(rxport, enable);
|
|
|
+}
|
|
|
+
|
|
|
+static int dpaa_set_hash_opts(struct net_device *dev,
|
|
|
+ struct ethtool_rxnfc *nfc)
|
|
|
+{
|
|
|
+ int ret = -EINVAL;
|
|
|
+
|
|
|
+ /* we support hashing on IPv4/v6 src/dest IP and L4 src/dest port */
|
|
|
+ if (nfc->data &
|
|
|
+ ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ switch (nfc->flow_type) {
|
|
|
+ case TCP_V4_FLOW:
|
|
|
+ case TCP_V6_FLOW:
|
|
|
+ case UDP_V4_FLOW:
|
|
|
+ case UDP_V6_FLOW:
|
|
|
+ case IPV4_FLOW:
|
|
|
+ case IPV6_FLOW:
|
|
|
+ case SCTP_V4_FLOW:
|
|
|
+ case SCTP_V6_FLOW:
|
|
|
+ case AH_ESP_V4_FLOW:
|
|
|
+ case AH_ESP_V6_FLOW:
|
|
|
+ case AH_V4_FLOW:
|
|
|
+ case AH_V6_FLOW:
|
|
|
+ case ESP_V4_FLOW:
|
|
|
+ case ESP_V6_FLOW:
|
|
|
+ dpaa_set_hash(dev, !!nfc->data);
|
|
|
+ ret = 0;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
|
|
|
+{
|
|
|
+ int ret = -EOPNOTSUPP;
|
|
|
+
|
|
|
+ switch (cmd->cmd) {
|
|
|
+ case ETHTOOL_SRXFH:
|
|
|
+ ret = dpaa_set_hash_opts(dev, cmd);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
const struct ethtool_ops dpaa_ethtool_ops = {
|
|
|
.get_drvinfo = dpaa_get_drvinfo,
|
|
|
.get_msglevel = dpaa_get_msglevel,
|
|
@@ -412,4 +523,6 @@ const struct ethtool_ops dpaa_ethtool_ops = {
|
|
|
.get_strings = dpaa_get_strings,
|
|
|
.get_link_ksettings = dpaa_get_link_ksettings,
|
|
|
.set_link_ksettings = dpaa_set_link_ksettings,
|
|
|
+ .get_rxnfc = dpaa_get_rxnfc,
|
|
|
+ .set_rxnfc = dpaa_set_rxnfc,
|
|
|
};
|