1
0
Fork 0

enic: fix UDP rss bits

In commit 48398b6e70 ("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: Govindarajulu Varadarajan <gvaradar@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
hifive-unleashed-5.1
Govindarajulu Varadarajan 2018-06-05 10:14:57 -07:00 committed by David S. Miller
parent 75d4e704fa
commit 4016a7f15e
7 changed files with 68 additions and 22 deletions

View File

@ -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:
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_IPV6)
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
/* Fall through */
break;
case UDP_V4_FLOW:
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;
break;
case SCTP_V4_FLOW:
case AH_ESP_V4_FLOW:
case AH_V4_FLOW:

View File

@ -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)) {

View File

@ -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)

View File

@ -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;
rss_hash_type = (a1 >> NIC_CFG_RSS_HASH_TYPE_SHIFT) &
NIC_CFG_RSS_HASH_TYPE_MASK_FIELD;
a1 = (a1 >> NIC_CFG_RSS_HASH_TYPE_SHIFT) &
NIC_CFG_RSS_HASH_TYPE_MASK_FIELD;
return (rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP);
*rss_hash_type = (u8)a1;
return 0;
}

View File

@ -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_ */

View File

@ -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),

View File

@ -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,