Intel-Wired-Lan Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Alan Brady <alan.brady@intel.com>
To: intel-wired-lan@osuosl.org
Subject: [Intel-wired-lan] [PATCH net-next 18/19] iecm: add advanced rss
Date: Thu, 27 Jan 2022 16:10:08 -0800	[thread overview]
Message-ID: <20220128001009.721392-19-alan.brady@intel.com> (raw)
In-Reply-To: <20220128001009.721392-1-alan.brady@intel.com>

From: Haiyue Wang <haiyue.wang@intel.com>

Continuing with advanced features this implements what's needed to do
advanced rss.

Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>
---
 drivers/net/ethernet/intel/iecm/iecm_lib.c    | 547 ++++++++++++++++++
 .../net/ethernet/intel/iecm/iecm_virtchnl.c   |  71 +++
 drivers/net/ethernet/intel/include/iecm.h     |  73 +++
 3 files changed, 691 insertions(+)

diff --git a/drivers/net/ethernet/intel/iecm/iecm_lib.c b/drivers/net/ethernet/intel/iecm/iecm_lib.c
index d11413cb438c..baa1e312652a 100644
--- a/drivers/net/ethernet/intel/iecm/iecm_lib.c
+++ b/drivers/net/ethernet/intel/iecm/iecm_lib.c
@@ -1013,6 +1013,52 @@ static void iecm_remove_vlan_filters(struct iecm_vport *vport)
 	}
 }
 
