net/enic: support UDP RSS on 1400 series adapters
authorJohn Daley <johndale@cisco.com>
Wed, 4 Apr 2018 23:54:52 +0000 (16:54 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 13 Apr 2018 22:41:44 +0000 (00:41 +0200)
Recent models support IPv4/IPv6 UDP RSS. There is no control bit to
enable UDP RSS alone. Instead, the NIC enables/disables TCP and UDP
RSS together.

Signed-off-by: John Daley <johndale@cisco.com>
Reviewed-by: Hyong Youb Kim <hyonkim@cisco.com>
doc/guides/nics/enic.rst
drivers/net/enic/base/vnic_dev.c
drivers/net/enic/base/vnic_dev.h
drivers/net/enic/base/vnic_nic.h
drivers/net/enic/enic_main.c
drivers/net/enic/enic_res.c

index 0bc5593..bbf18ac 100644 (file)
@@ -369,6 +369,7 @@ Supported features
 - VLAN filtering (supported via UCSM/CIMC only)
 - Execution of application by unprivileged system users
 - IPV4, IPV6 and TCP RSS hashing
+- UDP hashing (1400 series and later adapters)
 - Scattered Rx
 - MTU update
 - SR-IOV on UCS managed servers connected to Fabric Interconnects
@@ -382,7 +383,6 @@ Known bugs and unsupported features in this release
 - VLAN based flow direction
 - Non-IPV4 flow direction
 - Setting of extended VLAN
-- UDP RSS hashing
 - MTU update only works if Scattered Rx mode is disabled
 - Maximum receive packet length is ignored if Scattered Rx mode is used
 
index 1f8d222..eccbb30 100644 (file)
@@ -10,6 +10,7 @@
 #include "vnic_dev.h"
 #include "vnic_resource.h"
 #include "vnic_devcmd.h"
+#include "vnic_nic.h"
 #include "vnic_stats.h"
 
 
@@ -531,6 +532,23 @@ parse_max_level:
        return 0;
 }
 
+int vnic_dev_capable_udp_rss(struct vnic_dev *vdev)
+{
+       u64 a0 = CMD_NIC_CFG, a1 = 0;
+       u64 rss_hash_type;
+       int wait = 1000;
+       int err;
+
+       err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
+       if (err)
+               return 0;
+       if (a0 == 0)
+               return 0;
+       rss_hash_type = (a1 >> NIC_CFG_RSS_HASH_TYPE_SHIFT) &
+               NIC_CFG_RSS_HASH_TYPE_MASK_FIELD;
+       return ((rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP) ? 1 : 0);
+}
+
 int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
 {
        u64 a0 = (u32)cmd, a1 = 0;
index 7e5736b..fb3dd3c 100644 (file)
@@ -109,6 +109,7 @@ int vnic_dev_capable_adv_filters(struct vnic_dev *vdev);
 int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd);
 int vnic_dev_capable_filter_mode(struct vnic_dev *vdev, u32 *mode,
                                 u8 *filter_tags);
+int vnic_dev_capable_udp_rss(struct vnic_dev *vdev);
 int vnic_dev_asic_info(struct vnic_dev *vdev, u16 *asic_type, u16 *asic_rev);
 int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, size_t size,
        void *value);
index a753b3a..b20915e 100644 (file)
@@ -33,6 +33,7 @@
 #define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6         (1 << 4)
 #define NIC_CFG_RSS_HASH_TYPE_IPV6_EX          (1 << 5)
 #define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX      (1 << 6)
+#define NIC_CFG_RSS_HASH_TYPE_UDP              (1 << 7)
 
 static inline void vnic_set_nic_cfg(u32 *nic_cfg,
        u8 rss_default_cpu, u8 rss_hash_type,
index aaada88..d15d236 100644 (file)
@@ -1174,10 +1174,22 @@ int enic_set_rss_conf(struct enic *enic, struct rte_eth_rss_conf *rss_conf)
                        rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_IPV4;
                if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
                        rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV4;
+               if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) {
+                       /*
+                        * 'TCP' is not a typo. HW does not have a separate
+                        * enable bit for UDP RSS. The TCP bit enables both TCP
+                        * and UDP RSS..
+                        */
+                       rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV4;
+               }
                if (rss_hf & ETH_RSS_IPV6)
                        rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_IPV6;
                if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
                        rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
+               if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) {
+                       /* Again, 'TCP' is not a typo. */
+                       rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
+               }
                if (rss_hf & ETH_RSS_IPV6_EX)
                        rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_IPV6_EX;
                if (rss_hf & ETH_RSS_IPV6_TCP_EX)
index e7ad676..abe6929 100644 (file)
@@ -144,6 +144,11 @@ int enic_get_vnic_config(struct enic *enic)
                enic->flow_type_rss_offloads |= ETH_RSS_IPV6_EX;
        if (ENIC_SETTING(enic, RSSHASH_TCPIPV6_EX))
                enic->flow_type_rss_offloads |= ETH_RSS_IPV6_TCP_EX;
+       if (vnic_dev_capable_udp_rss(enic->vdev)) {
+               enic->flow_type_rss_offloads |=
+                       ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_NONFRAG_IPV6_UDP;
+       }
+
        /* Zero offloads if RSS is not enabled */
        if (!ENIC_SETTING(enic, RSS))
                enic->flow_type_rss_offloads = 0;