1290650Shselasky/*-
2290650Shselasky * Copyright (c) 2013-2015, Mellanox Technologies, Ltd.  All rights reserved.
3290650Shselasky *
4290650Shselasky * Redistribution and use in source and binary forms, with or without
5290650Shselasky * modification, are permitted provided that the following conditions
6290650Shselasky * are met:
7290650Shselasky * 1. Redistributions of source code must retain the above copyright
8290650Shselasky *    notice, this list of conditions and the following disclaimer.
9290650Shselasky * 2. Redistributions in binary form must reproduce the above copyright
10290650Shselasky *    notice, this list of conditions and the following disclaimer in the
11290650Shselasky *    documentation and/or other materials provided with the distribution.
12290650Shselasky *
13290650Shselasky * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14290650Shselasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15290650Shselasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16290650Shselasky * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17290650Shselasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18290650Shselasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19290650Shselasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20290650Shselasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21290650Shselasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22290650Shselasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23290650Shselasky * SUCH DAMAGE.
24290650Shselasky *
25290650Shselasky * $FreeBSD: releng/10.3/sys/dev/mlx5/mlx5_core/mlx5_mr.c 290650 2015-11-10 12:20:22Z hselasky $
26290650Shselasky */
27290650Shselasky
28290650Shselasky#include <linux/kernel.h>
29290650Shselasky#include <linux/module.h>
30290650Shselasky#include <dev/mlx5/driver.h>
31290650Shselasky#include "mlx5_core.h"
32290650Shselasky
33290650Shselaskyvoid mlx5_init_mr_table(struct mlx5_core_dev *dev)
34290650Shselasky{
35290650Shselasky	struct mlx5_mr_table *table = &dev->priv.mr_table;
36290650Shselasky
37290650Shselasky	rwlock_init(&table->lock);
38290650Shselasky	INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
39290650Shselasky}
40290650Shselasky
41290650Shselaskyvoid mlx5_cleanup_mr_table(struct mlx5_core_dev *dev)
42290650Shselasky{
43290650Shselasky}
44290650Shselasky
45290650Shselaskyint mlx5_core_create_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr,
46290650Shselasky			  struct mlx5_create_mkey_mbox_in *in, int inlen,
47290650Shselasky			  mlx5_cmd_cbk_t callback, void *context,
48290650Shselasky			  struct mlx5_create_mkey_mbox_out *out)
49290650Shselasky{
50290650Shselasky	struct mlx5_mr_table *table = &dev->priv.mr_table;
51290650Shselasky	struct mlx5_create_mkey_mbox_out lout;
52290650Shselasky	int err;
53290650Shselasky	u8 key;
54290650Shselasky	unsigned long irql;
55290650Shselasky
56290650Shselasky	memset(&lout, 0, sizeof(lout));
57290650Shselasky	spin_lock_irq(&dev->priv.mkey_lock);
58290650Shselasky	key = dev->priv.mkey_key++;
59290650Shselasky	spin_unlock_irq(&dev->priv.mkey_lock);
60290650Shselasky	in->seg.qpn_mkey7_0 |= cpu_to_be32(key);
61290650Shselasky	in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_MKEY);
62290650Shselasky	if (callback) {
63290650Shselasky		err = mlx5_cmd_exec_cb(dev, in, inlen, out, sizeof(*out),
64290650Shselasky				       callback, context);
65290650Shselasky		return err;
66290650Shselasky	} else {
67290650Shselasky		err = mlx5_cmd_exec(dev, in, inlen, &lout, sizeof(lout));
68290650Shselasky	}
69290650Shselasky
70290650Shselasky	if (err) {
71290650Shselasky		mlx5_core_dbg(dev, "cmd exec failed %d\n", err);
72290650Shselasky		return err;
73290650Shselasky	}
74290650Shselasky
75290650Shselasky	if (lout.hdr.status) {
76290650Shselasky		mlx5_core_dbg(dev, "status %d\n", lout.hdr.status);
77290650Shselasky		return mlx5_cmd_status_to_err(&lout.hdr);
78290650Shselasky	}
79290650Shselasky
80290650Shselasky	mr->iova = be64_to_cpu(in->seg.start_addr);
81290650Shselasky	mr->size = be64_to_cpu(in->seg.len);
82290650Shselasky	mr->key = mlx5_idx_to_mkey(be32_to_cpu(lout.mkey) & 0xffffff) | key;
83290650Shselasky	mr->pd = be32_to_cpu(in->seg.flags_pd) & 0xffffff;
84290650Shselasky
85290650Shselasky	mlx5_core_dbg(dev, "out 0x%x, key 0x%x, mkey 0x%x\n",
86290650Shselasky		      be32_to_cpu(lout.mkey), key, mr->key);
87290650Shselasky
88290650Shselasky	/* connect to MR tree */
89290650Shselasky	write_lock_irqsave(&table->lock, irql);
90290650Shselasky	err = radix_tree_insert(&table->tree, mlx5_base_mkey(mr->key), mr);
91290650Shselasky	write_unlock_irqrestore(&table->lock, irql);
92290650Shselasky	if (err) {
93290650Shselasky		mlx5_core_warn(dev, "failed radix tree insert of mr 0x%x, %d\n",
94290650Shselasky			       mlx5_base_mkey(mr->key), err);
95290650Shselasky		mlx5_core_destroy_mkey(dev, mr);
96290650Shselasky	}
97290650Shselasky
98290650Shselasky	return err;
99290650Shselasky}
100290650ShselaskyEXPORT_SYMBOL(mlx5_core_create_mkey);
101290650Shselasky
102290650Shselaskyint mlx5_core_destroy_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr)
103290650Shselasky{
104290650Shselasky	struct mlx5_mr_table *table = &dev->priv.mr_table;
105290650Shselasky	u32 in[MLX5_ST_SZ_DW(destroy_mkey_in)];
106290650Shselasky	u32 out[MLX5_ST_SZ_DW(destroy_mkey_out)];
107290650Shselasky	struct mlx5_core_mr *deleted_mr;
108290650Shselasky	unsigned long flags;
109290650Shselasky
110290650Shselasky	memset(in, 0, sizeof(in));
111290650Shselasky
112290650Shselasky	write_lock_irqsave(&table->lock, flags);
113290650Shselasky	deleted_mr = radix_tree_delete(&table->tree, mlx5_base_mkey(mr->key));
114290650Shselasky	write_unlock_irqrestore(&table->lock, flags);
115290650Shselasky	if (!deleted_mr) {
116290650Shselasky		mlx5_core_warn(dev, "failed radix tree delete of mr 0x%x\n",
117290650Shselasky			       mlx5_base_mkey(mr->key));
118290650Shselasky		return -ENOENT;
119290650Shselasky	}
120290650Shselasky
121290650Shselasky	MLX5_SET(destroy_mkey_in, in, opcode, MLX5_CMD_OP_DESTROY_MKEY);
122290650Shselasky	MLX5_SET(destroy_mkey_in, in, mkey_index, mlx5_mkey_to_idx(mr->key));
123290650Shselasky
124290650Shselasky	memset(out, 0, sizeof(out));
125290650Shselasky	return mlx5_cmd_exec_check_status(dev, in,  sizeof(in),
126290650Shselasky					       out, sizeof(out));
127290650Shselasky}
128290650ShselaskyEXPORT_SYMBOL(mlx5_core_destroy_mkey);
129290650Shselasky
130290650Shselaskyint mlx5_core_query_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr,
131290650Shselasky			 struct mlx5_query_mkey_mbox_out *out, int outlen)
132290650Shselasky{
133290650Shselasky	struct mlx5_query_mkey_mbox_in in;
134290650Shselasky	int err;
135290650Shselasky
136290650Shselasky	memset(&in, 0, sizeof(in));
137290650Shselasky	memset(out, 0, outlen);
138290650Shselasky
139290650Shselasky	in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_MKEY);
140290650Shselasky	in.mkey = cpu_to_be32(mlx5_mkey_to_idx(mr->key));
141290650Shselasky	err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen);
142290650Shselasky	if (err)
143290650Shselasky		return err;
144290650Shselasky
145290650Shselasky	if (out->hdr.status)
146290650Shselasky		return mlx5_cmd_status_to_err(&out->hdr);
147290650Shselasky
148290650Shselasky	return err;
149290650Shselasky}
150290650ShselaskyEXPORT_SYMBOL(mlx5_core_query_mkey);
151290650Shselasky
152290650Shselaskyint mlx5_core_dump_fill_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr,
153290650Shselasky			     u32 *mkey)
154290650Shselasky{
155290650Shselasky	struct mlx5_query_special_ctxs_mbox_in in;
156290650Shselasky	struct mlx5_query_special_ctxs_mbox_out out;
157290650Shselasky	int err;
158290650Shselasky
159290650Shselasky	memset(&in, 0, sizeof(in));
160290650Shselasky	memset(&out, 0, sizeof(out));
161290650Shselasky
162290650Shselasky	in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
163290650Shselasky	err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
164290650Shselasky	if (err)
165290650Shselasky		return err;
166290650Shselasky
167290650Shselasky	if (out.hdr.status)
168290650Shselasky		return mlx5_cmd_status_to_err(&out.hdr);
169290650Shselasky
170290650Shselasky	*mkey = be32_to_cpu(out.dump_fill_mkey);
171290650Shselasky
172290650Shselasky	return err;
173290650Shselasky}
174290650ShselaskyEXPORT_SYMBOL(mlx5_core_dump_fill_mkey);
175290650Shselasky
176290650Shselaskyint mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn,
177290650Shselasky			 int npsvs, u32 *sig_index)
178290650Shselasky{
179290650Shselasky	struct mlx5_allocate_psv_in in;
180290650Shselasky	struct mlx5_allocate_psv_out out;
181290650Shselasky	int i, err;
182290650Shselasky
183290650Shselasky	if (npsvs > MLX5_MAX_PSVS)
184290650Shselasky		return -EINVAL;
185290650Shselasky
186290650Shselasky	memset(&in, 0, sizeof(in));
187290650Shselasky	memset(&out, 0, sizeof(out));
188290650Shselasky
189290650Shselasky	in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_PSV);
190290650Shselasky	in.npsv_pd = cpu_to_be32((npsvs << 28) | pdn);
191290650Shselasky	err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
192290650Shselasky	if (err) {
193290650Shselasky		mlx5_core_err(dev, "cmd exec failed %d\n", err);
194290650Shselasky		return err;
195290650Shselasky	}
196290650Shselasky
197290650Shselasky	if (out.hdr.status) {
198290650Shselasky		mlx5_core_err(dev, "create_psv bad status %d\n",
199290650Shselasky			      out.hdr.status);
200290650Shselasky		return mlx5_cmd_status_to_err(&out.hdr);
201290650Shselasky	}
202290650Shselasky
203290650Shselasky	for (i = 0; i < npsvs; i++)
204290650Shselasky		sig_index[i] = be32_to_cpu(out.psv_idx[i]) & 0xffffff;
205290650Shselasky
206290650Shselasky	return err;
207290650Shselasky}
208290650ShselaskyEXPORT_SYMBOL(mlx5_core_create_psv);
209290650Shselasky
210290650Shselaskyint mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num)
211290650Shselasky{
212290650Shselasky	struct mlx5_destroy_psv_in in;
213290650Shselasky	struct mlx5_destroy_psv_out out;
214290650Shselasky	int err;
215290650Shselasky
216290650Shselasky	memset(&in, 0, sizeof(in));
217290650Shselasky	memset(&out, 0, sizeof(out));
218290650Shselasky
219290650Shselasky	in.psv_number = cpu_to_be32(psv_num);
220290650Shselasky	in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_PSV);
221290650Shselasky	err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
222290650Shselasky	if (err) {
223290650Shselasky		mlx5_core_err(dev, "destroy_psv cmd exec failed %d\n", err);
224290650Shselasky		goto out;
225290650Shselasky	}
226290650Shselasky
227290650Shselasky	if (out.hdr.status) {
228290650Shselasky		mlx5_core_err(dev, "destroy_psv bad status %d\n",
229290650Shselasky			      out.hdr.status);
230290650Shselasky		err = mlx5_cmd_status_to_err(&out.hdr);
231290650Shselasky		goto out;
232290650Shselasky	}
233290650Shselasky
234290650Shselaskyout:
235290650Shselasky	return err;
236290650Shselasky}
237290650ShselaskyEXPORT_SYMBOL(mlx5_core_destroy_psv);
238