Merge branch 'hns3-next'
Salil Mehta says: ==================== Adds support of RSS to HNS3 Driver for Rev 2(=0x21) H/W This patch-set mainly adds new additions related to RSS for the new hardware Revision 0x21. It also adds support to use RSS hash value provided by the hardware along with descriptor. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b7ec45a868
7 changed files with 407 additions and 65 deletions
|
|
@ -479,6 +479,7 @@ struct hnae3_knic_private_info {
|
|||
const struct hnae3_dcb_ops *dcb_ops;
|
||||
|
||||
u16 int_rl_setting;
|
||||
enum pkt_hash_types rss_type;
|
||||
};
|
||||
|
||||
struct hnae3_roce_private_info {
|
||||
|
|
|
|||
|
|
@ -2230,6 +2230,21 @@ static bool hns3_parse_vlan_tag(struct hns3_enet_ring *ring,
|
|||
}
|
||||
}
|
||||
|
||||
static void hns3_set_rx_skb_rss_type(struct hns3_enet_ring *ring,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hns3_desc *desc = &ring->desc[ring->next_to_clean];
|
||||
struct hnae3_handle *handle = ring->tqp->handle;
|
||||
enum pkt_hash_types rss_type;
|
||||
|
||||
if (le32_to_cpu(desc->rx.rss_hash))
|
||||
rss_type = handle->kinfo.rss_type;
|
||||
else
|
||||
rss_type = PKT_HASH_TYPE_NONE;
|
||||
|
||||
skb_set_hash(skb, le32_to_cpu(desc->rx.rss_hash), rss_type);
|
||||
}
|
||||
|
||||
static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
|
||||
struct sk_buff **out_skb, int *out_bnum)
|
||||
{
|
||||
|
|
@ -2371,6 +2386,8 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
|
|||
ring->tqp_vector->rx_group.total_bytes += skb->len;
|
||||
|
||||
hns3_rx_checksum(ring, skb, desc);
|
||||
hns3_set_rx_skb_rss_type(ring, skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -678,12 +678,13 @@ static int hns3_set_rss(struct net_device *netdev, const u32 *indir,
|
|||
if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->set_rss)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* currently we only support Toeplitz hash */
|
||||
if ((hfunc != ETH_RSS_HASH_NO_CHANGE) && (hfunc != ETH_RSS_HASH_TOP)) {
|
||||
netdev_err(netdev,
|
||||
"hash func not supported (only Toeplitz hash)\n");
|
||||
if ((h->pdev->revision == 0x20 &&
|
||||
hfunc != ETH_RSS_HASH_TOP) || (hfunc != ETH_RSS_HASH_NO_CHANGE &&
|
||||
hfunc != ETH_RSS_HASH_TOP && hfunc != ETH_RSS_HASH_XOR)) {
|
||||
netdev_err(netdev, "hash func not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!indir) {
|
||||
netdev_err(netdev,
|
||||
"set rss failed for indir is empty\n");
|
||||
|
|
@ -1077,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,
|
||||
|
|
|
|||
|
|
@ -2773,6 +2773,22 @@ static int hclge_set_rss_tc_mode(struct hclge_dev *hdev, u16 *tc_valid,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void hclge_get_rss_type(struct hclge_vport *vport)
|
||||
{
|
||||
if (vport->rss_tuple_sets.ipv4_tcp_en ||
|
||||
vport->rss_tuple_sets.ipv4_udp_en ||
|
||||
vport->rss_tuple_sets.ipv4_sctp_en ||
|
||||
vport->rss_tuple_sets.ipv6_tcp_en ||
|
||||
vport->rss_tuple_sets.ipv6_udp_en ||
|
||||
vport->rss_tuple_sets.ipv6_sctp_en)
|
||||
vport->nic.kinfo.rss_type = PKT_HASH_TYPE_L4;
|
||||
else if (vport->rss_tuple_sets.ipv4_fragment_en ||
|
||||
vport->rss_tuple_sets.ipv6_fragment_en)
|
||||
vport->nic.kinfo.rss_type = PKT_HASH_TYPE_L3;
|
||||
else
|
||||
vport->nic.kinfo.rss_type = PKT_HASH_TYPE_NONE;
|
||||
}
|
||||
|
||||
static int hclge_set_rss_input_tuple(struct hclge_dev *hdev)
|
||||
{
|
||||
struct hclge_rss_input_tuple_cmd *req;
|
||||
|
|
@ -2792,6 +2808,7 @@ static int hclge_set_rss_input_tuple(struct hclge_dev *hdev)
|
|||
req->ipv6_udp_en = hdev->vport[0].rss_tuple_sets.ipv6_udp_en;
|
||||
req->ipv6_sctp_en = hdev->vport[0].rss_tuple_sets.ipv6_sctp_en;
|
||||
req->ipv6_fragment_en = hdev->vport[0].rss_tuple_sets.ipv6_fragment_en;
|
||||
hclge_get_rss_type(&hdev->vport[0]);
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret)
|
||||
dev_err(&hdev->pdev->dev,
|
||||
|
|
@ -2806,8 +2823,19 @@ static int hclge_get_rss(struct hnae3_handle *handle, u32 *indir,
|
|||
int i;
|
||||
|
||||
/* Get hash algorithm */
|
||||
if (hfunc)
|
||||
*hfunc = vport->rss_algo;
|
||||
if (hfunc) {
|
||||
switch (vport->rss_algo) {
|
||||
case HCLGE_RSS_HASH_ALGO_TOEPLITZ:
|
||||
*hfunc = ETH_RSS_HASH_TOP;
|
||||
break;
|
||||
case HCLGE_RSS_HASH_ALGO_SIMPLE:
|
||||
*hfunc = ETH_RSS_HASH_XOR;
|
||||
break;
|
||||
default:
|
||||
*hfunc = ETH_RSS_HASH_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the RSS Key required by the user */
|
||||
if (key)
|
||||
|
|
@ -2831,12 +2859,20 @@ static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir,
|
|||
|
||||
/* Set the RSS Hash Key if specififed by the user */
|
||||
if (key) {
|
||||
|
||||
if (hfunc == ETH_RSS_HASH_TOP ||
|
||||
hfunc == ETH_RSS_HASH_NO_CHANGE)
|
||||
switch (hfunc) {
|
||||
case ETH_RSS_HASH_TOP:
|
||||
hash_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ;
|
||||
else
|
||||
break;
|
||||
case ETH_RSS_HASH_XOR:
|
||||
hash_algo = HCLGE_RSS_HASH_ALGO_SIMPLE;
|
||||
break;
|
||||
case ETH_RSS_HASH_NO_CHANGE:
|
||||
hash_algo = vport->rss_algo;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = hclge_set_rss_algo_key(hdev, hash_algo, key);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -2954,6 +2990,7 @@ static int hclge_set_rss_tuple(struct hnae3_handle *handle,
|
|||
vport->rss_tuple_sets.ipv6_udp_en = req->ipv6_udp_en;
|
||||
vport->rss_tuple_sets.ipv6_sctp_en = req->ipv6_sctp_en;
|
||||
vport->rss_tuple_sets.ipv6_fragment_en = req->ipv6_fragment_en;
|
||||
hclge_get_rss_type(vport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -148,7 +149,8 @@ struct hclgevf_query_res_cmd {
|
|||
__le16 rsv[7];
|
||||
};
|
||||
|
||||
#define HCLGEVF_RSS_HASH_KEY_OFFSET 4
|
||||
#define HCLGEVF_RSS_DEFAULT_OUTPORT_B 4
|
||||
#define HCLGEVF_RSS_HASH_KEY_OFFSET_B 4
|
||||
#define HCLGEVF_RSS_HASH_KEY_NUM 16
|
||||
struct hclgevf_rss_config_cmd {
|
||||
u8 hash_config;
|
||||
|
|
@ -159,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];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -386,6 +386,47 @@ static int hclgevf_get_vector_index(struct hclgevf_dev *hdev, int vector)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int hclgevf_set_rss_algo_key(struct hclgevf_dev *hdev,
|
||||
const u8 hfunc, const u8 *key)
|
||||
{
|
||||
struct hclgevf_rss_config_cmd *req;
|
||||
struct hclgevf_desc desc;
|
||||
int key_offset;
|
||||
int key_size;
|
||||
int ret;
|
||||
|
||||
req = (struct hclgevf_rss_config_cmd *)desc.data;
|
||||
|
||||
for (key_offset = 0; key_offset < 3; key_offset++) {
|
||||
hclgevf_cmd_setup_basic_desc(&desc,
|
||||
HCLGEVF_OPC_RSS_GENERIC_CONFIG,
|
||||
false);
|
||||
|
||||
req->hash_config |= (hfunc & HCLGEVF_RSS_HASH_ALGO_MASK);
|
||||
req->hash_config |=
|
||||
(key_offset << HCLGEVF_RSS_HASH_KEY_OFFSET_B);
|
||||
|
||||
if (key_offset == 2)
|
||||
key_size =
|
||||
HCLGEVF_RSS_KEY_SIZE - HCLGEVF_RSS_HASH_KEY_NUM * 2;
|
||||
else
|
||||
key_size = HCLGEVF_RSS_HASH_KEY_NUM;
|
||||
|
||||
memcpy(req->hash_key,
|
||||
key + key_offset * HCLGEVF_RSS_HASH_KEY_NUM, key_size);
|
||||
|
||||
ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"Configure RSS config fail, status = %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 hclgevf_get_rss_key_size(struct hnae3_handle *handle)
|
||||
{
|
||||
return HCLGEVF_RSS_KEY_SIZE;
|
||||
|
|
@ -466,56 +507,6 @@ static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size)
|
|||
return status;
|
||||
}
|
||||
|
||||
static int hclgevf_get_rss_hw_cfg(struct hnae3_handle *handle, u8 *hash,
|
||||
u8 *key)
|
||||
{
|
||||
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
||||
struct hclgevf_rss_config_cmd *req;
|
||||
int lkup_times = key ? 3 : 1;
|
||||
struct hclgevf_desc desc;
|
||||
int key_offset;
|
||||
int key_size;
|
||||
int status;
|
||||
|
||||
req = (struct hclgevf_rss_config_cmd *)desc.data;
|
||||
lkup_times = (lkup_times == 3) ? 3 : ((hash) ? 1 : 0);
|
||||
|
||||
for (key_offset = 0; key_offset < lkup_times; key_offset++) {
|
||||
hclgevf_cmd_setup_basic_desc(&desc,
|
||||
HCLGEVF_OPC_RSS_GENERIC_CONFIG,
|
||||
true);
|
||||
req->hash_config |= (key_offset << HCLGEVF_RSS_HASH_KEY_OFFSET);
|
||||
|
||||
status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (status) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"failed to get hardware RSS cfg, status = %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (key_offset == 2)
|
||||
key_size =
|
||||
HCLGEVF_RSS_KEY_SIZE - HCLGEVF_RSS_HASH_KEY_NUM * 2;
|
||||
else
|
||||
key_size = HCLGEVF_RSS_HASH_KEY_NUM;
|
||||
|
||||
if (key)
|
||||
memcpy(key + key_offset * HCLGEVF_RSS_HASH_KEY_NUM,
|
||||
req->hash_key,
|
||||
key_size);
|
||||
}
|
||||
|
||||
if (hash) {
|
||||
if ((req->hash_config & 0xf) == HCLGEVF_RSS_HASH_ALGO_TOEPLITZ)
|
||||
*hash = ETH_RSS_HASH_TOP;
|
||||
else
|
||||
*hash = ETH_RSS_HASH_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
|
||||
u8 *hfunc)
|
||||
{
|
||||
|
|
@ -523,11 +514,33 @@ static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
|
|||
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
|
||||
int i;
|
||||
|
||||
if (handle->pdev->revision >= 0x21) {
|
||||
/* Get hash algorithm */
|
||||
if (hfunc) {
|
||||
switch (rss_cfg->hash_algo) {
|
||||
case HCLGEVF_RSS_HASH_ALGO_TOEPLITZ:
|
||||
*hfunc = ETH_RSS_HASH_TOP;
|
||||
break;
|
||||
case HCLGEVF_RSS_HASH_ALGO_SIMPLE:
|
||||
*hfunc = ETH_RSS_HASH_XOR;
|
||||
break;
|
||||
default:
|
||||
*hfunc = ETH_RSS_HASH_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the RSS Key required by the user */
|
||||
if (key)
|
||||
memcpy(key, rss_cfg->rss_hash_key,
|
||||
HCLGEVF_RSS_KEY_SIZE);
|
||||
}
|
||||
|
||||
if (indir)
|
||||
for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++)
|
||||
indir[i] = rss_cfg->rss_indirection_tbl[i];
|
||||
|
||||
return hclgevf_get_rss_hw_cfg(handle, hfunc, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir,
|
||||
|
|
@ -535,7 +548,36 @@ static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir,
|
|||
{
|
||||
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
||||
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
|
||||
int i;
|
||||
int ret, i;
|
||||
|
||||
if (handle->pdev->revision >= 0x21) {
|
||||
/* Set the RSS Hash Key if specififed by the user */
|
||||
if (key) {
|
||||
switch (hfunc) {
|
||||
case ETH_RSS_HASH_TOP:
|
||||
rss_cfg->hash_algo =
|
||||
HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
|
||||
break;
|
||||
case ETH_RSS_HASH_XOR:
|
||||
rss_cfg->hash_algo =
|
||||
HCLGEVF_RSS_HASH_ALGO_SIMPLE;
|
||||
break;
|
||||
case ETH_RSS_HASH_NO_CHANGE:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo,
|
||||
key);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Update the shadow RSS key with user specified qids */
|
||||
memcpy(rss_cfg->rss_hash_key, key,
|
||||
HCLGEVF_RSS_KEY_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/* update the shadow RSS table with user specified qids */
|
||||
for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++)
|
||||
|
|
@ -545,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);
|
||||
|
|
@ -1276,6 +1505,39 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
|
|||
|
||||
rss_cfg->rss_size = hdev->rss_size_max;
|
||||
|
||||
if (hdev->pdev->revision >= 0x21) {
|
||||
rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
|
||||
netdev_rss_key_fill(rss_cfg->rss_hash_key,
|
||||
HCLGEVF_RSS_KEY_SIZE);
|
||||
|
||||
ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo,
|
||||
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 */
|
||||
for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++)
|
||||
rss_cfg->rss_indirection_tbl[i] = i % hdev->rss_size_max;
|
||||
|
|
@ -1918,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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue