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
next prev 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