+/**
+ * iecm_remove_adv_rss_cfgs - Remove all RSS configuration
+ * @vport: vport structure
+ */
+static void iecm_remove_adv_rss_cfgs(struct iecm_vport *vport)
+{
+	struct iecm_adapter *adapter = vport->adapter;
+
+	if (!iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_ADV_RSS))
+		return;
+
+	if (!list_empty(&adapter->config_data.adv_rss_list)) {
+		struct iecm_adv_rss *rss;
+
+		spin_lock_bh(&adapter->adv_rss_list_lock);
+		list_for_each_entry(rss, &adapter->config_data.adv_rss_list,
+				    list) {
+			rss->remove = true;
+		}
+		spin_unlock_bh(&adapter->adv_rss_list_lock);
+		iecm_send_add_del_adv_rss_cfg_msg(vport, false);
+	}
+}
+
+/**
+ * iecm_del_all_adv_rss_cfgs - delete all RSS configuration
+ * @vport: vport structure
+ *
+ * This function will loop through the list of RSS configuration and deletes
+ * them.
+ **/
+static void iecm_del_all_adv_rss_cfgs(struct iecm_vport *vport)
+{
+	struct iecm_adapter *adapter = vport->adapter;
+	struct iecm_adv_rss *rss, *rss_tmp;
+
+	spin_lock_bh(&adapter->adv_rss_list_lock);
+	list_for_each_entry_safe(rss, rss_tmp,
+				 &adapter->config_data.adv_rss_list,
+				 list) {
+		list_del(&rss->list);
+		kfree(rss);
+	}
+	spin_unlock_bh(&adapter->adv_rss_list_lock);
+}
+
 /**
  * iecm_remove_fdir_filters - Remove all Flow Director filters
  * @vport: vport structure
@@ -1099,6 +1145,7 @@ static void iecm_vport_stop(struct iecm_vport *vport)
 		iecm_remove_vlan_filters(vport);
 	}
 
+	iecm_remove_adv_rss_cfgs(vport);
 	iecm_remove_fdir_filters(vport);
 
 	adapter->link_up = false;
@@ -1332,6 +1379,27 @@ static void iecm_restore_cloud_filters(struct iecm_vport *vport)
 	}
 }
 
+/**
+ * iecm_restore_adv_rss_cfgs - Restore all RSS configuration
+ * @vport: vport structure
+ */
+static void iecm_restore_adv_rss_cfgs(struct iecm_vport *vport)
+{
+	struct iecm_adapter *adapter = vport->adapter;
+
+	if (!list_empty(&adapter->config_data.adv_rss_list)) {
+		struct iecm_adv_rss *rss;
+
+		spin_lock_bh(&adapter->adv_rss_list_lock);
+		list_for_each_entry(rss, &adapter->config_data.adv_rss_list,
+				    list) {
+			rss->add = true;
+		}
+		spin_unlock_bh(&adapter->adv_rss_list_lock);
+		iecm_send_add_del_adv_rss_cfg_msg(vport, true);
+	}
+}
+
 /**
  * iecm_restore_fdir_filters - Restore all Flow Director filters
  * @vport: vport structure
@@ -1380,6 +1448,9 @@ static void iecm_restore_features(struct iecm_vport *vport)
 	if (iecm_is_feature_ena(vport, NETIF_F_HW_TC))
 		iecm_restore_cloud_filters(vport);
 
+	if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_ADV_RSS))
+		iecm_restore_adv_rss_cfgs(vport);
+
 	if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_FDIR))
 		iecm_restore_fdir_filters(vport);
 }
@@ -2219,6 +2290,7 @@ static void iecm_del_user_cfg_data(struct iecm_adapter *adapter)
 		if (!adapter->vports[i])
 			continue;
 
+		iecm_del_all_adv_rss_cfgs(adapter->vports[i]);
 		iecm_del_all_fdir_filters(adapter->vports[i]);
 	}
 }
@@ -3633,6 +3705,481 @@ static int iecm_setup_tc(struct net_device *netdev, enum tc_setup_type type,
 	return err;
 }
 
+/**
+ * iecm_fill_adv_rss_ip4_hdr - fill the IPv4 RSS protocol header
+ * @hdr: the virtchnl message protocol header data structure
+ * @hash_flds: the RSS configuration protocol hash fields
+ */
+static void
+iecm_fill_adv_rss_ip4_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
+{
+	VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV4);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_IPV4_SA)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, SRC);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_IPV4_DA)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST);
+}
+
+/**
+ * iecm_fill_adv_rss_ip6_hdr - fill the IPv6 RSS protocol header
+ * @hdr: the virtchnl message protocol header data structure
+ * @hash_flds: the RSS configuration protocol hash fields
+ */
+static void
+iecm_fill_adv_rss_ip6_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
+{
+	VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV6);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_IPV6_SA)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, SRC);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_IPV6_DA)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST);
+}
+
+/**
+ * iecm_fill_adv_rss_tcp_hdr - fill the TCP RSS protocol header
+ * @hdr: the virtchnl message protocol header data structure
+ * @hash_flds: the RSS configuration protocol hash fields
+ */
+static void
+iecm_fill_adv_rss_tcp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
+{
+	VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, TCP);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_TCP_SRC_PORT)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, SRC_PORT);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_TCP_DST_PORT)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, DST_PORT);
+}
+
+/**
+ * iecm_fill_adv_rss_udp_hdr - fill the UDP RSS protocol header
+ * @hdr: the virtchnl message protocol header data structure
+ * @hash_flds: the RSS configuration protocol hash fields
+ */
+static void
+iecm_fill_adv_rss_udp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
+{
+	VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, UDP);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_UDP_SRC_PORT)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, SRC_PORT);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_UDP_DST_PORT)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, DST_PORT);
+}
+
+/**
+ * iecm_fill_adv_rss_sctp_hdr - fill the SCTP RSS protocol header
+ * @hdr: the virtchnl message protocol header data structure
+ * @hash_flds: the RSS configuration protocol hash fields
+ */
+static void
+iecm_fill_adv_rss_sctp_hdr(struct virtchnl_proto_hdr *hdr, s64 hash_flds)
+{
+	VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, SCTP);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_SCTP_SRC_PORT)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, SRC_PORT);
+
+	if (hash_flds & IECM_ADV_RSS_HASH_FLD_SCTP_DST_PORT)
+		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, DST_PORT);
+}
+
+/**
+ * iecm_fill_adv_rss_cfg_msg - fill the RSS configuration into virtchnl message
+ * @rss_cfg: the virtchnl message to be filled with RSS configuration setting
+ * @packet_hdrs: the RSS configuration protocol header types
+ * @hash_flds: the RSS configuration protocol hash fields
+ *
+ * Returns 0 if the RSS configuration virtchnl message is filled successfully
+ */
+static int
+iecm_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
+			  u32 packet_hdrs, u64 hash_flds)
+{
+	struct virtchnl_proto_hdrs *proto_hdrs = &rss_cfg->proto_hdrs;
+	struct virtchnl_proto_hdr *hdr;
+
+	rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
+
+	proto_hdrs->tunnel_level = 0;	/* always outer layer */
+
+	hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
+	switch (packet_hdrs & IECM_ADV_RSS_FLOW_SEG_HDR_L3) {
+	case IECM_ADV_RSS_FLOW_SEG_HDR_IPV4:
+		iecm_fill_adv_rss_ip4_hdr(hdr, hash_flds);
+		break;
+	case IECM_ADV_RSS_FLOW_SEG_HDR_IPV6:
+		iecm_fill_adv_rss_ip6_hdr(hdr, hash_flds);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
+	switch (packet_hdrs & IECM_ADV_RSS_FLOW_SEG_HDR_L4) {
+	case IECM_ADV_RSS_FLOW_SEG_HDR_TCP:
+		iecm_fill_adv_rss_tcp_hdr(hdr, hash_flds);
+		break;
+	case IECM_ADV_RSS_FLOW_SEG_HDR_UDP:
+		iecm_fill_adv_rss_udp_hdr(hdr, hash_flds);
+		break;
+	case IECM_ADV_RSS_FLOW_SEG_HDR_SCTP:
+		iecm_fill_adv_rss_sctp_hdr(hdr, hash_flds);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * iecm_find_adv_rss_cfg_by_hdrs - find RSS configuration with header type
+ * @vport: vport structure
+ * @packet_hdrs: protocol header type to find.
+ *
+ * Returns pointer to advance RSS configuration if found or null
+ */
+static struct iecm_adv_rss *
+iecm_find_adv_rss_cfg_by_hdrs(struct iecm_vport *vport, u32 packet_hdrs)
+{
+	struct iecm_adapter *adapter = vport->adapter;
+	struct iecm_adv_rss *rss;
+
+	list_for_each_entry(rss, &adapter->config_data.adv_rss_list, list)
+		if (rss->packet_hdrs == packet_hdrs)
+			return rss;
+
+	return NULL;
+}
+
+/**
+ * iecm_dump_adv_rss_cfg_info
+ * @vport: vport structure
+ * @packet_hdrs: The protocol headers for RSS configuration
+ * @hash_flds: The protocol hash fields for RSS configuration
+ * @prefix: the prefix string description to dump the RSS
+ * @postfix: the postfix string description to dump the RSS
+ *
+ * Dump the advance RSS configuration
+ **/
+static void
+iecm_dump_adv_rss_cfg_info(struct iecm_vport *vport,
+			   u32 packet_hdrs, u64 hash_flds,
+			   const char *prefix, const char *postfix)
+{
+	static char hash_opt[300];
+	const char *proto;
+
+	if (packet_hdrs & IECM_ADV_RSS_FLOW_SEG_HDR_TCP)
+		proto = "TCP";
+	else if (packet_hdrs & IECM_ADV_RSS_FLOW_SEG_HDR_UDP)
+		proto = "UDP";
+	else if (packet_hdrs & IECM_ADV_RSS_FLOW_SEG_HDR_SCTP)
+		proto = "SCTP";
+	else
+		return;
+
+	memset(hash_opt, 0, sizeof(hash_opt));
+
+	strcat(hash_opt, proto);
+	if (packet_hdrs & IECM_ADV_RSS_FLOW_SEG_HDR_IPV4)
+		strcat(hash_opt, "v4 ");
+	else
+		strcat(hash_opt, "v6 ");
+
+	if (hash_flds & (IECM_ADV_RSS_HASH_FLD_IPV4_SA |
+			 IECM_ADV_RSS_HASH_FLD_IPV6_SA))
+		strcat(hash_opt, "[IP SA] ");
+	if (hash_flds & (IECM_ADV_RSS_HASH_FLD_IPV4_DA |
+			 IECM_ADV_RSS_HASH_FLD_IPV6_DA))
+		strcat(hash_opt, "[IP DA] ");
+	if (hash_flds & (IECM_ADV_RSS_HASH_FLD_TCP_SRC_PORT |
+			 IECM_ADV_RSS_HASH_FLD_UDP_SRC_PORT |
+			 IECM_ADV_RSS_HASH_FLD_SCTP_SRC_PORT))
+		strcat(hash_opt, "[src port] ");
+	if (hash_flds & (IECM_ADV_RSS_HASH_FLD_TCP_DST_PORT |
+			 IECM_ADV_RSS_HASH_FLD_UDP_DST_PORT |
+			 IECM_ADV_RSS_HASH_FLD_SCTP_DST_PORT))
+		strcat(hash_opt, "[dst port] ");
+
+	if (!prefix)
+		prefix = "";
+
+	if (!postfix)
+		postfix = "";
+
+	dev_info(&vport->adapter->pdev->dev, "%s %s %s\n",
+		 prefix, hash_opt, postfix);
+}
+
+/**
+ * iecm_adv_rss_parse_hdrs - parses headers from RSS hash input
+ * @cmd: ethtool rxnfc command
+ *
+ * This function parses the rxnfc command and returns intended
+ * header types for RSS configuration
+ */
+static u32 iecm_adv_rss_parse_hdrs(struct ethtool_rxnfc *cmd)
+{
+	u32 hdrs = IECM_ADV_RSS_FLOW_SEG_HDR_NONE;
+
+	switch (cmd->flow_type) {
+	case TCP_V4_FLOW:
+		hdrs |= IECM_ADV_RSS_FLOW_SEG_HDR_TCP |
+			IECM_ADV_RSS_FLOW_SEG_HDR_IPV4;
+		break;
+	case UDP_V4_FLOW:
+		hdrs |= IECM_ADV_RSS_FLOW_SEG_HDR_UDP |
+			IECM_ADV_RSS_FLOW_SEG_HDR_IPV4;
+		break;
+	case SCTP_V4_FLOW:
+		hdrs |= IECM_ADV_RSS_FLOW_SEG_HDR_SCTP |
+			IECM_ADV_RSS_FLOW_SEG_HDR_IPV4;
+		break;
+	case TCP_V6_FLOW:
+		hdrs |= IECM_ADV_RSS_FLOW_SEG_HDR_TCP |
+			IECM_ADV_RSS_FLOW_SEG_HDR_IPV6;
+		break;
+	case UDP_V6_FLOW:
+		hdrs |= IECM_ADV_RSS_FLOW_SEG_HDR_UDP |
+			IECM_ADV_RSS_FLOW_SEG_HDR_IPV6;
+		break;
+	case SCTP_V6_FLOW:
+		hdrs |= IECM_ADV_RSS_FLOW_SEG_HDR_SCTP |
+			IECM_ADV_RSS_FLOW_SEG_HDR_IPV6;
+		break;
+	default:
+		break;
+	}
+
+	return hdrs;
+}
+
+/**
+ * iecm_adv_rss_parse_hash_flds - parses hash fields from RSS hash input
+ * @cmd: ethtool rxnfc command
+ *
+ * This function parses the rxnfc command and returns intended hash fields for
+ * RSS configuration
+ */
+static u64 iecm_adv_rss_parse_hash_flds(struct ethtool_rxnfc *cmd)
+{
+	u64 hfld = IECM_ADV_RSS_HASH_INVALID;
+
+	if (cmd->data & RXH_IP_SRC || cmd->data & RXH_IP_DST) {
+		switch (cmd->flow_type) {
+		case TCP_V4_FLOW:
+		case UDP_V4_FLOW:
+		case SCTP_V4_FLOW:
+			if (cmd->data & RXH_IP_SRC)
+				hfld |= IECM_ADV_RSS_HASH_FLD_IPV4_SA;
+			if (cmd->data & RXH_IP_DST)
+				hfld |= IECM_ADV_RSS_HASH_FLD_IPV4_DA;
+			break;
+		case TCP_V6_FLOW:
+		case UDP_V6_FLOW:
+		case SCTP_V6_FLOW:
+			if (cmd->data & RXH_IP_SRC)
+				hfld |= IECM_ADV_RSS_HASH_FLD_IPV6_SA;
+			if (cmd->data & RXH_IP_DST)
+				hfld |= IECM_ADV_RSS_HASH_FLD_IPV6_DA;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (cmd->data & RXH_L4_B_0_1 || cmd->data & RXH_L4_B_2_3) {
+		switch (cmd->flow_type) {
+		case TCP_V4_FLOW:
+		case TCP_V6_FLOW:
+			if (cmd->data & RXH_L4_B_0_1)
+				hfld |= IECM_ADV_RSS_HASH_FLD_TCP_SRC_PORT;
+			if (cmd->data & RXH_L4_B_2_3)
+				hfld |= IECM_ADV_RSS_HASH_FLD_TCP_DST_PORT;
+			break;
+		case UDP_V4_FLOW:
+		case UDP_V6_FLOW:
+			if (cmd->data & RXH_L4_B_0_1)
+				hfld |= IECM_ADV_RSS_HASH_FLD_UDP_SRC_PORT;
+			if (cmd->data & RXH_L4_B_2_3)
+				hfld |= IECM_ADV_RSS_HASH_FLD_UDP_DST_PORT;
+			break;
+		case SCTP_V4_FLOW:
+		case SCTP_V6_FLOW:
+			if (cmd->data & RXH_L4_B_0_1)
+				hfld |= IECM_ADV_RSS_HASH_FLD_SCTP_SRC_PORT;
+			if (cmd->data & RXH_L4_B_2_3)
+				hfld |= IECM_ADV_RSS_HASH_FLD_SCTP_DST_PORT;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return hfld;
+}
+
+/**
+ * iecm_set_adv_rss_hash_opt - Enable/Disable flow types for RSS hash
+ * @vport: vport structure
+ * @cmd: ethtool rxnfc command
+ *
+ * Returns Success if the flow input set is supported.
+ */
+int
+iecm_set_adv_rss_hash_opt(struct iecm_vport *vport, struct ethtool_rxnfc *cmd)
+{
+	struct iecm_adapter *adapter = vport->adapter;
+	struct iecm_adv_rss *rss, *rss_new;
+	u64 hash_flds;
+	u32 hdrs;
+	int err;
+
+	if (adapter->state != __IECM_UP)
+		return -EIO;
+
+	if (!iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_ADV_RSS))
+		return -EOPNOTSUPP;
+
+	hdrs = iecm_adv_rss_parse_hdrs(cmd);
+	if (hdrs == IECM_ADV_RSS_FLOW_SEG_HDR_NONE)
+		return -EINVAL;
+
+	hash_flds = iecm_adv_rss_parse_hash_flds(cmd);
+	if (hash_flds == IECM_ADV_RSS_HASH_INVALID)
+		return -EINVAL;
+
+	rss_new = kzalloc(sizeof(*rss_new), GFP_KERNEL);
+	if (!rss_new)
+		return -ENOMEM;
+
+	/* Since this can fail, do it now to avoid dirtying the list, we'll
+	 * copy it from rss_new if it turns out we're updating an existing
+	 * filter instead of adding a new one.
+	 */
+	if (iecm_fill_adv_rss_cfg_msg(&rss_new->cfg_msg, hdrs, hash_flds)) {
+		kfree(rss_new);
+		return -EINVAL;
+	}
+
+	iecm_dump_adv_rss_cfg_info(vport, hdrs, hash_flds,
+				   "Input set change for", "is pending");
+
+	spin_lock_bh(&adapter->adv_rss_list_lock);
+	rss = iecm_find_adv_rss_cfg_by_hdrs(vport, hdrs);
+	if (rss) {
+		if (rss->hash_flds != hash_flds) {
+			rss->remove = false;
+			memcpy(&rss->cfg_msg, &rss_new->cfg_msg,
+			       sizeof(rss_new->cfg_msg));
+			kfree(rss_new);
+		} else {
+			kfree(rss_new);
+			spin_unlock_bh(&adapter->adv_rss_list_lock);
+			return -EEXIST;
+		}
+	} else {
+		rss = rss_new;
+		rss->packet_hdrs = hdrs;
+		list_add_tail(&rss->list, &adapter->config_data.adv_rss_list);
+	}
+	rss->add = true;
+	rss->hash_flds = hash_flds;
+	spin_unlock_bh(&adapter->adv_rss_list_lock);
+
+	err = iecm_send_add_del_adv_rss_cfg_msg(vport, true);
+	if (err) {
+		spin_lock_bh(&adapter->adv_rss_list_lock);
+		/* We have to find it again to make sure another thread hasn't
+		 * already deleted and kfreed it.
+		 */
+		rss = iecm_find_adv_rss_cfg_by_hdrs(vport, hdrs);
+		if (rss) {
+			list_del(&rss->list);
+			kfree(rss);
+		}
+		spin_unlock_bh(&adapter->adv_rss_list_lock);
+	}
+
+	if (!err)
+		iecm_dump_adv_rss_cfg_info(vport, hdrs, hash_flds,
+					   "Input set change for",
+					   "successful");
+	else
+		iecm_dump_adv_rss_cfg_info(vport, hdrs, hash_flds,
+					   "Failed to change the input set for",
+					   NULL);
+
+	return err;
+}
+
+/**
+ * iecm_get_adv_rss_hash_opt - Retrieve hash fields for a given flow-type
+ * @vport: vport structure
+ * @cmd: ethtool rxnfc command
+ *
+ * Returns Success if the flow input set is supported.
+ */
+int
+iecm_get_adv_rss_hash_opt(struct iecm_vport *vport, struct ethtool_rxnfc *cmd)
+{
+	struct iecm_adapter *adapter = vport->adapter;
+	struct iecm_adv_rss *rss;
+	u64 hash_flds;
+	u32 hdrs;
+
+	if (adapter->state != __IECM_UP)
+		return -EIO;
+
+	if (!iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_ADV_RSS))
+		return -EOPNOTSUPP;
+
+	cmd->data = 0;
+
+	hdrs = iecm_adv_rss_parse_hdrs(cmd);
+	if (hdrs == IECM_ADV_RSS_FLOW_SEG_HDR_NONE)
+		return -EINVAL;
+
+	spin_lock_bh(&adapter->adv_rss_list_lock);
+	rss = iecm_find_adv_rss_cfg_by_hdrs(vport, hdrs);
+	if (rss)
+		hash_flds = rss->hash_flds;
+	else
+		hash_flds = IECM_ADV_RSS_HASH_INVALID;
+	spin_unlock_bh(&adapter->adv_rss_list_lock);
+
+	if (hash_flds == IECM_ADV_RSS_HASH_INVALID)
+		return -EINVAL;
+
+	if (hash_flds & (IECM_ADV_RSS_HASH_FLD_IPV4_SA |
+			 IECM_ADV_RSS_HASH_FLD_IPV6_SA))
+		cmd->data |= (u64)RXH_IP_SRC;
+
+	if (hash_flds & (IECM_ADV_RSS_HASH_FLD_IPV4_DA |
+			 IECM_ADV_RSS_HASH_FLD_IPV6_DA))
+		cmd->data |= (u64)RXH_IP_DST;
+
+	if (hash_flds & (IECM_ADV_RSS_HASH_FLD_TCP_SRC_PORT |
+			 IECM_ADV_RSS_HASH_FLD_UDP_SRC_PORT |
+			 IECM_ADV_RSS_HASH_FLD_SCTP_SRC_PORT))
+		cmd->data |= (u64)RXH_L4_B_0_1;
+
+	if (hash_flds & (IECM_ADV_RSS_HASH_FLD_TCP_DST_PORT |
+			 IECM_ADV_RSS_HASH_FLD_UDP_DST_PORT |
+			 IECM_ADV_RSS_HASH_FLD_SCTP_DST_PORT))
+		cmd->data |= (u64)RXH_L4_B_2_3;
+
+	return 0;
+}
+
 /**
  * iecm_pkt_udp_no_pay_len - the length of UDP packet without payload
  * @fltr: Flow Director filter data structure
diff --git a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
index 94af45c36866..c05baf12515c 100644
--- a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
+++ b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
@@ -2799,6 +2799,77 @@ int iecm_send_add_del_cloud_filter_msg(struct iecm_vport *vport, bool add)
 	return err;
 }
 
+/**
+ * iecm_send_add_del_adv_rss_cfg_msg: Send add/del RSS configuration message
+ * @vport: vport structure
+ * @add: True to add, false to delete RSS configuration
+ *
+ * Request the CP/PF to add/del RSS configuration as specified by the user via
+ * ethtool
+ *
+ * Return 0 on success, negative on failure
+ **/
+int iecm_send_add_del_adv_rss_cfg_msg(struct iecm_vport *vport, bool add)
+{
+	struct iecm_adapter *adapter = vport->adapter;
+	struct virtchnl_rss_cfg *rss_cfg;
+	struct iecm_adv_rss *rss;
+	int len, err = -ENXIO;
+
+	len = sizeof(struct virtchnl_rss_cfg);
+	rss_cfg = kzalloc(len, GFP_KERNEL);
+	if (!rss_cfg)
+		return -ENOMEM;
+
+	while (true) {
+		bool process_rss = false;
+
+		spin_lock_bh(&adapter->adv_rss_list_lock);
+		list_for_each_entry(rss, &adapter->config_data.adv_rss_list, list) {
+			if (add && rss->add) {
+				/* Only add needs print the RSS information */
+				process_rss = true;
+				rss->add = false;
+				memcpy(rss_cfg, &rss->cfg_msg, len);
+				break;
+			} else if (!add && rss->remove) {
+				process_rss = true;
+				rss->remove = false;
+				memcpy(rss_cfg, &rss->cfg_msg, len);
+				break;
+			}
+		}
+		spin_unlock_bh(&adapter->adv_rss_list_lock);
+
+		/* Don't send mailbox message when there are no RSS to add/del */
+		if (!process_rss)
+			break;
+
+		if (add) {
+			err = iecm_send_mb_msg(adapter, VIRTCHNL_OP_ADD_RSS_CFG,
+					       len, (u8 *)rss_cfg);
+			if (err)
+				break;
+
+			err = iecm_wait_for_event(adapter, IECM_VC_ADD_RSS_CFG,
+						  IECM_VC_ADD_RSS_CFG_ERR);
+		} else {
+			err = iecm_send_mb_msg(adapter, VIRTCHNL_OP_DEL_RSS_CFG,
+					       len, (u8 *)rss_cfg);
+			if (err)
+				break;
+
+			err = iecm_min_wait_for_event(adapter, IECM_VC_DEL_RSS_CFG,
+						      IECM_VC_DEL_RSS_CFG_ERR);
+		}
+		if (err)
+			break;
+	}
+
+	kfree(rss_cfg);
+	return err;
+}
+
 /**
  * iecm_send_add_fdir_filter_msg: Send add Flow Director filter message
  * @vport: vport structure
diff --git a/drivers/net/ethernet/intel/include/iecm.h b/drivers/net/ethernet/intel/include/iecm.h
index 0aab41cf982c..c7be8c88f9b3 100644
--- a/drivers/net/ethernet/intel/include/iecm.h
+++ b/drivers/net/ethernet/intel/include/iecm.h
@@ -432,6 +432,74 @@ struct iecm_channel_config {
 	u8 num_tc;
 };
 
+enum iecm_adv_rss_flow_seg_hdr {
+	IECM_ADV_RSS_FLOW_SEG_HDR_NONE	= 0x00000000,
+	IECM_ADV_RSS_FLOW_SEG_HDR_IPV4	= 0x00000001,
+	IECM_ADV_RSS_FLOW_SEG_HDR_IPV6	= 0x00000002,
+	IECM_ADV_RSS_FLOW_SEG_HDR_TCP	= 0x00000004,
+	IECM_ADV_RSS_FLOW_SEG_HDR_UDP	= 0x00000008,
+	IECM_ADV_RSS_FLOW_SEG_HDR_SCTP	= 0x00000010,
+};
+
+#define IECM_ADV_RSS_FLOW_SEG_HDR_L3		\
+	(IECM_ADV_RSS_FLOW_SEG_HDR_IPV4	|	\
+	 IECM_ADV_RSS_FLOW_SEG_HDR_IPV6)
+
+#define IECM_ADV_RSS_FLOW_SEG_HDR_L4		\
+	(IECM_ADV_RSS_FLOW_SEG_HDR_TCP |	\
+	 IECM_ADV_RSS_FLOW_SEG_HDR_UDP |	\
+	 IECM_ADV_RSS_FLOW_SEG_HDR_SCTP)
+
+enum iecm_adv_rss_flow_field {
+	/* L3 */
+	IECM_ADV_RSS_FLOW_FIELD_IDX_IPV4_SA,
+	IECM_ADV_RSS_FLOW_FIELD_IDX_IPV4_DA,
+	IECM_ADV_RSS_FLOW_FIELD_IDX_IPV6_SA,
+	IECM_ADV_RSS_FLOW_FIELD_IDX_IPV6_DA,
+	/* L4 */
+	IECM_ADV_RSS_FLOW_FIELD_IDX_TCP_SRC_PORT,
+	IECM_ADV_RSS_FLOW_FIELD_IDX_TCP_DST_PORT,
+	IECM_ADV_RSS_FLOW_FIELD_IDX_UDP_SRC_PORT,
+	IECM_ADV_RSS_FLOW_FIELD_IDX_UDP_DST_PORT,
+	IECM_ADV_RSS_FLOW_FIELD_IDX_SCTP_SRC_PORT,
+	IECM_ADV_RSS_FLOW_FIELD_IDX_SCTP_DST_PORT,
+
+	/* The total number of enums must not exceed 64 */
+	IECM_ADV_RSS_FLOW_FIELD_IDX_MAX
+};
+
+#define IECM_ADV_RSS_HASH_INVALID	0
+#define IECM_ADV_RSS_HASH_FLD_IPV4_SA	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_IPV4_SA)
+#define IECM_ADV_RSS_HASH_FLD_IPV6_SA	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_IPV6_SA)
+#define IECM_ADV_RSS_HASH_FLD_IPV4_DA	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_IPV4_DA)
+#define IECM_ADV_RSS_HASH_FLD_IPV6_DA	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_IPV6_DA)
+#define IECM_ADV_RSS_HASH_FLD_TCP_SRC_PORT	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_TCP_SRC_PORT)
+#define IECM_ADV_RSS_HASH_FLD_TCP_DST_PORT	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_TCP_DST_PORT)
+#define IECM_ADV_RSS_HASH_FLD_UDP_SRC_PORT	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_UDP_SRC_PORT)
+#define IECM_ADV_RSS_HASH_FLD_UDP_DST_PORT	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_UDP_DST_PORT)
+#define IECM_ADV_RSS_HASH_FLD_SCTP_SRC_PORT	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_SCTP_SRC_PORT)
+#define IECM_ADV_RSS_HASH_FLD_SCTP_DST_PORT	\
+	BIT_ULL(IECM_ADV_RSS_FLOW_FIELD_IDX_SCTP_DST_PORT)
+
+/* bookkeeping of advanced RSS configuration */
+struct iecm_adv_rss {
+	struct list_head list;
+	u32 packet_hdrs;
+	u64 hash_flds;
+	struct virtchnl_rss_cfg cfg_msg;
+	bool remove;	/* RSS filter needs to be deleted */
+	bool add;	/* RSS filter needs to be added */
+};
+
 enum iecm_fdir_flow_type {
 	/* NONE - used for undef/error */
 	IECM_FDIR_FLOW_NONE = 0,
@@ -878,6 +946,11 @@ void iecm_vport_set_hsplit(struct iecm_vport *vport, bool ena);
 void iecm_add_del_ether_addrs(struct iecm_vport *vport, bool add, bool async);
 int iecm_set_promiscuous(struct iecm_adapter *adapter);
 int iecm_send_add_del_cloud_filter_msg(struct iecm_vport *vport, bool add);
+int iecm_send_add_del_adv_rss_cfg_msg(struct iecm_vport *vport, bool add);
+int iecm_set_adv_rss_hash_opt(struct iecm_vport *vport,
+			      struct ethtool_rxnfc *cmd);
+int iecm_get_adv_rss_hash_opt(struct iecm_vport *vport,
+			      struct ethtool_rxnfc *cmd);
 int iecm_send_add_fdir_filter_msg(struct iecm_vport *vport);
 int iecm_send_del_fdir_filter_msg(struct iecm_vport *vport);
 int iecm_get_fdir_fltr_entry(struct iecm_vport *vport,
-- 
2.33.0


  parent reply	other threads:[~2022-01-28  0:10 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-28  0:09 [Intel-wired-lan] [PATCH net-next 00/19] Add iecm and idpf Alan Brady
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 01/19] virtchnl: Add new virtchnl2 ops Alan Brady
2022-02-02 22:13   ` Brady, Alan
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 02/19] iecm: add basic module init and documentation Alan Brady
2022-01-28 11:56   ` Alexander Lobakin
2022-02-02 22:15     ` Brady, Alan
2022-02-01 19:44   ` Shannon Nelson
2022-02-03  3:08     ` Brady, Alan
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 03/19] iecm: add probe and remove Alan Brady
2022-02-01 20:02   ` Shannon Nelson
2022-02-03  3:13     ` Brady, Alan
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 04/19] iecm: add api_init and controlq init Alan Brady
2022-01-28 12:09   ` Alexander Lobakin
2022-02-02 22:16     ` Brady, Alan
2022-02-01 21:26   ` Shannon Nelson
2022-02-03  3:24     ` Brady, Alan
2022-02-03  3:40       ` Brady, Alan
2022-02-03  5:26         ` Shannon Nelson
2022-02-03 13:13       ` Alexander Lobakin
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 05/19] iecm: add vport alloc and virtchnl messages Alan Brady
2022-01-28  4:19   ` kernel test robot
2022-01-28 12:39     ` Alexander Lobakin
2022-02-02 22:23       ` Brady, Alan
2022-01-28 12:32   ` Alexander Lobakin
2022-02-02 22:21     ` Brady, Alan
2022-02-03 13:23       ` Alexander Lobakin
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 06/19] iecm: add virtchnl messages for queues Alan Brady
2022-01-28 13:03   ` Alexander Lobakin
2022-02-02 22:48     ` Brady, Alan
2022-02-03 10:08       ` Maciej Fijalkowski
2022-02-03 14:09       ` Alexander Lobakin
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 07/19] iecm: finish virtchnl messages Alan Brady
2022-01-28 13:19   ` Alexander Lobakin
2022-02-02 23:06     ` Brady, Alan
2022-02-03 15:05       ` Alexander Lobakin
2022-02-03 15:16         ` Maciej Fijalkowski
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 08/19] iecm: add interrupts and configure netdev Alan Brady
2022-01-28 13:34   ` Alexander Lobakin
2022-02-02 23:17     ` Brady, Alan
2022-02-03 15:55       ` Alexander Lobakin
2022-01-28  0:09 ` [Intel-wired-lan] [PATCH net-next 09/19] iecm: alloc vport TX resources Alan Brady
2022-02-02 23:45   ` Brady, Alan
2022-02-03 17:56     ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 10/19] iecm: alloc vport RX resources Alan Brady
2022-01-28 14:16   ` Alexander Lobakin
2022-02-03  0:13     ` Brady, Alan
2022-02-03 18:29       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 11/19] iecm: add start_xmit and set_rx_mode Alan Brady
2022-01-28 16:35   ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 12/19] iecm: finish netdev_ops Alan Brady
2022-01-28 17:06   ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 13/19] iecm: implement splitq napi_poll Alan Brady
2022-01-28  5:21   ` kernel test robot
2022-01-28 17:44     ` Alexander Lobakin
2022-02-03  1:15       ` Brady, Alan
2022-01-28 17:38   ` Alexander Lobakin
2022-02-03  1:07     ` Brady, Alan
2022-02-04 11:50       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 14/19] iecm: implement singleq napi_poll Alan Brady
2022-01-28 17:57   ` Alexander Lobakin
2022-02-03  1:45     ` Brady, Alan
2022-02-03 19:05       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 15/19] iecm: implement ethtool callbacks Alan Brady
2022-01-28 18:13   ` Alexander Lobakin
2022-02-03  2:13     ` Brady, Alan
2022-02-03 19:54       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 16/19] iecm: implement flow director Alan Brady
2022-01-28 19:04   ` Alexander Lobakin
2022-02-03  2:41     ` Brady, Alan
2022-02-04 10:08       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 17/19] iecm: implement cloud filters Alan Brady
2022-01-28 19:38   ` Alexander Lobakin
2022-02-03  2:53     ` Brady, Alan
2022-01-28  0:10 ` Alan Brady [this message]
2022-01-28 19:53   ` [Intel-wired-lan] [PATCH net-next 18/19] iecm: add advanced rss Alexander Lobakin
2022-02-03  2:55     ` Brady, Alan
2022-02-03 10:46       ` Maciej Fijalkowski
2022-02-04 10:22       ` Alexander Lobakin
2022-01-28  0:10 ` [Intel-wired-lan] [PATCH net-next 19/19] idpf: introduce idpf driver Alan Brady
2022-01-28 20:08   ` Alexander Lobakin
2022-02-03  3:07     ` Brady, Alan
2022-02-04 10:35       ` Alexander Lobakin
2022-02-04 12:05 ` [Intel-wired-lan] [PATCH net-next 00/19] Add iecm and idpf Alexander Lobakin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220128001009.721392-19-alan.brady@intel.com \
    --to=alan.brady@intel.com \
    --cc=intel-wired-lan@osuosl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox