mlx4_qp.c revision 219820
1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004 Topspin Communications.  All rights reserved.
3219820Sjeff * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
4219820Sjeff * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
5219820Sjeff * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
6219820Sjeff *
7219820Sjeff * This software is available to you under a choice of one of two
8219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
9219820Sjeff * General Public License (GPL) Version 2, available from the file
10219820Sjeff * COPYING in the main directory of this source tree, or the
11219820Sjeff * OpenIB.org BSD license below:
12219820Sjeff *
13219820Sjeff *     Redistribution and use in source and binary forms, with or
14219820Sjeff *     without modification, are permitted provided that the following
15219820Sjeff *     conditions are met:
16219820Sjeff *
17219820Sjeff *      - Redistributions of source code must retain the above
18219820Sjeff *        copyright notice, this list of conditions and the following
19219820Sjeff *        disclaimer.
20219820Sjeff *
21219820Sjeff *      - Redistributions in binary form must reproduce the above
22219820Sjeff *        copyright notice, this list of conditions and the following
23219820Sjeff *        disclaimer in the documentation and/or other materials
24219820Sjeff *        provided with the distribution.
25219820Sjeff *
26219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33219820Sjeff * SOFTWARE.
34219820Sjeff */
35219820Sjeff
36219820Sjeff#include <linux/init.h>
37219820Sjeff
38219820Sjeff#include <linux/mlx4/cmd.h>
39219820Sjeff#include <linux/mlx4/qp.h>
40219820Sjeff
41219820Sjeff#include "mlx4.h"
42219820Sjeff#include "icm.h"
43219820Sjeff
44219820Sjeffvoid mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type)
45219820Sjeff{
46219820Sjeff	struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
47219820Sjeff	struct mlx4_qp *qp;
48219820Sjeff
49219820Sjeff	spin_lock(&qp_table->lock);
50219820Sjeff
51219820Sjeff	qp = __mlx4_qp_lookup(dev, qpn);
52219820Sjeff	if (qp)
53219820Sjeff		atomic_inc(&qp->refcount);
54219820Sjeff
55219820Sjeff	spin_unlock(&qp_table->lock);
56219820Sjeff
57219820Sjeff	if (!qp) {
58219820Sjeff		mlx4_warn(dev, "Async event for bogus QP %08x\n", qpn);
59219820Sjeff		return;
60219820Sjeff	}
61219820Sjeff
62219820Sjeff	qp->event(qp, event_type);
63219820Sjeff
64219820Sjeff	if (atomic_dec_and_test(&qp->refcount))
65219820Sjeff		complete(&qp->free);
66219820Sjeff}
67219820Sjeff
68219820Sjeffint mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
69219820Sjeff		   enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state,
70219820Sjeff		   struct mlx4_qp_context *context, enum mlx4_qp_optpar optpar,
71219820Sjeff		   int sqd_event, struct mlx4_qp *qp)
72219820Sjeff{
73219820Sjeff	static const u16 op[MLX4_QP_NUM_STATE][MLX4_QP_NUM_STATE] = {
74219820Sjeff		[MLX4_QP_STATE_RST] = {
75219820Sjeff			[MLX4_QP_STATE_RST]	= MLX4_CMD_2RST_QP,
76219820Sjeff			[MLX4_QP_STATE_ERR]	= MLX4_CMD_2ERR_QP,
77219820Sjeff			[MLX4_QP_STATE_INIT]	= MLX4_CMD_RST2INIT_QP,
78219820Sjeff		},
79219820Sjeff		[MLX4_QP_STATE_INIT]  = {
80219820Sjeff			[MLX4_QP_STATE_RST]	= MLX4_CMD_2RST_QP,
81219820Sjeff			[MLX4_QP_STATE_ERR]	= MLX4_CMD_2ERR_QP,
82219820Sjeff			[MLX4_QP_STATE_INIT]	= MLX4_CMD_INIT2INIT_QP,
83219820Sjeff			[MLX4_QP_STATE_RTR]	= MLX4_CMD_INIT2RTR_QP,
84219820Sjeff		},
85219820Sjeff		[MLX4_QP_STATE_RTR]   = {
86219820Sjeff			[MLX4_QP_STATE_RST]	= MLX4_CMD_2RST_QP,
87219820Sjeff			[MLX4_QP_STATE_ERR]	= MLX4_CMD_2ERR_QP,
88219820Sjeff			[MLX4_QP_STATE_RTS]	= MLX4_CMD_RTR2RTS_QP,
89219820Sjeff		},
90219820Sjeff		[MLX4_QP_STATE_RTS]   = {
91219820Sjeff			[MLX4_QP_STATE_RST]	= MLX4_CMD_2RST_QP,
92219820Sjeff			[MLX4_QP_STATE_ERR]	= MLX4_CMD_2ERR_QP,
93219820Sjeff			[MLX4_QP_STATE_RTS]	= MLX4_CMD_RTS2RTS_QP,
94219820Sjeff			[MLX4_QP_STATE_SQD]	= MLX4_CMD_RTS2SQD_QP,
95219820Sjeff		},
96219820Sjeff		[MLX4_QP_STATE_SQD] = {
97219820Sjeff			[MLX4_QP_STATE_RST]	= MLX4_CMD_2RST_QP,
98219820Sjeff			[MLX4_QP_STATE_ERR]	= MLX4_CMD_2ERR_QP,
99219820Sjeff			[MLX4_QP_STATE_RTS]	= MLX4_CMD_SQD2RTS_QP,
100219820Sjeff			[MLX4_QP_STATE_SQD]	= MLX4_CMD_SQD2SQD_QP,
101219820Sjeff		},
102219820Sjeff		[MLX4_QP_STATE_SQER] = {
103219820Sjeff			[MLX4_QP_STATE_RST]	= MLX4_CMD_2RST_QP,
104219820Sjeff			[MLX4_QP_STATE_ERR]	= MLX4_CMD_2ERR_QP,
105219820Sjeff			[MLX4_QP_STATE_RTS]	= MLX4_CMD_SQERR2RTS_QP,
106219820Sjeff		},
107219820Sjeff		[MLX4_QP_STATE_ERR] = {
108219820Sjeff			[MLX4_QP_STATE_RST]	= MLX4_CMD_2RST_QP,
109219820Sjeff			[MLX4_QP_STATE_ERR]	= MLX4_CMD_2ERR_QP,
110219820Sjeff		}
111219820Sjeff	};
112219820Sjeff
113219820Sjeff	struct mlx4_cmd_mailbox *mailbox;
114219820Sjeff	int ret = 0;
115219820Sjeff
116219820Sjeff	if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE ||
117219820Sjeff	    !op[cur_state][new_state])
118219820Sjeff		return -EINVAL;
119219820Sjeff
120219820Sjeff	if (op[cur_state][new_state] == MLX4_CMD_2RST_QP)
121219820Sjeff		return mlx4_cmd(dev, 0, qp->qpn, 2,
122219820Sjeff				MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A);
123219820Sjeff
124219820Sjeff	mailbox = mlx4_alloc_cmd_mailbox(dev);
125219820Sjeff	if (IS_ERR(mailbox))
126219820Sjeff		return PTR_ERR(mailbox);
127219820Sjeff
128219820Sjeff	if (cur_state == MLX4_QP_STATE_RST && new_state == MLX4_QP_STATE_INIT) {
129219820Sjeff		u64 mtt_addr = mlx4_mtt_addr(dev, mtt);
130219820Sjeff		context->mtt_base_addr_h = mtt_addr >> 32;
131219820Sjeff		context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
132219820Sjeff		context->log_page_size   = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
133219820Sjeff	}
134219820Sjeff
135219820Sjeff	*(__be32 *) mailbox->buf = cpu_to_be32(optpar);
136219820Sjeff	memcpy(mailbox->buf + 8, context, sizeof *context);
137219820Sjeff
138219820Sjeff	((struct mlx4_qp_context *) (mailbox->buf + 8))->local_qpn =
139219820Sjeff		cpu_to_be32(qp->qpn);
140219820Sjeff
141219820Sjeff	ret = mlx4_cmd(dev, mailbox->dma, qp->qpn | (!!sqd_event << 31),
142219820Sjeff		       new_state == MLX4_QP_STATE_RST ? 2 : 0,
143219820Sjeff		       op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C);
144219820Sjeff
145219820Sjeff	mlx4_free_cmd_mailbox(dev, mailbox);
146219820Sjeff	return ret;
147219820Sjeff}
148219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_modify);
149219820Sjeff
150219820Sjeffint mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base)
151219820Sjeff{
152219820Sjeff	struct mlx4_priv *priv = mlx4_priv(dev);
153219820Sjeff	struct mlx4_qp_table *qp_table = &priv->qp_table;
154219820Sjeff	int qpn;
155219820Sjeff
156219820Sjeff	qpn = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align);
157219820Sjeff	if (qpn == -1)
158219820Sjeff		return -ENOMEM;
159219820Sjeff
160219820Sjeff	*base = qpn;
161219820Sjeff	return 0;
162219820Sjeff}
163219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_reserve_range);
164219820Sjeff
165219820Sjeffvoid mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
166219820Sjeff{
167219820Sjeff	struct mlx4_priv *priv = mlx4_priv(dev);
168219820Sjeff	struct mlx4_qp_table *qp_table = &priv->qp_table;
169219820Sjeff	if (base_qpn < dev->caps.sqp_start + 8)
170219820Sjeff		return;
171219820Sjeff
172219820Sjeff	mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt);
173219820Sjeff}
174219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_release_range);
175219820Sjeff
176219820Sjeffint mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp)
177219820Sjeff{
178219820Sjeff	struct mlx4_priv *priv = mlx4_priv(dev);
179219820Sjeff	struct mlx4_qp_table *qp_table = &priv->qp_table;
180219820Sjeff	int err;
181219820Sjeff
182219820Sjeff	if (!qpn)
183219820Sjeff		return -EINVAL;
184219820Sjeff
185219820Sjeff	qp->qpn = qpn;
186219820Sjeff
187219820Sjeff	err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn);
188219820Sjeff	if (err)
189219820Sjeff		goto err_out;
190219820Sjeff
191219820Sjeff	err = mlx4_table_get(dev, &qp_table->auxc_table, qp->qpn);
192219820Sjeff	if (err)
193219820Sjeff		goto err_put_qp;
194219820Sjeff
195219820Sjeff	err = mlx4_table_get(dev, &qp_table->altc_table, qp->qpn);
196219820Sjeff	if (err)
197219820Sjeff		goto err_put_auxc;
198219820Sjeff
199219820Sjeff	err = mlx4_table_get(dev, &qp_table->rdmarc_table, qp->qpn);
200219820Sjeff	if (err)
201219820Sjeff		goto err_put_altc;
202219820Sjeff
203219820Sjeff	err = mlx4_table_get(dev, &qp_table->cmpt_table, qp->qpn);
204219820Sjeff	if (err)
205219820Sjeff		goto err_put_rdmarc;
206219820Sjeff
207219820Sjeff	spin_lock_irq(&qp_table->lock);
208219820Sjeff	err = radix_tree_insert(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1), qp);
209219820Sjeff	spin_unlock_irq(&qp_table->lock);
210219820Sjeff	if (err)
211219820Sjeff		goto err_put_cmpt;
212219820Sjeff
213219820Sjeff	atomic_set(&qp->refcount, 1);
214219820Sjeff	init_completion(&qp->free);
215219820Sjeff
216219820Sjeff	return 0;
217219820Sjeff
218219820Sjefferr_put_cmpt:
219219820Sjeff	mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn);
220219820Sjeff
221219820Sjefferr_put_rdmarc:
222219820Sjeff	mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn);
223219820Sjeff
224219820Sjefferr_put_altc:
225219820Sjeff	mlx4_table_put(dev, &qp_table->altc_table, qp->qpn);
226219820Sjeff
227219820Sjefferr_put_auxc:
228219820Sjeff	mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
229219820Sjeff
230219820Sjefferr_put_qp:
231219820Sjeff	mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
232219820Sjeff
233219820Sjefferr_out:
234219820Sjeff	return err;
235219820Sjeff}
236219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_alloc);
237219820Sjeff
238219820Sjeffstruct mlx4_qp *mlx4_qp_lookup_lock(struct mlx4_dev *dev, u32 qpn)
239219820Sjeff{
240219820Sjeff	struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
241219820Sjeff	unsigned long flags;
242219820Sjeff	struct mlx4_qp *qp;
243219820Sjeff
244219820Sjeff	spin_lock_irqsave(&qp_table->lock, flags);
245219820Sjeff	qp = radix_tree_lookup(&dev->qp_table_tree, qpn & (dev->caps.num_qps - 1));
246219820Sjeff	spin_unlock_irqrestore(&qp_table->lock, flags);
247219820Sjeff	return qp;
248219820Sjeff}
249219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_lookup_lock);
250219820Sjeff
251219820Sjeffvoid mlx4_qp_remove(struct mlx4_dev *dev, struct mlx4_qp *qp)
252219820Sjeff{
253219820Sjeff	struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
254219820Sjeff	unsigned long flags;
255219820Sjeff
256219820Sjeff	spin_lock_irqsave(&qp_table->lock, flags);
257219820Sjeff	radix_tree_delete(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1));
258219820Sjeff	spin_unlock_irqrestore(&qp_table->lock, flags);
259219820Sjeff}
260219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_remove);
261219820Sjeff
262219820Sjeffvoid mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp)
263219820Sjeff{
264219820Sjeff	struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
265219820Sjeff
266219820Sjeff	if (atomic_dec_and_test(&qp->refcount))
267219820Sjeff		complete(&qp->free);
268219820Sjeff	wait_for_completion(&qp->free);
269219820Sjeff
270219820Sjeff	mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn);
271219820Sjeff	mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn);
272219820Sjeff	mlx4_table_put(dev, &qp_table->altc_table, qp->qpn);
273219820Sjeff	mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
274219820Sjeff	mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
275219820Sjeff}
276219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_free);
277219820Sjeff
278219820Sjeffstatic int mlx4_CONF_SPECIAL_QP(struct mlx4_dev *dev, u32 base_qpn)
279219820Sjeff{
280219820Sjeff	return mlx4_cmd(dev, 0, base_qpn,
281219820Sjeff			(dev->caps.flags & MLX4_DEV_CAP_FLAG_RAW_ETY) ? 4 : 0,
282219820Sjeff			MLX4_CMD_CONF_SPECIAL_QP, MLX4_CMD_TIME_CLASS_B);
283219820Sjeff}
284219820Sjeff
285219820Sjeffint mlx4_init_qp_table(struct mlx4_dev *dev)
286219820Sjeff{
287219820Sjeff	struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
288219820Sjeff	int err;
289219820Sjeff	int reserved_from_top = 0;
290219820Sjeff
291219820Sjeff	spin_lock_init(&qp_table->lock);
292219820Sjeff	INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC);
293219820Sjeff
294219820Sjeff	/*
295219820Sjeff	 * We reserve 2 extra QPs per port for the special QPs.  The
296219820Sjeff	 * block of special QPs must be aligned to a multiple of 8, so
297219820Sjeff	 * round up.
298219820Sjeff	 * We also reserve the MSB of the 24-bit QP number to indicate
299219820Sjeff	 * an XRC qp.
300219820Sjeff	 */
301219820Sjeff	dev->caps.sqp_start =
302219820Sjeff		ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8);
303219820Sjeff
304219820Sjeff	{
305219820Sjeff		int sort[MLX4_NUM_QP_REGION];
306219820Sjeff		int i, j, tmp;
307219820Sjeff		int last_base = dev->caps.num_qps;
308219820Sjeff
309219820Sjeff		for (i = 1; i < MLX4_NUM_QP_REGION; ++i)
310219820Sjeff			sort[i] = i;
311219820Sjeff
312219820Sjeff		for (i = MLX4_NUM_QP_REGION; i > 0; --i) {
313219820Sjeff			for (j = 2; j < i; ++j) {
314219820Sjeff				if (dev->caps.reserved_qps_cnt[sort[j]] >
315219820Sjeff				    dev->caps.reserved_qps_cnt[sort[j - 1]]) {
316219820Sjeff					tmp             = sort[j];
317219820Sjeff					sort[j]         = sort[j - 1];
318219820Sjeff					sort[j - 1]     = tmp;
319219820Sjeff				}
320219820Sjeff			}
321219820Sjeff		}
322219820Sjeff
323219820Sjeff		for (i = 1; i < MLX4_NUM_QP_REGION; ++i) {
324219820Sjeff			last_base -= dev->caps.reserved_qps_cnt[sort[i]];
325219820Sjeff			dev->caps.reserved_qps_base[sort[i]] = last_base;
326219820Sjeff			reserved_from_top +=
327219820Sjeff				dev->caps.reserved_qps_cnt[sort[i]];
328219820Sjeff		}
329219820Sjeff
330219820Sjeff	}
331219820Sjeff
332219820Sjeff	err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps,
333219820Sjeff			       (1 << 23) - 1, dev->caps.sqp_start + 8,
334219820Sjeff			       reserved_from_top);
335219820Sjeff	if (err)
336219820Sjeff		return err;
337219820Sjeff
338219820Sjeff	return mlx4_CONF_SPECIAL_QP(dev, dev->caps.sqp_start);
339219820Sjeff}
340219820Sjeff
341219820Sjeffvoid mlx4_cleanup_qp_table(struct mlx4_dev *dev)
342219820Sjeff{
343219820Sjeff	mlx4_CONF_SPECIAL_QP(dev, 0);
344219820Sjeff	mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap);
345219820Sjeff}
346219820Sjeff
347219820Sjeffint mlx4_qp_get_region(struct mlx4_dev *dev, enum mlx4_qp_region region,
348219820Sjeff			int *base_qpn, int *cnt)
349219820Sjeff{
350219820Sjeff	if ((region < 0) || (region >= MLX4_NUM_QP_REGION))
351219820Sjeff		return -EINVAL;
352219820Sjeff
353219820Sjeff	*base_qpn = dev->caps.reserved_qps_base[region];
354219820Sjeff	*cnt = dev->caps.reserved_qps_cnt[region];
355219820Sjeff
356219820Sjeff	return 0;
357219820Sjeff}
358219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_get_region);
359219820Sjeff
360219820Sjeffint mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
361219820Sjeff		  struct mlx4_qp_context *context)
362219820Sjeff{
363219820Sjeff	struct mlx4_cmd_mailbox *mailbox;
364219820Sjeff	int err;
365219820Sjeff
366219820Sjeff	mailbox = mlx4_alloc_cmd_mailbox(dev);
367219820Sjeff	if (IS_ERR(mailbox))
368219820Sjeff		return PTR_ERR(mailbox);
369219820Sjeff
370219820Sjeff	err = mlx4_cmd_box(dev, 0, mailbox->dma, qp->qpn, 0,
371219820Sjeff			   MLX4_CMD_QUERY_QP, MLX4_CMD_TIME_CLASS_A);
372219820Sjeff	if (!err)
373219820Sjeff		memcpy(context, mailbox->buf + 8, sizeof *context);
374219820Sjeff
375219820Sjeff	mlx4_free_cmd_mailbox(dev, mailbox);
376219820Sjeff	return err;
377219820Sjeff}
378219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_query);
379219820Sjeff
380219820Sjeffint mlx4_qp_to_ready(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
381219820Sjeff		     struct mlx4_qp_context *context,
382219820Sjeff		     struct mlx4_qp *qp, enum mlx4_qp_state *qp_state)
383219820Sjeff{
384219820Sjeff	int err;
385219820Sjeff	int i;
386219820Sjeff	enum mlx4_qp_state states[] = {
387219820Sjeff		MLX4_QP_STATE_RST,
388219820Sjeff		MLX4_QP_STATE_INIT,
389219820Sjeff		MLX4_QP_STATE_RTR,
390219820Sjeff		MLX4_QP_STATE_RTS
391219820Sjeff	};
392219820Sjeff
393219820Sjeff	for (i = 0; i < ARRAY_SIZE(states) - 1; i++) {
394219820Sjeff		context->flags &= cpu_to_be32(~(0xf << 28));
395219820Sjeff		context->flags |= cpu_to_be32(states[i + 1] << 28);
396219820Sjeff		err = mlx4_qp_modify(dev, mtt, states[i], states[i + 1],
397219820Sjeff				     context, 0, 0, qp);
398219820Sjeff		if (err) {
399219820Sjeff			mlx4_err(dev, "Failed to bring QP to state: "
400219820Sjeff				 "%d with error: %d\n",
401219820Sjeff				 states[i + 1], err);
402219820Sjeff			return err;
403219820Sjeff		}
404219820Sjeff
405219820Sjeff		*qp_state = states[i + 1];
406219820Sjeff	}
407219820Sjeff
408219820Sjeff	return 0;
409219820Sjeff}
410219820SjeffEXPORT_SYMBOL_GPL(mlx4_qp_to_ready);
411