linux/drivers/net/ethernet/mellanox/mlx5/core/mr.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013, Mellanox Technologies inc.  All rights reserved.
   3 *
   4 * This software is available to you under a choice of one of two
   5 * licenses.  You may choose to be licensed under the terms of the GNU
   6 * General Public License (GPL) Version 2, available from the file
   7 * COPYING in the main directory of this source tree, or the
   8 * OpenIB.org BSD license below:
   9 *
  10 *     Redistribution and use in source and binary forms, with or
  11 *     without modification, are permitted provided that the following
  12 *     conditions are met:
  13 *
  14 *      - Redistributions of source code must retain the above
  15 *        copyright notice, this list of conditions and the following
  16 *        disclaimer.
  17 *
  18 *      - Redistributions in binary form must reproduce the above
  19 *        copyright notice, this list of conditions and the following
  20 *        disclaimer in the documentation and/or other materials
  21 *        provided with the distribution.
  22 *
  23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30 * SOFTWARE.
  31 */
  32
  33#include <linux/kernel.h>
  34#include <linux/module.h>
  35#include <linux/mlx5/driver.h>
  36#include <linux/mlx5/cmd.h>
  37#include "mlx5_core.h"
  38
  39void mlx5_init_mr_table(struct mlx5_core_dev *dev)
  40{
  41        struct mlx5_mr_table *table = &dev->priv.mr_table;
  42
  43        rwlock_init(&table->lock);
  44        INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
  45}
  46
  47void mlx5_cleanup_mr_table(struct mlx5_core_dev *dev)
  48{
  49}
  50
  51int mlx5_core_create_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr,
  52                          struct mlx5_create_mkey_mbox_in *in, int inlen,
  53                          mlx5_cmd_cbk_t callback, void *context,
  54                          struct mlx5_create_mkey_mbox_out *out)
  55{
  56        struct mlx5_mr_table *table = &dev->priv.mr_table;
  57        struct mlx5_create_mkey_mbox_out lout;
  58        int err;
  59        u8 key;
  60
  61        memset(&lout, 0, sizeof(lout));
  62        spin_lock_irq(&dev->priv.mkey_lock);
  63        key = dev->priv.mkey_key++;
  64        spin_unlock_irq(&dev->priv.mkey_lock);
  65        in->seg.qpn_mkey7_0 |= cpu_to_be32(key);
  66        in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_MKEY);
  67        if (callback) {
  68                err = mlx5_cmd_exec_cb(dev, in, inlen, out, sizeof(*out),
  69                                       callback, context);
  70                return err;
  71        } else {
  72                err = mlx5_cmd_exec(dev, in, inlen, &lout, sizeof(lout));
  73        }
  74
  75        if (err) {
  76                mlx5_core_dbg(dev, "cmd exec failed %d\n", err);
  77                return err;
  78        }
  79
  80        if (lout.hdr.status) {
  81                mlx5_core_dbg(dev, "status %d\n", lout.hdr.status);
  82                return mlx5_cmd_status_to_err(&lout.hdr);
  83        }
  84
  85        mr->iova = be64_to_cpu(in->seg.start_addr);
  86        mr->size = be64_to_cpu(in->seg.len);
  87        mr->key = mlx5_idx_to_mkey(be32_to_cpu(lout.mkey) & 0xffffff) | key;
  88        mr->pd = be32_to_cpu(in->seg.flags_pd) & 0xffffff;
  89
  90        mlx5_core_dbg(dev, "out 0x%x, key 0x%x, mkey 0x%x\n",
  91                      be32_to_cpu(lout.mkey), key, mr->key);
  92
  93        /* connect to MR tree */
  94        write_lock_irq(&table->lock);
  95        err = radix_tree_insert(&table->tree, mlx5_base_mkey(mr->key), mr);
  96        write_unlock_irq(&table->lock);
  97        if (err) {
  98                mlx5_core_warn(dev, "failed radix tree insert of mr 0x%x, %d\n",
  99                               mlx5_base_mkey(mr->key), err);
 100                mlx5_core_destroy_mkey(dev, mr);
 101        }
 102
 103        return err;
 104}
 105EXPORT_SYMBOL(mlx5_core_create_mkey);
 106
 107int mlx5_core_destroy_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr)
 108{
 109        struct mlx5_mr_table *table = &dev->priv.mr_table;
 110        struct mlx5_destroy_mkey_mbox_in in;
 111        struct mlx5_destroy_mkey_mbox_out out;
 112        struct mlx5_core_mr *deleted_mr;
 113        unsigned long flags;
 114        int err;
 115
 116        memset(&in, 0, sizeof(in));
 117        memset(&out, 0, sizeof(out));
 118
 119        write_lock_irqsave(&table->lock, flags);
 120        deleted_mr = radix_tree_delete(&table->tree, mlx5_base_mkey(mr->key));
 121        write_unlock_irqrestore(&table->lock, flags);
 122        if (!deleted_mr) {
 123                mlx5_core_warn(dev, "failed radix tree delete of mr 0x%x\n",
 124                               mlx5_base_mkey(mr->key));
 125                return -ENOENT;
 126        }
 127
 128        in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_MKEY);
 129        in.mkey = cpu_to_be32(mlx5_mkey_to_idx(mr->key));
 130        err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
 131        if (err)
 132                return err;
 133
 134        if (out.hdr.status)
 135                return mlx5_cmd_status_to_err(&out.hdr);
 136
 137        return err;
 138}
 139EXPORT_SYMBOL(mlx5_core_destroy_mkey);
 140
 141int mlx5_core_query_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr,
 142                         struct mlx5_query_mkey_mbox_out *out, int outlen)
 143{
 144        struct mlx5_destroy_mkey_mbox_in in;
 145        int err;
 146
 147        memset(&in, 0, sizeof(in));
 148        memset(out, 0, outlen);
 149
 150        in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_MKEY);
 151        in.mkey = cpu_to_be32(mlx5_mkey_to_idx(mr->key));
 152        err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen);
 153        if (err)
 154                return err;
 155
 156        if (out->hdr.status)
 157                return mlx5_cmd_status_to_err(&out->hdr);
 158
 159        return err;
 160}
 161EXPORT_SYMBOL(mlx5_core_query_mkey);
 162
 163int mlx5_core_dump_fill_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr,
 164                             u32 *mkey)
 165{
 166        struct mlx5_query_special_ctxs_mbox_in in;
 167        struct mlx5_query_special_ctxs_mbox_out out;
 168        int err;
 169
 170        memset(&in, 0, sizeof(in));
 171        memset(&out, 0, sizeof(out));
 172
 173        in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
 174        err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
 175        if (err)
 176                return err;
 177
 178        if (out.hdr.status)
 179                return mlx5_cmd_status_to_err(&out.hdr);
 180
 181        *mkey = be32_to_cpu(out.dump_fill_mkey);
 182
 183        return err;
 184}
 185EXPORT_SYMBOL(mlx5_core_dump_fill_mkey);
 186
 187int mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn,
 188                         int npsvs, u32 *sig_index)
 189{
 190        struct mlx5_allocate_psv_in in;
 191        struct mlx5_allocate_psv_out out;
 192        int i, err;
 193
 194        if (npsvs > MLX5_MAX_PSVS)
 195                return -EINVAL;
 196
 197        memset(&in, 0, sizeof(in));
 198        memset(&out, 0, sizeof(out));
 199
 200        in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_PSV);
 201        in.npsv_pd = cpu_to_be32((npsvs << 28) | pdn);
 202        err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
 203        if (err) {
 204                mlx5_core_err(dev, "cmd exec failed %d\n", err);
 205                return err;
 206        }
 207
 208        if (out.hdr.status) {
 209                mlx5_core_err(dev, "create_psv bad status %d\n",
 210                              out.hdr.status);
 211                return mlx5_cmd_status_to_err(&out.hdr);
 212        }
 213
 214        for (i = 0; i < npsvs; i++)
 215                sig_index[i] = be32_to_cpu(out.psv_idx[i]) & 0xffffff;
 216
 217        return err;
 218}
 219EXPORT_SYMBOL(mlx5_core_create_psv);
 220
 221int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num)
 222{
 223        struct mlx5_destroy_psv_in in;
 224        struct mlx5_destroy_psv_out out;
 225        int err;
 226
 227        memset(&in, 0, sizeof(in));
 228        memset(&out, 0, sizeof(out));
 229
 230        in.psv_number = cpu_to_be32(psv_num);
 231        in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_PSV);
 232        err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
 233        if (err) {
 234                mlx5_core_err(dev, "destroy_psv cmd exec failed %d\n", err);
 235                goto out;
 236        }
 237
 238        if (out.hdr.status) {
 239                mlx5_core_err(dev, "destroy_psv bad status %d\n",
 240                              out.hdr.status);
 241                err = mlx5_cmd_status_to_err(&out.hdr);
 242                goto out;
 243        }
 244
 245out:
 246        return err;
 247}
 248EXPORT_SYMBOL(mlx5_core_destroy_psv);
 249