1329222Shselasky/*
2329222Shselasky * Copyright (c) 2004 Topspin Communications.  All rights reserved.
3329222Shselasky * Copyright (c) 2005 Cisco Systems. All rights reserved.
4329222Shselasky * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
5329222Shselasky * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
6329222Shselasky *
7329222Shselasky * This software is available to you under a choice of one of two
8329222Shselasky * licenses.  You may choose to be licensed under the terms of the GNU
9329222Shselasky * General Public License (GPL) Version 2, available from the file
10329222Shselasky * COPYING in the main directory of this source tree, or the
11329222Shselasky * OpenIB.org BSD license below:
12329222Shselasky *
13329222Shselasky *     Redistribution and use in source and binary forms, with or
14329222Shselasky *     without modification, are permitted provided that the following
15329222Shselasky *     conditions are met:
16329222Shselasky *
17329222Shselasky *      - Redistributions of source code must retain the above
18329222Shselasky *        copyright notice, this list of conditions and the following
19329222Shselasky *        disclaimer.
20329222Shselasky *
21329222Shselasky *      - Redistributions in binary form must reproduce the above
22329222Shselasky *        copyright notice, this list of conditions and the following
23329222Shselasky *        disclaimer in the documentation and/or other materials
24329222Shselasky *        provided with the distribution.
25329222Shselasky *
26329222Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27329222Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28329222Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29329222Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30329222Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31329222Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32329222Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33329222Shselasky * SOFTWARE.
34329222Shselasky */
35329222Shselasky
36329222Shselasky#include <linux/string.h>
37329222Shselasky#include <linux/slab.h>
38329222Shselasky#include <linux/sched.h>
39329222Shselasky
40329222Shselasky#include <asm/io.h>
41329222Shselasky
42329222Shselasky#include <rdma/ib_verbs.h>
43329222Shselasky#include <rdma/ib_cache.h>
44329222Shselasky#include <rdma/ib_pack.h>
45329222Shselasky
46329222Shselasky#include "mthca_dev.h"
47329222Shselasky#include "mthca_cmd.h"
48329222Shselasky#include "mthca_memfree.h"
49329222Shselasky#include "mthca_wqe.h"
50329222Shselasky
51329222Shselaskyenum {
52329222Shselasky	MTHCA_MAX_DIRECT_QP_SIZE = 4 * PAGE_SIZE,
53329222Shselasky	MTHCA_ACK_REQ_FREQ       = 10,
54329222Shselasky	MTHCA_FLIGHT_LIMIT       = 9,
55329222Shselasky	MTHCA_UD_HEADER_SIZE     = 72, /* largest UD header possible */
56329222Shselasky	MTHCA_INLINE_HEADER_SIZE = 4,  /* data segment overhead for inline */
57329222Shselasky	MTHCA_INLINE_CHUNK_SIZE  = 16  /* inline data segment chunk */
58329222Shselasky};
59329222Shselasky
60329222Shselaskyenum {
61329222Shselasky	MTHCA_QP_STATE_RST  = 0,
62329222Shselasky	MTHCA_QP_STATE_INIT = 1,
63329222Shselasky	MTHCA_QP_STATE_RTR  = 2,
64329222Shselasky	MTHCA_QP_STATE_RTS  = 3,
65329222Shselasky	MTHCA_QP_STATE_SQE  = 4,
66329222Shselasky	MTHCA_QP_STATE_SQD  = 5,
67329222Shselasky	MTHCA_QP_STATE_ERR  = 6,
68329222Shselasky	MTHCA_QP_STATE_DRAINING = 7
69329222Shselasky};
70329222Shselasky
71329222Shselaskyenum {
72329222Shselasky	MTHCA_QP_ST_RC 	= 0x0,
73329222Shselasky	MTHCA_QP_ST_UC 	= 0x1,
74329222Shselasky	MTHCA_QP_ST_RD 	= 0x2,
75329222Shselasky	MTHCA_QP_ST_UD 	= 0x3,
76329222Shselasky	MTHCA_QP_ST_MLX = 0x7
77329222Shselasky};
78329222Shselasky
79329222Shselaskyenum {
80329222Shselasky	MTHCA_QP_PM_MIGRATED = 0x3,
81329222Shselasky	MTHCA_QP_PM_ARMED    = 0x0,
82329222Shselasky	MTHCA_QP_PM_REARM    = 0x1
83329222Shselasky};
84329222Shselasky
85329222Shselaskyenum {
86329222Shselasky	/* qp_context flags */
87329222Shselasky	MTHCA_QP_BIT_DE  = 1 <<  8,
88329222Shselasky	/* params1 */
89329222Shselasky	MTHCA_QP_BIT_SRE = 1 << 15,
90329222Shselasky	MTHCA_QP_BIT_SWE = 1 << 14,
91329222Shselasky	MTHCA_QP_BIT_SAE = 1 << 13,
92329222Shselasky	MTHCA_QP_BIT_SIC = 1 <<  4,
93329222Shselasky	MTHCA_QP_BIT_SSC = 1 <<  3,
94329222Shselasky	/* params2 */
95329222Shselasky	MTHCA_QP_BIT_RRE = 1 << 15,
96329222Shselasky	MTHCA_QP_BIT_RWE = 1 << 14,
97329222Shselasky	MTHCA_QP_BIT_RAE = 1 << 13,
98329222Shselasky	MTHCA_QP_BIT_RIC = 1 <<  4,
99329222Shselasky	MTHCA_QP_BIT_RSC = 1 <<  3
100329222Shselasky};
101329222Shselasky
102329222Shselaskyenum {
103329222Shselasky	MTHCA_SEND_DOORBELL_FENCE = 1 << 5
104329222Shselasky};
105329222Shselasky
106329222Shselaskystruct mthca_qp_path {
107329222Shselasky	__be32 port_pkey;
108329222Shselasky	u8     rnr_retry;
109329222Shselasky	u8     g_mylmc;
110329222Shselasky	__be16 rlid;
111329222Shselasky	u8     ackto;
112329222Shselasky	u8     mgid_index;
113329222Shselasky	u8     static_rate;
114329222Shselasky	u8     hop_limit;
115329222Shselasky	__be32 sl_tclass_flowlabel;
116329222Shselasky	u8     rgid[16];
117329222Shselasky} __attribute__((packed));
118329222Shselasky
119329222Shselaskystruct mthca_qp_context {
120329222Shselasky	__be32 flags;
121329222Shselasky	__be32 tavor_sched_queue; /* Reserved on Arbel */
122329222Shselasky	u8     mtu_msgmax;
123329222Shselasky	u8     rq_size_stride;	/* Reserved on Tavor */
124329222Shselasky	u8     sq_size_stride;	/* Reserved on Tavor */
125329222Shselasky	u8     rlkey_arbel_sched_queue;	/* Reserved on Tavor */
126329222Shselasky	__be32 usr_page;
127329222Shselasky	__be32 local_qpn;
128329222Shselasky	__be32 remote_qpn;
129329222Shselasky	u32    reserved1[2];
130329222Shselasky	struct mthca_qp_path pri_path;
131329222Shselasky	struct mthca_qp_path alt_path;
132329222Shselasky	__be32 rdd;
133329222Shselasky	__be32 pd;
134329222Shselasky	__be32 wqe_base;
135329222Shselasky	__be32 wqe_lkey;
136329222Shselasky	__be32 params1;
137329222Shselasky	__be32 reserved2;
138329222Shselasky	__be32 next_send_psn;
139329222Shselasky	__be32 cqn_snd;
140329222Shselasky	__be32 snd_wqe_base_l;	/* Next send WQE on Tavor */
141329222Shselasky	__be32 snd_db_index;	/* (debugging only entries) */
142329222Shselasky	__be32 last_acked_psn;
143329222Shselasky	__be32 ssn;
144329222Shselasky	__be32 params2;
145329222Shselasky	__be32 rnr_nextrecvpsn;
146329222Shselasky	__be32 ra_buff_indx;
147329222Shselasky	__be32 cqn_rcv;
148329222Shselasky	__be32 rcv_wqe_base_l;	/* Next recv WQE on Tavor */
149329222Shselasky	__be32 rcv_db_index;	/* (debugging only entries) */
150329222Shselasky	__be32 qkey;
151329222Shselasky	__be32 srqn;
152329222Shselasky	__be32 rmsn;
153329222Shselasky	__be16 rq_wqe_counter;	/* reserved on Tavor */
154329222Shselasky	__be16 sq_wqe_counter;	/* reserved on Tavor */
155329222Shselasky	u32    reserved3[18];
156329222Shselasky} __attribute__((packed));
157329222Shselasky
158329222Shselaskystruct mthca_qp_param {
159329222Shselasky	__be32 opt_param_mask;
160329222Shselasky	u32    reserved1;
161329222Shselasky	struct mthca_qp_context context;
162329222Shselasky	u32    reserved2[62];
163329222Shselasky} __attribute__((packed));
164329222Shselasky
165329222Shselaskyenum {
166329222Shselasky	MTHCA_QP_OPTPAR_ALT_ADDR_PATH     = 1 << 0,
167329222Shselasky	MTHCA_QP_OPTPAR_RRE               = 1 << 1,
168329222Shselasky	MTHCA_QP_OPTPAR_RAE               = 1 << 2,
169329222Shselasky	MTHCA_QP_OPTPAR_RWE               = 1 << 3,
170329222Shselasky	MTHCA_QP_OPTPAR_PKEY_INDEX        = 1 << 4,
171329222Shselasky	MTHCA_QP_OPTPAR_Q_KEY             = 1 << 5,
172329222Shselasky	MTHCA_QP_OPTPAR_RNR_TIMEOUT       = 1 << 6,
173329222Shselasky	MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH = 1 << 7,
174329222Shselasky	MTHCA_QP_OPTPAR_SRA_MAX           = 1 << 8,
175329222Shselasky	MTHCA_QP_OPTPAR_RRA_MAX           = 1 << 9,
176329222Shselasky	MTHCA_QP_OPTPAR_PM_STATE          = 1 << 10,
177329222Shselasky	MTHCA_QP_OPTPAR_PORT_NUM          = 1 << 11,
178329222Shselasky	MTHCA_QP_OPTPAR_RETRY_COUNT       = 1 << 12,
179329222Shselasky	MTHCA_QP_OPTPAR_ALT_RNR_RETRY     = 1 << 13,
180329222Shselasky	MTHCA_QP_OPTPAR_ACK_TIMEOUT       = 1 << 14,
181329222Shselasky	MTHCA_QP_OPTPAR_RNR_RETRY         = 1 << 15,
182329222Shselasky	MTHCA_QP_OPTPAR_SCHED_QUEUE       = 1 << 16
183329222Shselasky};
184329222Shselasky
185329222Shselaskystatic const u8 mthca_opcode[] = {
186329222Shselasky	[IB_WR_SEND]                 = MTHCA_OPCODE_SEND,
187329222Shselasky	[IB_WR_SEND_WITH_IMM]        = MTHCA_OPCODE_SEND_IMM,
188329222Shselasky	[IB_WR_RDMA_WRITE]           = MTHCA_OPCODE_RDMA_WRITE,
189329222Shselasky	[IB_WR_RDMA_WRITE_WITH_IMM]  = MTHCA_OPCODE_RDMA_WRITE_IMM,
190329222Shselasky	[IB_WR_RDMA_READ]            = MTHCA_OPCODE_RDMA_READ,
191329222Shselasky	[IB_WR_ATOMIC_CMP_AND_SWP]   = MTHCA_OPCODE_ATOMIC_CS,
192329222Shselasky	[IB_WR_ATOMIC_FETCH_AND_ADD] = MTHCA_OPCODE_ATOMIC_FA,
193329222Shselasky};
194329222Shselasky
195329222Shselaskystatic int is_sqp(struct mthca_dev *dev, struct mthca_qp *qp)
196329222Shselasky{
197329222Shselasky	return qp->qpn >= dev->qp_table.sqp_start &&
198329222Shselasky		qp->qpn <= dev->qp_table.sqp_start + 3;
199329222Shselasky}
200329222Shselasky
201329222Shselaskystatic int is_qp0(struct mthca_dev *dev, struct mthca_qp *qp)
202329222Shselasky{
203329222Shselasky	return qp->qpn >= dev->qp_table.sqp_start &&
204329222Shselasky		qp->qpn <= dev->qp_table.sqp_start + 1;
205329222Shselasky}
206329222Shselasky
207329222Shselaskystatic void *get_recv_wqe(struct mthca_qp *qp, int n)
208329222Shselasky{
209329222Shselasky	if (qp->is_direct)
210329222Shselasky		return qp->queue.direct.buf + (n << qp->rq.wqe_shift);
211329222Shselasky	else
212329222Shselasky		return qp->queue.page_list[(n << qp->rq.wqe_shift) >> PAGE_SHIFT].buf +
213329222Shselasky			((n << qp->rq.wqe_shift) & (PAGE_SIZE - 1));
214329222Shselasky}
215329222Shselasky
216329222Shselaskystatic void *get_send_wqe(struct mthca_qp *qp, int n)
217329222Shselasky{
218329222Shselasky	if (qp->is_direct)
219329222Shselasky		return qp->queue.direct.buf + qp->send_wqe_offset +
220329222Shselasky			(n << qp->sq.wqe_shift);
221329222Shselasky	else
222329222Shselasky		return qp->queue.page_list[(qp->send_wqe_offset +
223329222Shselasky					    (n << qp->sq.wqe_shift)) >>
224329222Shselasky					   PAGE_SHIFT].buf +
225329222Shselasky			((qp->send_wqe_offset + (n << qp->sq.wqe_shift)) &
226329222Shselasky			 (PAGE_SIZE - 1));
227329222Shselasky}
228329222Shselasky
229329222Shselaskystatic void mthca_wq_reset(struct mthca_wq *wq)
230329222Shselasky{
231329222Shselasky	wq->next_ind  = 0;
232329222Shselasky	wq->last_comp = wq->max - 1;
233329222Shselasky	wq->head      = 0;
234329222Shselasky	wq->tail      = 0;
235329222Shselasky}
236329222Shselasky
237329222Shselaskyvoid mthca_qp_event(struct mthca_dev *dev, u32 qpn,
238329222Shselasky		    enum ib_event_type event_type)
239329222Shselasky{
240329222Shselasky	struct mthca_qp *qp;
241329222Shselasky	struct ib_event event;
242329222Shselasky
243329222Shselasky	spin_lock(&dev->qp_table.lock);
244329222Shselasky	qp = mthca_array_get(&dev->qp_table.qp, qpn & (dev->limits.num_qps - 1));
245329222Shselasky	if (qp)
246329222Shselasky		++qp->refcount;
247329222Shselasky	spin_unlock(&dev->qp_table.lock);
248329222Shselasky
249329222Shselasky	if (!qp) {
250329222Shselasky		mthca_warn(dev, "Async event %d for bogus QP %08x\n",
251329222Shselasky			   event_type, qpn);
252329222Shselasky		return;
253329222Shselasky	}
254329222Shselasky
255329222Shselasky	if (event_type == IB_EVENT_PATH_MIG)
256329222Shselasky		qp->port = qp->alt_port;
257329222Shselasky
258329222Shselasky	event.device      = &dev->ib_dev;
259329222Shselasky	event.event       = event_type;
260329222Shselasky	event.element.qp  = &qp->ibqp;
261329222Shselasky	if (qp->ibqp.event_handler)
262329222Shselasky		qp->ibqp.event_handler(&event, qp->ibqp.qp_context);
263329222Shselasky
264329222Shselasky	spin_lock(&dev->qp_table.lock);
265329222Shselasky	if (!--qp->refcount)
266329222Shselasky		wake_up(&qp->wait);
267329222Shselasky	spin_unlock(&dev->qp_table.lock);
268329222Shselasky}
269329222Shselasky
270329222Shselaskystatic int to_mthca_state(enum ib_qp_state ib_state)
271329222Shselasky{
272329222Shselasky	switch (ib_state) {
273329222Shselasky	case IB_QPS_RESET: return MTHCA_QP_STATE_RST;
274329222Shselasky	case IB_QPS_INIT:  return MTHCA_QP_STATE_INIT;
275329222Shselasky	case IB_QPS_RTR:   return MTHCA_QP_STATE_RTR;
276329222Shselasky	case IB_QPS_RTS:   return MTHCA_QP_STATE_RTS;
277329222Shselasky	case IB_QPS_SQD:   return MTHCA_QP_STATE_SQD;
278329222Shselasky	case IB_QPS_SQE:   return MTHCA_QP_STATE_SQE;
279329222Shselasky	case IB_QPS_ERR:   return MTHCA_QP_STATE_ERR;
280329222Shselasky	default:                return -1;
281329222Shselasky	}
282329222Shselasky}
283329222Shselasky
284329222Shselaskyenum { RC, UC, UD, RD, RDEE, MLX, NUM_TRANS };
285329222Shselasky
286329222Shselaskystatic int to_mthca_st(int transport)
287329222Shselasky{
288329222Shselasky	switch (transport) {
289329222Shselasky	case RC:  return MTHCA_QP_ST_RC;
290329222Shselasky	case UC:  return MTHCA_QP_ST_UC;
291329222Shselasky	case UD:  return MTHCA_QP_ST_UD;
292329222Shselasky	case RD:  return MTHCA_QP_ST_RD;
293329222Shselasky	case MLX: return MTHCA_QP_ST_MLX;
294329222Shselasky	default:  return -1;
295329222Shselasky	}
296329222Shselasky}
297329222Shselasky
298329222Shselaskystatic void store_attrs(struct mthca_sqp *sqp, const struct ib_qp_attr *attr,
299329222Shselasky			int attr_mask)
300329222Shselasky{
301329222Shselasky	if (attr_mask & IB_QP_PKEY_INDEX)
302329222Shselasky		sqp->pkey_index = attr->pkey_index;
303329222Shselasky	if (attr_mask & IB_QP_QKEY)
304329222Shselasky		sqp->qkey = attr->qkey;
305329222Shselasky	if (attr_mask & IB_QP_SQ_PSN)
306329222Shselasky		sqp->send_psn = attr->sq_psn;
307329222Shselasky}
308329222Shselasky
309329222Shselaskystatic void init_port(struct mthca_dev *dev, int port)
310329222Shselasky{
311329222Shselasky	int err;
312329222Shselasky	struct mthca_init_ib_param param;
313329222Shselasky
314329222Shselasky	memset(&param, 0, sizeof param);
315329222Shselasky
316329222Shselasky	param.port_width = dev->limits.port_width_cap;
317329222Shselasky	param.vl_cap     = dev->limits.vl_cap;
318329222Shselasky	param.mtu_cap    = dev->limits.mtu_cap;
319329222Shselasky	param.gid_cap    = dev->limits.gid_table_len;
320329222Shselasky	param.pkey_cap   = dev->limits.pkey_table_len;
321329222Shselasky
322329222Shselasky	err = mthca_INIT_IB(dev, &param, port);
323329222Shselasky	if (err)
324329222Shselasky		mthca_warn(dev, "INIT_IB failed, return code %d.\n", err);
325329222Shselasky}
326329222Shselasky
327329222Shselaskystatic __be32 get_hw_access_flags(struct mthca_qp *qp, const struct ib_qp_attr *attr,
328329222Shselasky				  int attr_mask)
329329222Shselasky{
330329222Shselasky	u8 dest_rd_atomic;
331329222Shselasky	u32 access_flags;
332329222Shselasky	u32 hw_access_flags = 0;
333329222Shselasky
334329222Shselasky	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
335329222Shselasky		dest_rd_atomic = attr->max_dest_rd_atomic;
336329222Shselasky	else
337329222Shselasky		dest_rd_atomic = qp->resp_depth;
338329222Shselasky
339329222Shselasky	if (attr_mask & IB_QP_ACCESS_FLAGS)
340329222Shselasky		access_flags = attr->qp_access_flags;
341329222Shselasky	else
342329222Shselasky		access_flags = qp->atomic_rd_en;
343329222Shselasky
344329222Shselasky	if (!dest_rd_atomic)
345329222Shselasky		access_flags &= IB_ACCESS_REMOTE_WRITE;
346329222Shselasky
347329222Shselasky	if (access_flags & IB_ACCESS_REMOTE_READ)
348329222Shselasky		hw_access_flags |= MTHCA_QP_BIT_RRE;
349329222Shselasky	if (access_flags & IB_ACCESS_REMOTE_ATOMIC)
350329222Shselasky		hw_access_flags |= MTHCA_QP_BIT_RAE;
351329222Shselasky	if (access_flags & IB_ACCESS_REMOTE_WRITE)
352329222Shselasky		hw_access_flags |= MTHCA_QP_BIT_RWE;
353329222Shselasky
354329222Shselasky	return cpu_to_be32(hw_access_flags);
355329222Shselasky}
356329222Shselasky
357329222Shselaskystatic inline enum ib_qp_state to_ib_qp_state(int mthca_state)
358329222Shselasky{
359329222Shselasky	switch (mthca_state) {
360329222Shselasky	case MTHCA_QP_STATE_RST:      return IB_QPS_RESET;
361329222Shselasky	case MTHCA_QP_STATE_INIT:     return IB_QPS_INIT;
362329222Shselasky	case MTHCA_QP_STATE_RTR:      return IB_QPS_RTR;
363329222Shselasky	case MTHCA_QP_STATE_RTS:      return IB_QPS_RTS;
364329222Shselasky	case MTHCA_QP_STATE_DRAINING:
365329222Shselasky	case MTHCA_QP_STATE_SQD:      return IB_QPS_SQD;
366329222Shselasky	case MTHCA_QP_STATE_SQE:      return IB_QPS_SQE;
367329222Shselasky	case MTHCA_QP_STATE_ERR:      return IB_QPS_ERR;
368329222Shselasky	default:                      return -1;
369329222Shselasky	}
370329222Shselasky}
371329222Shselasky
372329222Shselaskystatic inline enum ib_mig_state to_ib_mig_state(int mthca_mig_state)
373329222Shselasky{
374329222Shselasky	switch (mthca_mig_state) {
375329222Shselasky	case 0:  return IB_MIG_ARMED;
376329222Shselasky	case 1:  return IB_MIG_REARM;
377329222Shselasky	case 3:  return IB_MIG_MIGRATED;
378329222Shselasky	default: return -1;
379329222Shselasky	}
380329222Shselasky}
381329222Shselasky
382329222Shselaskystatic int to_ib_qp_access_flags(int mthca_flags)
383329222Shselasky{
384329222Shselasky	int ib_flags = 0;
385329222Shselasky
386329222Shselasky	if (mthca_flags & MTHCA_QP_BIT_RRE)
387329222Shselasky		ib_flags |= IB_ACCESS_REMOTE_READ;
388329222Shselasky	if (mthca_flags & MTHCA_QP_BIT_RWE)
389329222Shselasky		ib_flags |= IB_ACCESS_REMOTE_WRITE;
390329222Shselasky	if (mthca_flags & MTHCA_QP_BIT_RAE)
391329222Shselasky		ib_flags |= IB_ACCESS_REMOTE_ATOMIC;
392329222Shselasky
393329222Shselasky	return ib_flags;
394329222Shselasky}
395329222Shselasky
396329222Shselaskystatic void to_ib_ah_attr(struct mthca_dev *dev, struct ib_ah_attr *ib_ah_attr,
397329222Shselasky				struct mthca_qp_path *path)
398329222Shselasky{
399329222Shselasky	memset(ib_ah_attr, 0, sizeof *ib_ah_attr);
400329222Shselasky	ib_ah_attr->port_num 	  = (be32_to_cpu(path->port_pkey) >> 24) & 0x3;
401329222Shselasky
402329222Shselasky	if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->limits.num_ports)
403329222Shselasky		return;
404329222Shselasky
405329222Shselasky	ib_ah_attr->dlid     	  = be16_to_cpu(path->rlid);
406329222Shselasky	ib_ah_attr->sl       	  = be32_to_cpu(path->sl_tclass_flowlabel) >> 28;
407329222Shselasky	ib_ah_attr->src_path_bits = path->g_mylmc & 0x7f;
408329222Shselasky	ib_ah_attr->static_rate   = mthca_rate_to_ib(dev,
409329222Shselasky						     path->static_rate & 0xf,
410329222Shselasky						     ib_ah_attr->port_num);
411329222Shselasky	ib_ah_attr->ah_flags      = (path->g_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
412329222Shselasky	if (ib_ah_attr->ah_flags) {
413329222Shselasky		ib_ah_attr->grh.sgid_index = path->mgid_index & (dev->limits.gid_table_len - 1);
414329222Shselasky		ib_ah_attr->grh.hop_limit  = path->hop_limit;
415329222Shselasky		ib_ah_attr->grh.traffic_class =
416329222Shselasky			(be32_to_cpu(path->sl_tclass_flowlabel) >> 20) & 0xff;
417329222Shselasky		ib_ah_attr->grh.flow_label =
418329222Shselasky			be32_to_cpu(path->sl_tclass_flowlabel) & 0xfffff;
419329222Shselasky		memcpy(ib_ah_attr->grh.dgid.raw,
420329222Shselasky			path->rgid, sizeof ib_ah_attr->grh.dgid.raw);
421329222Shselasky	}
422329222Shselasky}
423329222Shselasky
424329222Shselaskyint mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
425329222Shselasky		   struct ib_qp_init_attr *qp_init_attr)
426329222Shselasky{
427329222Shselasky	struct mthca_dev *dev = to_mdev(ibqp->device);
428329222Shselasky	struct mthca_qp *qp = to_mqp(ibqp);
429329222Shselasky	int err = 0;
430329222Shselasky	struct mthca_mailbox *mailbox = NULL;
431329222Shselasky	struct mthca_qp_param *qp_param;
432329222Shselasky	struct mthca_qp_context *context;
433329222Shselasky	int mthca_state;
434329222Shselasky
435329222Shselasky	mutex_lock(&qp->mutex);
436329222Shselasky
437329222Shselasky	if (qp->state == IB_QPS_RESET) {
438329222Shselasky		qp_attr->qp_state = IB_QPS_RESET;
439329222Shselasky		goto done;
440329222Shselasky	}
441329222Shselasky
442329222Shselasky	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
443329222Shselasky	if (IS_ERR(mailbox)) {
444329222Shselasky		err = PTR_ERR(mailbox);
445329222Shselasky		goto out;
446329222Shselasky	}
447329222Shselasky
448329222Shselasky	err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox);
449329222Shselasky	if (err) {
450329222Shselasky		mthca_warn(dev, "QUERY_QP failed (%d)\n", err);
451329222Shselasky		goto out_mailbox;
452329222Shselasky	}
453329222Shselasky
454329222Shselasky	qp_param    = mailbox->buf;
455329222Shselasky	context     = &qp_param->context;
456329222Shselasky	mthca_state = be32_to_cpu(context->flags) >> 28;
457329222Shselasky
458329222Shselasky	qp->state		     = to_ib_qp_state(mthca_state);
459329222Shselasky	qp_attr->qp_state	     = qp->state;
460329222Shselasky	qp_attr->path_mtu 	     = context->mtu_msgmax >> 5;
461329222Shselasky	qp_attr->path_mig_state      =
462329222Shselasky		to_ib_mig_state((be32_to_cpu(context->flags) >> 11) & 0x3);
463329222Shselasky	qp_attr->qkey 		     = be32_to_cpu(context->qkey);
464329222Shselasky	qp_attr->rq_psn 	     = be32_to_cpu(context->rnr_nextrecvpsn) & 0xffffff;
465329222Shselasky	qp_attr->sq_psn 	     = be32_to_cpu(context->next_send_psn) & 0xffffff;
466329222Shselasky	qp_attr->dest_qp_num 	     = be32_to_cpu(context->remote_qpn) & 0xffffff;
467329222Shselasky	qp_attr->qp_access_flags     =
468329222Shselasky		to_ib_qp_access_flags(be32_to_cpu(context->params2));
469329222Shselasky
470329222Shselasky	if (qp->transport == RC || qp->transport == UC) {
471329222Shselasky		to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
472329222Shselasky		to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
473329222Shselasky		qp_attr->alt_pkey_index =
474329222Shselasky			be32_to_cpu(context->alt_path.port_pkey) & 0x7f;
475329222Shselasky		qp_attr->alt_port_num 	= qp_attr->alt_ah_attr.port_num;
476329222Shselasky	}
477329222Shselasky
478329222Shselasky	qp_attr->pkey_index = be32_to_cpu(context->pri_path.port_pkey) & 0x7f;
479329222Shselasky	qp_attr->port_num   =
480329222Shselasky		(be32_to_cpu(context->pri_path.port_pkey) >> 24) & 0x3;
481329222Shselasky
482329222Shselasky	/* qp_attr->en_sqd_async_notify is only applicable in modify qp */
483329222Shselasky	qp_attr->sq_draining = mthca_state == MTHCA_QP_STATE_DRAINING;
484329222Shselasky
485329222Shselasky	qp_attr->max_rd_atomic = 1 << ((be32_to_cpu(context->params1) >> 21) & 0x7);
486329222Shselasky
487329222Shselasky	qp_attr->max_dest_rd_atomic =
488329222Shselasky		1 << ((be32_to_cpu(context->params2) >> 21) & 0x7);
489329222Shselasky	qp_attr->min_rnr_timer 	    =
490329222Shselasky		(be32_to_cpu(context->rnr_nextrecvpsn) >> 24) & 0x1f;
491329222Shselasky	qp_attr->timeout 	    = context->pri_path.ackto >> 3;
492329222Shselasky	qp_attr->retry_cnt 	    = (be32_to_cpu(context->params1) >> 16) & 0x7;
493329222Shselasky	qp_attr->rnr_retry 	    = context->pri_path.rnr_retry >> 5;
494329222Shselasky	qp_attr->alt_timeout 	    = context->alt_path.ackto >> 3;
495329222Shselasky
496329222Shselaskydone:
497329222Shselasky	qp_attr->cur_qp_state	     = qp_attr->qp_state;
498329222Shselasky	qp_attr->cap.max_send_wr     = qp->sq.max;
499329222Shselasky	qp_attr->cap.max_recv_wr     = qp->rq.max;
500329222Shselasky	qp_attr->cap.max_send_sge    = qp->sq.max_gs;
501329222Shselasky	qp_attr->cap.max_recv_sge    = qp->rq.max_gs;
502329222Shselasky	qp_attr->cap.max_inline_data = qp->max_inline_data;
503329222Shselasky
504329222Shselasky	qp_init_attr->cap	     = qp_attr->cap;
505329222Shselasky	qp_init_attr->sq_sig_type    = qp->sq_policy;
506329222Shselasky
507329222Shselaskyout_mailbox:
508329222Shselasky	mthca_free_mailbox(dev, mailbox);
509329222Shselasky
510329222Shselaskyout:
511329222Shselasky	mutex_unlock(&qp->mutex);
512329222Shselasky	return err;
513329222Shselasky}
514329222Shselasky
515329222Shselaskystatic int mthca_path_set(struct mthca_dev *dev, const struct ib_ah_attr *ah,
516329222Shselasky			  struct mthca_qp_path *path, u8 port)
517329222Shselasky{
518329222Shselasky	path->g_mylmc     = ah->src_path_bits & 0x7f;
519329222Shselasky	path->rlid        = cpu_to_be16(ah->dlid);
520329222Shselasky	path->static_rate = mthca_get_rate(dev, ah->static_rate, port);
521329222Shselasky
522329222Shselasky	if (ah->ah_flags & IB_AH_GRH) {
523329222Shselasky		if (ah->grh.sgid_index >= dev->limits.gid_table_len) {
524329222Shselasky			mthca_dbg(dev, "sgid_index (%u) too large. max is %d\n",
525329222Shselasky				  ah->grh.sgid_index, dev->limits.gid_table_len-1);
526329222Shselasky			return -1;
527329222Shselasky		}
528329222Shselasky
529329222Shselasky		path->g_mylmc   |= 1 << 7;
530329222Shselasky		path->mgid_index = ah->grh.sgid_index;
531329222Shselasky		path->hop_limit  = ah->grh.hop_limit;
532329222Shselasky		path->sl_tclass_flowlabel =
533329222Shselasky			cpu_to_be32((ah->sl << 28)                |
534329222Shselasky				    (ah->grh.traffic_class << 20) |
535329222Shselasky				    (ah->grh.flow_label));
536329222Shselasky		memcpy(path->rgid, ah->grh.dgid.raw, 16);
537329222Shselasky	} else
538329222Shselasky		path->sl_tclass_flowlabel = cpu_to_be32(ah->sl << 28);
539329222Shselasky
540329222Shselasky	return 0;
541329222Shselasky}
542329222Shselasky
543329222Shselaskystatic int __mthca_modify_qp(struct ib_qp *ibqp,
544329222Shselasky			     const struct ib_qp_attr *attr, int attr_mask,
545329222Shselasky			     enum ib_qp_state cur_state, enum ib_qp_state new_state)
546329222Shselasky{
547329222Shselasky	struct mthca_dev *dev = to_mdev(ibqp->device);
548329222Shselasky	struct mthca_qp *qp = to_mqp(ibqp);
549329222Shselasky	struct mthca_mailbox *mailbox;
550329222Shselasky	struct mthca_qp_param *qp_param;
551329222Shselasky	struct mthca_qp_context *qp_context;
552329222Shselasky	u32 sqd_event = 0;
553329222Shselasky	int err = -EINVAL;
554329222Shselasky
555329222Shselasky	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
556329222Shselasky	if (IS_ERR(mailbox)) {
557329222Shselasky		err = PTR_ERR(mailbox);
558329222Shselasky		goto out;
559329222Shselasky	}
560329222Shselasky	qp_param = mailbox->buf;
561329222Shselasky	qp_context = &qp_param->context;
562329222Shselasky	memset(qp_param, 0, sizeof *qp_param);
563329222Shselasky
564329222Shselasky	qp_context->flags      = cpu_to_be32((to_mthca_state(new_state) << 28) |
565329222Shselasky					     (to_mthca_st(qp->transport) << 16));
566329222Shselasky	qp_context->flags     |= cpu_to_be32(MTHCA_QP_BIT_DE);
567329222Shselasky	if (!(attr_mask & IB_QP_PATH_MIG_STATE))
568329222Shselasky		qp_context->flags |= cpu_to_be32(MTHCA_QP_PM_MIGRATED << 11);
569329222Shselasky	else {
570329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PM_STATE);
571329222Shselasky		switch (attr->path_mig_state) {
572329222Shselasky		case IB_MIG_MIGRATED:
573329222Shselasky			qp_context->flags |= cpu_to_be32(MTHCA_QP_PM_MIGRATED << 11);
574329222Shselasky			break;
575329222Shselasky		case IB_MIG_REARM:
576329222Shselasky			qp_context->flags |= cpu_to_be32(MTHCA_QP_PM_REARM << 11);
577329222Shselasky			break;
578329222Shselasky		case IB_MIG_ARMED:
579329222Shselasky			qp_context->flags |= cpu_to_be32(MTHCA_QP_PM_ARMED << 11);
580329222Shselasky			break;
581329222Shselasky		}
582329222Shselasky	}
583329222Shselasky
584329222Shselasky	/* leave tavor_sched_queue as 0 */
585329222Shselasky
586329222Shselasky	if (qp->transport == MLX || qp->transport == UD)
587329222Shselasky		qp_context->mtu_msgmax = (IB_MTU_2048 << 5) | 11;
588329222Shselasky	else if (attr_mask & IB_QP_PATH_MTU) {
589329222Shselasky		if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_2048) {
590329222Shselasky			mthca_dbg(dev, "path MTU (%u) is invalid\n",
591329222Shselasky				  attr->path_mtu);
592329222Shselasky			goto out_mailbox;
593329222Shselasky		}
594329222Shselasky		qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
595329222Shselasky	}
596329222Shselasky
597329222Shselasky	if (mthca_is_memfree(dev)) {
598329222Shselasky		if (qp->rq.max)
599329222Shselasky			qp_context->rq_size_stride = ilog2(qp->rq.max) << 3;
600329222Shselasky		qp_context->rq_size_stride |= qp->rq.wqe_shift - 4;
601329222Shselasky
602329222Shselasky		if (qp->sq.max)
603329222Shselasky			qp_context->sq_size_stride = ilog2(qp->sq.max) << 3;
604329222Shselasky		qp_context->sq_size_stride |= qp->sq.wqe_shift - 4;
605329222Shselasky	}
606329222Shselasky
607329222Shselasky	/* leave arbel_sched_queue as 0 */
608329222Shselasky
609329222Shselasky	if (qp->ibqp.uobject)
610329222Shselasky		qp_context->usr_page =
611329222Shselasky			cpu_to_be32(to_mucontext(qp->ibqp.uobject->context)->uar.index);
612329222Shselasky	else
613329222Shselasky		qp_context->usr_page = cpu_to_be32(dev->driver_uar.index);
614329222Shselasky	qp_context->local_qpn  = cpu_to_be32(qp->qpn);
615329222Shselasky	if (attr_mask & IB_QP_DEST_QPN) {
616329222Shselasky		qp_context->remote_qpn = cpu_to_be32(attr->dest_qp_num);
617329222Shselasky	}
618329222Shselasky
619329222Shselasky	if (qp->transport == MLX)
620329222Shselasky		qp_context->pri_path.port_pkey |=
621329222Shselasky			cpu_to_be32(qp->port << 24);
622329222Shselasky	else {
623329222Shselasky		if (attr_mask & IB_QP_PORT) {
624329222Shselasky			qp_context->pri_path.port_pkey |=
625329222Shselasky				cpu_to_be32(attr->port_num << 24);
626329222Shselasky			qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PORT_NUM);
627329222Shselasky		}
628329222Shselasky	}
629329222Shselasky
630329222Shselasky	if (attr_mask & IB_QP_PKEY_INDEX) {
631329222Shselasky		qp_context->pri_path.port_pkey |=
632329222Shselasky			cpu_to_be32(attr->pkey_index);
633329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PKEY_INDEX);
634329222Shselasky	}
635329222Shselasky
636329222Shselasky	if (attr_mask & IB_QP_RNR_RETRY) {
637329222Shselasky		qp_context->alt_path.rnr_retry = qp_context->pri_path.rnr_retry =
638329222Shselasky			attr->rnr_retry << 5;
639329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY |
640329222Shselasky							MTHCA_QP_OPTPAR_ALT_RNR_RETRY);
641329222Shselasky	}
642329222Shselasky
643329222Shselasky	if (attr_mask & IB_QP_AV) {
644329222Shselasky		if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path,
645329222Shselasky				   attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
646329222Shselasky			goto out_mailbox;
647329222Shselasky
648329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
649329222Shselasky	}
650329222Shselasky
651329222Shselasky	if (ibqp->qp_type == IB_QPT_RC &&
652329222Shselasky	    cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
653329222Shselasky		u8 sched_queue = ibqp->uobject ? 0x2 : 0x1;
654329222Shselasky
655329222Shselasky		if (mthca_is_memfree(dev))
656329222Shselasky			qp_context->rlkey_arbel_sched_queue |= sched_queue;
657329222Shselasky		else
658329222Shselasky			qp_context->tavor_sched_queue |= cpu_to_be32(sched_queue);
659329222Shselasky
660329222Shselasky		qp_param->opt_param_mask |=
661329222Shselasky			cpu_to_be32(MTHCA_QP_OPTPAR_SCHED_QUEUE);
662329222Shselasky	}
663329222Shselasky
664329222Shselasky	if (attr_mask & IB_QP_TIMEOUT) {
665329222Shselasky		qp_context->pri_path.ackto = attr->timeout << 3;
666329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT);
667329222Shselasky	}
668329222Shselasky
669329222Shselasky	if (attr_mask & IB_QP_ALT_PATH) {
670329222Shselasky		if (attr->alt_pkey_index >= dev->limits.pkey_table_len) {
671329222Shselasky			mthca_dbg(dev, "Alternate P_Key index (%u) too large. max is %d\n",
672329222Shselasky				  attr->alt_pkey_index, dev->limits.pkey_table_len-1);
673329222Shselasky			goto out_mailbox;
674329222Shselasky		}
675329222Shselasky
676329222Shselasky		if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) {
677329222Shselasky			mthca_dbg(dev, "Alternate port number (%u) is invalid\n",
678329222Shselasky				attr->alt_port_num);
679329222Shselasky			goto out_mailbox;
680329222Shselasky		}
681329222Shselasky
682329222Shselasky		if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path,
683329222Shselasky				   attr->alt_ah_attr.port_num))
684329222Shselasky			goto out_mailbox;
685329222Shselasky
686329222Shselasky		qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
687329222Shselasky							      attr->alt_port_num << 24);
688329222Shselasky		qp_context->alt_path.ackto = attr->alt_timeout << 3;
689329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ALT_ADDR_PATH);
690329222Shselasky	}
691329222Shselasky
692329222Shselasky	/* leave rdd as 0 */
693329222Shselasky	qp_context->pd         = cpu_to_be32(to_mpd(ibqp->pd)->pd_num);
694329222Shselasky	/* leave wqe_base as 0 (we always create an MR based at 0 for WQs) */
695329222Shselasky	qp_context->wqe_lkey   = cpu_to_be32(qp->mr.ibmr.lkey);
696329222Shselasky	qp_context->params1    = cpu_to_be32((MTHCA_ACK_REQ_FREQ << 28) |
697329222Shselasky					     (MTHCA_FLIGHT_LIMIT << 24) |
698329222Shselasky					     MTHCA_QP_BIT_SWE);
699329222Shselasky	if (qp->sq_policy == IB_SIGNAL_ALL_WR)
700329222Shselasky		qp_context->params1 |= cpu_to_be32(MTHCA_QP_BIT_SSC);
701329222Shselasky	if (attr_mask & IB_QP_RETRY_CNT) {
702329222Shselasky		qp_context->params1 |= cpu_to_be32(attr->retry_cnt << 16);
703329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RETRY_COUNT);
704329222Shselasky	}
705329222Shselasky
706329222Shselasky	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
707329222Shselasky		if (attr->max_rd_atomic) {
708329222Shselasky			qp_context->params1 |=
709329222Shselasky				cpu_to_be32(MTHCA_QP_BIT_SRE |
710329222Shselasky					    MTHCA_QP_BIT_SAE);
711329222Shselasky			qp_context->params1 |=
712329222Shselasky				cpu_to_be32(fls(attr->max_rd_atomic - 1) << 21);
713329222Shselasky		}
714329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_SRA_MAX);
715329222Shselasky	}
716329222Shselasky
717329222Shselasky	if (attr_mask & IB_QP_SQ_PSN)
718329222Shselasky		qp_context->next_send_psn = cpu_to_be32(attr->sq_psn);
719329222Shselasky	qp_context->cqn_snd = cpu_to_be32(to_mcq(ibqp->send_cq)->cqn);
720329222Shselasky
721329222Shselasky	if (mthca_is_memfree(dev)) {
722329222Shselasky		qp_context->snd_wqe_base_l = cpu_to_be32(qp->send_wqe_offset);
723329222Shselasky		qp_context->snd_db_index   = cpu_to_be32(qp->sq.db_index);
724329222Shselasky	}
725329222Shselasky
726329222Shselasky	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
727329222Shselasky		if (attr->max_dest_rd_atomic)
728329222Shselasky			qp_context->params2 |=
729329222Shselasky				cpu_to_be32(fls(attr->max_dest_rd_atomic - 1) << 21);
730329222Shselasky
731329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX);
732329222Shselasky	}
733329222Shselasky
734329222Shselasky	if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) {
735329222Shselasky		qp_context->params2      |= get_hw_access_flags(qp, attr, attr_mask);
736329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE |
737329222Shselasky							MTHCA_QP_OPTPAR_RRE |
738329222Shselasky							MTHCA_QP_OPTPAR_RAE);
739329222Shselasky	}
740329222Shselasky
741329222Shselasky	qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
742329222Shselasky
743329222Shselasky	if (ibqp->srq)
744329222Shselasky		qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RIC);
745329222Shselasky
746329222Shselasky	if (attr_mask & IB_QP_MIN_RNR_TIMER) {
747329222Shselasky		qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24);
748329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_TIMEOUT);
749329222Shselasky	}
750329222Shselasky	if (attr_mask & IB_QP_RQ_PSN)
751329222Shselasky		qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
752329222Shselasky
753329222Shselasky	qp_context->ra_buff_indx =
754329222Shselasky		cpu_to_be32(dev->qp_table.rdb_base +
755329222Shselasky			    ((qp->qpn & (dev->limits.num_qps - 1)) * MTHCA_RDB_ENTRY_SIZE <<
756329222Shselasky			     dev->qp_table.rdb_shift));
757329222Shselasky
758329222Shselasky	qp_context->cqn_rcv = cpu_to_be32(to_mcq(ibqp->recv_cq)->cqn);
759329222Shselasky
760329222Shselasky	if (mthca_is_memfree(dev))
761329222Shselasky		qp_context->rcv_db_index   = cpu_to_be32(qp->rq.db_index);
762329222Shselasky
763329222Shselasky	if (attr_mask & IB_QP_QKEY) {
764329222Shselasky		qp_context->qkey = cpu_to_be32(attr->qkey);
765329222Shselasky		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_Q_KEY);
766329222Shselasky	}
767329222Shselasky
768329222Shselasky	if (ibqp->srq)
769329222Shselasky		qp_context->srqn = cpu_to_be32(1 << 24 |
770329222Shselasky					       to_msrq(ibqp->srq)->srqn);
771329222Shselasky
772329222Shselasky	if (cur_state == IB_QPS_RTS && new_state == IB_QPS_SQD	&&
773329222Shselasky	    attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY		&&
774329222Shselasky	    attr->en_sqd_async_notify)
775329222Shselasky		sqd_event = 1 << 31;
776329222Shselasky
777329222Shselasky	err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0,
778329222Shselasky			      mailbox, sqd_event);
779329222Shselasky	if (err) {
780329222Shselasky		mthca_warn(dev, "modify QP %d->%d returned %d.\n",
781329222Shselasky			   cur_state, new_state, err);
782329222Shselasky		goto out_mailbox;
783329222Shselasky	}
784329222Shselasky
785329222Shselasky	qp->state = new_state;
786329222Shselasky	if (attr_mask & IB_QP_ACCESS_FLAGS)
787329222Shselasky		qp->atomic_rd_en = attr->qp_access_flags;
788329222Shselasky	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
789329222Shselasky		qp->resp_depth = attr->max_dest_rd_atomic;
790329222Shselasky	if (attr_mask & IB_QP_PORT)
791329222Shselasky		qp->port = attr->port_num;
792329222Shselasky	if (attr_mask & IB_QP_ALT_PATH)
793329222Shselasky		qp->alt_port = attr->alt_port_num;
794329222Shselasky
795329222Shselasky	if (is_sqp(dev, qp))
796329222Shselasky		store_attrs(to_msqp(qp), attr, attr_mask);
797329222Shselasky
798329222Shselasky	/*
799329222Shselasky	 * If we moved QP0 to RTR, bring the IB link up; if we moved
800329222Shselasky	 * QP0 to RESET or ERROR, bring the link back down.
801329222Shselasky	 */
802329222Shselasky	if (is_qp0(dev, qp)) {
803329222Shselasky		if (cur_state != IB_QPS_RTR &&
804329222Shselasky		    new_state == IB_QPS_RTR)
805329222Shselasky			init_port(dev, qp->port);
806329222Shselasky
807329222Shselasky		if (cur_state != IB_QPS_RESET &&
808329222Shselasky		    cur_state != IB_QPS_ERR &&
809329222Shselasky		    (new_state == IB_QPS_RESET ||
810329222Shselasky		     new_state == IB_QPS_ERR))
811329222Shselasky			mthca_CLOSE_IB(dev, qp->port);
812329222Shselasky	}
813329222Shselasky
814329222Shselasky	/*
815329222Shselasky	 * If we moved a kernel QP to RESET, clean up all old CQ
816329222Shselasky	 * entries and reinitialize the QP.
817329222Shselasky	 */
818329222Shselasky	if (new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
819329222Shselasky		mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn,
820329222Shselasky			       qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
821329222Shselasky		if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
822329222Shselasky			mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq), qp->qpn, NULL);
823329222Shselasky
824329222Shselasky		mthca_wq_reset(&qp->sq);
825329222Shselasky		qp->sq.last = get_send_wqe(qp, qp->sq.max - 1);
826329222Shselasky
827329222Shselasky		mthca_wq_reset(&qp->rq);
828329222Shselasky		qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1);
829329222Shselasky
830329222Shselasky		if (mthca_is_memfree(dev)) {
831329222Shselasky			*qp->sq.db = 0;
832329222Shselasky			*qp->rq.db = 0;
833329222Shselasky		}
834329222Shselasky	}
835329222Shselasky
836329222Shselaskyout_mailbox:
837329222Shselasky	mthca_free_mailbox(dev, mailbox);
838329222Shselaskyout:
839329222Shselasky	return err;
840329222Shselasky}
841329222Shselasky
842329222Shselaskyint mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
843329222Shselasky		    struct ib_udata *udata)
844329222Shselasky{
845329222Shselasky	struct mthca_dev *dev = to_mdev(ibqp->device);
846329222Shselasky	struct mthca_qp *qp = to_mqp(ibqp);
847329222Shselasky	enum ib_qp_state cur_state, new_state;
848329222Shselasky	int err = -EINVAL;
849329222Shselasky
850329222Shselasky	mutex_lock(&qp->mutex);
851329222Shselasky	if (attr_mask & IB_QP_CUR_STATE) {
852329222Shselasky		cur_state = attr->cur_qp_state;
853329222Shselasky	} else {
854329222Shselasky		spin_lock_irq(&qp->sq.lock);
855329222Shselasky		spin_lock(&qp->rq.lock);
856329222Shselasky		cur_state = qp->state;
857329222Shselasky		spin_unlock(&qp->rq.lock);
858329222Shselasky		spin_unlock_irq(&qp->sq.lock);
859329222Shselasky	}
860329222Shselasky
861329222Shselasky	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
862329222Shselasky
863329222Shselasky	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask,
864329222Shselasky				IB_LINK_LAYER_UNSPECIFIED)) {
865329222Shselasky		mthca_dbg(dev, "Bad QP transition (transport %d) "
866329222Shselasky			  "%d->%d with attr 0x%08x\n",
867329222Shselasky			  qp->transport, cur_state, new_state,
868329222Shselasky			  attr_mask);
869329222Shselasky		goto out;
870329222Shselasky	}
871329222Shselasky
872329222Shselasky	if ((attr_mask & IB_QP_PKEY_INDEX) &&
873329222Shselasky	     attr->pkey_index >= dev->limits.pkey_table_len) {
874329222Shselasky		mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
875329222Shselasky			  attr->pkey_index, dev->limits.pkey_table_len-1);
876329222Shselasky		goto out;
877329222Shselasky	}
878329222Shselasky
879329222Shselasky	if ((attr_mask & IB_QP_PORT) &&
880329222Shselasky	    (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
881329222Shselasky		mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
882329222Shselasky		goto out;
883329222Shselasky	}
884329222Shselasky
885329222Shselasky	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
886329222Shselasky	    attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
887329222Shselasky		mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
888329222Shselasky			  attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
889329222Shselasky		goto out;
890329222Shselasky	}
891329222Shselasky
892329222Shselasky	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
893329222Shselasky	    attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
894329222Shselasky		mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
895329222Shselasky			  attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
896329222Shselasky		goto out;
897329222Shselasky	}
898329222Shselasky
899329222Shselasky	if (cur_state == new_state && cur_state == IB_QPS_RESET) {
900329222Shselasky		err = 0;
901329222Shselasky		goto out;
902329222Shselasky	}
903329222Shselasky
904329222Shselasky	err = __mthca_modify_qp(ibqp, attr, attr_mask, cur_state, new_state);
905329222Shselasky
906329222Shselaskyout:
907329222Shselasky	mutex_unlock(&qp->mutex);
908329222Shselasky	return err;
909329222Shselasky}
910329222Shselasky
911329222Shselaskystatic int mthca_max_data_size(struct mthca_dev *dev, struct mthca_qp *qp, int desc_sz)
912329222Shselasky{
913329222Shselasky	/*
914329222Shselasky	 * Calculate the maximum size of WQE s/g segments, excluding
915329222Shselasky	 * the next segment and other non-data segments.
916329222Shselasky	 */
917329222Shselasky	int max_data_size = desc_sz - sizeof (struct mthca_next_seg);
918329222Shselasky
919329222Shselasky	switch (qp->transport) {
920329222Shselasky	case MLX:
921329222Shselasky		max_data_size -= 2 * sizeof (struct mthca_data_seg);
922329222Shselasky		break;
923329222Shselasky
924329222Shselasky	case UD:
925329222Shselasky		if (mthca_is_memfree(dev))
926329222Shselasky			max_data_size -= sizeof (struct mthca_arbel_ud_seg);
927329222Shselasky		else
928329222Shselasky			max_data_size -= sizeof (struct mthca_tavor_ud_seg);
929329222Shselasky		break;
930329222Shselasky
931329222Shselasky	default:
932329222Shselasky		max_data_size -= sizeof (struct mthca_raddr_seg);
933329222Shselasky		break;
934329222Shselasky	}
935329222Shselasky
936329222Shselasky	return max_data_size;
937329222Shselasky}
938329222Shselasky
939329222Shselaskystatic inline int mthca_max_inline_data(struct mthca_pd *pd, int max_data_size)
940329222Shselasky{
941329222Shselasky	/* We don't support inline data for kernel QPs (yet). */
942329222Shselasky	return pd->ibpd.uobject ? max_data_size - MTHCA_INLINE_HEADER_SIZE : 0;
943329222Shselasky}
944329222Shselasky
945329222Shselaskystatic void mthca_adjust_qp_caps(struct mthca_dev *dev,
946329222Shselasky				 struct mthca_pd *pd,
947329222Shselasky				 struct mthca_qp *qp)
948329222Shselasky{
949329222Shselasky	int max_data_size = mthca_max_data_size(dev, qp,
950329222Shselasky						min(dev->limits.max_desc_sz,
951329222Shselasky						    1 << qp->sq.wqe_shift));
952329222Shselasky
953329222Shselasky	qp->max_inline_data = mthca_max_inline_data(pd, max_data_size);
954329222Shselasky
955329222Shselasky	qp->sq.max_gs = min_t(int, dev->limits.max_sg,
956329222Shselasky			      max_data_size / sizeof (struct mthca_data_seg));
957329222Shselasky	qp->rq.max_gs = min_t(int, dev->limits.max_sg,
958329222Shselasky			       (min(dev->limits.max_desc_sz, 1 << qp->rq.wqe_shift) -
959329222Shselasky				sizeof (struct mthca_next_seg)) /
960329222Shselasky			       sizeof (struct mthca_data_seg));
961329222Shselasky}
962329222Shselasky
963329222Shselasky/*
964329222Shselasky * Allocate and register buffer for WQEs.  qp->rq.max, sq.max,
965329222Shselasky * rq.max_gs and sq.max_gs must all be assigned.
966329222Shselasky * mthca_alloc_wqe_buf will calculate rq.wqe_shift and
967329222Shselasky * sq.wqe_shift (as well as send_wqe_offset, is_direct, and
968329222Shselasky * queue)
969329222Shselasky */
970329222Shselaskystatic int mthca_alloc_wqe_buf(struct mthca_dev *dev,
971329222Shselasky			       struct mthca_pd *pd,
972329222Shselasky			       struct mthca_qp *qp)
973329222Shselasky{
974329222Shselasky	int size;
975329222Shselasky	int err = -ENOMEM;
976329222Shselasky
977329222Shselasky	size = sizeof (struct mthca_next_seg) +
978329222Shselasky		qp->rq.max_gs * sizeof (struct mthca_data_seg);
979329222Shselasky
980329222Shselasky	if (size > dev->limits.max_desc_sz)
981329222Shselasky		return -EINVAL;
982329222Shselasky
983329222Shselasky	for (qp->rq.wqe_shift = 6; 1 << qp->rq.wqe_shift < size;
984329222Shselasky	     qp->rq.wqe_shift++)
985329222Shselasky		; /* nothing */
986329222Shselasky
987329222Shselasky	size = qp->sq.max_gs * sizeof (struct mthca_data_seg);
988329222Shselasky	switch (qp->transport) {
989329222Shselasky	case MLX:
990329222Shselasky		size += 2 * sizeof (struct mthca_data_seg);
991329222Shselasky		break;
992329222Shselasky
993329222Shselasky	case UD:
994329222Shselasky		size += mthca_is_memfree(dev) ?
995329222Shselasky			sizeof (struct mthca_arbel_ud_seg) :
996329222Shselasky			sizeof (struct mthca_tavor_ud_seg);
997329222Shselasky		break;
998329222Shselasky
999329222Shselasky	case UC:
1000329222Shselasky		size += sizeof (struct mthca_raddr_seg);
1001329222Shselasky		break;
1002329222Shselasky
1003329222Shselasky	case RC:
1004329222Shselasky		size += sizeof (struct mthca_raddr_seg);
1005329222Shselasky		/*
1006329222Shselasky		 * An atomic op will require an atomic segment, a
1007329222Shselasky		 * remote address segment and one scatter entry.
1008329222Shselasky		 */
1009329222Shselasky		size = max_t(int, size,
1010329222Shselasky			     sizeof (struct mthca_atomic_seg) +
1011329222Shselasky			     sizeof (struct mthca_raddr_seg) +
1012329222Shselasky			     sizeof (struct mthca_data_seg));
1013329222Shselasky		break;
1014329222Shselasky
1015329222Shselasky	default:
1016329222Shselasky		break;
1017329222Shselasky	}
1018329222Shselasky
1019329222Shselasky	/* Make sure that we have enough space for a bind request */
1020329222Shselasky	size = max_t(int, size, sizeof (struct mthca_bind_seg));
1021329222Shselasky
1022329222Shselasky	size += sizeof (struct mthca_next_seg);
1023329222Shselasky
1024329222Shselasky	if (size > dev->limits.max_desc_sz)
1025329222Shselasky		return -EINVAL;
1026329222Shselasky
1027329222Shselasky	for (qp->sq.wqe_shift = 6; 1 << qp->sq.wqe_shift < size;
1028329222Shselasky	     qp->sq.wqe_shift++)
1029329222Shselasky		; /* nothing */
1030329222Shselasky
1031329222Shselasky	qp->send_wqe_offset = ALIGN(qp->rq.max << qp->rq.wqe_shift,
1032329222Shselasky				    1 << qp->sq.wqe_shift);
1033329222Shselasky
1034329222Shselasky	/*
1035329222Shselasky	 * If this is a userspace QP, we don't actually have to
1036329222Shselasky	 * allocate anything.  All we need is to calculate the WQE
1037329222Shselasky	 * sizes and the send_wqe_offset, so we're done now.
1038329222Shselasky	 */
1039329222Shselasky	if (pd->ibpd.uobject)
1040329222Shselasky		return 0;
1041329222Shselasky
1042329222Shselasky	size = PAGE_ALIGN(qp->send_wqe_offset +
1043329222Shselasky			  (qp->sq.max << qp->sq.wqe_shift));
1044329222Shselasky
1045329222Shselasky	qp->wrid = kmalloc((qp->rq.max + qp->sq.max) * sizeof (u64),
1046329222Shselasky			   GFP_KERNEL);
1047329222Shselasky	if (!qp->wrid)
1048329222Shselasky		goto err_out;
1049329222Shselasky
1050329222Shselasky	err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_QP_SIZE,
1051329222Shselasky			      &qp->queue, &qp->is_direct, pd, 0, &qp->mr);
1052329222Shselasky	if (err)
1053329222Shselasky		goto err_out;
1054329222Shselasky
1055329222Shselasky	return 0;
1056329222Shselasky
1057329222Shselaskyerr_out:
1058329222Shselasky	kfree(qp->wrid);
1059329222Shselasky	return err;
1060329222Shselasky}
1061329222Shselasky
1062329222Shselaskystatic void mthca_free_wqe_buf(struct mthca_dev *dev,
1063329222Shselasky			       struct mthca_qp *qp)
1064329222Shselasky{
1065329222Shselasky	mthca_buf_free(dev, PAGE_ALIGN(qp->send_wqe_offset +
1066329222Shselasky				       (qp->sq.max << qp->sq.wqe_shift)),
1067329222Shselasky		       &qp->queue, qp->is_direct, &qp->mr);
1068329222Shselasky	kfree(qp->wrid);
1069329222Shselasky}
1070329222Shselasky
1071329222Shselaskystatic int mthca_map_memfree(struct mthca_dev *dev,
1072329222Shselasky			     struct mthca_qp *qp)
1073329222Shselasky{
1074329222Shselasky	int ret;
1075329222Shselasky
1076329222Shselasky	if (mthca_is_memfree(dev)) {
1077329222Shselasky		ret = mthca_table_get(dev, dev->qp_table.qp_table, qp->qpn);
1078329222Shselasky		if (ret)
1079329222Shselasky			return ret;
1080329222Shselasky
1081329222Shselasky		ret = mthca_table_get(dev, dev->qp_table.eqp_table, qp->qpn);
1082329222Shselasky		if (ret)
1083329222Shselasky			goto err_qpc;
1084329222Shselasky
1085329222Shselasky		ret = mthca_table_get(dev, dev->qp_table.rdb_table,
1086329222Shselasky				      qp->qpn << dev->qp_table.rdb_shift);
1087329222Shselasky		if (ret)
1088329222Shselasky			goto err_eqpc;
1089329222Shselasky
1090329222Shselasky	}
1091329222Shselasky
1092329222Shselasky	return 0;
1093329222Shselasky
1094329222Shselaskyerr_eqpc:
1095329222Shselasky	mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
1096329222Shselasky
1097329222Shselaskyerr_qpc:
1098329222Shselasky	mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
1099329222Shselasky
1100329222Shselasky	return ret;
1101329222Shselasky}
1102329222Shselasky
1103329222Shselaskystatic void mthca_unmap_memfree(struct mthca_dev *dev,
1104329222Shselasky				struct mthca_qp *qp)
1105329222Shselasky{
1106329222Shselasky	mthca_table_put(dev, dev->qp_table.rdb_table,
1107329222Shselasky			qp->qpn << dev->qp_table.rdb_shift);
1108329222Shselasky	mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
1109329222Shselasky	mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
1110329222Shselasky}
1111329222Shselasky
1112329222Shselaskystatic int mthca_alloc_memfree(struct mthca_dev *dev,
1113329222Shselasky			       struct mthca_qp *qp)
1114329222Shselasky{
1115329222Shselasky	if (mthca_is_memfree(dev)) {
1116329222Shselasky		qp->rq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_RQ,
1117329222Shselasky						 qp->qpn, &qp->rq.db);
1118329222Shselasky		if (qp->rq.db_index < 0)
1119329222Shselasky			return -ENOMEM;
1120329222Shselasky
1121329222Shselasky		qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ,
1122329222Shselasky						 qp->qpn, &qp->sq.db);
1123329222Shselasky		if (qp->sq.db_index < 0) {
1124329222Shselasky			mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
1125329222Shselasky			return -ENOMEM;
1126329222Shselasky		}
1127329222Shselasky	}
1128329222Shselasky
1129329222Shselasky	return 0;
1130329222Shselasky}
1131329222Shselasky
1132329222Shselaskystatic void mthca_free_memfree(struct mthca_dev *dev,
1133329222Shselasky			       struct mthca_qp *qp)
1134329222Shselasky{
1135329222Shselasky	if (mthca_is_memfree(dev)) {
1136329222Shselasky		mthca_free_db(dev, MTHCA_DB_TYPE_SQ, qp->sq.db_index);
1137329222Shselasky		mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
1138329222Shselasky	}
1139329222Shselasky}
1140329222Shselasky
1141329222Shselaskystatic int mthca_alloc_qp_common(struct mthca_dev *dev,
1142329222Shselasky				 struct mthca_pd *pd,
1143329222Shselasky				 struct mthca_cq *send_cq,
1144329222Shselasky				 struct mthca_cq *recv_cq,
1145329222Shselasky				 enum ib_sig_type send_policy,
1146329222Shselasky				 struct mthca_qp *qp)
1147329222Shselasky{
1148329222Shselasky	int ret;
1149329222Shselasky	int i;
1150329222Shselasky	struct mthca_next_seg *next;
1151329222Shselasky
1152329222Shselasky	qp->refcount = 1;
1153329222Shselasky	init_waitqueue_head(&qp->wait);
1154329222Shselasky	mutex_init(&qp->mutex);
1155329222Shselasky	qp->state    	 = IB_QPS_RESET;
1156329222Shselasky	qp->atomic_rd_en = 0;
1157329222Shselasky	qp->resp_depth   = 0;
1158329222Shselasky	qp->sq_policy    = send_policy;
1159329222Shselasky	mthca_wq_reset(&qp->sq);
1160329222Shselasky	mthca_wq_reset(&qp->rq);
1161329222Shselasky
1162329222Shselasky	spin_lock_init(&qp->sq.lock);
1163329222Shselasky	spin_lock_init(&qp->rq.lock);
1164329222Shselasky
1165329222Shselasky	ret = mthca_map_memfree(dev, qp);
1166329222Shselasky	if (ret)
1167329222Shselasky		return ret;
1168329222Shselasky
1169329222Shselasky	ret = mthca_alloc_wqe_buf(dev, pd, qp);
1170329222Shselasky	if (ret) {
1171329222Shselasky		mthca_unmap_memfree(dev, qp);
1172329222Shselasky		return ret;
1173329222Shselasky	}
1174329222Shselasky
1175329222Shselasky	mthca_adjust_qp_caps(dev, pd, qp);
1176329222Shselasky
1177329222Shselasky	/*
1178329222Shselasky	 * If this is a userspace QP, we're done now.  The doorbells
1179329222Shselasky	 * will be allocated and buffers will be initialized in
1180329222Shselasky	 * userspace.
1181329222Shselasky	 */
1182329222Shselasky	if (pd->ibpd.uobject)
1183329222Shselasky		return 0;
1184329222Shselasky
1185329222Shselasky	ret = mthca_alloc_memfree(dev, qp);
1186329222Shselasky	if (ret) {
1187329222Shselasky		mthca_free_wqe_buf(dev, qp);
1188329222Shselasky		mthca_unmap_memfree(dev, qp);
1189329222Shselasky		return ret;
1190329222Shselasky	}
1191329222Shselasky
1192329222Shselasky	if (mthca_is_memfree(dev)) {
1193329222Shselasky		struct mthca_data_seg *scatter;
1194329222Shselasky		int size = (sizeof (struct mthca_next_seg) +
1195329222Shselasky			    qp->rq.max_gs * sizeof (struct mthca_data_seg)) / 16;
1196329222Shselasky
1197329222Shselasky		for (i = 0; i < qp->rq.max; ++i) {
1198329222Shselasky			next = get_recv_wqe(qp, i);
1199329222Shselasky			next->nda_op = cpu_to_be32(((i + 1) & (qp->rq.max - 1)) <<
1200329222Shselasky						   qp->rq.wqe_shift);
1201329222Shselasky			next->ee_nds = cpu_to_be32(size);
1202329222Shselasky
1203329222Shselasky			for (scatter = (void *) (next + 1);
1204329222Shselasky			     (void *) scatter < (void *) next + (1 << qp->rq.wqe_shift);
1205329222Shselasky			     ++scatter)
1206329222Shselasky				scatter->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
1207329222Shselasky		}
1208329222Shselasky
1209329222Shselasky		for (i = 0; i < qp->sq.max; ++i) {
1210329222Shselasky			next = get_send_wqe(qp, i);
1211329222Shselasky			next->nda_op = cpu_to_be32((((i + 1) & (qp->sq.max - 1)) <<
1212329222Shselasky						    qp->sq.wqe_shift) +
1213329222Shselasky						   qp->send_wqe_offset);
1214329222Shselasky		}
1215329222Shselasky	} else {
1216329222Shselasky		for (i = 0; i < qp->rq.max; ++i) {
1217329222Shselasky			next = get_recv_wqe(qp, i);
1218329222Shselasky			next->nda_op = htonl((((i + 1) % qp->rq.max) <<
1219329222Shselasky					      qp->rq.wqe_shift) | 1);
1220329222Shselasky		}
1221329222Shselasky
1222329222Shselasky	}
1223329222Shselasky
1224329222Shselasky	qp->sq.last = get_send_wqe(qp, qp->sq.max - 1);
1225329222Shselasky	qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1);
1226329222Shselasky
1227329222Shselasky	return 0;
1228329222Shselasky}
1229329222Shselasky
1230329222Shselaskystatic int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
1231329222Shselasky			     struct mthca_pd *pd, struct mthca_qp *qp)
1232329222Shselasky{
1233329222Shselasky	int max_data_size = mthca_max_data_size(dev, qp, dev->limits.max_desc_sz);
1234329222Shselasky
1235329222Shselasky	/* Sanity check QP size before proceeding */
1236329222Shselasky	if (cap->max_send_wr  	 > dev->limits.max_wqes ||
1237329222Shselasky	    cap->max_recv_wr  	 > dev->limits.max_wqes ||
1238329222Shselasky	    cap->max_send_sge 	 > dev->limits.max_sg   ||
1239329222Shselasky	    cap->max_recv_sge 	 > dev->limits.max_sg   ||
1240329222Shselasky	    cap->max_inline_data > mthca_max_inline_data(pd, max_data_size))
1241329222Shselasky		return -EINVAL;
1242329222Shselasky
1243329222Shselasky	/*
1244329222Shselasky	 * For MLX transport we need 2 extra send gather entries:
1245329222Shselasky	 * one for the header and one for the checksum at the end
1246329222Shselasky	 */
1247329222Shselasky	if (qp->transport == MLX && cap->max_send_sge + 2 > dev->limits.max_sg)
1248329222Shselasky		return -EINVAL;
1249329222Shselasky
1250329222Shselasky	if (mthca_is_memfree(dev)) {
1251329222Shselasky		qp->rq.max = cap->max_recv_wr ?
1252329222Shselasky			roundup_pow_of_two(cap->max_recv_wr) : 0;
1253329222Shselasky		qp->sq.max = cap->max_send_wr ?
1254329222Shselasky			roundup_pow_of_two(cap->max_send_wr) : 0;
1255329222Shselasky	} else {
1256329222Shselasky		qp->rq.max = cap->max_recv_wr;
1257329222Shselasky		qp->sq.max = cap->max_send_wr;
1258329222Shselasky	}
1259329222Shselasky
1260329222Shselasky	qp->rq.max_gs = cap->max_recv_sge;
1261329222Shselasky	qp->sq.max_gs = max_t(int, cap->max_send_sge,
1262329222Shselasky			      ALIGN(cap->max_inline_data + MTHCA_INLINE_HEADER_SIZE,
1263329222Shselasky				    MTHCA_INLINE_CHUNK_SIZE) /
1264329222Shselasky			      sizeof (struct mthca_data_seg));
1265329222Shselasky
1266329222Shselasky	return 0;
1267329222Shselasky}
1268329222Shselasky
1269329222Shselaskyint mthca_alloc_qp(struct mthca_dev *dev,
1270329222Shselasky		   struct mthca_pd *pd,
1271329222Shselasky		   struct mthca_cq *send_cq,
1272329222Shselasky		   struct mthca_cq *recv_cq,
1273329222Shselasky		   enum ib_qp_type type,
1274329222Shselasky		   enum ib_sig_type send_policy,
1275329222Shselasky		   struct ib_qp_cap *cap,
1276329222Shselasky		   struct mthca_qp *qp)
1277329222Shselasky{
1278329222Shselasky	int err;
1279329222Shselasky
1280329222Shselasky	switch (type) {
1281329222Shselasky	case IB_QPT_RC: qp->transport = RC; break;
1282329222Shselasky	case IB_QPT_UC: qp->transport = UC; break;
1283329222Shselasky	case IB_QPT_UD: qp->transport = UD; break;
1284329222Shselasky	default: return -EINVAL;
1285329222Shselasky	}
1286329222Shselasky
1287329222Shselasky	err = mthca_set_qp_size(dev, cap, pd, qp);
1288329222Shselasky	if (err)
1289329222Shselasky		return err;
1290329222Shselasky
1291329222Shselasky	qp->qpn = mthca_alloc(&dev->qp_table.alloc);
1292329222Shselasky	if (qp->qpn == -1)
1293329222Shselasky		return -ENOMEM;
1294329222Shselasky
1295329222Shselasky	/* initialize port to zero for error-catching. */
1296329222Shselasky	qp->port = 0;
1297329222Shselasky
1298329222Shselasky	err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
1299329222Shselasky				    send_policy, qp);
1300329222Shselasky	if (err) {
1301329222Shselasky		mthca_free(&dev->qp_table.alloc, qp->qpn);
1302329222Shselasky		return err;
1303329222Shselasky	}
1304329222Shselasky
1305329222Shselasky	spin_lock_irq(&dev->qp_table.lock);
1306329222Shselasky	mthca_array_set(&dev->qp_table.qp,
1307329222Shselasky			qp->qpn & (dev->limits.num_qps - 1), qp);
1308329222Shselasky	spin_unlock_irq(&dev->qp_table.lock);
1309329222Shselasky
1310329222Shselasky	return 0;
1311329222Shselasky}
1312329222Shselasky
1313329222Shselaskystatic void mthca_lock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq)
1314329222Shselasky	__acquires(&send_cq->lock) __acquires(&recv_cq->lock)
1315329222Shselasky{
1316329222Shselasky	if (send_cq == recv_cq) {
1317329222Shselasky		spin_lock_irq(&send_cq->lock);
1318329222Shselasky		__acquire(&recv_cq->lock);
1319329222Shselasky	} else if (send_cq->cqn < recv_cq->cqn) {
1320329222Shselasky		spin_lock_irq(&send_cq->lock);
1321329222Shselasky		spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING);
1322329222Shselasky	} else {
1323329222Shselasky		spin_lock_irq(&recv_cq->lock);
1324329222Shselasky		spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING);
1325329222Shselasky	}
1326329222Shselasky}
1327329222Shselasky
1328329222Shselaskystatic void mthca_unlock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq)
1329329222Shselasky	__releases(&send_cq->lock) __releases(&recv_cq->lock)
1330329222Shselasky{
1331329222Shselasky	if (send_cq == recv_cq) {
1332329222Shselasky		__release(&recv_cq->lock);
1333329222Shselasky		spin_unlock_irq(&send_cq->lock);
1334329222Shselasky	} else if (send_cq->cqn < recv_cq->cqn) {
1335329222Shselasky		spin_unlock(&recv_cq->lock);
1336329222Shselasky		spin_unlock_irq(&send_cq->lock);
1337329222Shselasky	} else {
1338329222Shselasky		spin_unlock(&send_cq->lock);
1339329222Shselasky		spin_unlock_irq(&recv_cq->lock);
1340329222Shselasky	}
1341329222Shselasky}
1342329222Shselasky
1343329222Shselaskyint mthca_alloc_sqp(struct mthca_dev *dev,
1344329222Shselasky		    struct mthca_pd *pd,
1345329222Shselasky		    struct mthca_cq *send_cq,
1346329222Shselasky		    struct mthca_cq *recv_cq,
1347329222Shselasky		    enum ib_sig_type send_policy,
1348329222Shselasky		    struct ib_qp_cap *cap,
1349329222Shselasky		    int qpn,
1350329222Shselasky		    int port,
1351329222Shselasky		    struct mthca_sqp *sqp)
1352329222Shselasky{
1353329222Shselasky	u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
1354329222Shselasky	int err;
1355329222Shselasky
1356329222Shselasky	sqp->qp.transport = MLX;
1357329222Shselasky	err = mthca_set_qp_size(dev, cap, pd, &sqp->qp);
1358329222Shselasky	if (err)
1359329222Shselasky		return err;
1360329222Shselasky
1361329222Shselasky	sqp->header_buf_size = sqp->qp.sq.max * MTHCA_UD_HEADER_SIZE;
1362329222Shselasky	sqp->header_buf = dma_alloc_coherent(&dev->pdev->dev, sqp->header_buf_size,
1363329222Shselasky					     &sqp->header_dma, GFP_KERNEL);
1364329222Shselasky	if (!sqp->header_buf)
1365329222Shselasky		return -ENOMEM;
1366329222Shselasky
1367329222Shselasky	spin_lock_irq(&dev->qp_table.lock);
1368329222Shselasky	if (mthca_array_get(&dev->qp_table.qp, mqpn))
1369329222Shselasky		err = -EBUSY;
1370329222Shselasky	else
1371329222Shselasky		mthca_array_set(&dev->qp_table.qp, mqpn, sqp);
1372329222Shselasky	spin_unlock_irq(&dev->qp_table.lock);
1373329222Shselasky
1374329222Shselasky	if (err)
1375329222Shselasky		goto err_out;
1376329222Shselasky
1377329222Shselasky	sqp->qp.port      = port;
1378329222Shselasky	sqp->qp.qpn       = mqpn;
1379329222Shselasky	sqp->qp.transport = MLX;
1380329222Shselasky
1381329222Shselasky	err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
1382329222Shselasky				    send_policy, &sqp->qp);
1383329222Shselasky	if (err)
1384329222Shselasky		goto err_out_free;
1385329222Shselasky
1386329222Shselasky	atomic_inc(&pd->sqp_count);
1387329222Shselasky
1388329222Shselasky	return 0;
1389329222Shselasky
1390329222Shselasky err_out_free:
1391329222Shselasky	/*
1392329222Shselasky	 * Lock CQs here, so that CQ polling code can do QP lookup
1393329222Shselasky	 * without taking a lock.
1394329222Shselasky	 */
1395329222Shselasky	mthca_lock_cqs(send_cq, recv_cq);
1396329222Shselasky
1397329222Shselasky	spin_lock(&dev->qp_table.lock);
1398329222Shselasky	mthca_array_clear(&dev->qp_table.qp, mqpn);
1399329222Shselasky	spin_unlock(&dev->qp_table.lock);
1400329222Shselasky
1401329222Shselasky	mthca_unlock_cqs(send_cq, recv_cq);
1402329222Shselasky
1403329222Shselasky err_out:
1404329222Shselasky	dma_free_coherent(&dev->pdev->dev, sqp->header_buf_size,
1405329222Shselasky			  sqp->header_buf, sqp->header_dma);
1406329222Shselasky
1407329222Shselasky	return err;
1408329222Shselasky}
1409329222Shselasky
1410329222Shselaskystatic inline int get_qp_refcount(struct mthca_dev *dev, struct mthca_qp *qp)
1411329222Shselasky{
1412329222Shselasky	int c;
1413329222Shselasky
1414329222Shselasky	spin_lock_irq(&dev->qp_table.lock);
1415329222Shselasky	c = qp->refcount;
1416329222Shselasky	spin_unlock_irq(&dev->qp_table.lock);
1417329222Shselasky
1418329222Shselasky	return c;
1419329222Shselasky}
1420329222Shselasky
1421329222Shselaskyvoid mthca_free_qp(struct mthca_dev *dev,
1422329222Shselasky		   struct mthca_qp *qp)
1423329222Shselasky{
1424329222Shselasky	struct mthca_cq *send_cq;
1425329222Shselasky	struct mthca_cq *recv_cq;
1426329222Shselasky
1427329222Shselasky	send_cq = to_mcq(qp->ibqp.send_cq);
1428329222Shselasky	recv_cq = to_mcq(qp->ibqp.recv_cq);
1429329222Shselasky
1430329222Shselasky	/*
1431329222Shselasky	 * Lock CQs here, so that CQ polling code can do QP lookup
1432329222Shselasky	 * without taking a lock.
1433329222Shselasky	 */
1434329222Shselasky	mthca_lock_cqs(send_cq, recv_cq);
1435329222Shselasky
1436329222Shselasky	spin_lock(&dev->qp_table.lock);
1437329222Shselasky	mthca_array_clear(&dev->qp_table.qp,
1438329222Shselasky			  qp->qpn & (dev->limits.num_qps - 1));
1439329222Shselasky	--qp->refcount;
1440329222Shselasky	spin_unlock(&dev->qp_table.lock);
1441329222Shselasky
1442329222Shselasky	mthca_unlock_cqs(send_cq, recv_cq);
1443329222Shselasky
1444329222Shselasky	wait_event(qp->wait, !get_qp_refcount(dev, qp));
1445329222Shselasky
1446329222Shselasky	if (qp->state != IB_QPS_RESET)
1447329222Shselasky		mthca_MODIFY_QP(dev, qp->state, IB_QPS_RESET, qp->qpn, 0,
1448329222Shselasky				NULL, 0);
1449329222Shselasky
1450329222Shselasky	/*
1451329222Shselasky	 * If this is a userspace QP, the buffers, MR, CQs and so on
1452329222Shselasky	 * will be cleaned up in userspace, so all we have to do is
1453329222Shselasky	 * unref the mem-free tables and free the QPN in our table.
1454329222Shselasky	 */
1455329222Shselasky	if (!qp->ibqp.uobject) {
1456329222Shselasky		mthca_cq_clean(dev, recv_cq, qp->qpn,
1457329222Shselasky			       qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
1458329222Shselasky		if (send_cq != recv_cq)
1459329222Shselasky			mthca_cq_clean(dev, send_cq, qp->qpn, NULL);
1460329222Shselasky
1461329222Shselasky		mthca_free_memfree(dev, qp);
1462329222Shselasky		mthca_free_wqe_buf(dev, qp);
1463329222Shselasky	}
1464329222Shselasky
1465329222Shselasky	mthca_unmap_memfree(dev, qp);
1466329222Shselasky
1467329222Shselasky	if (is_sqp(dev, qp)) {
1468329222Shselasky		atomic_dec(&(to_mpd(qp->ibqp.pd)->sqp_count));
1469329222Shselasky		dma_free_coherent(&dev->pdev->dev,
1470329222Shselasky				  to_msqp(qp)->header_buf_size,
1471329222Shselasky				  to_msqp(qp)->header_buf,
1472329222Shselasky				  to_msqp(qp)->header_dma);
1473329222Shselasky	} else
1474329222Shselasky		mthca_free(&dev->qp_table.alloc, qp->qpn);
1475329222Shselasky}
1476329222Shselasky
1477329222Shselasky/* Create UD header for an MLX send and build a data segment for it */
1478329222Shselaskystatic int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
1479329222Shselasky			    int ind, struct ib_ud_wr *wr,
1480329222Shselasky			    struct mthca_mlx_seg *mlx,
1481329222Shselasky			    struct mthca_data_seg *data)
1482329222Shselasky{
1483329222Shselasky	int header_size;
1484329222Shselasky	int err;
1485329222Shselasky	u16 pkey;
1486329222Shselasky
1487329222Shselasky	ib_ud_header_init(256, /* assume a MAD */ 1, 0, 0,
1488329222Shselasky			  mthca_ah_grh_present(to_mah(wr->ah)), 0, 0, 0,
1489329222Shselasky			  &sqp->ud_header);
1490329222Shselasky
1491329222Shselasky	err = mthca_read_ah(dev, to_mah(wr->ah), &sqp->ud_header);
1492329222Shselasky	if (err)
1493329222Shselasky		return err;
1494329222Shselasky	mlx->flags &= ~cpu_to_be32(MTHCA_NEXT_SOLICIT | 1);
1495329222Shselasky	mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MTHCA_MLX_VL15 : 0) |
1496329222Shselasky				  (sqp->ud_header.lrh.destination_lid ==
1497329222Shselasky				   IB_LID_PERMISSIVE ? MTHCA_MLX_SLR : 0) |
1498329222Shselasky				  (sqp->ud_header.lrh.service_level << 8));
1499329222Shselasky	mlx->rlid = sqp->ud_header.lrh.destination_lid;
1500329222Shselasky	mlx->vcrc = 0;
1501329222Shselasky
1502329222Shselasky	switch (wr->wr.opcode) {
1503329222Shselasky	case IB_WR_SEND:
1504329222Shselasky		sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY;
1505329222Shselasky		sqp->ud_header.immediate_present = 0;
1506329222Shselasky		break;
1507329222Shselasky	case IB_WR_SEND_WITH_IMM:
1508329222Shselasky		sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
1509329222Shselasky		sqp->ud_header.immediate_present = 1;
1510329222Shselasky		sqp->ud_header.immediate_data = wr->wr.ex.imm_data;
1511329222Shselasky		break;
1512329222Shselasky	default:
1513329222Shselasky		return -EINVAL;
1514329222Shselasky	}
1515329222Shselasky
1516329222Shselasky	sqp->ud_header.lrh.virtual_lane    = !sqp->qp.ibqp.qp_num ? 15 : 0;
1517329222Shselasky	if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
1518329222Shselasky		sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
1519329222Shselasky	sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
1520329222Shselasky	if (!sqp->qp.ibqp.qp_num)
1521329222Shselasky		ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
1522329222Shselasky				   sqp->pkey_index, &pkey);
1523329222Shselasky	else
1524329222Shselasky		ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
1525329222Shselasky				   wr->pkey_index, &pkey);
1526329222Shselasky	sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
1527329222Shselasky	sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
1528329222Shselasky	sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
1529329222Shselasky	sqp->ud_header.deth.qkey = cpu_to_be32(wr->remote_qkey & 0x80000000 ?
1530329222Shselasky					       sqp->qkey : wr->remote_qkey);
1531329222Shselasky	sqp->ud_header.deth.source_qpn = cpu_to_be32(sqp->qp.ibqp.qp_num);
1532329222Shselasky
1533329222Shselasky	header_size = ib_ud_header_pack(&sqp->ud_header,
1534329222Shselasky					sqp->header_buf +
1535329222Shselasky					ind * MTHCA_UD_HEADER_SIZE);
1536329222Shselasky
1537329222Shselasky	data->byte_count = cpu_to_be32(header_size);
1538329222Shselasky	data->lkey       = cpu_to_be32(to_mpd(sqp->qp.ibqp.pd)->ntmr.ibmr.lkey);
1539329222Shselasky	data->addr       = cpu_to_be64(sqp->header_dma +
1540329222Shselasky				       ind * MTHCA_UD_HEADER_SIZE);
1541329222Shselasky
1542329222Shselasky	return 0;
1543329222Shselasky}
1544329222Shselasky
1545329222Shselaskystatic inline int mthca_wq_overflow(struct mthca_wq *wq, int nreq,
1546329222Shselasky				    struct ib_cq *ib_cq)
1547329222Shselasky{
1548329222Shselasky	unsigned cur;
1549329222Shselasky	struct mthca_cq *cq;
1550329222Shselasky
1551329222Shselasky	cur = wq->head - wq->tail;
1552329222Shselasky	if (likely(cur + nreq < wq->max))
1553329222Shselasky		return 0;
1554329222Shselasky
1555329222Shselasky	cq = to_mcq(ib_cq);
1556329222Shselasky	spin_lock(&cq->lock);
1557329222Shselasky	cur = wq->head - wq->tail;
1558329222Shselasky	spin_unlock(&cq->lock);
1559329222Shselasky
1560329222Shselasky	return cur + nreq >= wq->max;
1561329222Shselasky}
1562329222Shselasky
1563329222Shselaskystatic __always_inline void set_raddr_seg(struct mthca_raddr_seg *rseg,
1564329222Shselasky					  u64 remote_addr, u32 rkey)
1565329222Shselasky{
1566329222Shselasky	rseg->raddr    = cpu_to_be64(remote_addr);
1567329222Shselasky	rseg->rkey     = cpu_to_be32(rkey);
1568329222Shselasky	rseg->reserved = 0;
1569329222Shselasky}
1570329222Shselasky
1571329222Shselaskystatic __always_inline void set_atomic_seg(struct mthca_atomic_seg *aseg,
1572329222Shselasky					   struct ib_atomic_wr *wr)
1573329222Shselasky{
1574329222Shselasky	if (wr->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
1575329222Shselasky		aseg->swap_add = cpu_to_be64(wr->swap);
1576329222Shselasky		aseg->compare  = cpu_to_be64(wr->compare_add);
1577329222Shselasky	} else {
1578329222Shselasky		aseg->swap_add = cpu_to_be64(wr->compare_add);
1579329222Shselasky		aseg->compare  = 0;
1580329222Shselasky	}
1581329222Shselasky
1582329222Shselasky}
1583329222Shselasky
1584329222Shselaskystatic void set_tavor_ud_seg(struct mthca_tavor_ud_seg *useg,
1585329222Shselasky			     struct ib_ud_wr *wr)
1586329222Shselasky{
1587329222Shselasky	useg->lkey    = cpu_to_be32(to_mah(wr->ah)->key);
1588329222Shselasky	useg->av_addr =	cpu_to_be64(to_mah(wr->ah)->avdma);
1589329222Shselasky	useg->dqpn    =	cpu_to_be32(wr->remote_qpn);
1590329222Shselasky	useg->qkey    =	cpu_to_be32(wr->remote_qkey);
1591329222Shselasky
1592329222Shselasky}
1593329222Shselasky
1594329222Shselaskystatic void set_arbel_ud_seg(struct mthca_arbel_ud_seg *useg,
1595329222Shselasky			     struct ib_ud_wr *wr)
1596329222Shselasky{
1597329222Shselasky	memcpy(useg->av, to_mah(wr->ah)->av, MTHCA_AV_SIZE);
1598329222Shselasky	useg->dqpn = cpu_to_be32(wr->remote_qpn);
1599329222Shselasky	useg->qkey = cpu_to_be32(wr->remote_qkey);
1600329222Shselasky}
1601329222Shselasky
1602329222Shselaskyint mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
1603329222Shselasky			  struct ib_send_wr **bad_wr)
1604329222Shselasky{
1605329222Shselasky	struct mthca_dev *dev = to_mdev(ibqp->device);
1606329222Shselasky	struct mthca_qp *qp = to_mqp(ibqp);
1607329222Shselasky	void *wqe;
1608329222Shselasky	void *prev_wqe;
1609329222Shselasky	unsigned long flags;
1610329222Shselasky	int err = 0;
1611329222Shselasky	int nreq;
1612329222Shselasky	int i;
1613329222Shselasky	int size;
1614329222Shselasky	/*
1615329222Shselasky	 * f0 and size0 are only used if nreq != 0, and they will
1616329222Shselasky	 * always be initialized the first time through the main loop
1617329222Shselasky	 * before nreq is incremented.  So nreq cannot become non-zero
1618329222Shselasky	 * without initializing f0 and size0, and they are in fact
1619329222Shselasky	 * never used uninitialized.
1620329222Shselasky	 */
1621329222Shselasky	int uninitialized_var(size0);
1622329222Shselasky	u32 uninitialized_var(f0);
1623329222Shselasky	int ind;
1624329222Shselasky	u8 op0 = 0;
1625329222Shselasky
1626329222Shselasky	spin_lock_irqsave(&qp->sq.lock, flags);
1627329222Shselasky
1628329222Shselasky	/* XXX check that state is OK to post send */
1629329222Shselasky
1630329222Shselasky	ind = qp->sq.next_ind;
1631329222Shselasky
1632329222Shselasky	for (nreq = 0; wr; ++nreq, wr = wr->next) {
1633329222Shselasky		if (mthca_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
1634329222Shselasky			mthca_err(dev, "SQ %06x full (%u head, %u tail,"
1635329222Shselasky					" %d max, %d nreq)\n", qp->qpn,
1636329222Shselasky					qp->sq.head, qp->sq.tail,
1637329222Shselasky					qp->sq.max, nreq);
1638329222Shselasky			err = -ENOMEM;
1639329222Shselasky			*bad_wr = wr;
1640329222Shselasky			goto out;
1641329222Shselasky		}
1642329222Shselasky
1643329222Shselasky		wqe = get_send_wqe(qp, ind);
1644329222Shselasky		prev_wqe = qp->sq.last;
1645329222Shselasky		qp->sq.last = wqe;
1646329222Shselasky
1647329222Shselasky		((struct mthca_next_seg *) wqe)->nda_op = 0;
1648329222Shselasky		((struct mthca_next_seg *) wqe)->ee_nds = 0;
1649329222Shselasky		((struct mthca_next_seg *) wqe)->flags =
1650329222Shselasky			((wr->send_flags & IB_SEND_SIGNALED) ?
1651329222Shselasky			 cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0) |
1652329222Shselasky			((wr->send_flags & IB_SEND_SOLICITED) ?
1653329222Shselasky			 cpu_to_be32(MTHCA_NEXT_SOLICIT) : 0)   |
1654329222Shselasky			cpu_to_be32(1);
1655329222Shselasky		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
1656329222Shselasky		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
1657329222Shselasky			((struct mthca_next_seg *) wqe)->imm = wr->ex.imm_data;
1658329222Shselasky
1659329222Shselasky		wqe += sizeof (struct mthca_next_seg);
1660329222Shselasky		size = sizeof (struct mthca_next_seg) / 16;
1661329222Shselasky
1662329222Shselasky		switch (qp->transport) {
1663329222Shselasky		case RC:
1664329222Shselasky			switch (wr->opcode) {
1665329222Shselasky			case IB_WR_ATOMIC_CMP_AND_SWP:
1666329222Shselasky			case IB_WR_ATOMIC_FETCH_AND_ADD:
1667329222Shselasky				set_raddr_seg(wqe, atomic_wr(wr)->remote_addr,
1668329222Shselasky					      atomic_wr(wr)->rkey);
1669329222Shselasky				wqe += sizeof (struct mthca_raddr_seg);
1670329222Shselasky
1671329222Shselasky				set_atomic_seg(wqe, atomic_wr(wr));
1672329222Shselasky				wqe += sizeof (struct mthca_atomic_seg);
1673329222Shselasky				size += (sizeof (struct mthca_raddr_seg) +
1674329222Shselasky					 sizeof (struct mthca_atomic_seg)) / 16;
1675329222Shselasky				break;
1676329222Shselasky
1677329222Shselasky			case IB_WR_RDMA_WRITE:
1678329222Shselasky			case IB_WR_RDMA_WRITE_WITH_IMM:
1679329222Shselasky			case IB_WR_RDMA_READ:
1680329222Shselasky				set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
1681329222Shselasky					      rdma_wr(wr)->rkey);
1682329222Shselasky				wqe  += sizeof (struct mthca_raddr_seg);
1683329222Shselasky				size += sizeof (struct mthca_raddr_seg) / 16;
1684329222Shselasky				break;
1685329222Shselasky
1686329222Shselasky			default:
1687329222Shselasky				/* No extra segments required for sends */
1688329222Shselasky				break;
1689329222Shselasky			}
1690329222Shselasky
1691329222Shselasky			break;
1692329222Shselasky
1693329222Shselasky		case UC:
1694329222Shselasky			switch (wr->opcode) {
1695329222Shselasky			case IB_WR_RDMA_WRITE:
1696329222Shselasky			case IB_WR_RDMA_WRITE_WITH_IMM:
1697329222Shselasky				set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
1698329222Shselasky					      rdma_wr(wr)->rkey);
1699329222Shselasky				wqe  += sizeof (struct mthca_raddr_seg);
1700329222Shselasky				size += sizeof (struct mthca_raddr_seg) / 16;
1701329222Shselasky				break;
1702329222Shselasky
1703329222Shselasky			default:
1704329222Shselasky				/* No extra segments required for sends */
1705329222Shselasky				break;
1706329222Shselasky			}
1707329222Shselasky
1708329222Shselasky			break;
1709329222Shselasky
1710329222Shselasky		case UD:
1711329222Shselasky			set_tavor_ud_seg(wqe, ud_wr(wr));
1712329222Shselasky			wqe  += sizeof (struct mthca_tavor_ud_seg);
1713329222Shselasky			size += sizeof (struct mthca_tavor_ud_seg) / 16;
1714329222Shselasky			break;
1715329222Shselasky
1716329222Shselasky		case MLX:
1717329222Shselasky			err = build_mlx_header(dev, to_msqp(qp), ind, ud_wr(wr),
1718329222Shselasky					       wqe - sizeof (struct mthca_next_seg),
1719329222Shselasky					       wqe);
1720329222Shselasky			if (err) {
1721329222Shselasky				*bad_wr = wr;
1722329222Shselasky				goto out;
1723329222Shselasky			}
1724329222Shselasky			wqe += sizeof (struct mthca_data_seg);
1725329222Shselasky			size += sizeof (struct mthca_data_seg) / 16;
1726329222Shselasky			break;
1727329222Shselasky		}
1728329222Shselasky
1729329222Shselasky		if (wr->num_sge > qp->sq.max_gs) {
1730329222Shselasky			mthca_err(dev, "too many gathers\n");
1731329222Shselasky			err = -EINVAL;
1732329222Shselasky			*bad_wr = wr;
1733329222Shselasky			goto out;
1734329222Shselasky		}
1735329222Shselasky
1736329222Shselasky		for (i = 0; i < wr->num_sge; ++i) {
1737329222Shselasky			mthca_set_data_seg(wqe, wr->sg_list + i);
1738329222Shselasky			wqe  += sizeof (struct mthca_data_seg);
1739329222Shselasky			size += sizeof (struct mthca_data_seg) / 16;
1740329222Shselasky		}
1741329222Shselasky
1742329222Shselasky		/* Add one more inline data segment for ICRC */
1743329222Shselasky		if (qp->transport == MLX) {
1744329222Shselasky			((struct mthca_data_seg *) wqe)->byte_count =
1745329222Shselasky				cpu_to_be32((1 << 31) | 4);
1746329222Shselasky			((u32 *) wqe)[1] = 0;
1747329222Shselasky			wqe += sizeof (struct mthca_data_seg);
1748329222Shselasky			size += sizeof (struct mthca_data_seg) / 16;
1749329222Shselasky		}
1750329222Shselasky
1751329222Shselasky		qp->wrid[ind + qp->rq.max] = wr->wr_id;
1752329222Shselasky
1753329222Shselasky		if (wr->opcode >= ARRAY_SIZE(mthca_opcode)) {
1754329222Shselasky			mthca_err(dev, "opcode invalid\n");
1755329222Shselasky			err = -EINVAL;
1756329222Shselasky			*bad_wr = wr;
1757329222Shselasky			goto out;
1758329222Shselasky		}
1759329222Shselasky
1760329222Shselasky		((struct mthca_next_seg *) prev_wqe)->nda_op =
1761329222Shselasky			cpu_to_be32(((ind << qp->sq.wqe_shift) +
1762329222Shselasky				     qp->send_wqe_offset) |
1763329222Shselasky				    mthca_opcode[wr->opcode]);
1764329222Shselasky		wmb();
1765329222Shselasky		((struct mthca_next_seg *) prev_wqe)->ee_nds =
1766329222Shselasky			cpu_to_be32((nreq ? 0 : MTHCA_NEXT_DBD) | size |
1767329222Shselasky				    ((wr->send_flags & IB_SEND_FENCE) ?
1768329222Shselasky				    MTHCA_NEXT_FENCE : 0));
1769329222Shselasky
1770329222Shselasky		if (!nreq) {
1771329222Shselasky			size0 = size;
1772329222Shselasky			op0   = mthca_opcode[wr->opcode];
1773329222Shselasky			f0    = wr->send_flags & IB_SEND_FENCE ?
1774329222Shselasky				MTHCA_SEND_DOORBELL_FENCE : 0;
1775329222Shselasky		}
1776329222Shselasky
1777329222Shselasky		++ind;
1778329222Shselasky		if (unlikely(ind >= qp->sq.max))
1779329222Shselasky			ind -= qp->sq.max;
1780329222Shselasky	}
1781329222Shselasky
1782329222Shselaskyout:
1783329222Shselasky	if (likely(nreq)) {
1784329222Shselasky		wmb();
1785329222Shselasky
1786329222Shselasky		mthca_write64(((qp->sq.next_ind << qp->sq.wqe_shift) +
1787329222Shselasky			       qp->send_wqe_offset) | f0 | op0,
1788329222Shselasky			      (qp->qpn << 8) | size0,
1789329222Shselasky			      dev->kar + MTHCA_SEND_DOORBELL,
1790329222Shselasky			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
1791329222Shselasky		/*
1792329222Shselasky		 * Make sure doorbells don't leak out of SQ spinlock
1793329222Shselasky		 * and reach the HCA out of order:
1794329222Shselasky		 */
1795329222Shselasky		mmiowb();
1796329222Shselasky	}
1797329222Shselasky
1798329222Shselasky	qp->sq.next_ind = ind;
1799329222Shselasky	qp->sq.head    += nreq;
1800329222Shselasky
1801329222Shselasky	spin_unlock_irqrestore(&qp->sq.lock, flags);
1802329222Shselasky	return err;
1803329222Shselasky}
1804329222Shselasky
1805329222Shselaskyint mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
1806329222Shselasky			     struct ib_recv_wr **bad_wr)
1807329222Shselasky{
1808329222Shselasky	struct mthca_dev *dev = to_mdev(ibqp->device);
1809329222Shselasky	struct mthca_qp *qp = to_mqp(ibqp);
1810329222Shselasky	unsigned long flags;
1811329222Shselasky	int err = 0;
1812329222Shselasky	int nreq;
1813329222Shselasky	int i;
1814329222Shselasky	int size;
1815329222Shselasky	/*
1816329222Shselasky	 * size0 is only used if nreq != 0, and it will always be
1817329222Shselasky	 * initialized the first time through the main loop before
1818329222Shselasky	 * nreq is incremented.  So nreq cannot become non-zero
1819329222Shselasky	 * without initializing size0, and it is in fact never used
1820329222Shselasky	 * uninitialized.
1821329222Shselasky	 */
1822329222Shselasky	int uninitialized_var(size0);
1823329222Shselasky	int ind;
1824329222Shselasky	void *wqe;
1825329222Shselasky	void *prev_wqe;
1826329222Shselasky
1827329222Shselasky	spin_lock_irqsave(&qp->rq.lock, flags);
1828329222Shselasky
1829329222Shselasky	/* XXX check that state is OK to post receive */
1830329222Shselasky
1831329222Shselasky	ind = qp->rq.next_ind;
1832329222Shselasky
1833329222Shselasky	for (nreq = 0; wr; wr = wr->next) {
1834329222Shselasky		if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
1835329222Shselasky			mthca_err(dev, "RQ %06x full (%u head, %u tail,"
1836329222Shselasky					" %d max, %d nreq)\n", qp->qpn,
1837329222Shselasky					qp->rq.head, qp->rq.tail,
1838329222Shselasky					qp->rq.max, nreq);
1839329222Shselasky			err = -ENOMEM;
1840329222Shselasky			*bad_wr = wr;
1841329222Shselasky			goto out;
1842329222Shselasky		}
1843329222Shselasky
1844329222Shselasky		wqe = get_recv_wqe(qp, ind);
1845329222Shselasky		prev_wqe = qp->rq.last;
1846329222Shselasky		qp->rq.last = wqe;
1847329222Shselasky
1848329222Shselasky		((struct mthca_next_seg *) wqe)->ee_nds =
1849329222Shselasky			cpu_to_be32(MTHCA_NEXT_DBD);
1850329222Shselasky		((struct mthca_next_seg *) wqe)->flags = 0;
1851329222Shselasky
1852329222Shselasky		wqe += sizeof (struct mthca_next_seg);
1853329222Shselasky		size = sizeof (struct mthca_next_seg) / 16;
1854329222Shselasky
1855329222Shselasky		if (unlikely(wr->num_sge > qp->rq.max_gs)) {
1856329222Shselasky			err = -EINVAL;
1857329222Shselasky			*bad_wr = wr;
1858329222Shselasky			goto out;
1859329222Shselasky		}
1860329222Shselasky
1861329222Shselasky		for (i = 0; i < wr->num_sge; ++i) {
1862329222Shselasky			mthca_set_data_seg(wqe, wr->sg_list + i);
1863329222Shselasky			wqe  += sizeof (struct mthca_data_seg);
1864329222Shselasky			size += sizeof (struct mthca_data_seg) / 16;
1865329222Shselasky		}
1866329222Shselasky
1867329222Shselasky		qp->wrid[ind] = wr->wr_id;
1868329222Shselasky
1869329222Shselasky		((struct mthca_next_seg *) prev_wqe)->ee_nds =
1870329222Shselasky			cpu_to_be32(MTHCA_NEXT_DBD | size);
1871329222Shselasky
1872329222Shselasky		if (!nreq)
1873329222Shselasky			size0 = size;
1874329222Shselasky
1875329222Shselasky		++ind;
1876329222Shselasky		if (unlikely(ind >= qp->rq.max))
1877329222Shselasky			ind -= qp->rq.max;
1878329222Shselasky
1879329222Shselasky		++nreq;
1880329222Shselasky		if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
1881329222Shselasky			nreq = 0;
1882329222Shselasky
1883329222Shselasky			wmb();
1884329222Shselasky
1885329222Shselasky			mthca_write64((qp->rq.next_ind << qp->rq.wqe_shift) | size0,
1886329222Shselasky				      qp->qpn << 8, dev->kar + MTHCA_RECEIVE_DOORBELL,
1887329222Shselasky				      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
1888329222Shselasky
1889329222Shselasky			qp->rq.next_ind = ind;
1890329222Shselasky			qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB;
1891329222Shselasky		}
1892329222Shselasky	}
1893329222Shselasky
1894329222Shselaskyout:
1895329222Shselasky	if (likely(nreq)) {
1896329222Shselasky		wmb();
1897329222Shselasky
1898329222Shselasky		mthca_write64((qp->rq.next_ind << qp->rq.wqe_shift) | size0,
1899329222Shselasky			      qp->qpn << 8 | nreq, dev->kar + MTHCA_RECEIVE_DOORBELL,
1900329222Shselasky			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
1901329222Shselasky	}
1902329222Shselasky
1903329222Shselasky	qp->rq.next_ind = ind;
1904329222Shselasky	qp->rq.head    += nreq;
1905329222Shselasky
1906329222Shselasky	/*
1907329222Shselasky	 * Make sure doorbells don't leak out of RQ spinlock and reach
1908329222Shselasky	 * the HCA out of order:
1909329222Shselasky	 */
1910329222Shselasky	mmiowb();
1911329222Shselasky
1912329222Shselasky	spin_unlock_irqrestore(&qp->rq.lock, flags);
1913329222Shselasky	return err;
1914329222Shselasky}
1915329222Shselasky
1916329222Shselaskyint mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
1917329222Shselasky			  struct ib_send_wr **bad_wr)
1918329222Shselasky{
1919329222Shselasky	struct mthca_dev *dev = to_mdev(ibqp->device);
1920329222Shselasky	struct mthca_qp *qp = to_mqp(ibqp);
1921329222Shselasky	u32 dbhi;
1922329222Shselasky	void *wqe;
1923329222Shselasky	void *prev_wqe;
1924329222Shselasky	unsigned long flags;
1925329222Shselasky	int err = 0;
1926329222Shselasky	int nreq;
1927329222Shselasky	int i;
1928329222Shselasky	int size;
1929329222Shselasky	/*
1930329222Shselasky	 * f0 and size0 are only used if nreq != 0, and they will
1931329222Shselasky	 * always be initialized the first time through the main loop
1932329222Shselasky	 * before nreq is incremented.  So nreq cannot become non-zero
1933329222Shselasky	 * without initializing f0 and size0, and they are in fact
1934329222Shselasky	 * never used uninitialized.
1935329222Shselasky	 */
1936329222Shselasky	int uninitialized_var(size0);
1937329222Shselasky	u32 uninitialized_var(f0);
1938329222Shselasky	int ind;
1939329222Shselasky	u8 op0 = 0;
1940329222Shselasky
1941329222Shselasky	spin_lock_irqsave(&qp->sq.lock, flags);
1942329222Shselasky
1943329222Shselasky	/* XXX check that state is OK to post send */
1944329222Shselasky
1945329222Shselasky	ind = qp->sq.head & (qp->sq.max - 1);
1946329222Shselasky
1947329222Shselasky	for (nreq = 0; wr; ++nreq, wr = wr->next) {
1948329222Shselasky		if (unlikely(nreq == MTHCA_ARBEL_MAX_WQES_PER_SEND_DB)) {
1949329222Shselasky			nreq = 0;
1950329222Shselasky
1951329222Shselasky			dbhi = (MTHCA_ARBEL_MAX_WQES_PER_SEND_DB << 24) |
1952329222Shselasky				((qp->sq.head & 0xffff) << 8) | f0 | op0;
1953329222Shselasky
1954329222Shselasky			qp->sq.head += MTHCA_ARBEL_MAX_WQES_PER_SEND_DB;
1955329222Shselasky
1956329222Shselasky			/*
1957329222Shselasky			 * Make sure that descriptors are written before
1958329222Shselasky			 * doorbell record.
1959329222Shselasky			 */
1960329222Shselasky			wmb();
1961329222Shselasky			*qp->sq.db = cpu_to_be32(qp->sq.head & 0xffff);
1962329222Shselasky
1963329222Shselasky			/*
1964329222Shselasky			 * Make sure doorbell record is written before we
1965329222Shselasky			 * write MMIO send doorbell.
1966329222Shselasky			 */
1967329222Shselasky			wmb();
1968329222Shselasky
1969329222Shselasky			mthca_write64(dbhi, (qp->qpn << 8) | size0,
1970329222Shselasky				      dev->kar + MTHCA_SEND_DOORBELL,
1971329222Shselasky				      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
1972329222Shselasky		}
1973329222Shselasky
1974329222Shselasky		if (mthca_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
1975329222Shselasky			mthca_err(dev, "SQ %06x full (%u head, %u tail,"
1976329222Shselasky					" %d max, %d nreq)\n", qp->qpn,
1977329222Shselasky					qp->sq.head, qp->sq.tail,
1978329222Shselasky					qp->sq.max, nreq);
1979329222Shselasky			err = -ENOMEM;
1980329222Shselasky			*bad_wr = wr;
1981329222Shselasky			goto out;
1982329222Shselasky		}
1983329222Shselasky
1984329222Shselasky		wqe = get_send_wqe(qp, ind);
1985329222Shselasky		prev_wqe = qp->sq.last;
1986329222Shselasky		qp->sq.last = wqe;
1987329222Shselasky
1988329222Shselasky		((struct mthca_next_seg *) wqe)->flags =
1989329222Shselasky			((wr->send_flags & IB_SEND_SIGNALED) ?
1990329222Shselasky			 cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0) |
1991329222Shselasky			((wr->send_flags & IB_SEND_SOLICITED) ?
1992329222Shselasky			 cpu_to_be32(MTHCA_NEXT_SOLICIT) : 0)   |
1993329222Shselasky			((wr->send_flags & IB_SEND_IP_CSUM) ?
1994329222Shselasky			 cpu_to_be32(MTHCA_NEXT_IP_CSUM | MTHCA_NEXT_TCP_UDP_CSUM) : 0) |
1995329222Shselasky			cpu_to_be32(1);
1996329222Shselasky		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
1997329222Shselasky		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
1998329222Shselasky			((struct mthca_next_seg *) wqe)->imm = wr->ex.imm_data;
1999329222Shselasky
2000329222Shselasky		wqe += sizeof (struct mthca_next_seg);
2001329222Shselasky		size = sizeof (struct mthca_next_seg) / 16;
2002329222Shselasky
2003329222Shselasky		switch (qp->transport) {
2004329222Shselasky		case RC:
2005329222Shselasky			switch (wr->opcode) {
2006329222Shselasky			case IB_WR_ATOMIC_CMP_AND_SWP:
2007329222Shselasky			case IB_WR_ATOMIC_FETCH_AND_ADD:
2008329222Shselasky				set_raddr_seg(wqe, atomic_wr(wr)->remote_addr,
2009329222Shselasky					      atomic_wr(wr)->rkey);
2010329222Shselasky				wqe += sizeof (struct mthca_raddr_seg);
2011329222Shselasky
2012329222Shselasky				set_atomic_seg(wqe, atomic_wr(wr));
2013329222Shselasky				wqe  += sizeof (struct mthca_atomic_seg);
2014329222Shselasky				size += (sizeof (struct mthca_raddr_seg) +
2015329222Shselasky					 sizeof (struct mthca_atomic_seg)) / 16;
2016329222Shselasky				break;
2017329222Shselasky
2018329222Shselasky			case IB_WR_RDMA_READ:
2019329222Shselasky			case IB_WR_RDMA_WRITE:
2020329222Shselasky			case IB_WR_RDMA_WRITE_WITH_IMM:
2021329222Shselasky				set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
2022329222Shselasky					      rdma_wr(wr)->rkey);
2023329222Shselasky				wqe  += sizeof (struct mthca_raddr_seg);
2024329222Shselasky				size += sizeof (struct mthca_raddr_seg) / 16;
2025329222Shselasky				break;
2026329222Shselasky
2027329222Shselasky			default:
2028329222Shselasky				/* No extra segments required for sends */
2029329222Shselasky				break;
2030329222Shselasky			}
2031329222Shselasky
2032329222Shselasky			break;
2033329222Shselasky
2034329222Shselasky		case UC:
2035329222Shselasky			switch (wr->opcode) {
2036329222Shselasky			case IB_WR_RDMA_WRITE:
2037329222Shselasky			case IB_WR_RDMA_WRITE_WITH_IMM:
2038329222Shselasky				set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
2039329222Shselasky					      rdma_wr(wr)->rkey);
2040329222Shselasky				wqe  += sizeof (struct mthca_raddr_seg);
2041329222Shselasky				size += sizeof (struct mthca_raddr_seg) / 16;
2042329222Shselasky				break;
2043329222Shselasky
2044329222Shselasky			default:
2045329222Shselasky				/* No extra segments required for sends */
2046329222Shselasky				break;
2047329222Shselasky			}
2048329222Shselasky
2049329222Shselasky			break;
2050329222Shselasky
2051329222Shselasky		case UD:
2052329222Shselasky			set_arbel_ud_seg(wqe, ud_wr(wr));
2053329222Shselasky			wqe  += sizeof (struct mthca_arbel_ud_seg);
2054329222Shselasky			size += sizeof (struct mthca_arbel_ud_seg) / 16;
2055329222Shselasky			break;
2056329222Shselasky
2057329222Shselasky		case MLX:
2058329222Shselasky			err = build_mlx_header(dev, to_msqp(qp), ind, ud_wr(wr),
2059329222Shselasky					       wqe - sizeof (struct mthca_next_seg),
2060329222Shselasky					       wqe);
2061329222Shselasky			if (err) {
2062329222Shselasky				*bad_wr = wr;
2063329222Shselasky				goto out;
2064329222Shselasky			}
2065329222Shselasky			wqe += sizeof (struct mthca_data_seg);
2066329222Shselasky			size += sizeof (struct mthca_data_seg) / 16;
2067329222Shselasky			break;
2068329222Shselasky		}
2069329222Shselasky
2070329222Shselasky		if (wr->num_sge > qp->sq.max_gs) {
2071329222Shselasky			mthca_err(dev, "too many gathers\n");
2072329222Shselasky			err = -EINVAL;
2073329222Shselasky			*bad_wr = wr;
2074329222Shselasky			goto out;
2075329222Shselasky		}
2076329222Shselasky
2077329222Shselasky		for (i = 0; i < wr->num_sge; ++i) {
2078329222Shselasky			mthca_set_data_seg(wqe, wr->sg_list + i);
2079329222Shselasky			wqe  += sizeof (struct mthca_data_seg);
2080329222Shselasky			size += sizeof (struct mthca_data_seg) / 16;
2081329222Shselasky		}
2082329222Shselasky
2083329222Shselasky		/* Add one more inline data segment for ICRC */
2084329222Shselasky		if (qp->transport == MLX) {
2085329222Shselasky			((struct mthca_data_seg *) wqe)->byte_count =
2086329222Shselasky				cpu_to_be32((1 << 31) | 4);
2087329222Shselasky			((u32 *) wqe)[1] = 0;
2088329222Shselasky			wqe += sizeof (struct mthca_data_seg);
2089329222Shselasky			size += sizeof (struct mthca_data_seg) / 16;
2090329222Shselasky		}
2091329222Shselasky
2092329222Shselasky		qp->wrid[ind + qp->rq.max] = wr->wr_id;
2093329222Shselasky
2094329222Shselasky		if (wr->opcode >= ARRAY_SIZE(mthca_opcode)) {
2095329222Shselasky			mthca_err(dev, "opcode invalid\n");
2096329222Shselasky			err = -EINVAL;
2097329222Shselasky			*bad_wr = wr;
2098329222Shselasky			goto out;
2099329222Shselasky		}
2100329222Shselasky
2101329222Shselasky		((struct mthca_next_seg *) prev_wqe)->nda_op =
2102329222Shselasky			cpu_to_be32(((ind << qp->sq.wqe_shift) +
2103329222Shselasky				     qp->send_wqe_offset) |
2104329222Shselasky				    mthca_opcode[wr->opcode]);
2105329222Shselasky		wmb();
2106329222Shselasky		((struct mthca_next_seg *) prev_wqe)->ee_nds =
2107329222Shselasky			cpu_to_be32(MTHCA_NEXT_DBD | size |
2108329222Shselasky				    ((wr->send_flags & IB_SEND_FENCE) ?
2109329222Shselasky				     MTHCA_NEXT_FENCE : 0));
2110329222Shselasky
2111329222Shselasky		if (!nreq) {
2112329222Shselasky			size0 = size;
2113329222Shselasky			op0   = mthca_opcode[wr->opcode];
2114329222Shselasky			f0    = wr->send_flags & IB_SEND_FENCE ?
2115329222Shselasky				MTHCA_SEND_DOORBELL_FENCE : 0;
2116329222Shselasky		}
2117329222Shselasky
2118329222Shselasky		++ind;
2119329222Shselasky		if (unlikely(ind >= qp->sq.max))
2120329222Shselasky			ind -= qp->sq.max;
2121329222Shselasky	}
2122329222Shselasky
2123329222Shselaskyout:
2124329222Shselasky	if (likely(nreq)) {
2125329222Shselasky		dbhi = (nreq << 24) | ((qp->sq.head & 0xffff) << 8) | f0 | op0;
2126329222Shselasky
2127329222Shselasky		qp->sq.head += nreq;
2128329222Shselasky
2129329222Shselasky		/*
2130329222Shselasky		 * Make sure that descriptors are written before
2131329222Shselasky		 * doorbell record.
2132329222Shselasky		 */
2133329222Shselasky		wmb();
2134329222Shselasky		*qp->sq.db = cpu_to_be32(qp->sq.head & 0xffff);
2135329222Shselasky
2136329222Shselasky		/*
2137329222Shselasky		 * Make sure doorbell record is written before we
2138329222Shselasky		 * write MMIO send doorbell.
2139329222Shselasky		 */
2140329222Shselasky		wmb();
2141329222Shselasky
2142329222Shselasky		mthca_write64(dbhi, (qp->qpn << 8) | size0, dev->kar + MTHCA_SEND_DOORBELL,
2143329222Shselasky			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
2144329222Shselasky	}
2145329222Shselasky
2146329222Shselasky	/*
2147329222Shselasky	 * Make sure doorbells don't leak out of SQ spinlock and reach
2148329222Shselasky	 * the HCA out of order:
2149329222Shselasky	 */
2150329222Shselasky	mmiowb();
2151329222Shselasky
2152329222Shselasky	spin_unlock_irqrestore(&qp->sq.lock, flags);
2153329222Shselasky	return err;
2154329222Shselasky}
2155329222Shselasky
2156329222Shselaskyint mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
2157329222Shselasky			     struct ib_recv_wr **bad_wr)
2158329222Shselasky{
2159329222Shselasky	struct mthca_dev *dev = to_mdev(ibqp->device);
2160329222Shselasky	struct mthca_qp *qp = to_mqp(ibqp);
2161329222Shselasky	unsigned long flags;
2162329222Shselasky	int err = 0;
2163329222Shselasky	int nreq;
2164329222Shselasky	int ind;
2165329222Shselasky	int i;
2166329222Shselasky	void *wqe;
2167329222Shselasky
2168329222Shselasky	spin_lock_irqsave(&qp->rq.lock, flags);
2169329222Shselasky
2170329222Shselasky	/* XXX check that state is OK to post receive */
2171329222Shselasky
2172329222Shselasky	ind = qp->rq.head & (qp->rq.max - 1);
2173329222Shselasky
2174329222Shselasky	for (nreq = 0; wr; ++nreq, wr = wr->next) {
2175329222Shselasky		if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
2176329222Shselasky			mthca_err(dev, "RQ %06x full (%u head, %u tail,"
2177329222Shselasky					" %d max, %d nreq)\n", qp->qpn,
2178329222Shselasky					qp->rq.head, qp->rq.tail,
2179329222Shselasky					qp->rq.max, nreq);
2180329222Shselasky			err = -ENOMEM;
2181329222Shselasky			*bad_wr = wr;
2182329222Shselasky			goto out;
2183329222Shselasky		}
2184329222Shselasky
2185329222Shselasky		wqe = get_recv_wqe(qp, ind);
2186329222Shselasky
2187329222Shselasky		((struct mthca_next_seg *) wqe)->flags = 0;
2188329222Shselasky
2189329222Shselasky		wqe += sizeof (struct mthca_next_seg);
2190329222Shselasky
2191329222Shselasky		if (unlikely(wr->num_sge > qp->rq.max_gs)) {
2192329222Shselasky			err = -EINVAL;
2193329222Shselasky			*bad_wr = wr;
2194329222Shselasky			goto out;
2195329222Shselasky		}
2196329222Shselasky
2197329222Shselasky		for (i = 0; i < wr->num_sge; ++i) {
2198329222Shselasky			mthca_set_data_seg(wqe, wr->sg_list + i);
2199329222Shselasky			wqe += sizeof (struct mthca_data_seg);
2200329222Shselasky		}
2201329222Shselasky
2202329222Shselasky		if (i < qp->rq.max_gs)
2203329222Shselasky			mthca_set_data_seg_inval(wqe);
2204329222Shselasky
2205329222Shselasky		qp->wrid[ind] = wr->wr_id;
2206329222Shselasky
2207329222Shselasky		++ind;
2208329222Shselasky		if (unlikely(ind >= qp->rq.max))
2209329222Shselasky			ind -= qp->rq.max;
2210329222Shselasky	}
2211329222Shselaskyout:
2212329222Shselasky	if (likely(nreq)) {
2213329222Shselasky		qp->rq.head += nreq;
2214329222Shselasky
2215329222Shselasky		/*
2216329222Shselasky		 * Make sure that descriptors are written before
2217329222Shselasky		 * doorbell record.
2218329222Shselasky		 */
2219329222Shselasky		wmb();
2220329222Shselasky		*qp->rq.db = cpu_to_be32(qp->rq.head & 0xffff);
2221329222Shselasky	}
2222329222Shselasky
2223329222Shselasky	spin_unlock_irqrestore(&qp->rq.lock, flags);
2224329222Shselasky	return err;
2225329222Shselasky}
2226329222Shselasky
2227329222Shselaskyvoid mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
2228329222Shselasky			int index, int *dbd, __be32 *new_wqe)
2229329222Shselasky{
2230329222Shselasky	struct mthca_next_seg *next;
2231329222Shselasky
2232329222Shselasky	/*
2233329222Shselasky	 * For SRQs, all receive WQEs generate a CQE, so we're always
2234329222Shselasky	 * at the end of the doorbell chain.
2235329222Shselasky	 */
2236329222Shselasky	if (qp->ibqp.srq && !is_send) {
2237329222Shselasky		*new_wqe = 0;
2238329222Shselasky		return;
2239329222Shselasky	}
2240329222Shselasky
2241329222Shselasky	if (is_send)
2242329222Shselasky		next = get_send_wqe(qp, index);
2243329222Shselasky	else
2244329222Shselasky		next = get_recv_wqe(qp, index);
2245329222Shselasky
2246329222Shselasky	*dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
2247329222Shselasky	if (next->ee_nds & cpu_to_be32(0x3f))
2248329222Shselasky		*new_wqe = (next->nda_op & cpu_to_be32(~0x3f)) |
2249329222Shselasky			(next->ee_nds & cpu_to_be32(0x3f));
2250329222Shselasky	else
2251329222Shselasky		*new_wqe = 0;
2252329222Shselasky}
2253329222Shselasky
2254329222Shselaskyint mthca_init_qp_table(struct mthca_dev *dev)
2255329222Shselasky{
2256329222Shselasky	int err;
2257329222Shselasky	int i;
2258329222Shselasky
2259329222Shselasky	spin_lock_init(&dev->qp_table.lock);
2260329222Shselasky
2261329222Shselasky	/*
2262329222Shselasky	 * We reserve 2 extra QPs per port for the special QPs.  The
2263329222Shselasky	 * special QP for port 1 has to be even, so round up.
2264329222Shselasky	 */
2265329222Shselasky	dev->qp_table.sqp_start = (dev->limits.reserved_qps + 1) & ~1UL;
2266329222Shselasky	err = mthca_alloc_init(&dev->qp_table.alloc,
2267329222Shselasky			       dev->limits.num_qps,
2268329222Shselasky			       (1 << 24) - 1,
2269329222Shselasky			       dev->qp_table.sqp_start +
2270329222Shselasky			       MTHCA_MAX_PORTS * 2);
2271329222Shselasky	if (err)
2272329222Shselasky		return err;
2273329222Shselasky
2274329222Shselasky	err = mthca_array_init(&dev->qp_table.qp,
2275329222Shselasky			       dev->limits.num_qps);
2276329222Shselasky	if (err) {
2277329222Shselasky		mthca_alloc_cleanup(&dev->qp_table.alloc);
2278329222Shselasky		return err;
2279329222Shselasky	}
2280329222Shselasky
2281329222Shselasky	for (i = 0; i < 2; ++i) {
2282329222Shselasky		err = mthca_CONF_SPECIAL_QP(dev, i ? IB_QPT_GSI : IB_QPT_SMI,
2283329222Shselasky				    dev->qp_table.sqp_start + i * 2);
2284329222Shselasky		if (err) {
2285329222Shselasky			mthca_warn(dev, "CONF_SPECIAL_QP returned "
2286329222Shselasky				   "%d, aborting.\n", err);
2287329222Shselasky			goto err_out;
2288329222Shselasky		}
2289329222Shselasky	}
2290329222Shselasky	return 0;
2291329222Shselasky
2292329222Shselasky err_out:
2293329222Shselasky	for (i = 0; i < 2; ++i)
2294329222Shselasky		mthca_CONF_SPECIAL_QP(dev, i, 0);
2295329222Shselasky
2296329222Shselasky	mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
2297329222Shselasky	mthca_alloc_cleanup(&dev->qp_table.alloc);
2298329222Shselasky
2299329222Shselasky	return err;
2300329222Shselasky}
2301329222Shselasky
2302329222Shselaskyvoid mthca_cleanup_qp_table(struct mthca_dev *dev)
2303329222Shselasky{
2304329222Shselasky	int i;
2305329222Shselasky
2306329222Shselasky	for (i = 0; i < 2; ++i)
2307329222Shselasky		mthca_CONF_SPECIAL_QP(dev, i, 0);
2308329222Shselasky
2309329222Shselasky	mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
2310329222Shselasky	mthca_alloc_cleanup(&dev->qp_table.alloc);
2311329222Shselasky}
2312