diff options
author | Jian Shen <shenjian15@huawei.com> | 2018-10-10 15:05:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-11 01:59:08 -0400 |
commit | 374ad291762a24b7ed3118129aca7fcfe4f1ba9d (patch) | |
tree | f8da56590c958144e2e8baac79e9391c53918d79 | |
parent | 775501a1aabab99c5fd0864f42c7a48cdc521db7 (diff) |
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>
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 155 |
2 files changed, 106 insertions, 52 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index 19b32860309c..eb8ed11d6964 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | |||
@@ -148,7 +148,8 @@ struct hclgevf_query_res_cmd { | |||
148 | __le16 rsv[7]; | 148 | __le16 rsv[7]; |
149 | }; | 149 | }; |
150 | 150 | ||
151 | #define HCLGEVF_RSS_HASH_KEY_OFFSET 4 | 151 | #define HCLGEVF_RSS_DEFAULT_OUTPORT_B 4 |
152 | #define HCLGEVF_RSS_HASH_KEY_OFFSET_B 4 | ||
152 | #define HCLGEVF_RSS_HASH_KEY_NUM 16 | 153 | #define HCLGEVF_RSS_HASH_KEY_NUM 16 |
153 | struct hclgevf_rss_config_cmd { | 154 | struct hclgevf_rss_config_cmd { |
154 | u8 hash_config; | 155 | u8 hash_config; |
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index ca4a9f790917..f21196b675cb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | |||
@@ -386,6 +386,47 @@ static int hclgevf_get_vector_index(struct hclgevf_dev *hdev, int vector) | |||
386 | return -EINVAL; | 386 | return -EINVAL; |
387 | } | 387 | } |
388 | 388 | ||
389 | static int hclgevf_set_rss_algo_key(struct hclgevf_dev *hdev, | ||
390 | const u8 hfunc, const u8 *key) | ||
391 | { | ||
392 | struct hclgevf_rss_config_cmd *req; | ||
393 | struct hclgevf_desc desc; | ||
394 | int key_offset; | ||
395 | int key_size; | ||
396 | int ret; | ||
397 | |||
398 | req = (struct hclgevf_rss_config_cmd *)desc.data; | ||
399 | |||
400 | for (key_offset = 0; key_offset < 3; key_offset++) { | ||
401 | hclgevf_cmd_setup_basic_desc(&desc, | ||
402 | HCLGEVF_OPC_RSS_GENERIC_CONFIG, | ||
403 | false); | ||
404 | |||
405 | req->hash_config |= (hfunc & HCLGEVF_RSS_HASH_ALGO_MASK); | ||
406 | req->hash_config |= | ||
407 | (key_offset << HCLGEVF_RSS_HASH_KEY_OFFSET_B); | ||
408 | |||
409 | if (key_offset == 2) | ||
410 | key_size = | ||
411 | HCLGEVF_RSS_KEY_SIZE - HCLGEVF_RSS_HASH_KEY_NUM * 2; | ||
412 | else | ||
413 | key_size = HCLGEVF_RSS_HASH_KEY_NUM; | ||
414 | |||
415 | memcpy(req->hash_key, | ||
416 | key + key_offset * HCLGEVF_RSS_HASH_KEY_NUM, key_size); | ||
417 | |||
418 | ret = hclgevf_cmd_send(&hdev->hw, &desc, 1); | ||
419 | if (ret) { | ||
420 | dev_err(&hdev->pdev->dev, | ||
421 | "Configure RSS config fail, status = %d\n", | ||
422 | ret); | ||
423 | return ret; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
389 | static u32 hclgevf_get_rss_key_size(struct hnae3_handle *handle) | 430 | static u32 hclgevf_get_rss_key_size(struct hnae3_handle *handle) |
390 | { | 431 | { |
391 | return HCLGEVF_RSS_KEY_SIZE; | 432 | return HCLGEVF_RSS_KEY_SIZE; |
@@ -466,68 +507,40 @@ static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size) | |||
466 | return status; | 507 | return status; |
467 | } | 508 | } |
468 | 509 | ||
469 | static int hclgevf_get_rss_hw_cfg(struct hnae3_handle *handle, u8 *hash, | 510 | static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key, |
470 | u8 *key) | 511 | u8 *hfunc) |
471 | { | 512 | { |
472 | struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); | 513 | struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); |
473 | struct hclgevf_rss_config_cmd *req; | 514 | struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; |
474 | int lkup_times = key ? 3 : 1; | 515 | int i; |
475 | struct hclgevf_desc desc; | ||
476 | int key_offset; | ||
477 | int key_size; | ||
478 | int status; | ||
479 | |||
480 | req = (struct hclgevf_rss_config_cmd *)desc.data; | ||
481 | lkup_times = (lkup_times == 3) ? 3 : ((hash) ? 1 : 0); | ||
482 | |||
483 | for (key_offset = 0; key_offset < lkup_times; key_offset++) { | ||
484 | hclgevf_cmd_setup_basic_desc(&desc, | ||
485 | HCLGEVF_OPC_RSS_GENERIC_CONFIG, | ||
486 | true); | ||
487 | req->hash_config |= (key_offset << HCLGEVF_RSS_HASH_KEY_OFFSET); | ||
488 | 516 | ||
489 | status = hclgevf_cmd_send(&hdev->hw, &desc, 1); | 517 | if (handle->pdev->revision >= 0x21) { |
490 | if (status) { | 518 | /* Get hash algorithm */ |
491 | dev_err(&hdev->pdev->dev, | 519 | if (hfunc) { |
492 | "failed to get hardware RSS cfg, status = %d\n", | 520 | switch (rss_cfg->hash_algo) { |
493 | status); | 521 | case HCLGEVF_RSS_HASH_ALGO_TOEPLITZ: |
494 | return status; | 522 | *hfunc = ETH_RSS_HASH_TOP; |
523 | break; | ||
524 | case HCLGEVF_RSS_HASH_ALGO_SIMPLE: | ||
525 | *hfunc = ETH_RSS_HASH_XOR; | ||
526 | break; | ||
527 | default: | ||
528 | *hfunc = ETH_RSS_HASH_UNKNOWN; | ||
529 | break; | ||
530 | } | ||
495 | } | 531 | } |
496 | 532 | ||
497 | if (key_offset == 2) | 533 | /* Get the RSS Key required by the user */ |
498 | key_size = | ||
499 | HCLGEVF_RSS_KEY_SIZE - HCLGEVF_RSS_HASH_KEY_NUM * 2; | ||
500 | else | ||
501 | key_size = HCLGEVF_RSS_HASH_KEY_NUM; | ||
502 | |||
503 | if (key) | 534 | if (key) |
504 | memcpy(key + key_offset * HCLGEVF_RSS_HASH_KEY_NUM, | 535 | memcpy(key, rss_cfg->rss_hash_key, |
505 | req->hash_key, | 536 | HCLGEVF_RSS_KEY_SIZE); |
506 | key_size); | ||
507 | } | 537 | } |
508 | 538 | ||
509 | if (hash) { | ||
510 | if ((req->hash_config & 0xf) == HCLGEVF_RSS_HASH_ALGO_TOEPLITZ) | ||
511 | *hash = ETH_RSS_HASH_TOP; | ||
512 | else | ||
513 | *hash = ETH_RSS_HASH_UNKNOWN; | ||
514 | } | ||
515 | |||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key, | ||
520 | u8 *hfunc) | ||
521 | { | ||
522 | struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); | ||
523 | struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; | ||
524 | int i; | ||
525 | |||
526 | if (indir) | 539 | if (indir) |
527 | for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) | 540 | for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) |
528 | indir[i] = rss_cfg->rss_indirection_tbl[i]; | 541 | indir[i] = rss_cfg->rss_indirection_tbl[i]; |
529 | 542 | ||
530 | return hclgevf_get_rss_hw_cfg(handle, hfunc, key); | 543 | return 0; |
531 | } | 544 | } |
532 | 545 | ||
533 | static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir, | 546 | 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, | |||
535 | { | 548 | { |
536 | struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); | 549 | struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); |
537 | struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; | 550 | struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; |
538 | int i; | 551 | int ret, i; |
552 | |||
553 | if (handle->pdev->revision >= 0x21) { | ||
554 | /* Set the RSS Hash Key if specififed by the user */ | ||
555 | if (key) { | ||
556 | switch (hfunc) { | ||
557 | case ETH_RSS_HASH_TOP: | ||
558 | rss_cfg->hash_algo = | ||
559 | HCLGEVF_RSS_HASH_ALGO_TOEPLITZ; | ||
560 | break; | ||
561 | case ETH_RSS_HASH_XOR: | ||
562 | rss_cfg->hash_algo = | ||
563 | HCLGEVF_RSS_HASH_ALGO_SIMPLE; | ||
564 | break; | ||
565 | case ETH_RSS_HASH_NO_CHANGE: | ||
566 | break; | ||
567 | default: | ||
568 | return -EINVAL; | ||
569 | } | ||
570 | |||
571 | ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo, | ||
572 | key); | ||
573 | if (ret) | ||
574 | return ret; | ||
575 | |||
576 | /* Update the shadow RSS key with user specified qids */ | ||
577 | memcpy(rss_cfg->rss_hash_key, key, | ||
578 | HCLGEVF_RSS_KEY_SIZE); | ||
579 | } | ||
580 | } | ||
539 | 581 | ||
540 | /* update the shadow RSS table with user specified qids */ | 582 | /* update the shadow RSS table with user specified qids */ |
541 | for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) | 583 | for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) |
@@ -1276,6 +1318,17 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) | |||
1276 | 1318 | ||
1277 | rss_cfg->rss_size = hdev->rss_size_max; | 1319 | rss_cfg->rss_size = hdev->rss_size_max; |
1278 | 1320 | ||
1321 | if (hdev->pdev->revision >= 0x21) { | ||
1322 | rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_TOEPLITZ; | ||
1323 | netdev_rss_key_fill(rss_cfg->rss_hash_key, | ||
1324 | HCLGEVF_RSS_KEY_SIZE); | ||
1325 | |||
1326 | ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo, | ||
1327 | rss_cfg->rss_hash_key); | ||
1328 | if (ret) | ||
1329 | return ret; | ||
1330 | } | ||
1331 | |||
1279 | /* Initialize RSS indirect table for each vport */ | 1332 | /* Initialize RSS indirect table for each vport */ |
1280 | for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) | 1333 | for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) |
1281 | rss_cfg->rss_indirection_tbl[i] = i % hdev->rss_size_max; | 1334 | rss_cfg->rss_indirection_tbl[i] = i % hdev->rss_size_max; |