@@ -931,6 +931,7 @@ struct hns_roce_hem_item {
931931 size_t count ; /* max ba numbers */
932932 int start ; /* start buf offset in this hem */
933933 int end ; /* end buf offset in this hem */
934+ bool exist_bt ;
934935};
935936
936937/* All HEM items are linked in a tree structure */
@@ -959,6 +960,7 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
959960 }
960961 }
961962
963+ hem -> exist_bt = exist_bt ;
962964 hem -> count = count ;
963965 hem -> start = start ;
964966 hem -> end = end ;
@@ -969,22 +971,22 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
969971}
970972
971973static void hem_list_free_item (struct hns_roce_dev * hr_dev ,
972- struct hns_roce_hem_item * hem , bool exist_bt )
974+ struct hns_roce_hem_item * hem )
973975{
974- if (exist_bt )
976+ if (hem -> exist_bt )
975977 dma_free_coherent (hr_dev -> dev , hem -> count * BA_BYTE_LEN ,
976978 hem -> addr , hem -> dma_addr );
977979 kfree (hem );
978980}
979981
980982static void hem_list_free_all (struct hns_roce_dev * hr_dev ,
981- struct list_head * head , bool exist_bt )
983+ struct list_head * head )
982984{
983985 struct hns_roce_hem_item * hem , * temp_hem ;
984986
985987 list_for_each_entry_safe (hem , temp_hem , head , list ) {
986988 list_del (& hem -> list );
987- hem_list_free_item (hr_dev , hem , exist_bt );
989+ hem_list_free_item (hr_dev , hem );
988990 }
989991}
990992
@@ -1084,6 +1086,10 @@ int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions,
10841086
10851087 for (i = 0 ; i < region_cnt ; i ++ ) {
10861088 r = (struct hns_roce_buf_region * )& regions [i ];
1089+ /* when r->hopnum = 0, the region should not occupy root_ba. */
1090+ if (!r -> hopnum )
1091+ continue ;
1092+
10871093 if (r -> hopnum > 1 ) {
10881094 step = hem_list_calc_ba_range (r -> hopnum , 1 , unit );
10891095 if (step > 0 )
@@ -1177,7 +1183,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev,
11771183
11781184err_exit :
11791185 for (level = 1 ; level < hopnum ; level ++ )
1180- hem_list_free_all (hr_dev , & temp_list [level ], true );
1186+ hem_list_free_all (hr_dev , & temp_list [level ]);
11811187
11821188 return ret ;
11831189}
@@ -1218,16 +1224,26 @@ static int alloc_fake_root_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
12181224{
12191225 struct hns_roce_hem_item * hem ;
12201226
1227+ /* This is on the has_mtt branch, if r->hopnum
1228+ * is 0, there is no root_ba to reuse for the
1229+ * region's fake hem, so a dma_alloc request is
1230+ * necessary here.
1231+ */
12211232 hem = hem_list_alloc_item (hr_dev , r -> offset , r -> offset + r -> count - 1 ,
1222- r -> count , false );
1233+ r -> count , ! r -> hopnum );
12231234 if (!hem )
12241235 return - ENOMEM ;
12251236
1226- hem_list_assign_bt (hem , cpu_base , phy_base );
1237+ /* The root_ba can be reused only when r->hopnum > 0. */
1238+ if (r -> hopnum )
1239+ hem_list_assign_bt (hem , cpu_base , phy_base );
12271240 list_add (& hem -> list , branch_head );
12281241 list_add (& hem -> sibling , leaf_head );
12291242
1230- return r -> count ;
1243+ /* If r->hopnum == 0, 0 is returned,
1244+ * so that the root_bt entry is not occupied.
1245+ */
1246+ return r -> hopnum ? r -> count : 0 ;
12311247}
12321248
12331249static int setup_middle_bt (struct hns_roce_dev * hr_dev , void * cpu_base ,
@@ -1271,7 +1287,7 @@ setup_root_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem_list *hem_list,
12711287 return - ENOMEM ;
12721288
12731289 total = 0 ;
1274- for (i = 0 ; i < region_cnt && total < max_ba_num ; i ++ ) {
1290+ for (i = 0 ; i < region_cnt && total <= max_ba_num ; i ++ ) {
12751291 r = & regions [i ];
12761292 if (!r -> count )
12771293 continue ;
@@ -1337,9 +1353,9 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev,
13371353 region_cnt );
13381354 if (ret ) {
13391355 for (i = 0 ; i < region_cnt ; i ++ )
1340- hem_list_free_all (hr_dev , & head .branch [i ], false );
1356+ hem_list_free_all (hr_dev , & head .branch [i ]);
13411357
1342- hem_list_free_all (hr_dev , & head .root , true );
1358+ hem_list_free_all (hr_dev , & head .root );
13431359 }
13441360
13451361 return ret ;
@@ -1402,10 +1418,9 @@ void hns_roce_hem_list_release(struct hns_roce_dev *hr_dev,
14021418
14031419 for (i = 0 ; i < HNS_ROCE_MAX_BT_REGION ; i ++ )
14041420 for (j = 0 ; j < HNS_ROCE_MAX_BT_LEVEL ; j ++ )
1405- hem_list_free_all (hr_dev , & hem_list -> mid_bt [i ][j ],
1406- j != 0 );
1421+ hem_list_free_all (hr_dev , & hem_list -> mid_bt [i ][j ]);
14071422
1408- hem_list_free_all (hr_dev , & hem_list -> root_bt , true );
1423+ hem_list_free_all (hr_dev , & hem_list -> root_bt );
14091424 INIT_LIST_HEAD (& hem_list -> btm_bt );
14101425 hem_list -> root_ba = 0 ;
14111426}
0 commit comments