net/enic: update the UDP RSS detection mechanism
authorHyong Youb Kim <hyonkim@cisco.com>
Fri, 29 Jun 2018 09:29:31 +0000 (02:29 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 2 Jul 2018 23:53:26 +0000 (01:53 +0200)
The UDP RSS interface has changed in the release firmware for 100G VIC
adapters. The capability bit is now in NIC_CFG. Also the driver is
supposed to use CMD_NIC_CFG_CHK and check if RSS config is
successful. No more changes are expected with respect to UDP RSS API.

Fixes: 94c351895888 ("net/enic: update UDP RSS controls")
Cc: stable@dpdk.org
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
drivers/net/enic/base/vnic_dev.c
drivers/net/enic/base/vnic_dev.h
drivers/net/enic/base/vnic_devcmd.h
drivers/net/enic/base/vnic_enet.h
drivers/net/enic/base/vnic_nic.h
drivers/net/enic/enic.h
drivers/net/enic/enic_main.c
drivers/net/enic/enic_res.c

index 8483f76..16e8814 100644 (file)
@@ -528,6 +528,22 @@ parse_max_level:
        return 0;
 }
 
+void vnic_dev_capable_udp_rss_weak(struct vnic_dev *vdev, bool *cfg_chk,
+                                  bool *weak)
+{
+       u64 a0 = CMD_NIC_CFG, a1 = 0;
+       int wait = 1000;
+       int err;
+
+       *cfg_chk = false;
+       *weak = false;
+       err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
+       if (err == 0 && a0 != 0 && a1 != 0) {
+               *cfg_chk = true;
+               *weak = !!((a1 >> 32) & CMD_NIC_CFG_CAPF_UDP_WEAK);
+       }
+}
+
 int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
 {
        u64 a0 = (u32)cmd, a1 = 0;
index 3c90843..270a47b 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef _VNIC_DEV_H_
 #define _VNIC_DEV_H_
 
+#include <stdbool.h>
+
 #include <rte_pci.h>
 #include <rte_bus_pci.h>
 
@@ -109,6 +111,8 @@ 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_actions);
+void vnic_dev_capable_udp_rss_weak(struct vnic_dev *vdev, bool *cfg_chk,
+                                  bool *weak);
 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 2865eb4..a22d8a7 100644 (file)
@@ -138,9 +138,27 @@ enum vnic_devcmd_cmd {
        /* del VLAN id in (u16)a0 */
        CMD_VLAN_DEL            = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 15),
 
-       /* nic_cfg in (u32)a0 */
+       /*
+        * nic_cfg in (u32)a0
+        *
+        * Capability query:
+        * out: (u64) a0= 1 if a1 is valid
+        *      (u64) a1= (NIC_CFG bits supported) | (flags << 32)
+        *                              (flags are CMD_NIC_CFG_CAPF_xxx)
+        */
        CMD_NIC_CFG             = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 16),
 
+       /*
+        * nic_cfg_chk  (same as nic_cfg, but may return error)
+        * in (u32)a0
+        *
+        * Capability query:
+        * out: (u64) a0= 1 if a1 is valid
+        *      (u64) a1= (NIC_CFG bits supported) | (flags << 32)
+        *                              (flags are CMD_NIC_CFG_CAPF_xxx)
+        */
+       CMD_NIC_CFG_CHK         = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 16),
+
        /* union vnic_rss_key in mem: (u64)a0=paddr, (u16)a1=len */
        CMD_RSS_KEY             = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 17),
 
