0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #ifndef _HNS_ROCE_HEM_H
0035 #define _HNS_ROCE_HEM_H
0036
0037 #define HEM_HOP_STEP_DIRECT 0xff
0038
0039 enum {
0040
0041 HEM_TYPE_QPC = 0,
0042 HEM_TYPE_MTPT,
0043 HEM_TYPE_CQC,
0044 HEM_TYPE_SRQC,
0045 HEM_TYPE_SCCC,
0046 HEM_TYPE_QPC_TIMER,
0047 HEM_TYPE_CQC_TIMER,
0048 HEM_TYPE_GMV,
0049
0050
0051 HEM_TYPE_MTT,
0052 HEM_TYPE_CQE,
0053 HEM_TYPE_SRQWQE,
0054 HEM_TYPE_IDX,
0055 HEM_TYPE_IRRL,
0056 HEM_TYPE_TRRL,
0057 };
0058
0059 #define HNS_ROCE_HEM_CHUNK_LEN \
0060 ((256 - sizeof(struct list_head) - 2 * sizeof(int)) / \
0061 (sizeof(struct scatterlist) + sizeof(void *)))
0062
0063 #define check_whether_bt_num_3(type, hop_num) \
0064 (type < HEM_TYPE_MTT && hop_num == 2)
0065
0066 #define check_whether_bt_num_2(type, hop_num) \
0067 ((type < HEM_TYPE_MTT && hop_num == 1) || \
0068 (type >= HEM_TYPE_MTT && hop_num == 2))
0069
0070 #define check_whether_bt_num_1(type, hop_num) \
0071 ((type < HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0) || \
0072 (type >= HEM_TYPE_MTT && hop_num == 1) || \
0073 (type >= HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0))
0074
0075 struct hns_roce_hem_chunk {
0076 struct list_head list;
0077 int npages;
0078 int nsg;
0079 struct scatterlist mem[HNS_ROCE_HEM_CHUNK_LEN];
0080 void *buf[HNS_ROCE_HEM_CHUNK_LEN];
0081 };
0082
0083 struct hns_roce_hem {
0084 struct list_head chunk_list;
0085 refcount_t refcount;
0086 };
0087
0088 struct hns_roce_hem_iter {
0089 struct hns_roce_hem *hem;
0090 struct hns_roce_hem_chunk *chunk;
0091 int page_idx;
0092 };
0093
0094 struct hns_roce_hem_mhop {
0095 u32 hop_num;
0096 u32 buf_chunk_size;
0097 u32 bt_chunk_size;
0098 u32 ba_l0_num;
0099 u32 l0_idx;
0100 u32 l1_idx;
0101 u32 l2_idx;
0102 };
0103
0104 void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem);
0105 int hns_roce_table_get(struct hns_roce_dev *hr_dev,
0106 struct hns_roce_hem_table *table, unsigned long obj);
0107 void hns_roce_table_put(struct hns_roce_dev *hr_dev,
0108 struct hns_roce_hem_table *table, unsigned long obj);
0109 void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
0110 struct hns_roce_hem_table *table, unsigned long obj,
0111 dma_addr_t *dma_handle);
0112 int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
0113 struct hns_roce_hem_table *table, u32 type,
0114 unsigned long obj_size, unsigned long nobj,
0115 int use_lowmem);
0116 void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev,
0117 struct hns_roce_hem_table *table);
0118 void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev);
0119 int hns_roce_calc_hem_mhop(struct hns_roce_dev *hr_dev,
0120 struct hns_roce_hem_table *table, unsigned long *obj,
0121 struct hns_roce_hem_mhop *mhop);
0122 bool hns_roce_check_whether_mhop(struct hns_roce_dev *hr_dev, u32 type);
0123
0124 void hns_roce_hem_list_init(struct hns_roce_hem_list *hem_list);
0125 int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions,
0126 int region_cnt, int unit);
0127 int hns_roce_hem_list_request(struct hns_roce_dev *hr_dev,
0128 struct hns_roce_hem_list *hem_list,
0129 const struct hns_roce_buf_region *regions,
0130 int region_cnt, unsigned int bt_pg_shift);
0131 void hns_roce_hem_list_release(struct hns_roce_dev *hr_dev,
0132 struct hns_roce_hem_list *hem_list);
0133 void *hns_roce_hem_list_find_mtt(struct hns_roce_dev *hr_dev,
0134 struct hns_roce_hem_list *hem_list,
0135 int offset, int *mtt_cnt, u64 *phy_addr);
0136
0137 static inline void hns_roce_hem_first(struct hns_roce_hem *hem,
0138 struct hns_roce_hem_iter *iter)
0139 {
0140 iter->hem = hem;
0141 iter->chunk = list_empty(&hem->chunk_list) ? NULL :
0142 list_entry(hem->chunk_list.next,
0143 struct hns_roce_hem_chunk, list);
0144 iter->page_idx = 0;
0145 }
0146
0147 static inline int hns_roce_hem_last(struct hns_roce_hem_iter *iter)
0148 {
0149 return !iter->chunk;
0150 }
0151
0152 static inline void hns_roce_hem_next(struct hns_roce_hem_iter *iter)
0153 {
0154 if (++iter->page_idx >= iter->chunk->nsg) {
0155 if (iter->chunk->list.next == &iter->hem->chunk_list) {
0156 iter->chunk = NULL;
0157 return;
0158 }
0159
0160 iter->chunk = list_entry(iter->chunk->list.next,
0161 struct hns_roce_hem_chunk, list);
0162 iter->page_idx = 0;
0163 }
0164 }
0165
0166 static inline dma_addr_t hns_roce_hem_addr(struct hns_roce_hem_iter *iter)
0167 {
0168 return sg_dma_address(&iter->chunk->mem[iter->page_idx]);
0169 }
0170
0171 #endif