diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_ethtool.c | 18 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_main.c | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_res.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/vnic_dev.c | 18 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/vnic_dev.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/vnic_devcmd.h | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/vnic_nic.h | 3 |
7 files changed, 67 insertions, 21 deletions
diff --git a/drivers/net/ethernet/cisco/enic/enic_ethtool.c b/drivers/net/ethernet/cisco/enic/enic_ethtool.c index 869006c2002d..f42f7a6e1559 100644 --- a/drivers/net/ethernet/cisco/enic/enic_ethtool.c +++ b/drivers/net/ethernet/cisco/enic/enic_ethtool.c @@ -476,18 +476,28 @@ static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd) static int enic_get_rx_flow_hash(struct enic *enic, struct ethtool_rxnfc *cmd) { + u8 rss_hash_type = 0; cmd->data = 0; + spin_lock_bh(&enic->devcmd_lock); + (void)vnic_dev_capable_rss_hash_type(enic->vdev, &rss_hash_type); + spin_unlock_bh(&enic->devcmd_lock); switch (cmd->flow_type) { case TCP_V6_FLOW: case TCP_V4_FLOW: - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* Fall through */ + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 | + RXH_IP_SRC | RXH_IP_DST; + break; case UDP_V6_FLOW: + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + if (rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP_IPV6) + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + break; case UDP_V4_FLOW: - if (vnic_dev_capable_udp_rss(enic->vdev)) + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + if (rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP_IPV4) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* Fall through */ + break; case SCTP_V4_FLOW: case AH_ESP_V4_FLOW: case AH_V4_FLOW: diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 8a8b12b720ef..30d2eaa18c04 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -2320,16 +2320,24 @@ static int enic_set_rss_nic_cfg(struct enic *enic) { struct device *dev = enic_get_dev(enic); const u8 rss_default_cpu = 0; - u8 rss_hash_type = NIC_CFG_RSS_HASH_TYPE_IPV4 | - NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 | - NIC_CFG_RSS_HASH_TYPE_IPV6 | - NIC_CFG_RSS_HASH_TYPE_TCP_IPV6; const u8 rss_hash_bits = 7; const u8 rss_base_cpu = 0; + u8 rss_hash_type; + int res; u8 rss_enable = ENIC_SETTING(enic, RSS) && (enic->rq_count > 1); - if (vnic_dev_capable_udp_rss(enic->vdev)) - rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_UDP; + spin_lock_bh(&enic->devcmd_lock); + res = vnic_dev_capable_rss_hash_type(enic->vdev, &rss_hash_type); + spin_unlock_bh(&enic->devcmd_lock); + if (res) { + /* defaults for old adapters + */ + rss_hash_type = NIC_CFG_RSS_HASH_TYPE_IPV4 | + NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 | + NIC_CFG_RSS_HASH_TYPE_IPV6 | + NIC_CFG_RSS_HASH_TYPE_TCP_IPV6; + } + if (rss_enable) { if (!enic_set_rsskey(enic)) { if (enic_set_rsscpu(enic, rss_hash_bits)) { diff --git a/drivers/net/ethernet/cisco/enic/enic_res.c b/drivers/net/ethernet/cisco/enic/enic_res.c index 9c96911fb2c8..40b20817ddd5 100644 --- a/drivers/net/ethernet/cisco/enic/enic_res.c +++ b/drivers/net/ethernet/cisco/enic/enic_res.c @@ -149,6 +149,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 = CMD_NIC_CFG; u64 a0, a1; u32 nic_cfg; int wait = 1000; @@ -160,7 +161,11 @@ 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); + if (rss_hash_type & (NIC_CFG_RSS_HASH_TYPE_UDP_IPV4 | + NIC_CFG_RSS_HASH_TYPE_UDP_IPV6)) + cmd = CMD_NIC_CFG_CHK; + + 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) diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c index 76cdd4c9d11f..e9db811df59c 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_dev.c +++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c @@ -1282,19 +1282,23 @@ int vnic_dev_get_supported_feature_ver(struct vnic_dev *vdev, u8 feature, return ret; } -bool vnic_dev_capable_udp_rss(struct vnic_dev *vdev) +int vnic_dev_capable_rss_hash_type(struct vnic_dev *vdev, u8 *rss_hash_type) { 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 || !a0) - return false; + /* rss_hash_type is valid only when a0 is 1. Adapter which does not + * support CMD_CAPABILITY for rss_hash_type has a0 = 0 + */ + if (err || (a0 != 1)) + return -EOPNOTSUPP; + + a1 = (a1 >> NIC_CFG_RSS_HASH_TYPE_SHIFT) & + NIC_CFG_RSS_HASH_TYPE_MASK_FIELD; - rss_hash_type = (a1 >> NIC_CFG_RSS_HASH_TYPE_SHIFT) & - NIC_CFG_RSS_HASH_TYPE_MASK_FIELD; + *rss_hash_type = (u8)a1; - return (rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP); + return 0; } diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.h b/drivers/net/ethernet/cisco/enic/vnic_dev.h index 59d4cc8fbb85..714fc1ed79e3 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_dev.h +++ b/drivers/net/ethernet/cisco/enic/vnic_dev.h @@ -184,6 +184,6 @@ int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, u8 overlay, u16 vxlan_udp_port_number); int vnic_dev_get_supported_feature_ver(struct vnic_dev *vdev, u8 feature, u64 *supported_versions, u64 *a1); -bool vnic_dev_capable_udp_rss(struct vnic_dev *vdev); +int vnic_dev_capable_rss_hash_type(struct vnic_dev *vdev, u8 *rss_hash_type); #endif /* _VNIC_DEV_H_ */ diff --git a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h index 41de4ba622a1..fef5a0a0663d 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h +++ b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h @@ -148,8 +148,26 @@ 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 (no wait, always succeeds) + * 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 (will return error if flags are invalid) + * 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), diff --git a/drivers/net/ethernet/cisco/enic/vnic_nic.h b/drivers/net/ethernet/cisco/enic/vnic_nic.h index 5a93db0d7afc..84ff8ca17fcb 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_nic.h +++ b/drivers/net/ethernet/cisco/enic/vnic_nic.h @@ -41,13 +41,14 @@ #define NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD 1UL #define NIC_CFG_IG_VLAN_STRIP_EN_SHIFT 24 +#define NIC_CFG_RSS_HASH_TYPE_UDP_IPV4 (1 << 0) #define NIC_CFG_RSS_HASH_TYPE_IPV4 (1 << 1) #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_UDP (1 << 7) +#define NIC_CFG_RSS_HASH_TYPE_UDP_IPV6 (1 << 7) static inline void vnic_set_nic_cfg(u32 *nic_cfg, u8 rss_default_cpu, u8 rss_hash_type, |