linux/drivers/net/mlx4/srq.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
   3 * Copyright (c) 2007, 2008 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/mlx4/cmd.h>
  35
  36#include "mlx4.h"
  37#include "icm.h"
  38
  39struct mlx4_srq_context {
  40        __be32                  state_logsize_srqn;
  41        u8                      logstride;
  42        u8                      reserved1[3];
  43        u8                      pg_offset;
  44        u8                      reserved2[3];
  45        u32                     reserved3;
  46        u8                      log_page_size;
  47        u8                      reserved4[2];
  48        u8                      mtt_base_addr_h;
  49        __be32                  mtt_base_addr_l;
  50        __be32                  pd;
  51        __be16                  limit_watermark;
  52        __be16                  wqe_cnt;
  53        u16                     reserved5;
  54        __be16                  wqe_counter;
  55        u32                     reserved6;
  56        __be64                  db_rec_addr;
  57};
  58
  59void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type)
  60{
  61        struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
  62        struct mlx4_srq *srq;
  63
  64        spin_lock(&srq_table->lock);
  65
  66        srq = radix_tree_lookup(&srq_table->tree, srqn & (dev->caps.num_srqs - 1));
  67        if (srq)
  68                atomic_inc(&srq->refcount);
  69
  70        spin_unlock(&srq_table->lock);
  71
  72        if (!srq) {
  73                mlx4_warn(dev, "Async event for bogus SRQ %08x\n", srqn);
  74                return;
  75        }
  76
  77        srq->event(srq, event_type);
  78
  79        if (atomic_dec_and_test(&srq->refcount))
  80                complete(&srq->free);
  81}
  82
  83static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
  84                          int srq_num)
  85{
  86        return mlx4_cmd(dev, mailbox->dma, srq_num, 0, MLX4_CMD_SW2HW_SRQ,
  87                        MLX4_CMD_TIME_CLASS_A);
  88}
  89
  90static int mlx4_HW2SW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
  91                          int srq_num)
  92{
  93        return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, srq_num,
  94                            mailbox ? 0 : 1, MLX4_CMD_HW2SW_SRQ,
  95                            MLX4_CMD_TIME_CLASS_A);
  96}
  97
  98static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark)
  99{
 100        return mlx4_cmd(dev, limit_watermark, srq_num, 0, MLX4_CMD_ARM_SRQ,
 101                        MLX4_CMD_TIME_CLASS_B);
 102}
 103
 104static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
 105                          int srq_num)
 106{
 107        return mlx4_cmd_box(dev, 0, mailbox->dma, srq_num, 0, MLX4_CMD_QUERY_SRQ,
 108                            MLX4_CMD_TIME_CLASS_A);
 109}
 110
 111int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
 112                   u64 db_rec, struct mlx4_srq *srq)
 113{
 114        struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
 115        struct mlx4_cmd_mailbox *mailbox;
 116        struct mlx4_srq_context *srq_context;
 117        u64 mtt_addr;
 118        int err;
 119
 120        srq->srqn = mlx4_bitmap_alloc(&srq_table->bitmap);
 121        if (srq->srqn == -1)
 122                return -ENOMEM;
 123
 124        err = mlx4_table_get(dev, &srq_table->table, srq->srqn);
 125        if (err)
 126                goto err_out;
 127
 128        err = mlx4_table_get(dev, &srq_table->cmpt_table, srq->srqn);
 129        if (err)
 130                goto err_put;
 131
 132        spin_lock_irq(&srq_table->lock);
 133        err = radix_tree_insert(&srq_table->tree, srq->srqn, srq);
 134        spin_unlock_irq(&srq_table->lock);
 135        if (err)
 136                goto err_cmpt_put;
 137
 138        mailbox = mlx4_alloc_cmd_mailbox(dev);
 139        if (IS_ERR(mailbox)) {
 140                err = PTR_ERR(mailbox);
 141                goto err_radix;
 142        }
 143
 144        srq_context = mailbox->buf;
 145        memset(srq_context, 0, sizeof *srq_context);
 146
 147        srq_context->state_logsize_srqn = cpu_to_be32((ilog2(srq->max) << 24) |
 148                                                      srq->srqn);
 149        srq_context->logstride          = srq->wqe_shift - 4;
 150        srq_context->log_page_size      = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
 151
 152        mtt_addr = mlx4_mtt_addr(dev, mtt);
 153        srq_context->mtt_base_addr_h    = mtt_addr >> 32;
 154        srq_context->mtt_base_addr_l    = cpu_to_be32(mtt_addr & 0xffffffff);
 155        srq_context->pd                 = cpu_to_be32(pdn);
 156        srq_context->db_rec_addr        = cpu_to_be64(db_rec);
 157
 158        err = mlx4_SW2HW_SRQ(dev, mailbox, srq->srqn);
 159        mlx4_free_cmd_mailbox(dev, mailbox);
 160        if (err)
 161                goto err_radix;
 162
 163        atomic_set(&srq->refcount, 1);
 164        init_completion(&srq->free);
 165
 166        return 0;
 167
 168err_radix:
 169        spin_lock_irq(&srq_table->lock);
 170        radix_tree_delete(&srq_table->tree, srq->srqn);
 171        spin_unlock_irq(&srq_table->lock);
 172
 173err_cmpt_put:
 174        mlx4_table_put(dev, &srq_table->cmpt_table, srq->srqn);
 175
 176err_put:
 177        mlx4_table_put(dev, &srq_table->table, srq->srqn);
 178
 179err_out:
 180        mlx4_bitmap_free(&srq_table->bitmap, srq->srqn);
 181
 182        return err;
 183}
 184EXPORT_SYMBOL_GPL(mlx4_srq_alloc);
 185
 186void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq)
 187{
 188        struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
 189        int err;
 190
 191        err = mlx4_HW2SW_SRQ(dev, NULL, srq->srqn);
 192        if (err)
 193                mlx4_warn(dev, "HW2SW_SRQ failed (%d) for SRQN %06x\n", err, srq->srqn);
 194
 195        spin_lock_irq(&srq_table->lock);
 196        radix_tree_delete(&srq_table->tree, srq->srqn);
 197        spin_unlock_irq(&srq_table->lock);
 198
 199        if (atomic_dec_and_test(&srq->refcount))
 200                complete(&srq->free);
 201        wait_for_completion(&srq->free);
 202
 203        mlx4_table_put(dev, &srq_table->table, srq->srqn);
 204        mlx4_bitmap_free(&srq_table->bitmap, srq->srqn);
 205}
 206EXPORT_SYMBOL_GPL(mlx4_srq_free);
 207
 208int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark)
 209{
 210        return mlx4_ARM_SRQ(dev, srq->srqn, limit_watermark);
 211}
 212EXPORT_SYMBOL_GPL(mlx4_srq_arm);
 213
 214int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark)
 215{
 216        struct mlx4_cmd_mailbox *mailbox;
 217        struct mlx4_srq_context *srq_context;
 218        int err;
 219
 220        mailbox = mlx4_alloc_cmd_mailbox(dev);
 221        if (IS_ERR(mailbox))
 222                return PTR_ERR(mailbox);
 223
 224        srq_context = mailbox->buf;
 225
 226        err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn);
 227        if (err)
 228                goto err_out;
 229        *limit_watermark = be16_to_cpu(srq_context->limit_watermark);
 230
 231err_out:
 232        mlx4_free_cmd_mailbox(dev, mailbox);
 233        return err;
 234}
 235EXPORT_SYMBOL_GPL(mlx4_srq_query);
 236
 237int mlx4_init_srq_table(struct mlx4_dev *dev)
 238{
 239        struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
 240        int err;
 241
 242        spin_lock_init(&srq_table->lock);
 243        INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC);
 244
 245        err = mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs,
 246                               dev->caps.num_srqs - 1, dev->caps.reserved_srqs, 0);
 247        if (err)
 248                return err;
 249
 250        return 0;
 251}
 252
 253void mlx4_cleanup_srq_table(struct mlx4_dev *dev)
 254{
 255        mlx4_bitmap_cleanup(&mlx4_priv(dev)->srq_table.bitmap);
 256}
 257