net: hns3: Fix for setting rss_size incorrectly
authorYunsheng Lin <linyunsheng@huawei.com>
Wed, 20 Sep 2017 10:52:57 +0000 (18:52 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 20 Sep 2017 23:15:40 +0000 (16:15 -0700)
rss_size is 1, 2, 4, 8, 16, 32, 64, 128, but acutal tc queue
size can be any u16 less than 128. If tc queue size is 5, we
set the rss_size to 8, indirection table will be used to limit
the size of actual queue size.
It may cause dropping of receiving packet in hardware if
rss_size is not set correctly.
For now, each TC has the same rss size.

Fixes: 46a3df9f9718 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support")
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c

index c660f0caf7092ba1adc55137055e903b80f9c6a6..e0685e630afec795db1e5f1d3221919cd2766ba8 100644 (file)
@@ -2606,6 +2606,7 @@ static int hclge_rss_init_hw(struct hclge_dev *hdev)
        u16 tc_valid[HCLGE_MAX_TC_NUM];
        u16 tc_size[HCLGE_MAX_TC_NUM];
        u32 *rss_indir = NULL;
+       u16 rss_size = 0, roundup_size;
        const u8 *key;
        int i, ret, j;
 
@@ -2620,7 +2621,13 @@ static int hclge_rss_init_hw(struct hclge_dev *hdev)
        for (j = 0; j < hdev->num_vmdq_vport + 1; j++) {
                for (i = 0; i < HCLGE_RSS_IND_TBL_SIZE; i++) {
                        vport[j].rss_indirection_tbl[i] =
-                               i % hdev->rss_size_max;
+                               i % vport[j].alloc_rss_size;
+
+                       /* vport 0 is for PF */
+                       if (j != 0)
+                               continue;
+
+                       rss_size = vport[j].alloc_rss_size;
                        rss_indir[i] = vport[j].rss_indirection_tbl[i];
                }
        }
@@ -2637,42 +2644,31 @@ static int hclge_rss_init_hw(struct hclge_dev *hdev)
        if (ret)
                goto err;
 
+       /* Each TC have the same queue size, and tc_size set to hardware is
+        * the log2 of roundup power of two of rss_size, the acutal queue
+        * size is limited by indirection table.
+        */
+       if (rss_size > HCLGE_RSS_TC_SIZE_7 || rss_size == 0) {
+               dev_err(&hdev->pdev->dev,
+                       "Configure rss tc size failed, invalid TC_SIZE = %d\n",
+                       rss_size);
+               return -EINVAL;
+       }
+
+       roundup_size = roundup_pow_of_two(rss_size);
+       roundup_size = ilog2(roundup_size);
+
        for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
-               if (hdev->hw_tc_map & BIT(i))
-                       tc_valid[i] = 1;
-               else
-                       tc_valid[i] = 0;
+               tc_valid[i] = 0;
 
-               switch (hdev->rss_size_max) {
-               case HCLGE_RSS_TC_SIZE_0:
-                       tc_size[i] = 0;
-                       break;
-               case HCLGE_RSS_TC_SIZE_1:
-                       tc_size[i] = 1;
-                       break;
-               case HCLGE_RSS_TC_SIZE_2:
-                       tc_size[i] = 2;
-                       break;
-               case HCLGE_RSS_TC_SIZE_3:
-                       tc_size[i] = 3;
-                       break;
-               case HCLGE_RSS_TC_SIZE_4:
-                       tc_size[i] = 4;
-                       break;
-               case HCLGE_RSS_TC_SIZE_5:
-                       tc_size[i] = 5;
-                       break;
-               case HCLGE_RSS_TC_SIZE_6:
-                       tc_size[i] = 6;
-                       break;
-               case HCLGE_RSS_TC_SIZE_7:
-                       tc_size[i] = 7;
-                       break;
-               default:
-                       break;
-               }
-               tc_offset[i] = hdev->rss_size_max * i;
+               if (!(hdev->hw_tc_map & BIT(i)))
+                       continue;
+
+               tc_valid[i] = 1;
+               tc_size[i] = roundup_size;
+               tc_offset[i] = rss_size * i;
        }
+
        ret = hclge_set_rss_tc_mode(hdev, tc_valid, tc_size, tc_offset);
 
 err:
@@ -4167,12 +4163,6 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
                return ret;
        }
 
-       ret = hclge_rss_init_hw(hdev);
-       if (ret) {
-               dev_err(&pdev->dev, "Rss init fail, ret =%d\n", ret);
-               return  ret;
-       }
-
        ret = hclge_init_vlan_config(hdev);
        if (ret) {
                dev_err(&pdev->dev, "VLAN init fail, ret =%d\n", ret);
@@ -4185,6 +4175,12 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
                return ret;
        }
 
+       ret = hclge_rss_init_hw(hdev);
+       if (ret) {
+               dev_err(&pdev->dev, "Rss init fail, ret =%d\n", ret);
+               return ret;
+       }
+
        setup_timer(&hdev->service_timer, hclge_service_timer,
                    (unsigned long)hdev);
        INIT_WORK(&hdev->service_task, hclge_service_task);
index edb10ad075eb2520a3f671d8062f043ddb1c8280..7f8dd129c10d2139169cef76749f87d8b3e32f04 100644 (file)
@@ -477,6 +477,7 @@ struct hclge_vport {
        u8  rss_hash_key[HCLGE_RSS_KEY_SIZE]; /* User configured hash keys */
        /* User configured lookup table entries */
        u8  rss_indirection_tbl[HCLGE_RSS_IND_TBL_SIZE];
+       u16 alloc_rss_size;
 
        u16 qs_offset;
        u16 bw_limit;           /* VSI BW Limit (0 = disabled) */
index fe659f752237c042add4f45baa299590875e851d..b7ba7aa66620f58be08bfc1b8d8b4565c0464cee 100644 (file)
@@ -397,6 +397,7 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
                        kinfo->num_tqps / kinfo->num_tc);
        vport->qs_offset = hdev->tm_info.num_tc * vport->vport_id;
        vport->dwrr = 100;  /* 100 percent as init */
+       vport->alloc_rss_size = kinfo->rss_size;
 
        for (i = 0; i < kinfo->num_tc; i++) {
                if (hdev->hw_tc_map & BIT(i)) {