Commit 4016a7f1 authored by Govindarajulu Varadarajan's avatar Govindarajulu Varadarajan Committed by David S. Miller

enic: fix UDP rss bits

In commit 48398b6e ("enic: set UDP rss flag") driver needed to set a
single bit to enable UDP rss. This is changed to two bit. One for UDP
IPv4 and other bit for UDP IPv6. The hardware which supports this is not
released yet. When released, driver should set 2 bit to enable UDP rss for
both IPv4 and IPv6.

Also add spinlock around vnic_dev_capable_rss_hash_type().
Signed-off-by: default avatarGovindarajulu Varadarajan <gvaradar@cisco.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 75d4e704
......@@ -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:
......
......@@ -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)) {
......
......@@ -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)
......
......@@ -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;
}
......@@ -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_ */
......@@ -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),
......
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment