166776Skris/* 266776Skris * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 355163Sshin * Copyright (c) 2005, 2014 Mellanox Technologies. All rights reserved. 455163Sshin * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. 555163Sshin * 662632Skris * This software is available to you under a choice of one of two 755163Sshin * licenses. You may choose to be licensed under the terms of the GNU 855163Sshin * General Public License (GPL) Version 2, available from the file 955163Sshin * COPYING in the main directory of this source tree, or the 1055163Sshin * OpenIB.org BSD license below: 1155163Sshin * 1255163Sshin * Redistribution and use in source and binary forms, with or 1355163Sshin * without modification, are permitted provided that the following 1455163Sshin * conditions are met: 1555163Sshin * 1655163Sshin * - Redistributions of source code must retain the above 1755163Sshin * copyright notice, this list of conditions and the following 1862632Skris * disclaimer. 1955163Sshin * 2055163Sshin * - Redistributions in binary form must reproduce the above 2155163Sshin * copyright notice, this list of conditions and the following 2255163Sshin * disclaimer in the documentation and/or other materials 2355163Sshin * provided with the distribution. 2455163Sshin * 2555163Sshin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2655163Sshin * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2755163Sshin * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2855163Sshin * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2955163Sshin * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 3055163Sshin * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 3155163Sshin * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3255163Sshin * SOFTWARE. 3355163Sshin */ 3455163Sshin 3555163Sshin#include <linux/slab.h> 3662632Skris 3755163Sshin#include "mlx4.h" 3862632Skris#include "fw.h" 3955163Sshin 4055163Sshinenum { 4155163Sshin MLX4_RES_QP, 4255163Sshin MLX4_RES_RDMARC, 4355163Sshin MLX4_RES_ALTC, 4455163Sshin MLX4_RES_AUXC, 4555163Sshin MLX4_RES_SRQ, 4655163Sshin MLX4_RES_CQ, 4755163Sshin MLX4_RES_EQ, 4855163Sshin MLX4_RES_DMPT, 4955163Sshin MLX4_RES_CMPT, 5055163Sshin MLX4_RES_MTT, 5155163Sshin MLX4_RES_MCG, 5255163Sshin MLX4_RES_NUM 5366776Skris}; 5455163Sshin 5555163Sshinstatic const char *res_name[] = { 5655163Sshin [MLX4_RES_QP] = "QP", 5755163Sshin [MLX4_RES_RDMARC] = "RDMARC", 5866776Skris [MLX4_RES_ALTC] = "ALTC", 5966776Skris [MLX4_RES_AUXC] = "AUXC", 6055163Sshin [MLX4_RES_SRQ] = "SRQ", 6155163Sshin [MLX4_RES_CQ] = "CQ", 6255163Sshin [MLX4_RES_EQ] = "EQ", 6355163Sshin [MLX4_RES_DMPT] = "DMPT", 6462632Skris [MLX4_RES_CMPT] = "CMPT", 6562632Skris [MLX4_RES_MTT] = "MTT", 6662632Skris [MLX4_RES_MCG] = "MCG", 6755163Sshin}; 6855163Sshin 6962632Skrisu64 mlx4_make_profile(struct mlx4_dev *dev, 7055163Sshin struct mlx4_profile *request, 7155163Sshin struct mlx4_dev_cap *dev_cap, 7255163Sshin struct mlx4_init_hca_param *init_hca) 7362632Skris{ 7455163Sshin struct mlx4_priv *priv = mlx4_priv(dev); 7555163Sshin struct mlx4_resource { 7655163Sshin u64 size; 7755163Sshin u64 start; 7862632Skris int type; 7955163Sshin u64 num; 8055163Sshin int log_num; 8155163Sshin }; 8255163Sshin 8362632Skris u64 total_size = 0; 8455163Sshin struct mlx4_resource *profile; 8555163Sshin struct mlx4_resource tmp; 8655163Sshin int i, j; 8755163Sshin 8855163Sshin profile = kcalloc(MLX4_RES_NUM, sizeof(*profile), GFP_KERNEL); 8955163Sshin if (!profile) 9062632Skris return -ENOMEM; 9155163Sshin 9255163Sshin profile[MLX4_RES_QP].size = dev_cap->qpc_entry_sz; 9355163Sshin profile[MLX4_RES_RDMARC].size = dev_cap->rdmarc_entry_sz; 9462632Skris profile[MLX4_RES_ALTC].size = dev_cap->altc_entry_sz; 9562632Skris profile[MLX4_RES_AUXC].size = dev_cap->aux_entry_sz; 9662632Skris profile[MLX4_RES_SRQ].size = dev_cap->srq_entry_sz; 9755163Sshin profile[MLX4_RES_CQ].size = dev_cap->cqc_entry_sz; 9855163Sshin profile[MLX4_RES_EQ].size = dev_cap->eqc_entry_sz; 9955163Sshin profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz; 10055163Sshin profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz; 10155163Sshin profile[MLX4_RES_MTT].size = dev_cap->mtt_entry_sz; 10255163Sshin profile[MLX4_RES_MCG].size = mlx4_get_mgm_entry_size(dev); 10355163Sshin 10462632Skris profile[MLX4_RES_QP].num = request->num_qp; 10555163Sshin profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp; 10666776Skris profile[MLX4_RES_ALTC].num = request->num_qp; 10755163Sshin profile[MLX4_RES_AUXC].num = request->num_qp; 10855163Sshin profile[MLX4_RES_SRQ].num = request->num_srq; 10955163Sshin profile[MLX4_RES_CQ].num = request->num_cq; 11055163Sshin profile[MLX4_RES_EQ].num = mlx4_is_mfunc(dev) ? 11155163Sshin dev->phys_caps.num_phys_eqs : 11255163Sshin min_t(unsigned, dev_cap->max_eqs, MAX_MSIX); 11355163Sshin profile[MLX4_RES_DMPT].num = request->num_mpt; 11455163Sshin profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS; 11555163Sshin profile[MLX4_RES_MTT].num = ((u64)request->num_mtt_segs) * 11655163Sshin (1 << log_mtts_per_seg); 11755163Sshin profile[MLX4_RES_MCG].num = request->num_mcg; 11855163Sshin 11955163Sshin for (i = 0; i < MLX4_RES_NUM; ++i) { 12055163Sshin profile[i].type = i; 12155163Sshin profile[i].num = roundup_pow_of_two(profile[i].num); 12255163Sshin profile[i].log_num = ilog2(profile[i].num); 12355163Sshin profile[i].size *= profile[i].num; 12455163Sshin profile[i].size = max(profile[i].size, (u64) PAGE_SIZE); 12555163Sshin } 12655163Sshin 12755163Sshin /* 12855163Sshin * Sort the resources in decreasing order of size. Since they 12966776Skris * all have sizes that are powers of 2, we'll be able to keep 13055163Sshin * resources aligned to their size and pack them without gaps 13166776Skris * using the sorted order. 13255163Sshin */ 13355163Sshin for (i = MLX4_RES_NUM; i > 0; --i) 13466776Skris for (j = 1; j < i; ++j) { 13566776Skris if (profile[j].size > profile[j - 1].size) { 13666776Skris tmp = profile[j]; 13766776Skris profile[j] = profile[j - 1]; 13866776Skris profile[j - 1] = tmp; 13966776Skris } 14066776Skris } 14166776Skris 14266776Skris for (i = 0; i < MLX4_RES_NUM; ++i) { 14366776Skris if (profile[i].size) { 14466776Skris profile[i].start = total_size; 14566776Skris total_size += profile[i].size; 14666776Skris } 14766776Skris 14866776Skris if (total_size > dev_cap->max_icm_sz) { 14966776Skris mlx4_err(dev, "Profile requires 0x%llx bytes; " 15066776Skris "won't fit in 0x%llx bytes of context memory.\n", 15166776Skris (unsigned long long) total_size, 15266776Skris (unsigned long long) dev_cap->max_icm_sz); 15366776Skris kfree(profile); 15466776Skris return -ENOMEM; 15566776Skris } 15655163Sshin 15755163Sshin if (profile[i].size) 15855163Sshin mlx4_dbg(dev, " profile[%2d] (%6s): 2^%02d entries @ 0x%10llx, " 15955163Sshin "size 0x%10llx\n", 16066776Skris i, res_name[profile[i].type], profile[i].log_num, 16166776Skris (unsigned long long) profile[i].start, 16266776Skris (unsigned long long) profile[i].size); 16366776Skris } 16466776Skris 16566776Skris mlx4_dbg(dev, "HCA context memory: reserving %d KB\n", 16666776Skris (int) (total_size >> 10)); 16766776Skris 16866776Skris for (i = 0; i < MLX4_RES_NUM; ++i) { 16966776Skris switch (profile[i].type) { 17066776Skris case MLX4_RES_QP: 17166776Skris dev->caps.num_qps = profile[i].num; 17266776Skris init_hca->qpc_base = profile[i].start; 17366776Skris init_hca->log_num_qps = profile[i].log_num; 17466776Skris break; 17566776Skris case MLX4_RES_RDMARC: 17666776Skris for (priv->qp_table.rdmarc_shift = 0; 17766776Skris request->num_qp << priv->qp_table.rdmarc_shift < profile[i].num; 17866776Skris ++priv->qp_table.rdmarc_shift) 17966776Skris ; /* nothing */ 18055163Sshin dev->caps.max_qp_dest_rdma = 1 << priv->qp_table.rdmarc_shift; 18166776Skris priv->qp_table.rdmarc_base = (u32) profile[i].start; 18266776Skris init_hca->rdmarc_base = profile[i].start; 18355163Sshin init_hca->log_rd_per_qp = priv->qp_table.rdmarc_shift; 18455163Sshin break; 18555163Sshin case MLX4_RES_ALTC: 18655163Sshin init_hca->altc_base = profile[i].start; 18755163Sshin break; 18855163Sshin case MLX4_RES_AUXC: 18955163Sshin init_hca->auxc_base = profile[i].start; 19055163Sshin break; 19155163Sshin case MLX4_RES_SRQ: 19255163Sshin dev->caps.num_srqs = profile[i].num; 19355163Sshin init_hca->srqc_base = profile[i].start; 19455163Sshin init_hca->log_num_srqs = profile[i].log_num; 19555163Sshin break; 19655163Sshin case MLX4_RES_CQ: 19755163Sshin dev->caps.num_cqs = profile[i].num; 19855163Sshin init_hca->cqc_base = profile[i].start; 19962632Skris init_hca->log_num_cqs = profile[i].log_num; 20055163Sshin break; 20155163Sshin case MLX4_RES_EQ: 20262632Skris dev->caps.num_eqs = roundup_pow_of_two(min_t(unsigned, dev_cap->max_eqs, 20355163Sshin MAX_MSIX)); 20455163Sshin init_hca->eqc_base = profile[i].start; 20555163Sshin init_hca->log_num_eqs = ilog2(dev->caps.num_eqs); 20655163Sshin break; 20766776Skris case MLX4_RES_DMPT: 20866776Skris dev->caps.num_mpts = profile[i].num; 20966776Skris priv->mr_table.mpt_base = profile[i].start; 21055163Sshin init_hca->dmpt_base = profile[i].start; 21155163Sshin init_hca->log_mpt_sz = profile[i].log_num; 21266776Skris break; 21355163Sshin case MLX4_RES_CMPT: 21466776Skris init_hca->cmpt_base = profile[i].start; 21566776Skris break; 21655163Sshin case MLX4_RES_MTT: 21762632Skris dev->caps.num_mtts = profile[i].num; 21862632Skris priv->mr_table.mtt_base = profile[i].start; 21962632Skris init_hca->mtt_base = profile[i].start; 22062632Skris break; 22162632Skris case MLX4_RES_MCG: 22266776Skris init_hca->mc_base = profile[i].start; 22362632Skris init_hca->log_mc_entry_sz = 22466776Skris ilog2(mlx4_get_mgm_entry_size(dev)); 22566776Skris init_hca->log_mc_table_sz = profile[i].log_num; 22662632Skris if (dev->caps.steering_mode == 22755163Sshin MLX4_STEERING_MODE_DEVICE_MANAGED) { 22866776Skris dev->caps.num_mgms = profile[i].num; 22955163Sshin } else { 23066776Skris init_hca->log_mc_hash_sz = 23166776Skris profile[i].log_num - 1; 23255163Sshin dev->caps.num_mgms = profile[i].num >> 1; 23366776Skris dev->caps.num_amgms = profile[i].num >> 1; 23462632Skris } 23566776Skris break; 23666776Skris default: 23755163Sshin break; 23855163Sshin } 23955163Sshin } 24055163Sshin 24166776Skris /* 24255163Sshin * PDs don't take any HCA memory, but we assign them as part 24366776Skris * of the HCA profile anyway. 24466776Skris */ 24555163Sshin dev->caps.num_pds = MLX4_NUM_PDS; 24655163Sshin 24755163Sshin kfree(profile); 24855163Sshin return total_size; 24955163Sshin} 25055163Sshin