cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

srq.c (8422B)


      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
     35#include <linux/mlx4/cmd.h>
     36#include <linux/mlx4/srq.h>
     37#include <linux/export.h>
     38#include <linux/gfp.h>
     39
     40#include "mlx4.h"
     41#include "icm.h"
     42
     43void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type)
     44{
     45	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
     46	struct mlx4_srq *srq;
     47
     48	rcu_read_lock();
     49	srq = radix_tree_lookup(&srq_table->tree, srqn & (dev->caps.num_srqs - 1));
     50	rcu_read_unlock();
     51	if (srq)
     52		refcount_inc(&srq->refcount);
     53	else {
     54		mlx4_warn(dev, "Async event for bogus SRQ %08x\n", srqn);
     55		return;
     56	}
     57
     58	srq->event(srq, event_type);
     59
     60	if (refcount_dec_and_test(&srq->refcount))
     61		complete(&srq->free);
     62}
     63
     64static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
     65			  int srq_num)
     66{
     67	return mlx4_cmd(dev, mailbox->dma, srq_num, 0,
     68			MLX4_CMD_SW2HW_SRQ, MLX4_CMD_TIME_CLASS_A,
     69			MLX4_CMD_WRAPPED);
     70}
     71
     72static int mlx4_HW2SW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
     73			  int srq_num)
     74{
     75	return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, srq_num,
     76			    mailbox ? 0 : 1, MLX4_CMD_HW2SW_SRQ,
     77			    MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
     78}
     79
     80static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark)
     81{
     82	return mlx4_cmd(dev, limit_watermark, srq_num, 0, MLX4_CMD_ARM_SRQ,
     83			MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
     84}
     85
     86static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
     87			  int srq_num)
     88{
     89	return mlx4_cmd_box(dev, 0, mailbox->dma, srq_num, 0, MLX4_CMD_QUERY_SRQ,
     90			    MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
     91}
     92
     93int __mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn)
     94{
     95	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
     96	int err;
     97
     98
     99	*srqn = mlx4_bitmap_alloc(&srq_table->bitmap);
    100	if (*srqn == -1)
    101		return -ENOMEM;
    102
    103	err = mlx4_table_get(dev, &srq_table->table, *srqn);
    104	if (err)
    105		goto err_out;
    106
    107	err = mlx4_table_get(dev, &srq_table->cmpt_table, *srqn);
    108	if (err)
    109		goto err_put;
    110	return 0;
    111
    112err_put:
    113	mlx4_table_put(dev, &srq_table->table, *srqn);
    114
    115err_out:
    116	mlx4_bitmap_free(&srq_table->bitmap, *srqn, MLX4_NO_RR);
    117	return err;
    118}
    119
    120static int mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn)
    121{
    122	u64 out_param;
    123	int err;
    124
    125	if (mlx4_is_mfunc(dev)) {
    126		err = mlx4_cmd_imm(dev, 0, &out_param, RES_SRQ,
    127				   RES_OP_RESERVE_AND_MAP,
    128				   MLX4_CMD_ALLOC_RES,
    129				   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
    130		if (!err)
    131			*srqn = get_param_l(&out_param);
    132
    133		return err;
    134	}
    135	return __mlx4_srq_alloc_icm(dev, srqn);
    136}
    137
    138void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
    139{
    140	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
    141
    142	mlx4_table_put(dev, &srq_table->cmpt_table, srqn);
    143	mlx4_table_put(dev, &srq_table->table, srqn);
    144	mlx4_bitmap_free(&srq_table->bitmap, srqn, MLX4_NO_RR);
    145}
    146
    147static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
    148{
    149	u64 in_param = 0;
    150
    151	if (mlx4_is_mfunc(dev)) {
    152		set_param_l(&in_param, srqn);
    153		if (mlx4_cmd(dev, in_param, RES_SRQ, RES_OP_RESERVE_AND_MAP,
    154			     MLX4_CMD_FREE_RES,
    155			     MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED))
    156			mlx4_warn(dev, "Failed freeing cq:%d\n", srqn);
    157		return;
    158	}
    159	__mlx4_srq_free_icm(dev, srqn);
    160}
    161
    162int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
    163		   struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq)
    164{
    165	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
    166	struct mlx4_cmd_mailbox *mailbox;
    167	struct mlx4_srq_context *srq_context;
    168	u64 mtt_addr;
    169	int err;
    170
    171	err = mlx4_srq_alloc_icm(dev, &srq->srqn);
    172	if (err)
    173		return err;
    174
    175	spin_lock_irq(&srq_table->lock);
    176	err = radix_tree_insert(&srq_table->tree, srq->srqn, srq);
    177	spin_unlock_irq(&srq_table->lock);
    178	if (err)
    179		goto err_icm;
    180
    181	mailbox = mlx4_alloc_cmd_mailbox(dev);
    182	if (IS_ERR(mailbox)) {
    183		err = PTR_ERR(mailbox);
    184		goto err_radix;
    185	}
    186
    187	srq_context = mailbox->buf;
    188	srq_context->state_logsize_srqn = cpu_to_be32((ilog2(srq->max) << 24) |
    189						      srq->srqn);
    190	srq_context->logstride          = srq->wqe_shift - 4;
    191	srq_context->xrcd		= cpu_to_be16(xrcd);
    192	srq_context->pg_offset_cqn	= cpu_to_be32(cqn & 0xffffff);
    193	srq_context->log_page_size      = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
    194
    195	mtt_addr = mlx4_mtt_addr(dev, mtt);
    196	srq_context->mtt_base_addr_h    = mtt_addr >> 32;
    197	srq_context->mtt_base_addr_l    = cpu_to_be32(mtt_addr & 0xffffffff);
    198	srq_context->pd			= cpu_to_be32(pdn);
    199	srq_context->db_rec_addr        = cpu_to_be64(db_rec);
    200
    201	err = mlx4_SW2HW_SRQ(dev, mailbox, srq->srqn);
    202	mlx4_free_cmd_mailbox(dev, mailbox);
    203	if (err)
    204		goto err_radix;
    205
    206	refcount_set(&srq->refcount, 1);
    207	init_completion(&srq->free);
    208
    209	return 0;
    210
    211err_radix:
    212	spin_lock_irq(&srq_table->lock);
    213	radix_tree_delete(&srq_table->tree, srq->srqn);
    214	spin_unlock_irq(&srq_table->lock);
    215
    216err_icm:
    217	mlx4_srq_free_icm(dev, srq->srqn);
    218	return err;
    219}
    220EXPORT_SYMBOL_GPL(mlx4_srq_alloc);
    221
    222void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq)
    223{
    224	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
    225	int err;
    226
    227	err = mlx4_HW2SW_SRQ(dev, NULL, srq->srqn);
    228	if (err)
    229		mlx4_warn(dev, "HW2SW_SRQ failed (%d) for SRQN %06x\n", err, srq->srqn);
    230
    231	spin_lock_irq(&srq_table->lock);
    232	radix_tree_delete(&srq_table->tree, srq->srqn);
    233	spin_unlock_irq(&srq_table->lock);
    234
    235	if (refcount_dec_and_test(&srq->refcount))
    236		complete(&srq->free);
    237	wait_for_completion(&srq->free);
    238
    239	mlx4_srq_free_icm(dev, srq->srqn);
    240}
    241EXPORT_SYMBOL_GPL(mlx4_srq_free);
    242
    243int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark)
    244{
    245	return mlx4_ARM_SRQ(dev, srq->srqn, limit_watermark);
    246}
    247EXPORT_SYMBOL_GPL(mlx4_srq_arm);
    248
    249int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark)
    250{
    251	struct mlx4_cmd_mailbox *mailbox;
    252	struct mlx4_srq_context *srq_context;
    253	int err;
    254
    255	mailbox = mlx4_alloc_cmd_mailbox(dev);
    256	if (IS_ERR(mailbox))
    257		return PTR_ERR(mailbox);
    258
    259	srq_context = mailbox->buf;
    260
    261	err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn);
    262	if (err)
    263		goto err_out;
    264	*limit_watermark = be16_to_cpu(srq_context->limit_watermark);
    265
    266err_out:
    267	mlx4_free_cmd_mailbox(dev, mailbox);
    268	return err;
    269}
    270EXPORT_SYMBOL_GPL(mlx4_srq_query);
    271
    272int mlx4_init_srq_table(struct mlx4_dev *dev)
    273{
    274	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
    275
    276	spin_lock_init(&srq_table->lock);
    277	INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC);
    278	if (mlx4_is_slave(dev))
    279		return 0;
    280
    281	return mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs,
    282				dev->caps.num_srqs - 1, dev->caps.reserved_srqs, 0);
    283}
    284
    285void mlx4_cleanup_srq_table(struct mlx4_dev *dev)
    286{
    287	if (mlx4_is_slave(dev))
    288		return;
    289	mlx4_bitmap_cleanup(&mlx4_priv(dev)->srq_table.bitmap);
    290}
    291
    292struct mlx4_srq *mlx4_srq_lookup(struct mlx4_dev *dev, u32 srqn)
    293{
    294	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
    295	struct mlx4_srq *srq;
    296
    297	rcu_read_lock();
    298	srq = radix_tree_lookup(&srq_table->tree,
    299				srqn & (dev->caps.num_srqs - 1));
    300	rcu_read_unlock();
    301
    302	return srq;
    303}
    304EXPORT_SYMBOL_GPL(mlx4_srq_lookup);