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