@@ -931,6 +931,7 @@ struct hns_roce_hem_item {
931
931
size_t count ; /* max ba numbers */
932
932
int start ; /* start buf offset in this hem */
933
933
int end ; /* end buf offset in this hem */
934
+ bool exist_bt ;
934
935
};
935
936
936
937
/* 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,
959
960
}
960
961
}
961
962
963
+ hem -> exist_bt = exist_bt ;
962
964
hem -> count = count ;
963
965
hem -> start = start ;
964
966
hem -> end = end ;
@@ -969,22 +971,22 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
969
971
}
970
972
971
973
static 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 )
973
975
{
974
- if (exist_bt )
976
+ if (hem -> exist_bt )
975
977
dma_free_coherent (hr_dev -> dev , hem -> count * BA_BYTE_LEN ,
976
978
hem -> addr , hem -> dma_addr );
977
979
kfree (hem );
978
980
}
979
981
980
982
static void hem_list_free_all (struct hns_roce_dev * hr_dev ,
981
- struct list_head * head , bool exist_bt )
983
+ struct list_head * head )
982
984
{
983
985
struct hns_roce_hem_item * hem , * temp_hem ;
984
986
985
987
list_for_each_entry_safe (hem , temp_hem , head , list ) {
986
988
list_del (& hem -> list );
987
- hem_list_free_item (hr_dev , hem , exist_bt );
989
+ hem_list_free_item (hr_dev , hem );
988
990
}
989
991
}
990
992
@@ -1084,6 +1086,10 @@ int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions,
1084
1086
1085
1087
for (i = 0 ; i < region_cnt ; i ++ ) {
1086
1088
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
+
1087
1093
if (r -> hopnum > 1 ) {
1088
1094
step = hem_list_calc_ba_range (r -> hopnum , 1 , unit );
1089
1095
if (step > 0 )
@@ -1177,7 +1183,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev,
1177
1183
1178
1184
err_exit :
1179
1185
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 ]);
1181
1187
1182
1188
return ret ;
1183
1189
}
@@ -1218,16 +1224,26 @@ static int alloc_fake_root_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
1218
1224
{
1219
1225
struct hns_roce_hem_item * hem ;
1220
1226
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
+ */
1221
1232
hem = hem_list_alloc_item (hr_dev , r -> offset , r -> offset + r -> count - 1 ,
1222
- r -> count , false );
1233
+ r -> count , ! r -> hopnum );
1223
1234
if (!hem )
1224
1235
return - ENOMEM ;
1225
1236
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 );
1227
1240
list_add (& hem -> list , branch_head );
1228
1241
list_add (& hem -> sibling , leaf_head );
1229
1242
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 ;
1231
1247
}
1232
1248
1233
1249
static 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,
1271
1287
return - ENOMEM ;
1272
1288
1273
1289
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 ++ ) {
1275
1291
r = & regions [i ];
1276
1292
if (!r -> count )
1277
1293
continue ;
@@ -1337,9 +1353,9 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev,
1337
1353
region_cnt );
1338
1354
if (ret ) {
1339
1355
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 ]);
1341
1357
1342
- hem_list_free_all (hr_dev , & head .root , true );
1358
+ hem_list_free_all (hr_dev , & head .root );
1343
1359
}
1344
1360
1345
1361
return ret ;
@@ -1402,10 +1418,9 @@ void hns_roce_hem_list_release(struct hns_roce_dev *hr_dev,
1402
1418
1403
1419
for (i = 0 ; i < HNS_ROCE_MAX_BT_REGION ; i ++ )
1404
1420
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 ]);
1407
1422
1408
- hem_list_free_all (hr_dev , & hem_list -> root_bt , true );
1423
+ hem_list_free_all (hr_dev , & hem_list -> root_bt );
1409
1424
INIT_LIST_HEAD (& hem_list -> btm_bt );
1410
1425
hem_list -> root_ba = 0 ;
1411
1426
}
0 commit comments