1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 3219820Sjeff * Copyright (c) 2005 Mellanox Technologies. All rights reserved. 4219820Sjeff * 5219820Sjeff * This software is available to you under a choice of one of two 6219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 7219820Sjeff * General Public License (GPL) Version 2, available from the file 8219820Sjeff * COPYING in the main directory of this source tree, or the 9219820Sjeff * OpenIB.org BSD license below: 10219820Sjeff * 11219820Sjeff * Redistribution and use in source and binary forms, with or 12219820Sjeff * without modification, are permitted provided that the following 13219820Sjeff * conditions are met: 14219820Sjeff * 15219820Sjeff * - Redistributions of source code must retain the above 16219820Sjeff * copyright notice, this list of conditions and the following 17219820Sjeff * disclaimer. 18219820Sjeff * 19219820Sjeff * - Redistributions in binary form must reproduce the above 20219820Sjeff * copyright notice, this list of conditions and the following 21219820Sjeff * disclaimer in the documentation and/or other materials 22219820Sjeff * provided with the distribution. 23219820Sjeff * 24219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31219820Sjeff * SOFTWARE. 32219820Sjeff */ 33219820Sjeff 34219820Sjeff#include <linux/module.h> 35219820Sjeff#include <linux/moduleparam.h> 36219820Sjeff#include <linux/string.h> 37219820Sjeff#include <linux/slab.h> 38219820Sjeff 39219820Sjeff#include "mthca_profile.h" 40219820Sjeff 41219820Sjeffenum { 42219820Sjeff MTHCA_RES_QP, 43219820Sjeff MTHCA_RES_EEC, 44219820Sjeff MTHCA_RES_SRQ, 45219820Sjeff MTHCA_RES_CQ, 46219820Sjeff MTHCA_RES_EQP, 47219820Sjeff MTHCA_RES_EEEC, 48219820Sjeff MTHCA_RES_EQ, 49219820Sjeff MTHCA_RES_RDB, 50219820Sjeff MTHCA_RES_MCG, 51219820Sjeff MTHCA_RES_MPT, 52219820Sjeff MTHCA_RES_MTT, 53219820Sjeff MTHCA_RES_UAR, 54219820Sjeff MTHCA_RES_UDAV, 55219820Sjeff MTHCA_RES_UARC, 56219820Sjeff MTHCA_RES_NUM 57219820Sjeff}; 58219820Sjeff 59219820Sjeffenum { 60219820Sjeff MTHCA_NUM_EQS = 32, 61219820Sjeff MTHCA_NUM_PDS = 1 << 15 62219820Sjeff}; 63219820Sjeff 64219820Sjeffs64 mthca_make_profile(struct mthca_dev *dev, 65219820Sjeff struct mthca_profile *request, 66219820Sjeff struct mthca_dev_lim *dev_lim, 67219820Sjeff struct mthca_init_hca_param *init_hca) 68219820Sjeff{ 69219820Sjeff struct mthca_resource { 70219820Sjeff u64 size; 71219820Sjeff u64 start; 72219820Sjeff int type; 73219820Sjeff int num; 74219820Sjeff int log_num; 75219820Sjeff }; 76219820Sjeff 77219820Sjeff u64 mem_base, mem_avail; 78219820Sjeff s64 total_size = 0; 79219820Sjeff struct mthca_resource *profile; 80219820Sjeff struct mthca_resource tmp; 81219820Sjeff int i, j; 82219820Sjeff 83219820Sjeff profile = kzalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL); 84219820Sjeff if (!profile) 85219820Sjeff return -ENOMEM; 86219820Sjeff 87219820Sjeff profile[MTHCA_RES_QP].size = dev_lim->qpc_entry_sz; 88219820Sjeff profile[MTHCA_RES_EEC].size = dev_lim->eec_entry_sz; 89219820Sjeff profile[MTHCA_RES_SRQ].size = dev_lim->srq_entry_sz; 90219820Sjeff profile[MTHCA_RES_CQ].size = dev_lim->cqc_entry_sz; 91219820Sjeff profile[MTHCA_RES_EQP].size = dev_lim->eqpc_entry_sz; 92219820Sjeff profile[MTHCA_RES_EEEC].size = dev_lim->eeec_entry_sz; 93219820Sjeff profile[MTHCA_RES_EQ].size = dev_lim->eqc_entry_sz; 94219820Sjeff profile[MTHCA_RES_RDB].size = MTHCA_RDB_ENTRY_SIZE; 95219820Sjeff profile[MTHCA_RES_MCG].size = MTHCA_MGM_ENTRY_SIZE; 96219820Sjeff profile[MTHCA_RES_MPT].size = dev_lim->mpt_entry_sz; 97219820Sjeff profile[MTHCA_RES_MTT].size = dev->limits.mtt_seg_size; 98219820Sjeff profile[MTHCA_RES_UAR].size = dev_lim->uar_scratch_entry_sz; 99219820Sjeff profile[MTHCA_RES_UDAV].size = MTHCA_AV_SIZE; 100219820Sjeff profile[MTHCA_RES_UARC].size = request->uarc_size; 101219820Sjeff 102219820Sjeff profile[MTHCA_RES_QP].num = request->num_qp; 103219820Sjeff profile[MTHCA_RES_SRQ].num = request->num_srq; 104219820Sjeff profile[MTHCA_RES_EQP].num = request->num_qp; 105219820Sjeff profile[MTHCA_RES_RDB].num = request->num_qp * request->rdb_per_qp; 106219820Sjeff profile[MTHCA_RES_CQ].num = request->num_cq; 107219820Sjeff profile[MTHCA_RES_EQ].num = MTHCA_NUM_EQS; 108219820Sjeff profile[MTHCA_RES_MCG].num = request->num_mcg; 109219820Sjeff profile[MTHCA_RES_MPT].num = request->num_mpt; 110219820Sjeff profile[MTHCA_RES_MTT].num = request->num_mtt; 111219820Sjeff profile[MTHCA_RES_UAR].num = request->num_uar; 112219820Sjeff profile[MTHCA_RES_UARC].num = request->num_uar; 113219820Sjeff profile[MTHCA_RES_UDAV].num = request->num_udav; 114219820Sjeff 115219820Sjeff for (i = 0; i < MTHCA_RES_NUM; ++i) { 116219820Sjeff profile[i].type = i; 117219820Sjeff profile[i].log_num = max(ffs(profile[i].num) - 1, 0); 118219820Sjeff profile[i].size *= profile[i].num; 119219820Sjeff if (mthca_is_memfree(dev)) 120219820Sjeff profile[i].size = max(profile[i].size, (u64) PAGE_SIZE); 121219820Sjeff } 122219820Sjeff 123219820Sjeff if (mthca_is_memfree(dev)) { 124219820Sjeff mem_base = 0; 125219820Sjeff mem_avail = dev_lim->hca.arbel.max_icm_sz; 126219820Sjeff } else { 127219820Sjeff mem_base = dev->ddr_start; 128219820Sjeff mem_avail = dev->fw.tavor.fw_start - dev->ddr_start; 129219820Sjeff } 130219820Sjeff 131219820Sjeff /* 132219820Sjeff * Sort the resources in decreasing order of size. Since they 133219820Sjeff * all have sizes that are powers of 2, we'll be able to keep 134219820Sjeff * resources aligned to their size and pack them without gaps 135219820Sjeff * using the sorted order. 136219820Sjeff */ 137219820Sjeff for (i = MTHCA_RES_NUM; i > 0; --i) 138219820Sjeff for (j = 1; j < i; ++j) { 139219820Sjeff if (profile[j].size > profile[j - 1].size) { 140219820Sjeff tmp = profile[j]; 141219820Sjeff profile[j] = profile[j - 1]; 142219820Sjeff profile[j - 1] = tmp; 143219820Sjeff } 144219820Sjeff } 145219820Sjeff 146219820Sjeff for (i = 0; i < MTHCA_RES_NUM; ++i) { 147219820Sjeff if (profile[i].size) { 148219820Sjeff profile[i].start = mem_base + total_size; 149219820Sjeff total_size += profile[i].size; 150219820Sjeff } 151219820Sjeff if (total_size > mem_avail) { 152219820Sjeff mthca_err(dev, "Profile requires 0x%llx bytes; " 153219820Sjeff "won't fit in 0x%llx bytes of context memory.\n", 154219820Sjeff (unsigned long long) total_size, 155219820Sjeff (unsigned long long) mem_avail); 156219820Sjeff kfree(profile); 157219820Sjeff return -ENOMEM; 158219820Sjeff } 159219820Sjeff 160219820Sjeff if (profile[i].size) 161219820Sjeff mthca_dbg(dev, "profile[%2d]--%2d/%2d @ 0x%16llx " 162219820Sjeff "(size 0x%8llx)\n", 163219820Sjeff i, profile[i].type, profile[i].log_num, 164219820Sjeff (unsigned long long) profile[i].start, 165219820Sjeff (unsigned long long) profile[i].size); 166219820Sjeff } 167219820Sjeff 168219820Sjeff if (mthca_is_memfree(dev)) 169219820Sjeff mthca_dbg(dev, "HCA context memory: reserving %d KB\n", 170219820Sjeff (int) (total_size >> 10)); 171219820Sjeff else 172219820Sjeff mthca_dbg(dev, "HCA memory: allocated %d KB/%d KB (%d KB free)\n", 173219820Sjeff (int) (total_size >> 10), (int) (mem_avail >> 10), 174219820Sjeff (int) ((mem_avail - total_size) >> 10)); 175219820Sjeff 176219820Sjeff for (i = 0; i < MTHCA_RES_NUM; ++i) { 177219820Sjeff switch (profile[i].type) { 178219820Sjeff case MTHCA_RES_QP: 179219820Sjeff dev->limits.num_qps = profile[i].num; 180219820Sjeff init_hca->qpc_base = profile[i].start; 181219820Sjeff init_hca->log_num_qps = profile[i].log_num; 182219820Sjeff break; 183219820Sjeff case MTHCA_RES_EEC: 184219820Sjeff dev->limits.num_eecs = profile[i].num; 185219820Sjeff init_hca->eec_base = profile[i].start; 186219820Sjeff init_hca->log_num_eecs = profile[i].log_num; 187219820Sjeff break; 188219820Sjeff case MTHCA_RES_SRQ: 189219820Sjeff dev->limits.num_srqs = profile[i].num; 190219820Sjeff init_hca->srqc_base = profile[i].start; 191219820Sjeff init_hca->log_num_srqs = profile[i].log_num; 192219820Sjeff break; 193219820Sjeff case MTHCA_RES_CQ: 194219820Sjeff dev->limits.num_cqs = profile[i].num; 195219820Sjeff init_hca->cqc_base = profile[i].start; 196219820Sjeff init_hca->log_num_cqs = profile[i].log_num; 197219820Sjeff break; 198219820Sjeff case MTHCA_RES_EQP: 199219820Sjeff init_hca->eqpc_base = profile[i].start; 200219820Sjeff break; 201219820Sjeff case MTHCA_RES_EEEC: 202219820Sjeff init_hca->eeec_base = profile[i].start; 203219820Sjeff break; 204219820Sjeff case MTHCA_RES_EQ: 205219820Sjeff dev->limits.num_eqs = profile[i].num; 206219820Sjeff init_hca->eqc_base = profile[i].start; 207219820Sjeff init_hca->log_num_eqs = profile[i].log_num; 208219820Sjeff break; 209219820Sjeff case MTHCA_RES_RDB: 210219820Sjeff for (dev->qp_table.rdb_shift = 0; 211219820Sjeff request->num_qp << dev->qp_table.rdb_shift < profile[i].num; 212219820Sjeff ++dev->qp_table.rdb_shift) 213219820Sjeff ; /* nothing */ 214219820Sjeff dev->qp_table.rdb_base = (u32) profile[i].start; 215219820Sjeff init_hca->rdb_base = profile[i].start; 216219820Sjeff break; 217219820Sjeff case MTHCA_RES_MCG: 218219820Sjeff dev->limits.num_mgms = profile[i].num >> 1; 219219820Sjeff dev->limits.num_amgms = profile[i].num >> 1; 220219820Sjeff init_hca->mc_base = profile[i].start; 221219820Sjeff init_hca->log_mc_entry_sz = ffs(MTHCA_MGM_ENTRY_SIZE) - 1; 222219820Sjeff init_hca->log_mc_table_sz = profile[i].log_num; 223219820Sjeff init_hca->mc_hash_sz = 1 << (profile[i].log_num - 1); 224219820Sjeff break; 225219820Sjeff case MTHCA_RES_MPT: 226219820Sjeff dev->limits.num_mpts = profile[i].num; 227219820Sjeff dev->mr_table.mpt_base = profile[i].start; 228219820Sjeff init_hca->mpt_base = profile[i].start; 229219820Sjeff init_hca->log_mpt_sz = profile[i].log_num; 230219820Sjeff break; 231219820Sjeff case MTHCA_RES_MTT: 232219820Sjeff dev->limits.num_mtt_segs = profile[i].num; 233219820Sjeff dev->mr_table.mtt_base = profile[i].start; 234219820Sjeff init_hca->mtt_base = profile[i].start; 235219820Sjeff init_hca->mtt_seg_sz = ffs(dev->limits.mtt_seg_size) - 7; 236219820Sjeff break; 237219820Sjeff case MTHCA_RES_UAR: 238219820Sjeff dev->limits.num_uars = profile[i].num; 239219820Sjeff init_hca->uar_scratch_base = profile[i].start; 240219820Sjeff break; 241219820Sjeff case MTHCA_RES_UDAV: 242219820Sjeff dev->av_table.ddr_av_base = profile[i].start; 243219820Sjeff dev->av_table.num_ddr_avs = profile[i].num; 244219820Sjeff break; 245219820Sjeff case MTHCA_RES_UARC: 246219820Sjeff dev->uar_table.uarc_size = request->uarc_size; 247219820Sjeff dev->uar_table.uarc_base = profile[i].start; 248219820Sjeff init_hca->uarc_base = profile[i].start; 249219820Sjeff init_hca->log_uarc_sz = ffs(request->uarc_size) - 13; 250219820Sjeff init_hca->log_uar_sz = ffs(request->num_uar) - 1; 251219820Sjeff break; 252219820Sjeff default: 253219820Sjeff break; 254219820Sjeff } 255219820Sjeff } 256219820Sjeff 257219820Sjeff /* 258219820Sjeff * PDs don't take any HCA memory, but we assign them as part 259219820Sjeff * of the HCA profile anyway. 260219820Sjeff */ 261219820Sjeff dev->limits.num_pds = MTHCA_NUM_PDS; 262219820Sjeff 263219820Sjeff if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT && 264219820Sjeff init_hca->log_mpt_sz > 23) { 265219820Sjeff mthca_warn(dev, "MPT table too large (requested size 2^%d >= 2^24)\n", 266219820Sjeff init_hca->log_mpt_sz); 267219820Sjeff mthca_warn(dev, "Disabling memory key throughput optimization.\n"); 268219820Sjeff dev->mthca_flags &= ~MTHCA_FLAG_SINAI_OPT; 269219820Sjeff } 270219820Sjeff 271219820Sjeff /* 272219820Sjeff * For Tavor, FMRs use ioremapped PCI memory. For 32 bit 273219820Sjeff * systems it may use too much vmalloc space to map all MTT 274219820Sjeff * memory, so we reserve some MTTs for FMR access, taking them 275219820Sjeff * out of the MR pool. They don't use additional memory, but 276219820Sjeff * we assign them as part of the HCA profile anyway. 277219820Sjeff */ 278219820Sjeff if (mthca_is_memfree(dev) || BITS_PER_LONG == 64) 279219820Sjeff dev->limits.fmr_reserved_mtts = 0; 280219820Sjeff else 281219820Sjeff dev->limits.fmr_reserved_mtts = request->fmr_reserved_mtts; 282219820Sjeff 283219820Sjeff kfree(profile); 284219820Sjeff return total_size; 285219820Sjeff} 286