1/*
2 * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
3 * Copyright (c) 2005, 2014 Mellanox Technologies. All rights reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses.  You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
10 *
11 *     Redistribution and use in source and binary forms, with or
12 *     without modification, are permitted provided that the following
13 *     conditions are met:
14 *
15 *      - Redistributions of source code must retain the above
16 *        copyright notice, this list of conditions and the following
17 *        disclaimer.
18 *
19 *      - Redistributions in binary form must reproduce the above
20 *        copyright notice, this list of conditions and the following
21 *        disclaimer in the documentation and/or other materials
22 *        provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34#include <linux/bitops.h>
35/*
36 #include <linux/io-mapping.h>
37
38 #include <linux/page.h>
39 */
40#include "mlx4.h"
41#include <debug.h>
42/*
43 #include "icm.h"
44 */
45enum {
46	MLX4_NUM_RESERVED_UARS = 8
47};
48
49int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn) {
50	struct mlx4_priv *priv = mlx4_priv(dev);
51
52	*pdn = mlx4_bitmap_alloc(&priv->pd_bitmap);
53	if (*pdn == -1)
54		return -ENOMEM;
55
56	return 0;
57}
58/*
59 EXPORT_SYMBOL_GPL(mlx4_pd_alloc);
60
61 void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn)
62 {
63 mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn, MLX4_USE_RR);
64 }
65 EXPORT_SYMBOL_GPL(mlx4_pd_free);
66
67 int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
68 {
69 struct mlx4_dev *dev = mlx4_priv(dev);
70
71 *xrcdn = mlx4_bitmap_alloc(&priv->xrcd_bitmap);
72 if (*xrcdn == -1)
73 return -ENOMEM;
74
75 return 0;
76 }
77
78 int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
79 {
80 u64 out_param;
81 int err;
82
83 if (mlx4_is_mfunc(dev)) {
84 err = mlx4_cmd_imm(dev, 0, &out_param,
85 RES_XRCD, RES_OP_RESERVE,
86 MLX4_CMD_ALLOC_RES,
87 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
88 if (err)
89 return err;
90
91 *xrcdn = get_param_l(&out_param);
92 return 0;
93 }
94 return __mlx4_xrcd_alloc(dev, xrcdn);
95 }
96 EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc);
97
98 void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
99 {
100 mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn, MLX4_USE_RR);
101 }
102
103 void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
104 {
105 u64 in_param = 0;
106 int err;
107
108 if (mlx4_is_mfunc(dev)) {
109 set_param_l(&in_param, xrcdn);
110 err = mlx4_cmd(dev, in_param, RES_XRCD,
111 RES_OP_RESERVE, MLX4_CMD_FREE_RES,
112 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
113 if (err)
114 mlx4_warn(dev, "Failed to release xrcdn %d\n", xrcdn);
115 } else
116 __mlx4_xrcd_free(dev, xrcdn);
117 }
118 EXPORT_SYMBOL_GPL(mlx4_xrcd_free);
119 */
120int mlx4_init_pd_table(struct mlx4_priv *priv) {
121	return mlx4_bitmap_init(&priv->pd_bitmap, priv->dev.caps.num_pds,
122			(1 << NOT_MASKED_PD_BITS) - 1, priv->dev.caps.reserved_pds, 0);
123}
124/*
125 void mlx4_cleanup_pd_table(struct mlx4_dev *dev)
126 {
127 mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap);
128 }
129 */
130int mlx4_init_xrcd_table(struct mlx4_priv *priv) {
131	return mlx4_bitmap_init(&priv->xrcd_bitmap, (1 << 16), (1 << 16) - 1,
132			priv->dev.caps.reserved_xrcds + 1, 0);
133}
134/*
135 void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev)
136 {
137 mlx4_bitmap_cleanup(&mlx4_priv(dev)->xrcd_bitmap);
138 }
139 */
140#define PAGE_SHIFT	12		/* LOG2(PAGE_SIZE) */
141int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar) {
142	struct mlx4_priv *priv = mlx4_priv(dev);
143	int offset;
144
145	uar->index = mlx4_bitmap_alloc(&priv->uar_table.bitmap);
146	if (uar->index == -1)
147		return -ENOMEM;
148
149	if (mlx4_is_slave(&priv->dev))
150		offset = uar->index
151				% ((int) priv->dev.bar_info[1].bytes
152						/ priv->dev.caps.uar_page_size);
153	else
154		offset = uar->index;
155
156	/*MLX4_DEBUG("%p, %d\n", priv->dev.bar_info[1].vaddr, offset);*/
157
158	uar->pfn = ((volatile uint64_t) priv->dev.bar_info[1].vaddr >> PAGE_SHIFT)
159			+ offset;
160	uar->map = NULL;
161	return 0;
162}
163/*
164 EXPORT_SYMBOL_GPL(mlx4_uar_alloc);
165
166 void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar)
167 {
168 mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index, MLX4_USE_RR);
169 }
170 EXPORT_SYMBOL_GPL(mlx4_uar_free);
171
172 #ifndef CONFIG_PPC
173 */
174int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf, int node) {
175	struct mlx4_priv *priv = mlx4_priv(dev);
176	struct mlx4_uar *uar;
177	int err = 0;
178	int idx;
179
180	if (!priv->bf_mapping)
181		return -ENOMEM;
182
183	/*mutex_lock(&priv->bf_mutex);*/
184	if (!list_empty(&priv->bf_list))
185		uar = list_entry(priv->bf_list.next, struct mlx4_uar, bf_list);
186	else {
187		if (mlx4_bitmap_avail(&priv->uar_table.bitmap)
188				< MLX4_NUM_RESERVED_UARS) {
189			err = -ENOMEM;
190			goto out;
191		}
192		/*uar = kmalloc_node(sizeof *uar, GFP_KERNEL, node);
193		 if (!uar) {*/
194		uar = malloc(sizeof *uar);
195		if (!uar) {
196			err = -ENOMEM;
197			goto out;
198		}
199		/*}*/
200		err = mlx4_uar_alloc(dev, uar);
201		if (err)
202			goto free_kmalloc;
203
204		uar->map = (void *) (uar->pfn << PAGE_SHIFT);
205		if (!uar->map) {
206			err = -ENOMEM;
207			goto free_uar;
208		}
209
210		uar->bf_map = io_mapping_map_wc(priv->bf_mapping,
211				uar->index << PAGE_SHIFT);
212		if (!uar->bf_map) {
213			err = -ENOMEM;
214			goto unamp_uar;
215		}
216		uar->free_bf_bmap = 0;
217		list_add(&uar->bf_list, &priv->bf_list);
218	}
219
220	bf->uar = uar;
221	idx = ffz(uar->free_bf_bmap);
222	uar->free_bf_bmap |= 1 << idx;
223	bf->uar = uar;
224	bf->offset = 0;
225	bf->buf_size = priv->dev.caps.bf_reg_size / 2;
226	bf->reg = uar->bf_map + idx * priv->dev.caps.bf_reg_size;
227	if (uar->free_bf_bmap == (1 << priv->dev.caps.bf_regs_per_page) - 1)
228		list_del_init(&uar->bf_list);
229
230	goto out;
231
232	unamp_uar: bf->uar = NULL;
233	/*iounmap(uar->map);*/
234
235	free_uar: /*mlx4_uar_free(dev, uar);*/
236
237	free_kmalloc: free(uar);
238
239	out: /*mutex_unlock(&priv->bf_mutex);*/
240	return err;
241}
242/*
243 EXPORT_SYMBOL_GPL(mlx4_bf_alloc);
244
245 void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf)
246 {
247 struct mlx4_priv *priv = mlx4_priv(dev);
248 int idx;
249
250 if (!bf->uar || !bf->uar->bf_map)
251 return;
252
253 mutex_lock(&priv->bf_mutex);
254 idx = (bf->reg - bf->uar->bf_map) / priv->dev.caps.bf_reg_size;
255 bf->uar->free_bf_bmap &= ~(1 << idx);
256 if (!bf->uar->free_bf_bmap) {
257 if (!list_empty(&bf->uar->bf_list))
258 list_del(&bf->uar->bf_list);
259
260 io_mapping_unmap(bf->uar->bf_map);
261 iounmap(bf->uar->map);
262 mlx4_uar_free(dev, bf->uar);
263 kfree(bf->uar);
264 } else if (list_empty(&bf->uar->bf_list))
265 list_add(&bf->uar->bf_list, &priv->bf_list);
266
267 mutex_unlock(&priv->bf_mutex);
268 }
269 EXPORT_SYMBOL_GPL(mlx4_bf_free);
270
271 #else
272 int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf, int node)
273 {
274 memset(bf, 0, sizeof *bf);
275 return -ENOSYS;
276 }
277 EXPORT_SYMBOL_GPL(mlx4_bf_alloc);
278
279 void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf)
280 {
281 return;
282 }
283 EXPORT_SYMBOL_GPL(mlx4_bf_free);
284 #endif
285 */
286int mlx4_init_uar_table(struct mlx4_priv *priv) {
287	if (priv->dev.caps.num_uars <= 128) {
288		MLX4_DEBUG("Only %d UAR pages (need more than 128)\n",
289				priv->dev.caps.num_uars);
290		MLX4_DEBUG("Increase firmware log2_uar_bar_megabytes?\n");
291		return -ENODEV;
292	}
293
294	return mlx4_bitmap_init(&priv->uar_table.bitmap, priv->dev.caps.num_uars,
295			priv->dev.caps.num_uars - 1, priv->dev.caps.reserved_uars, 0);
296}
297/*
298 void mlx4_cleanup_uar_table(struct mlx4_dev *dev)
299 {
300 mlx4_bitmap_cleanup(&mlx4_priv(dev)->uar_table.bitmap);
301 }*/
302