net: hns3: Add RSS general configuration support for VF

This patch adds RSS key, hash algorithm configuration support
for VF in revision 0x21.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jian Shen 2018-10-10 20:05:35 +01:00 committed by David S. Miller
parent 775501a1aa
commit 374ad29176
2 changed files with 107 additions and 53 deletions

View File

@ -148,7 +148,8 @@ struct hclgevf_query_res_cmd {
__le16 rsv[7]; __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 #define HCLGEVF_RSS_HASH_KEY_NUM 16
struct hclgevf_rss_config_cmd { struct hclgevf_rss_config_cmd {
u8 hash_config; u8 hash_config;

View File

@ -386,6 +386,47 @@ static int hclgevf_get_vector_index(struct hclgevf_dev *hdev, int vector)
return -EINVAL; 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) static u32 hclgevf_get_rss_key_size(struct hnae3_handle *handle)
{ {
return HCLGEVF_RSS_KEY_SIZE; 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; 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, static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
u8 *hfunc) 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; struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
int i; 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) if (indir)
for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++)
indir[i] = rss_cfg->rss_indirection_tbl[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, 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_dev *hdev = hclgevf_ae_get_hdev(handle);
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; 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 */ /* update the shadow RSS table with user specified qids */
for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++)
@ -1276,6 +1318,17 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
rss_cfg->rss_size = hdev->rss_size_max; 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;
}
/* Initialize RSS indirect table for each vport */ /* Initialize RSS indirect table for each vport */
for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++)
rss_cfg->rss_indirection_tbl[i] = i % hdev->rss_size_max; rss_cfg->rss_indirection_tbl[i] = i % hdev->rss_size_max;