Commit d97b3072 authored by Jian Shen's avatar Jian Shen Committed by David S. Miller

net: hns3: Add RSS tuples support for VF

This patch adds RSS tuple support for VF in revision
0x21.
Signed-off-by: default avatarJian Shen <shenjian15@huawei.com>
Signed-off-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarSalil Mehta <salil.mehta@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 374ad291
......@@ -1078,6 +1078,7 @@ static const struct ethtool_ops hns3vf_ethtool_ops = {
.get_ethtool_stats = hns3_get_stats,
.get_sset_count = hns3_get_sset_count,
.get_rxnfc = hns3_get_rxnfc,
.set_rxnfc = hns3_set_rxnfc,
.get_rxfh_key_size = hns3_get_rss_key_size,
.get_rxfh_indir_size = hns3_get_rss_indir_size,
.get_rxfh = hns3_get_rss,
......
......@@ -89,6 +89,7 @@ enum hclgevf_opcode_type {
HCLGEVF_OPC_CFG_COM_TQP_QUEUE = 0x0B20,
/* RSS cmd */
HCLGEVF_OPC_RSS_GENERIC_CONFIG = 0x0D01,
HCLGEVF_OPC_RSS_INPUT_TUPLE = 0x0D02,
HCLGEVF_OPC_RSS_INDIR_TABLE = 0x0D07,
HCLGEVF_OPC_RSS_TC_MODE = 0x0D08,
/* Mailbox cmd */
......@@ -160,11 +161,11 @@ struct hclgevf_rss_config_cmd {
struct hclgevf_rss_input_tuple_cmd {
u8 ipv4_tcp_en;
u8 ipv4_udp_en;
u8 ipv4_stcp_en;
u8 ipv4_sctp_en;
u8 ipv4_fragment_en;
u8 ipv6_tcp_en;
u8 ipv6_udp_en;
u8 ipv6_stcp_en;
u8 ipv6_sctp_en;
u8 ipv6_fragment_en;
u8 rsv[16];
};
......
......@@ -587,6 +587,193 @@ static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir,
return hclgevf_set_rss_indir_table(hdev);
}
static u8 hclgevf_get_rss_hash_bits(struct ethtool_rxnfc *nfc)
{
u8 hash_sets = nfc->data & RXH_L4_B_0_1 ? HCLGEVF_S_PORT_BIT : 0;
if (nfc->data & RXH_L4_B_2_3)
hash_sets |= HCLGEVF_D_PORT_BIT;
else
hash_sets &= ~HCLGEVF_D_PORT_BIT;
if (nfc->data & RXH_IP_SRC)
hash_sets |= HCLGEVF_S_IP_BIT;
else
hash_sets &= ~HCLGEVF_S_IP_BIT;
if (nfc->data & RXH_IP_DST)
hash_sets |= HCLGEVF_D_IP_BIT;
else
hash_sets &= ~HCLGEVF_D_IP_BIT;
if (nfc->flow_type == SCTP_V4_FLOW || nfc->flow_type == SCTP_V6_FLOW)
hash_sets |= HCLGEVF_V_TAG_BIT;
return hash_sets;
}
static int hclgevf_set_rss_tuple(struct hnae3_handle *handle,
struct ethtool_rxnfc *nfc)
{
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
struct hclgevf_rss_input_tuple_cmd *req;
struct hclgevf_desc desc;
u8 tuple_sets;
int ret;
if (handle->pdev->revision == 0x20)
return -EOPNOTSUPP;
if (nfc->data &
~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3))
return -EINVAL;
req = (struct hclgevf_rss_input_tuple_cmd *)desc.data;
hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INPUT_TUPLE, false);
req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en;
req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en;
req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en;
req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en;
tuple_sets = hclgevf_get_rss_hash_bits(nfc);
switch (nfc->flow_type) {
case TCP_V4_FLOW:
req->ipv4_tcp_en = tuple_sets;
break;
case TCP_V6_FLOW:
req->ipv6_tcp_en = tuple_sets;
break;
case UDP_V4_FLOW:
req->ipv4_udp_en = tuple_sets;
break;
case UDP_V6_FLOW:
req->ipv6_udp_en = tuple_sets;
break;
case SCTP_V4_FLOW:
req->ipv4_sctp_en = tuple_sets;
break;
case SCTP_V6_FLOW:
if ((nfc->data & RXH_L4_B_0_1) ||
(nfc->data & RXH_L4_B_2_3))
return -EINVAL;
req->ipv6_sctp_en = tuple_sets;
break;
case IPV4_FLOW:
req->ipv4_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
break;
case IPV6_FLOW:
req->ipv6_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
break;
default:
return -EINVAL;
}
ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"Set rss tuple fail, status = %d\n", ret);
return ret;
}
rss_cfg->rss_tuple_sets.ipv4_tcp_en = req->ipv4_tcp_en;
rss_cfg->rss_tuple_sets.ipv4_udp_en = req->ipv4_udp_en;
rss_cfg->rss_tuple_sets.ipv4_sctp_en = req->ipv4_sctp_en;
rss_cfg->rss_tuple_sets.ipv4_fragment_en = req->ipv4_fragment_en;
rss_cfg->rss_tuple_sets.ipv6_tcp_en = req->ipv6_tcp_en;
rss_cfg->rss_tuple_sets.ipv6_udp_en = req->ipv6_udp_en;
rss_cfg->rss_tuple_sets.ipv6_sctp_en = req->ipv6_sctp_en;
rss_cfg->rss_tuple_sets.ipv6_fragment_en = req->ipv6_fragment_en;
return 0;
}
static int hclgevf_get_rss_tuple(struct hnae3_handle *handle,
struct ethtool_rxnfc *nfc)
{
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
u8 tuple_sets;
if (handle->pdev->revision == 0x20)
return -EOPNOTSUPP;
nfc->data = 0;
switch (nfc->flow_type) {
case TCP_V4_FLOW:
tuple_sets = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
break;
case UDP_V4_FLOW:
tuple_sets = rss_cfg->rss_tuple_sets.ipv4_udp_en;
break;
case TCP_V6_FLOW:
tuple_sets = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
break;
case UDP_V6_FLOW:
tuple_sets = rss_cfg->rss_tuple_sets.ipv6_udp_en;
break;
case SCTP_V4_FLOW:
tuple_sets = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
break;
case SCTP_V6_FLOW:
tuple_sets = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
break;
case IPV4_FLOW:
case IPV6_FLOW:
tuple_sets = HCLGEVF_S_IP_BIT | HCLGEVF_D_IP_BIT;
break;
default:
return -EINVAL;
}
if (!tuple_sets)
return 0;
if (tuple_sets & HCLGEVF_D_PORT_BIT)
nfc->data |= RXH_L4_B_2_3;
if (tuple_sets & HCLGEVF_S_PORT_BIT)
nfc->data |= RXH_L4_B_0_1;
if (tuple_sets & HCLGEVF_D_IP_BIT)
nfc->data |= RXH_IP_DST;
if (tuple_sets & HCLGEVF_S_IP_BIT)
nfc->data |= RXH_IP_SRC;
return 0;
}
static int hclgevf_set_rss_input_tuple(struct hclgevf_dev *hdev,
struct hclgevf_rss_cfg *rss_cfg)
{
struct hclgevf_rss_input_tuple_cmd *req;
struct hclgevf_desc desc;
int ret;
hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INPUT_TUPLE, false);
req = (struct hclgevf_rss_input_tuple_cmd *)desc.data;
req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en;
req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en;
req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en;
req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en;
ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
if (ret)
dev_err(&hdev->pdev->dev,
"Configure rss input fail, status = %d\n", ret);
return ret;
}
static int hclgevf_get_tc_size(struct hnae3_handle *handle)
{
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
......@@ -1327,6 +1514,28 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
rss_cfg->rss_hash_key);
if (ret)
return ret;
rss_cfg->rss_tuple_sets.ipv4_tcp_en =
HCLGEVF_RSS_INPUT_TUPLE_OTHER;
rss_cfg->rss_tuple_sets.ipv4_udp_en =
HCLGEVF_RSS_INPUT_TUPLE_OTHER;
rss_cfg->rss_tuple_sets.ipv4_sctp_en =
HCLGEVF_RSS_INPUT_TUPLE_SCTP;
rss_cfg->rss_tuple_sets.ipv4_fragment_en =
HCLGEVF_RSS_INPUT_TUPLE_OTHER;
rss_cfg->rss_tuple_sets.ipv6_tcp_en =
HCLGEVF_RSS_INPUT_TUPLE_OTHER;
rss_cfg->rss_tuple_sets.ipv6_udp_en =
HCLGEVF_RSS_INPUT_TUPLE_OTHER;
rss_cfg->rss_tuple_sets.ipv6_sctp_en =
HCLGEVF_RSS_INPUT_TUPLE_SCTP;
rss_cfg->rss_tuple_sets.ipv6_fragment_en =
HCLGEVF_RSS_INPUT_TUPLE_OTHER;
ret = hclgevf_set_rss_input_tuple(hdev, rss_cfg);
if (ret)
return ret;
}
/* Initialize RSS indirect table for each vport */
......@@ -1971,6 +2180,8 @@ static const struct hnae3_ae_ops hclgevf_ops = {
.get_rss_indir_size = hclgevf_get_rss_indir_size,
.get_rss = hclgevf_get_rss,
.set_rss = hclgevf_set_rss,
.get_rss_tuple = hclgevf_get_rss_tuple,
.set_rss_tuple = hclgevf_set_rss_tuple,
.get_tc_size = hclgevf_get_tc_size,
.get_fw_version = hclgevf_get_fw_version,
.set_vlan_filter = hclgevf_set_vlan_filter,
......
......@@ -46,6 +46,13 @@
#define HCLGEVF_RSS_HASH_ALGO_MASK 0xf
#define HCLGEVF_RSS_CFG_TBL_NUM \
(HCLGEVF_RSS_IND_TBL_SIZE / HCLGEVF_RSS_CFG_TBL_SIZE)
#define HCLGEVF_RSS_INPUT_TUPLE_OTHER GENMASK(3, 0)
#define HCLGEVF_RSS_INPUT_TUPLE_SCTP GENMASK(4, 0)
#define HCLGEVF_D_PORT_BIT BIT(0)
#define HCLGEVF_S_PORT_BIT BIT(1)
#define HCLGEVF_D_IP_BIT BIT(2)
#define HCLGEVF_S_IP_BIT BIT(3)
#define HCLGEVF_V_TAG_BIT BIT(4)
/* states of hclgevf device & tasks */
enum hclgevf_states {
......@@ -106,12 +113,24 @@ struct hclgevf_cfg {
u32 numa_node_map;
};
struct hclgevf_rss_tuple_cfg {
u8 ipv4_tcp_en;
u8 ipv4_udp_en;
u8 ipv4_sctp_en;
u8 ipv4_fragment_en;
u8 ipv6_tcp_en;
u8 ipv6_udp_en;
u8 ipv6_sctp_en;
u8 ipv6_fragment_en;
};
struct hclgevf_rss_cfg {
u8 rss_hash_key[HCLGEVF_RSS_KEY_SIZE]; /* user configured hash keys */
u32 hash_algo;
u32 rss_size;
u8 hw_tc_map;
u8 rss_indirection_tbl[HCLGEVF_RSS_IND_TBL_SIZE]; /* shadow table */
struct hclgevf_rss_tuple_cfg rss_tuple_sets;
};
struct hclgevf_misc_vector {
......
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