Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2016 Hisilicon Limited.
0003  * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
0004  *
0005  * This software is available to you under a choice of one of two
0006  * licenses.  You may choose to be licensed under the terms of the GNU
0007  * General Public License (GPL) Version 2, available from the file
0008  * COPYING in the main directory of this source tree, or the
0009  * OpenIB.org BSD license below:
0010  *
0011  *     Redistribution and use in source and binary forms, with or
0012  *     without modification, are permitted provided that the following
0013  *     conditions are met:
0014  *
0015  *      - Redistributions of source code must retain the above
0016  *        copyright notice, this list of conditions and the following
0017  *        disclaimer.
0018  *
0019  *      - Redistributions in binary form must reproduce the above
0020  *        copyright notice, this list of conditions and the following
0021  *        disclaimer in the documentation and/or other materials
0022  *        provided with the distribution.
0023  *
0024  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0025  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0026  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0027  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0028  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0029  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0030  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0031  * SOFTWARE.
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     /* MAP HEM(Hardware Entry Memory) */
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      /* UNMAP HEM */
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; /* level 0 base address table index */
0100     u32 l1_idx; /* level 1 base address table index */
0101     u32 l2_idx; /* level 2 base address table index */
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 /* _HNS_ROCE_HEM_H */