@@ -605,6 +623,9 @@ enum filter_cap_mode {
 /* flags for CMD_INIT */
 #define CMD_INITF_DEFAULT_MAC  0x1     /* init with default mac addr */
 
+/* flags for CMD_NIC_CFG */
+#define CMD_NIC_CFG_CAPF_UDP_WEAK      (1ULL << 0) /* Bodega-style UDP RSS */
+
 /* flags for CMD_PACKET_FILTER */
 #define CMD_PFILTER_DIRECTED           0x01
 #define CMD_PFILTER_MULTICAST          0x02
index 49504a7..901f3b4 100644 (file)
@@ -53,9 +53,8 @@ struct vnic_enet_config {
 #define VENETF_NVGRE    0x20000 /* NVGRE offload */
 #define VENETF_GRPINTR  0x40000 /* group interrupt */
 #define VENETF_NICSWITCH        0x80000 /* NICSWITCH enabled */
-#define VENETF_RSSHASH_UDP_WEAK 0x100000 /* VIC has Bodega-style UDP RSS */
-#define VENETF_RSSHASH_UDPIPV4  0x200000 /* Hash on UDP + IPv4 fields */
-#define VENETF_RSSHASH_UDPIPV6  0x400000 /* Hash on UDP + IPv6 fields */
+#define VENETF_RSSHASH_UDPIPV4  0x100000 /* Hash on UDP + IPv4 fields */
+#define VENETF_RSSHASH_UDPIPV6  0x200000 /* Hash on UDP + IPv6 fields */
 
 #define VENET_INTR_TYPE_MIN    0       /* Timer specs min interrupt spacing */
 #define VENET_INTR_TYPE_IDLE   1       /* Timer specs idle time before irq */
index e318d0c..1604085 100644 (file)
@@ -32,8 +32,8 @@
 #define NIC_CFG_RSS_HASH_TYPE_TCP_IPV4         (1 << 2)
 #define NIC_CFG_RSS_HASH_TYPE_IPV6             (1 << 3)
 #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_RSVD1            (1 << 5)
+#define NIC_CFG_RSS_HASH_TYPE_RSVD2            (1 << 6)
 #define NIC_CFG_RSS_HASH_TYPE_UDP_IPV6         (1 << 7)
 
 static inline void vnic_set_nic_cfg(u32 *nic_cfg,
index ee83fe5..ea0a688 100644 (file)
@@ -123,6 +123,8 @@ struct enic {
        u8 filter_actions; /* HW supported actions */
        bool vxlan;
        bool disable_overlay; /* devargs disable_overlay=1 */
+       bool nic_cfg_chk;     /* NIC_CFG_CHK available */
+       bool udp_rss_weak;    /* Bodega style UDP RSS */
 
        unsigned int flags;
        unsigned int priv_flags;
index a25d303..899603f 100644 (file)
@@ -1197,7 +1197,7 @@ int enic_set_rss_conf(struct enic *enic, struct rte_eth_rss_conf *rss_conf)
                        rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV4;
                if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) {
                        rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_UDP_IPV4;
-                       if (ENIC_SETTING(enic, RSSHASH_UDP_WEAK)) {
+                       if (enic->udp_rss_weak) {
                                /*
                                 * 'TCP' is not a typo. The "weak" version of
                                 * UDP RSS requires both the TCP and UDP bits
@@ -1213,7 +1213,7 @@ int enic_set_rss_conf(struct enic *enic, struct rte_eth_rss_conf *rss_conf)
                        rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
                if (rss_hf & (ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_IPV6_UDP_EX)) {
                        rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_UDP_IPV6;
-                       if (ENIC_SETTING(enic, RSSHASH_UDP_WEAK))
+                       if (enic->udp_rss_weak)
                                rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
                }
        } else {
@@ -1237,8 +1237,11 @@ int enic_set_rss_conf(struct enic *enic, struct rte_eth_rss_conf *rss_conf)
                enic->rss_hf = rss_hf;
                enic->rss_hash_type = rss_hash_type;
                enic->rss_enable = rss_enable;
+       } else {
+               dev_err(enic, "Failed to update RSS configurations."
+                       " hash=0x%x\n", rss_hash_type);
        }
-       return 0;
+       return ret;
 }
 
 int enic_set_vlan_strip(struct enic *enic)
index 6b404c3..d1113b2 100644 (file)
@@ -82,6 +82,8 @@ int enic_get_vnic_config(struct enic *enic)
                        "Error getting filter modes, %d\n", err);
                return err;
        }
+       vnic_dev_capable_udp_rss_weak(enic->vdev, &enic->nic_cfg_chk,
+                                     &enic->udp_rss_weak);
 
        dev_info(enic, "Flow api filter mode: %s Actions: %s%s%s\n",
                ((enic->flow_filter_mode == FILTER_DPDK_1) ? "DPDK" :
@@ -124,7 +126,7 @@ int enic_get_vnic_config(struct enic *enic)
                ENIC_SETTING(enic, RXCSUM) ? "yes" : "no",
                ENIC_SETTING(enic, RSS) ?
                        (ENIC_SETTING(enic, RSSHASH_UDPIPV4) ? "+UDP" :
-                       ((ENIC_SETTING(enic, RSSHASH_UDP_WEAK) ? "+udp" :
+                       ((enic->udp_rss_weak ? "+udp" :
                        "yes"))) : "no",
                c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" :
                c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" :
@@ -161,7 +163,7 @@ int enic_get_vnic_config(struct enic *enic)
        if (ENIC_SETTING(enic, RSSHASH_TCPIPV6))
                enic->flow_type_rss_offloads |= ETH_RSS_NONFRAG_IPV6_TCP |
                        ETH_RSS_IPV6_TCP_EX;
-       if (ENIC_SETTING(enic, RSSHASH_UDP_WEAK))
+       if (enic->udp_rss_weak)
                enic->flow_type_rss_offloads |=
                        ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_NONFRAG_IPV6_UDP |
                        ETH_RSS_IPV6_UDP_EX;
@@ -235,6 +237,7 @@ int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
        u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en,
        u8 ig_vlan_strip_en)
 {
+       enum vnic_devcmd_cmd cmd;
        u64 a0, a1;
        u32 nic_cfg;
        int wait = 1000;
@@ -245,8 +248,8 @@ int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
 
        a0 = nic_cfg;
        a1 = 0;
-
-       return vnic_dev_cmd(enic->vdev, CMD_NIC_CFG, &a0, &a1, wait);
+       cmd = enic->nic_cfg_chk ? CMD_NIC_CFG_CHK : CMD_NIC_CFG;
+       return vnic_dev_cmd(enic->vdev, cmd, &a0, &a1, wait);
 }
 
 int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len)