brintos

brintos / linux-shallow public Read only

0
0
Text · 8.2 KiB · dd890f5 Raw
305 lines · c
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 two6 * licenses.  You may choose to be licensed under the terms of the GNU7 * General Public License (GPL) Version 2, available from the file8 * COPYING in the main directory of this source tree, or the9 * OpenIB.org BSD license below:10 *11 *     Redistribution and use in source and binary forms, with or12 *     without modification, are permitted provided that the following13 *     conditions are met:14 *15 *      - Redistributions of source code must retain the above16 *        copyright notice, this list of conditions and the following17 *        disclaimer.18 *19 *      - Redistributions in binary form must reproduce the above20 *        copyright notice, this list of conditions and the following21 *        disclaimer in the documentation and/or other materials22 *        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 OF26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE31 * 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);305