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 #include <linux/string.h>
0035 #include <linux/slab.h>
0036
0037 #include "mthca_profile.h"
0038
0039 enum {
0040 MTHCA_RES_QP,
0041 MTHCA_RES_EEC,
0042 MTHCA_RES_SRQ,
0043 MTHCA_RES_CQ,
0044 MTHCA_RES_EQP,
0045 MTHCA_RES_EEEC,
0046 MTHCA_RES_EQ,
0047 MTHCA_RES_RDB,
0048 MTHCA_RES_MCG,
0049 MTHCA_RES_MPT,
0050 MTHCA_RES_MTT,
0051 MTHCA_RES_UAR,
0052 MTHCA_RES_UDAV,
0053 MTHCA_RES_UARC,
0054 MTHCA_RES_NUM
0055 };
0056
0057 enum {
0058 MTHCA_NUM_EQS = 32,
0059 MTHCA_NUM_PDS = 1 << 15
0060 };
0061
0062 s64 mthca_make_profile(struct mthca_dev *dev,
0063 struct mthca_profile *request,
0064 struct mthca_dev_lim *dev_lim,
0065 struct mthca_init_hca_param *init_hca)
0066 {
0067 struct mthca_resource {
0068 u64 size;
0069 u64 start;
0070 int type;
0071 int num;
0072 int log_num;
0073 };
0074
0075 u64 mem_base, mem_avail;
0076 s64 total_size = 0;
0077 struct mthca_resource *profile;
0078 int i, j;
0079
0080 profile = kcalloc(MTHCA_RES_NUM, sizeof(*profile), GFP_KERNEL);
0081 if (!profile)
0082 return -ENOMEM;
0083
0084 profile[MTHCA_RES_QP].size = dev_lim->qpc_entry_sz;
0085 profile[MTHCA_RES_EEC].size = dev_lim->eec_entry_sz;
0086 profile[MTHCA_RES_SRQ].size = dev_lim->srq_entry_sz;
0087 profile[MTHCA_RES_CQ].size = dev_lim->cqc_entry_sz;
0088 profile[MTHCA_RES_EQP].size = dev_lim->eqpc_entry_sz;
0089 profile[MTHCA_RES_EEEC].size = dev_lim->eeec_entry_sz;
0090 profile[MTHCA_RES_EQ].size = dev_lim->eqc_entry_sz;
0091 profile[MTHCA_RES_RDB].size = MTHCA_RDB_ENTRY_SIZE;
0092 profile[MTHCA_RES_MCG].size = MTHCA_MGM_ENTRY_SIZE;
0093 profile[MTHCA_RES_MPT].size = dev_lim->mpt_entry_sz;
0094 profile[MTHCA_RES_MTT].size = dev->limits.mtt_seg_size;
0095 profile[MTHCA_RES_UAR].size = dev_lim->uar_scratch_entry_sz;
0096 profile[MTHCA_RES_UDAV].size = MTHCA_AV_SIZE;
0097 profile[MTHCA_RES_UARC].size = request->uarc_size;
0098
0099 profile[MTHCA_RES_QP].num = request->num_qp;
0100 profile[MTHCA_RES_SRQ].num = request->num_srq;
0101 profile[MTHCA_RES_EQP].num = request->num_qp;
0102 profile[MTHCA_RES_RDB].num = request->num_qp * request->rdb_per_qp;
0103 profile[MTHCA_RES_CQ].num = request->num_cq;
0104 profile[MTHCA_RES_EQ].num = MTHCA_NUM_EQS;
0105 profile[MTHCA_RES_MCG].num = request->num_mcg;
0106 profile[MTHCA_RES_MPT].num = request->num_mpt;
0107 profile[MTHCA_RES_MTT].num = request->num_mtt;
0108 profile[MTHCA_RES_UAR].num = request->num_uar;
0109 profile[MTHCA_RES_UARC].num = request->num_uar;
0110 profile[MTHCA_RES_UDAV].num = request->num_udav;
0111
0112 for (i = 0; i < MTHCA_RES_NUM; ++i) {
0113 profile[i].type = i;
0114 profile[i].log_num = max(ffs(profile[i].num) - 1, 0);
0115 profile[i].size *= profile[i].num;
0116 if (mthca_is_memfree(dev))
0117 profile[i].size = max(profile[i].size, (u64) PAGE_SIZE);
0118 }
0119
0120 if (mthca_is_memfree(dev)) {
0121 mem_base = 0;
0122 mem_avail = dev_lim->hca.arbel.max_icm_sz;
0123 } else {
0124 mem_base = dev->ddr_start;
0125 mem_avail = dev->fw.tavor.fw_start - dev->ddr_start;
0126 }
0127
0128
0129
0130
0131
0132
0133
0134 for (i = MTHCA_RES_NUM; i > 0; --i)
0135 for (j = 1; j < i; ++j) {
0136 if (profile[j].size > profile[j - 1].size)
0137 swap(profile[j], profile[j - 1]);
0138 }
0139
0140 for (i = 0; i < MTHCA_RES_NUM; ++i) {
0141 if (profile[i].size) {
0142 profile[i].start = mem_base + total_size;
0143 total_size += profile[i].size;
0144 }
0145 if (total_size > mem_avail) {
0146 mthca_err(dev, "Profile requires 0x%llx bytes; "
0147 "won't fit in 0x%llx bytes of context memory.\n",
0148 (unsigned long long) total_size,
0149 (unsigned long long) mem_avail);
0150 kfree(profile);
0151 return -ENOMEM;
0152 }
0153
0154 if (profile[i].size)
0155 mthca_dbg(dev, "profile[%2d]--%2d/%2d @ 0x%16llx "
0156 "(size 0x%8llx)\n",
0157 i, profile[i].type, profile[i].log_num,
0158 (unsigned long long) profile[i].start,
0159 (unsigned long long) profile[i].size);
0160 }
0161
0162 if (mthca_is_memfree(dev))
0163 mthca_dbg(dev, "HCA context memory: reserving %d KB\n",
0164 (int) (total_size >> 10));
0165 else
0166 mthca_dbg(dev, "HCA memory: allocated %d KB/%d KB (%d KB free)\n",
0167 (int) (total_size >> 10), (int) (mem_avail >> 10),
0168 (int) ((mem_avail - total_size) >> 10));
0169
0170 for (i = 0; i < MTHCA_RES_NUM; ++i) {
0171 switch (profile[i].type) {
0172 case MTHCA_RES_QP:
0173 dev->limits.num_qps = profile[i].num;
0174 init_hca->qpc_base = profile[i].start;
0175 init_hca->log_num_qps = profile[i].log_num;
0176 break;
0177 case MTHCA_RES_EEC:
0178 dev->limits.num_eecs = profile[i].num;
0179 init_hca->eec_base = profile[i].start;
0180 init_hca->log_num_eecs = profile[i].log_num;
0181 break;
0182 case MTHCA_RES_SRQ:
0183 dev->limits.num_srqs = profile[i].num;
0184 init_hca->srqc_base = profile[i].start;
0185 init_hca->log_num_srqs = profile[i].log_num;
0186 break;
0187 case MTHCA_RES_CQ:
0188 dev->limits.num_cqs = profile[i].num;
0189 init_hca->cqc_base = profile[i].start;
0190 init_hca->log_num_cqs = profile[i].log_num;
0191 break;
0192 case MTHCA_RES_EQP:
0193 init_hca->eqpc_base = profile[i].start;
0194 break;
0195 case MTHCA_RES_EEEC:
0196 init_hca->eeec_base = profile[i].start;
0197 break;
0198 case MTHCA_RES_EQ:
0199 dev->limits.num_eqs = profile[i].num;
0200 init_hca->eqc_base = profile[i].start;
0201 init_hca->log_num_eqs = profile[i].log_num;
0202 break;
0203 case MTHCA_RES_RDB:
0204 for (dev->qp_table.rdb_shift = 0;
0205 request->num_qp << dev->qp_table.rdb_shift < profile[i].num;
0206 ++dev->qp_table.rdb_shift)
0207 ;
0208 dev->qp_table.rdb_base = (u32) profile[i].start;
0209 init_hca->rdb_base = profile[i].start;
0210 break;
0211 case MTHCA_RES_MCG:
0212 dev->limits.num_mgms = profile[i].num >> 1;
0213 dev->limits.num_amgms = profile[i].num >> 1;
0214 init_hca->mc_base = profile[i].start;
0215 init_hca->log_mc_entry_sz = ffs(MTHCA_MGM_ENTRY_SIZE) - 1;
0216 init_hca->log_mc_table_sz = profile[i].log_num;
0217 init_hca->mc_hash_sz = 1 << (profile[i].log_num - 1);
0218 break;
0219 case MTHCA_RES_MPT:
0220 dev->limits.num_mpts = profile[i].num;
0221 dev->mr_table.mpt_base = profile[i].start;
0222 init_hca->mpt_base = profile[i].start;
0223 init_hca->log_mpt_sz = profile[i].log_num;
0224 break;
0225 case MTHCA_RES_MTT:
0226 dev->limits.num_mtt_segs = profile[i].num;
0227 dev->mr_table.mtt_base = profile[i].start;
0228 init_hca->mtt_base = profile[i].start;
0229 init_hca->mtt_seg_sz = ffs(dev->limits.mtt_seg_size) - 7;
0230 break;
0231 case MTHCA_RES_UAR:
0232 dev->limits.num_uars = profile[i].num;
0233 init_hca->uar_scratch_base = profile[i].start;
0234 break;
0235 case MTHCA_RES_UDAV:
0236 dev->av_table.ddr_av_base = profile[i].start;
0237 dev->av_table.num_ddr_avs = profile[i].num;
0238 break;
0239 case MTHCA_RES_UARC:
0240 dev->uar_table.uarc_size = request->uarc_size;
0241 dev->uar_table.uarc_base = profile[i].start;
0242 init_hca->uarc_base = profile[i].start;
0243 init_hca->log_uarc_sz = ffs(request->uarc_size) - 13;
0244 init_hca->log_uar_sz = ffs(request->num_uar) - 1;
0245 break;
0246 default:
0247 break;
0248 }
0249 }
0250
0251
0252
0253
0254
0255 dev->limits.num_pds = MTHCA_NUM_PDS;
0256
0257 if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT &&
0258 init_hca->log_mpt_sz > 23) {
0259 mthca_warn(dev, "MPT table too large (requested size 2^%d >= 2^24)\n",
0260 init_hca->log_mpt_sz);
0261 mthca_warn(dev, "Disabling memory key throughput optimization.\n");
0262 dev->mthca_flags &= ~MTHCA_FLAG_SINAI_OPT;
0263 }
0264
0265
0266
0267
0268
0269
0270
0271
0272 if (mthca_is_memfree(dev) || BITS_PER_LONG == 64)
0273 dev->limits.fmr_reserved_mtts = 0;
0274 else
0275 dev->limits.fmr_reserved_mtts = request->fmr_reserved_mtts;
0276
0277 kfree(profile);
0278 return total_size;
0279 }