1/*
2 * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
3 * Copyright (c) 2005, 2014 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses.  You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 *     Redistribution and use in source and binary forms, with or
13 *     without modification, are permitted provided that the following
14 *     conditions are met:
15 *
16 *      - Redistributions of source code must retain the above
17 *        copyright notice, this list of conditions and the following
18 *        disclaimer.
19 *
20 *      - Redistributions in binary form must reproduce the above
21 *        copyright notice, this list of conditions and the following
22 *        disclaimer in the documentation and/or other materials
23 *        provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33
34
35 #include <linux/slab.h>
36 */
37#include "fw.h"
38#include <debug.h>
39#include <linux/kernel.h>
40#include <linux/log2.h>
41
42enum {
43	MLX4_RES_QP,
44	MLX4_RES_RDMARC,
45	MLX4_RES_ALTC,
46	MLX4_RES_AUXC,
47	MLX4_RES_SRQ,
48	MLX4_RES_CQ,
49	MLX4_RES_EQ,
50	MLX4_RES_DMPT,
51	MLX4_RES_CMPT,
52	MLX4_RES_MTT,
53	MLX4_RES_MCG,
54	MLX4_RES_NUM
55};
56
57static const char *res_name[] = { [MLX4_RES_QP] = "QP", [MLX4_RES_RDMARC
58		] = "RDMARC", [MLX4_RES_ALTC] = "ALTC", [MLX4_RES_AUXC] = "AUXC",
59		[MLX4_RES_SRQ] = "SRQ", [MLX4_RES_CQ] = "CQ", [MLX4_RES_EQ] = "EQ",
60		[MLX4_RES_DMPT] = "DMPT", [MLX4_RES_CMPT] = "CMPT", [MLX4_RES_MTT
61				] = "MTT", [MLX4_RES_MCG] = "MCG", };
62
63u64 mlx4_make_profile(struct mlx4_priv *priv, struct mlx4_profile *request,
64		struct mlx4_dev_cap *dev_cap, struct mlx4_init_hca_param *init_hca) {
65	struct mlx4_resource {
66		u64 size;
67		u64 start;
68		int type;
69		u64 num;
70		int log_num;
71	};
72
73	u64 total_size = 0;
74	struct mlx4_resource *profile;
75	struct mlx4_resource tmp;
76	int i, j;
77
78	profile = calloc(MLX4_RES_NUM, sizeof(*profile));
79	if (!profile)
80		return -ENOMEM;
81
82	profile[MLX4_RES_QP].size = dev_cap->qpc_entry_sz;
83	profile[MLX4_RES_RDMARC].size = dev_cap->rdmarc_entry_sz;
84	profile[MLX4_RES_ALTC].size = dev_cap->altc_entry_sz;
85	profile[MLX4_RES_AUXC].size = dev_cap->aux_entry_sz;
86	profile[MLX4_RES_SRQ].size = dev_cap->srq_entry_sz;
87	profile[MLX4_RES_CQ].size = dev_cap->cqc_entry_sz;
88	profile[MLX4_RES_EQ].size = dev_cap->eqc_entry_sz;
89	profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz;
90	profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz;
91	profile[MLX4_RES_MTT].size = dev_cap->mtt_entry_sz;
92	profile[MLX4_RES_MCG].size = mlx4_get_mgm_entry_size(&priv->dev);
93
94	profile[MLX4_RES_QP].num = request->num_qp;
95	profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp;
96	profile[MLX4_RES_ALTC].num = request->num_qp;
97	profile[MLX4_RES_AUXC].num = request->num_qp;
98	profile[MLX4_RES_SRQ].num = request->num_srq;
99	profile[MLX4_RES_CQ].num = request->num_cq;
100	profile[MLX4_RES_EQ].num = mlx4_is_mfunc(&priv->dev) ? priv->dev.phys_caps.num_phys_eqs : min_t(unsigned, dev_cap->max_eqs, MAX_MSIX);
101	profile[MLX4_RES_DMPT].num = request->num_mpt;
102	profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS;
103	profile[MLX4_RES_MTT].num = ((u64) request->num_mtt_segs)
104			* (1 << log_mtts_per_seg);
105	profile[MLX4_RES_MCG].num = request->num_mcg;
106
107	for (i = 0; i < MLX4_RES_NUM; ++i) {
108		profile[i].type = i;
109		profile[i].num = roundup_pow_of_two(profile[i].num);
110		profile[i].log_num = ilog2(profile[i].num);
111		profile[i].size *= profile[i].num;
112		profile[i].size = max(profile[i].size, (u64) BASE_PAGE_SIZE);
113	}
114
115	/*
116	 * Sort the resources in decreasing order of size.  Since they
117	 * all have sizes that are powers of 2, we'll be able to keep
118	 * resources aligned to their size and pack them without gaps
119	 * using the sorted order.
120	 */
121	for (i = MLX4_RES_NUM; i > 0; --i)
122		for (j = 1; j < i; ++j) {
123			if (profile[j].size > profile[j - 1].size) {
124				tmp = profile[j];
125				profile[j] = profile[j - 1];
126				profile[j - 1] = tmp;
127			}
128		}
129
130	for (i = 0; i < MLX4_RES_NUM; ++i) {
131		if (profile[i].size) {
132			profile[i].start = total_size;
133			total_size += profile[i].size;
134		}
135
136		if (total_size > dev_cap->max_icm_sz) {
137			MLX4_DEBUG("Profile requires 0x%llx bytes; "
138					"won't fit in 0x%llx bytes of context memory.\n",
139					(unsigned long long ) total_size,
140					(unsigned long long ) dev_cap->max_icm_sz);
141			free(profile);
142			return -ENOMEM;
143		}
144
145		if (profile[i].size)
146			MLX4_DEBUG("  profile[%2d] (%6s): 2^%02d entries @ 0x%10llx, "
147					"size 0x%10llx\n", i, res_name[profile[i].type],
148					profile[i].log_num, (unsigned long long ) profile[i].start,
149					(unsigned long long ) profile[i].size);
150	}
151
152	MLX4_DEBUG("HCA context memory: reserving %d KB\n",
153			(int ) (total_size >> 10));
154
155	for (i = 0; i < MLX4_RES_NUM; ++i) {
156		switch (profile[i].type) {
157		case MLX4_RES_QP:
158			priv->dev.caps.num_qps = profile[i].num;
159			init_hca->qpc_base = profile[i].start;
160			init_hca->log_num_qps = profile[i].log_num;
161			break;
162		case MLX4_RES_RDMARC:
163			for (priv->qp_table.rdmarc_shift = 0;
164					request->num_qp << priv->qp_table.rdmarc_shift
165							< profile[i].num; ++priv->qp_table.rdmarc_shift)
166				; /* nothing */
167			priv->dev.caps.max_qp_dest_rdma = 1 << priv->qp_table.rdmarc_shift;
168			priv->qp_table.rdmarc_base = (u32) profile[i].start;
169			init_hca->rdmarc_base = profile[i].start;
170			init_hca->log_rd_per_qp = priv->qp_table.rdmarc_shift;
171			break;
172		case MLX4_RES_ALTC:
173			init_hca->altc_base = profile[i].start;
174			break;
175		case MLX4_RES_AUXC:
176			init_hca->auxc_base = profile[i].start;
177			break;
178		case MLX4_RES_SRQ:
179			priv->dev.caps.num_srqs = profile[i].num;
180			init_hca->srqc_base = profile[i].start;
181			init_hca->log_num_srqs = profile[i].log_num;
182			break;
183		case MLX4_RES_CQ:
184			priv->dev.caps.num_cqs = profile[i].num;
185			init_hca->cqc_base = profile[i].start;
186			init_hca->log_num_cqs = profile[i].log_num;
187			break;
188		case MLX4_RES_EQ:
189			priv->dev.caps.num_eqs = roundup_pow_of_two(min_t(unsigned, dev_cap->max_eqs,
190							MAX_MSIX));
191			init_hca->eqc_base = profile[i].start;
192			init_hca->log_num_eqs = ilog2(priv->dev.caps.num_eqs);
193			break;
194		case MLX4_RES_DMPT:
195			priv->dev.caps.num_mpts = profile[i].num;
196			priv->mr_table.mpt_base = profile[i].start;
197			init_hca->dmpt_base = profile[i].start;
198			init_hca->log_mpt_sz = profile[i].log_num;
199			break;
200		case MLX4_RES_CMPT:
201			init_hca->cmpt_base = profile[i].start;
202			break;
203		case MLX4_RES_MTT:
204			priv->dev.caps.num_mtts = profile[i].num;
205			priv->mr_table.mtt_base = profile[i].start;
206			init_hca->mtt_base = profile[i].start;
207			break;
208		case MLX4_RES_MCG:
209			init_hca->mc_base = profile[i].start;
210			init_hca->log_mc_entry_sz = ilog2(
211					mlx4_get_mgm_entry_size(&priv->dev));
212			init_hca->log_mc_table_sz = profile[i].log_num;
213			if (priv->dev.caps.steering_mode
214					== MLX4_STEERING_MODE_DEVICE_MANAGED) {
215				priv->dev.caps.num_mgms = profile[i].num;
216			} else {
217				init_hca->log_mc_hash_sz = profile[i].log_num - 1;
218				priv->dev.caps.num_mgms = profile[i].num >> 1;
219				priv->dev.caps.num_amgms = profile[i].num >> 1;
220			}
221			break;
222		default:
223			break;
224		}
225	}
226
227	/*
228	 * PDs don't take any HCA memory, but we assign them as part
229	 * of the HCA profile anyway.
230	 */
231	priv->dev.caps.num_pds = MLX4_NUM_PDS;
232
233	free(profile);
234	return total_size;
235}
236