qib_qp.c revision f931551bafe1f10ded7f5282e2aa162c267a2e5d
1f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
2f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
3f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * All rights reserved.
4f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
5f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
6f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This software is available to you under a choice of one of two
7f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * licenses.  You may choose to be licensed under the terms of the GNU
8f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * General Public License (GPL) Version 2, available from the file
9f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * COPYING in the main directory of this source tree, or the
10f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * OpenIB.org BSD license below:
11f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
12f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *     Redistribution and use in source and binary forms, with or
13f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *     without modification, are permitted provided that the following
14f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *     conditions are met:
15f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
16f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *      - Redistributions of source code must retain the above
17f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        copyright notice, this list of conditions and the following
18f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        disclaimer.
19f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
20f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *      - Redistributions in binary form must reproduce the above
21f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        copyright notice, this list of conditions and the following
22f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        disclaimer in the documentation and/or other materials
23f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        provided with the distribution.
24f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
25f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * SOFTWARE.
33f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
34f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
35f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include <linux/err.h>
36f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include <linux/vmalloc.h>
37f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
38f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include "qib.h"
39f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
40f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define BITS_PER_PAGE           (PAGE_SIZE*BITS_PER_BYTE)
41f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define BITS_PER_PAGE_MASK      (BITS_PER_PAGE-1)
42f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
43f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic inline unsigned mk_qpn(struct qib_qpn_table *qpt,
44f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			      struct qpn_map *map, unsigned off)
45f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
46f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return (map - qpt->map) * BITS_PER_PAGE + off;
47f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
48f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
49f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic inline unsigned find_next_offset(struct qib_qpn_table *qpt,
50f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					struct qpn_map *map, unsigned off,
51f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					unsigned r)
52f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
53f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qpt->mask) {
54f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		off++;
55f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if ((off & qpt->mask) >> 1 != r)
56f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			off = ((off & qpt->mask) ?
57f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				(off | qpt->mask) + 1 : off) | (r << 1);
58f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
59f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		off = find_next_zero_bit(map->page, BITS_PER_PAGE, off);
60f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return off;
61f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
62f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
63f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
64f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Convert the AETH credit code into the number of credits.
65f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
66f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 credit_table[31] = {
67f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	0,                      /* 0 */
68f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	1,                      /* 1 */
69f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	2,                      /* 2 */
70f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	3,                      /* 3 */
71f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	4,                      /* 4 */
72f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	6,                      /* 5 */
73f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	8,                      /* 6 */
74f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	12,                     /* 7 */
75f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	16,                     /* 8 */
76f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	24,                     /* 9 */
77f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	32,                     /* A */
78f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	48,                     /* B */
79f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	64,                     /* C */
80f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	96,                     /* D */
81f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	128,                    /* E */
82f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	192,                    /* F */
83f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	256,                    /* 10 */
84f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	384,                    /* 11 */
85f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	512,                    /* 12 */
86f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	768,                    /* 13 */
87f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	1024,                   /* 14 */
88f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	1536,                   /* 15 */
89f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	2048,                   /* 16 */
90f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	3072,                   /* 17 */
91f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	4096,                   /* 18 */
92f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	6144,                   /* 19 */
93f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	8192,                   /* 1A */
94f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	12288,                  /* 1B */
95f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	16384,                  /* 1C */
96f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	24576,                  /* 1D */
97f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	32768                   /* 1E */
98f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell};
99f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
100f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void get_map_page(struct qib_qpn_table *qpt, struct qpn_map *map)
101f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
102f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long page = get_zeroed_page(GFP_KERNEL);
103f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
104f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
105f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Free the page if someone raced with us installing it.
106f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
107f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
108f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock(&qpt->lock);
109f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (map->page)
110f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		free_page(page);
111f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
112f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		map->page = (void *)page;
113f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock(&qpt->lock);
114f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
115f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
116f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
117f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Allocate the next available QPN or
118f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * zero/one for QP type IB_QPT_SMI/IB_QPT_GSI.
119f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
120f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt,
121f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		     enum ib_qp_type type, u8 port)
122f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
123f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 i, offset, max_scan, qpn;
124f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qpn_map *map;
125f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 ret;
126f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int r;
127f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
128f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (type == IB_QPT_SMI || type == IB_QPT_GSI) {
129f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		unsigned n;
130f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
131f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = type == IB_QPT_GSI;
132f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		n = 1 << (ret + 2 * (port - 1));
133f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock(&qpt->lock);
134f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qpt->flags & n)
135f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = -EINVAL;
136f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else
137f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qpt->flags |= n;
138f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock(&qpt->lock);
139f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
140f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
141f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
142f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	r = smp_processor_id();
143f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (r >= dd->n_krcv_queues)
144f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		r %= dd->n_krcv_queues;
145f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qpn = qpt->last + 1;
146f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qpn >= QPN_MAX)
147f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qpn = 2;
148f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qpt->mask && ((qpn & qpt->mask) >> 1) != r)
149f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qpn = ((qpn & qpt->mask) ? (qpn | qpt->mask) + 1 : qpn) |
150f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			(r << 1);
151f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	offset = qpn & BITS_PER_PAGE_MASK;
152f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	map = &qpt->map[qpn / BITS_PER_PAGE];
153f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	max_scan = qpt->nmaps - !offset;
154f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 0;;) {
155f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (unlikely(!map->page)) {
156f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			get_map_page(qpt, map);
157f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (unlikely(!map->page))
158f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
159f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
160f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		do {
161f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (!test_and_set_bit(offset, map->page)) {
162f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qpt->last = qpn;
163f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ret = qpn;
164f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				goto bail;
165f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
166f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			offset = find_next_offset(qpt, map, offset, r);
167f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qpn = mk_qpn(qpt, map, offset);
168f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/*
169f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * This test differs from alloc_pidmap().
170f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * If find_next_offset() does find a zero
171f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * bit, we don't need to check for QPN
172f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * wrapping around past our starting QPN.
173f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * We just need to be sure we don't loop
174f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * forever.
175f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 */
176f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} while (offset < BITS_PER_PAGE && qpn < QPN_MAX);
177f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
178f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * In order to keep the number of pages allocated to a
179f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * minimum, we scan the all existing pages before increasing
180f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * the size of the bitmap table.
181f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
182f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (++i > max_scan) {
183f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (qpt->nmaps == QPNMAP_ENTRIES)
184f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
185f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			map = &qpt->map[qpt->nmaps++];
186f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			offset = qpt->mask ? (r << 1) : 0;
187f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else if (map < &qpt->map[qpt->nmaps]) {
188f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			++map;
189f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			offset = qpt->mask ? (r << 1) : 0;
190f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else {
191f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			map = &qpt->map[0];
192f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			offset = qpt->mask ? (r << 1) : 2;
193f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
194f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qpn = mk_qpn(qpt, map, offset);
195f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
196f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
197f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = -ENOMEM;
198f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
199f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
200f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
201f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
202f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
203f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
204f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
205f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qpn_map *map;
206f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
207f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	map = qpt->map + qpn / BITS_PER_PAGE;
208f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (map->page)
209f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
210f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
211f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
212f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
213f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Put the QP into the hash table.
214f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * The hash table holds a reference to the QP.
215f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
216f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
217f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
218f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
219f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned n = qp->ibqp.qp_num % dev->qp_table_size;
220f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
221f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
222f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dev->qpt_lock, flags);
223f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
224f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->ibqp.qp_num == 0)
225f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ibp->qp0 = qp;
226f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else if (qp->ibqp.qp_num == 1)
227f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ibp->qp1 = qp;
228f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else {
229f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->next = dev->qp_table[n];
230f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dev->qp_table[n] = qp;
231f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
232f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	atomic_inc(&qp->refcount);
233f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
234f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dev->qpt_lock, flags);
235f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
236f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
237f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
238f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Remove the QP from the table so it can't be found asynchronously by
239f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * the receive interrupt routine.
240f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
241f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
242f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
243f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
244f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_qp *q, **qpp;
245f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
246f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
247f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qpp = &dev->qp_table[qp->ibqp.qp_num % dev->qp_table_size];
248f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
249f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dev->qpt_lock, flags);
250f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
251f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ibp->qp0 == qp) {
252f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ibp->qp0 = NULL;
253f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		atomic_dec(&qp->refcount);
254f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (ibp->qp1 == qp) {
255f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ibp->qp1 = NULL;
256f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		atomic_dec(&qp->refcount);
257f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
258f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (; (q = *qpp) != NULL; qpp = &q->next)
259f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (q == qp) {
260f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				*qpp = qp->next;
261f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qp->next = NULL;
262f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				atomic_dec(&qp->refcount);
263f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
264f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
265f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
266f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dev->qpt_lock, flags);
267f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
268f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
269f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
270f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_free_all_qps - check for QPs still in use
271f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @qpt: the QP table to empty
272f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
273f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * There should not be any QPs still in use.
274f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Free memory for table.
275f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
276f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellunsigned qib_free_all_qps(struct qib_devdata *dd)
277f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
278f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_ibdev *dev = &dd->verbs_dev;
279f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
280f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_qp *qp;
281f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned n, qp_inuse = 0;
282f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
283f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (n = 0; n < dd->num_pports; n++) {
284f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		struct qib_ibport *ibp = &dd->pport[n].ibport_data;
285f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
286f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!qib_mcast_tree_empty(ibp))
287f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp_inuse++;
288f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ibp->qp0)
289f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp_inuse++;
290f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ibp->qp1)
291f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp_inuse++;
292f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
293f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
294f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dev->qpt_lock, flags);
295f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (n = 0; n < dev->qp_table_size; n++) {
296f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp = dev->qp_table[n];
297f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dev->qp_table[n] = NULL;
298f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
299f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (; qp; qp = qp->next)
300f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp_inuse++;
301f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
302f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dev->qpt_lock, flags);
303f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
304f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return qp_inuse;
305f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
306f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
307f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
308f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_lookup_qpn - return the QP with the given QPN
309f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @qpt: the QP table
310f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @qpn: the QP number to look up
311f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
312f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * The caller is responsible for decrementing the QP reference count
313f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * when done.
314f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
315f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstruct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn)
316f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
317f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
318f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
319f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_qp *qp;
320f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
321f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dev->qpt_lock, flags);
322f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
323f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qpn == 0)
324f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp = ibp->qp0;
325f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else if (qpn == 1)
326f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp = ibp->qp1;
327f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
328f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (qp = dev->qp_table[qpn % dev->qp_table_size]; qp;
329f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		     qp = qp->next)
330f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (qp->ibqp.qp_num == qpn)
331f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
332f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp)
333f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		atomic_inc(&qp->refcount);
334f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
335f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dev->qpt_lock, flags);
336f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return qp;
337f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
338f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
339f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
340f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_reset_qp - initialize the QP state to the reset state
341f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @qp: the QP to reset
342f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @type: the QP type
343f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
344f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_reset_qp(struct qib_qp *qp, enum ib_qp_type type)
345f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
346f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->remote_qpn = 0;
347f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->qkey = 0;
348f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->qp_access_flags = 0;
349f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	atomic_set(&qp->s_dma_busy, 0);
350f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_flags &= QIB_S_SIGNAL_REQ_WR;
351f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_hdrwords = 0;
352f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_wqe = NULL;
353f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_draining = 0;
354f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_next_psn = 0;
355f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_last_psn = 0;
356f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_sending_psn = 0;
357f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_sending_hpsn = 0;
358f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_psn = 0;
359f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->r_psn = 0;
360f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->r_msn = 0;
361f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (type == IB_QPT_RC) {
362f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_state = IB_OPCODE_RC_SEND_LAST;
363f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->r_state = IB_OPCODE_RC_SEND_LAST;
364f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
365f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_state = IB_OPCODE_UC_SEND_LAST;
366f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->r_state = IB_OPCODE_UC_SEND_LAST;
367f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
368f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
369f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->r_nak_state = 0;
370f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->r_aflags = 0;
371f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->r_flags = 0;
372f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_head = 0;
373f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_tail = 0;
374f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_cur = 0;
375f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_acked = 0;
376f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_last = 0;
377f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_ssn = 1;
378f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_lsn = 0;
379f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_mig_state = IB_MIG_MIGRATED;
380f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	memset(qp->s_ack_queue, 0, sizeof(qp->s_ack_queue));
381f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->r_head_ack_queue = 0;
382f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_tail_ack_queue = 0;
383f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->s_num_rd_atomic = 0;
384f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->r_rq.wq) {
385f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->r_rq.wq->head = 0;
386f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->r_rq.wq->tail = 0;
387f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
388f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->r_sge.num_sge = 0;
389f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
390f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
391f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void clear_mr_refs(struct qib_qp *qp, int clr_sends)
392f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
393f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned n;
394f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
395f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (test_and_clear_bit(QIB_R_REWIND_SGE, &qp->r_aflags))
396f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		while (qp->s_rdma_read_sge.num_sge) {
397f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			atomic_dec(&qp->s_rdma_read_sge.sge.mr->refcount);
398f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (--qp->s_rdma_read_sge.num_sge)
399f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qp->s_rdma_read_sge.sge =
400f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					*qp->s_rdma_read_sge.sg_list++;
401f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
402f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
403f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	while (qp->r_sge.num_sge) {
404f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		atomic_dec(&qp->r_sge.sge.mr->refcount);
405f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (--qp->r_sge.num_sge)
406f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->r_sge.sge = *qp->r_sge.sg_list++;
407f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
408f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
409f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (clr_sends) {
410f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		while (qp->s_last != qp->s_head) {
411f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			struct qib_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
412f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			unsigned i;
413f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
414f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			for (i = 0; i < wqe->wr.num_sge; i++) {
415f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				struct qib_sge *sge = &wqe->sg_list[i];
416f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
417f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				atomic_dec(&sge->mr->refcount);
418f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
419f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (qp->ibqp.qp_type == IB_QPT_UD ||
420f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    qp->ibqp.qp_type == IB_QPT_SMI ||
421f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    qp->ibqp.qp_type == IB_QPT_GSI)
422f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				atomic_dec(&to_iah(wqe->wr.wr.ud.ah)->refcount);
423f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (++qp->s_last >= qp->s_size)
424f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qp->s_last = 0;
425f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
426f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qp->s_rdma_mr) {
427f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			atomic_dec(&qp->s_rdma_mr->refcount);
428f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->s_rdma_mr = NULL;
429f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
430f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
431f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
432f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->ibqp.qp_type != IB_QPT_RC)
433f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return;
434f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
435f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (n = 0; n < ARRAY_SIZE(qp->s_ack_queue); n++) {
436f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		struct qib_ack_entry *e = &qp->s_ack_queue[n];
437f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
438f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (e->opcode == IB_OPCODE_RC_RDMA_READ_REQUEST &&
439f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    e->rdma_sge.mr) {
440f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			atomic_dec(&e->rdma_sge.mr->refcount);
441f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			e->rdma_sge.mr = NULL;
442f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
443f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
444f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
445f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
446f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
447f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_error_qp - put a QP into the error state
448f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @qp: the QP to put into the error state
449f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @err: the receive completion error to signal if a RWQE is active
450f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
451f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Flushes both send and receive work queues.
452f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Returns true if last WQE event should be generated.
453f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * The QP s_lock should be held and interrupts disabled.
454f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * If we are already in error state, just return.
455f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
456f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellint qib_error_qp(struct qib_qp *qp, enum ib_wc_status err)
457f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
458f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_ibdev *dev = to_idev(qp->ibqp.device);
459f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct ib_wc wc;
460f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret = 0;
461f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
462f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->state == IB_QPS_ERR || qp->state == IB_QPS_RESET)
463f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
464f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
465f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qp->state = IB_QPS_ERR;
466f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
467f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->s_flags & (QIB_S_TIMER | QIB_S_WAIT_RNR)) {
468f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_flags &= ~(QIB_S_TIMER | QIB_S_WAIT_RNR);
469f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		del_timer(&qp->s_timer);
470f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
471f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock(&dev->pending_lock);
472f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!list_empty(&qp->iowait) && !(qp->s_flags & QIB_S_BUSY)) {
473f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_flags &= ~QIB_S_ANY_WAIT_IO;
474f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		list_del_init(&qp->iowait);
475f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
476f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock(&dev->pending_lock);
477f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
478f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!(qp->s_flags & QIB_S_BUSY)) {
479f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_hdrwords = 0;
480f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qp->s_rdma_mr) {
481f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			atomic_dec(&qp->s_rdma_mr->refcount);
482f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->s_rdma_mr = NULL;
483f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
484f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qp->s_tx) {
485f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_put_txreq(qp->s_tx);
486f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->s_tx = NULL;
487f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
488f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
489f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
490f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* Schedule the sending tasklet to drain the send work queue. */
491f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->s_last != qp->s_head)
492f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_schedule_send(qp);
493f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
494f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	clear_mr_refs(qp, 0);
495f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
496f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	memset(&wc, 0, sizeof(wc));
497f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	wc.qp = &qp->ibqp;
498f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	wc.opcode = IB_WC_RECV;
499f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
500f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (test_and_clear_bit(QIB_R_WRID_VALID, &qp->r_aflags)) {
501f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		wc.wr_id = qp->r_wr_id;
502f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		wc.status = err;
503f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
504f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
505f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	wc.status = IB_WC_WR_FLUSH_ERR;
506f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
507f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->r_rq.wq) {
508f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		struct qib_rwq *wq;
509f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 head;
510f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 tail;
511f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
512f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock(&qp->r_rq.lock);
513f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
514f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* sanity check pointers before trusting them */
515f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		wq = qp->r_rq.wq;
516f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		head = wq->head;
517f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (head >= qp->r_rq.size)
518f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			head = 0;
519f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tail = wq->tail;
520f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (tail >= qp->r_rq.size)
521f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			tail = 0;
522f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		while (tail != head) {
523f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			wc.wr_id = get_rwqe_ptr(&qp->r_rq, tail)->wr_id;
524f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (++tail >= qp->r_rq.size)
525f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				tail = 0;
526f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
527f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
528f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		wq->tail = tail;
529f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
530f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock(&qp->r_rq.lock);
531f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (qp->ibqp.event_handler)
532f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = 1;
533f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
534f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
535f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
536f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
537f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
538f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
539f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_modify_qp - modify the attributes of a queue pair
540f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ibqp: the queue pair who's attributes we're modifying
541f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @attr: the new attributes
542f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @attr_mask: the mask of attributes to modify
543f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @udata: user data for libibverbs.so
544f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
545f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Returns 0 on success, otherwise returns an errno.
546f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
547f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellint qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
548f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  int attr_mask, struct ib_udata *udata)
549f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
550f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_ibdev *dev = to_idev(ibqp->device);
551f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_qp *qp = to_iqp(ibqp);
552f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	enum ib_qp_state cur_state, new_state;
553f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct ib_event ev;
554f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int lastwqe = 0;
555f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int mig = 0;
556f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret;
557f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 pmtu = 0; /* for gcc warning only */
558f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
559f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irq(&qp->r_lock);
560f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock(&qp->s_lock);
561f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
562f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cur_state = attr_mask & IB_QP_CUR_STATE ?
563f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		attr->cur_qp_state : qp->state;
564f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
565f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
566f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type,
567f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				attr_mask))
568f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto inval;
569f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
570f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_AV) {
571f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->ah_attr.dlid >= QIB_MULTICAST_LID_BASE)
572f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
573f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qib_check_ah(qp->ibqp.device, &attr->ah_attr))
574f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
575f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
576f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
577f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_ALT_PATH) {
578f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->alt_ah_attr.dlid >= QIB_MULTICAST_LID_BASE)
579f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
580f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qib_check_ah(qp->ibqp.device, &attr->alt_ah_attr))
581f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
582f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->alt_pkey_index >= qib_get_npkeys(dd_from_dev(dev)))
583f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
584f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
585f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
586f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_PKEY_INDEX)
587f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->pkey_index >= qib_get_npkeys(dd_from_dev(dev)))
588f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
589f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
590f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_MIN_RNR_TIMER)
591f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->min_rnr_timer > 31)
592f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
593f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
594f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_PORT)
595f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qp->ibqp.qp_type == IB_QPT_SMI ||
596f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    qp->ibqp.qp_type == IB_QPT_GSI ||
597f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    attr->port_num == 0 ||
598f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    attr->port_num > ibqp->device->phys_port_cnt)
599f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
600f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
601f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_DEST_QPN)
602f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->dest_qp_num > QIB_QPN_MASK)
603f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
604f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
605f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_RETRY_CNT)
606f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->retry_cnt > 7)
607f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
608f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
609f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_RNR_RETRY)
610f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->rnr_retry > 7)
611f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
612f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
613f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
614f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Don't allow invalid path_mtu values.  OK to set greater
615f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * than the active mtu (or even the max_cap, if we have tuned
616f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * that to a small mtu.  We'll set qp->path_mtu
617f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * to the lesser of requested attribute mtu and active,
618f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * for packetizing messages.
619f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Note that the QP port has to be set in INIT and MTU in RTR.
620f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
621f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_PATH_MTU) {
622f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		struct qib_devdata *dd = dd_from_dev(dev);
623f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		int mtu, pidx = qp->port_num - 1;
624f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
625f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		mtu = ib_mtu_enum_to_int(attr->path_mtu);
626f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (mtu == -1)
627f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
628f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (mtu > dd->pport[pidx].ibmtu) {
629f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			switch (dd->pport[pidx].ibmtu) {
630f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			case 4096:
631f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				pmtu = IB_MTU_4096;
632f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
633f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			case 2048:
634f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				pmtu = IB_MTU_2048;
635f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
636f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			case 1024:
637f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				pmtu = IB_MTU_1024;
638f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
639f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			case 512:
640f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				pmtu = IB_MTU_512;
641f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
642f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			case 256:
643f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				pmtu = IB_MTU_256;
644f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
645f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			default:
646f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				pmtu = IB_MTU_2048;
647f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
648f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else
649f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			pmtu = attr->path_mtu;
650f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
651f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
652f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_PATH_MIG_STATE) {
653f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->path_mig_state == IB_MIG_REARM) {
654f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (qp->s_mig_state == IB_MIG_ARMED)
655f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				goto inval;
656f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (new_state != IB_QPS_RTS)
657f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				goto inval;
658f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else if (attr->path_mig_state == IB_MIG_MIGRATED) {
659f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (qp->s_mig_state == IB_MIG_REARM)
660f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				goto inval;
661f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (new_state != IB_QPS_RTS && new_state != IB_QPS_SQD)
662f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				goto inval;
663f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (qp->s_mig_state == IB_MIG_ARMED)
664f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				mig = 1;
665f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else
666f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
667f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
668f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
669f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
670f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (attr->max_dest_rd_atomic > QIB_MAX_RDMA_ATOMIC)
671f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
672f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
673f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (new_state) {
674f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPS_RESET:
675f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qp->state != IB_QPS_RESET) {
676f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->state = IB_QPS_RESET;
677f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_lock(&dev->pending_lock);
678f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (!list_empty(&qp->iowait))
679f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				list_del_init(&qp->iowait);
680f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock(&dev->pending_lock);
681f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->s_flags &= ~(QIB_S_TIMER | QIB_S_ANY_WAIT);
682f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock(&qp->s_lock);
683f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock_irq(&qp->r_lock);
684f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/* Stop the sending work queue and retry timer */
685f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			cancel_work_sync(&qp->s_work);
686f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			del_timer_sync(&qp->s_timer);
687f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			wait_event(qp->wait_dma, !atomic_read(&qp->s_dma_busy));
688f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (qp->s_tx) {
689f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_put_txreq(qp->s_tx);
690f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qp->s_tx = NULL;
691f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
692f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			remove_qp(dev, qp);
693f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			wait_event(qp->wait, !atomic_read(&qp->refcount));
694f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_lock_irq(&qp->r_lock);
695f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_lock(&qp->s_lock);
696f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			clear_mr_refs(qp, 1);
697f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_reset_qp(qp, ibqp->qp_type);
698f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
699f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
700f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
701f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPS_RTR:
702f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* Allow event to retrigger if QP set to RTR more than once */
703f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->r_flags &= ~QIB_R_COMM_EST;
704f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->state = new_state;
705f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
706f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
707f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPS_SQD:
708f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_draining = qp->s_last != qp->s_cur;
709f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->state = new_state;
710f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
711f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
712f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPS_SQE:
713f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qp->ibqp.qp_type == IB_QPT_RC)
714f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto inval;
715f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->state = new_state;
716f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
717f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
718f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPS_ERR:
719f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lastwqe = qib_error_qp(qp, IB_WC_WR_FLUSH_ERR);
720f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
721f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
722f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	default:
723f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->state = new_state;
724f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
725f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
726f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
727f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_PKEY_INDEX)
728f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_pkey_index = attr->pkey_index;
729f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
730f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_PORT)
731f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->port_num = attr->port_num;
732f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
733f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_DEST_QPN)
734f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->remote_qpn = attr->dest_qp_num;
735f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
736f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_SQ_PSN) {
737f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_next_psn = attr->sq_psn & QIB_PSN_MASK;
738f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_psn = qp->s_next_psn;
739f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_sending_psn = qp->s_next_psn;
740f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_last_psn = qp->s_next_psn - 1;
741f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_sending_hpsn = qp->s_last_psn;
742f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
743f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
744f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_RQ_PSN)
745f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->r_psn = attr->rq_psn & QIB_PSN_MASK;
746f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
747f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_ACCESS_FLAGS)
748f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->qp_access_flags = attr->qp_access_flags;
749f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
750f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_AV) {
751f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->remote_ah_attr = attr->ah_attr;
752f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_srate = attr->ah_attr.static_rate;
753f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
754f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
755f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_ALT_PATH) {
756f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->alt_ah_attr = attr->alt_ah_attr;
757f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_alt_pkey_index = attr->alt_pkey_index;
758f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
759f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
760f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_PATH_MIG_STATE) {
761f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_mig_state = attr->path_mig_state;
762f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (mig) {
763f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->remote_ah_attr = qp->alt_ah_attr;
764f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->port_num = qp->alt_ah_attr.port_num;
765f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->s_pkey_index = qp->s_alt_pkey_index;
766f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
767f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
768f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
769f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_PATH_MTU)
770f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->path_mtu = pmtu;
771f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
772f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_RETRY_CNT) {
773f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_retry_cnt = attr->retry_cnt;
774f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_retry = attr->retry_cnt;
775f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
776f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
777f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_RNR_RETRY) {
778f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_rnr_retry_cnt = attr->rnr_retry;
779f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_rnr_retry = attr->rnr_retry;
780f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
781f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
782f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_MIN_RNR_TIMER)
783f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->r_min_rnr_timer = attr->min_rnr_timer;
784f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
785f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_TIMEOUT)
786f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->timeout = attr->timeout;
787f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
788f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_QKEY)
789f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->qkey = attr->qkey;
790f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
791f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
792f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->r_max_rd_atomic = attr->max_dest_rd_atomic;
793f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
794f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC)
795f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_max_rd_atomic = attr->max_rd_atomic;
796f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
797f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock(&qp->s_lock);
798f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irq(&qp->r_lock);
799f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
800f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
801f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		insert_qp(dev, qp);
802f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
803f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (lastwqe) {
804f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ev.device = qp->ibqp.device;
805f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ev.element.qp = &qp->ibqp;
806f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ev.event = IB_EVENT_QP_LAST_WQE_REACHED;
807f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->ibqp.event_handler(&ev, qp->ibqp.qp_context);
808f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
809f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (mig) {
810f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ev.device = qp->ibqp.device;
811f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ev.element.qp = &qp->ibqp;
812f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ev.event = IB_EVENT_PATH_MIG;
813f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->ibqp.event_handler(&ev, qp->ibqp.qp_context);
814f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
815f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = 0;
816f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	goto bail;
817f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
818f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellinval:
819f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock(&qp->s_lock);
820f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irq(&qp->r_lock);
821f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = -EINVAL;
822f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
823f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
824f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
825f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
826f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
827f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellint qib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
828f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 int attr_mask, struct ib_qp_init_attr *init_attr)
829f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
830f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_qp *qp = to_iqp(ibqp);
831f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
832f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->qp_state = qp->state;
833f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->cur_qp_state = attr->qp_state;
834f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->path_mtu = qp->path_mtu;
835f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->path_mig_state = qp->s_mig_state;
836f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->qkey = qp->qkey;
837f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->rq_psn = qp->r_psn & QIB_PSN_MASK;
838f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->sq_psn = qp->s_next_psn & QIB_PSN_MASK;
839f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->dest_qp_num = qp->remote_qpn;
840f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->qp_access_flags = qp->qp_access_flags;
841f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->cap.max_send_wr = qp->s_size - 1;
842f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->cap.max_recv_wr = qp->ibqp.srq ? 0 : qp->r_rq.size - 1;
843f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->cap.max_send_sge = qp->s_max_sge;
844f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->cap.max_recv_sge = qp->r_rq.max_sge;
845f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->cap.max_inline_data = 0;
846f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->ah_attr = qp->remote_ah_attr;
847f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->alt_ah_attr = qp->alt_ah_attr;
848f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->pkey_index = qp->s_pkey_index;
849f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->alt_pkey_index = qp->s_alt_pkey_index;
850f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->en_sqd_async_notify = 0;
851f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->sq_draining = qp->s_draining;
852f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->max_rd_atomic = qp->s_max_rd_atomic;
853f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->max_dest_rd_atomic = qp->r_max_rd_atomic;
854f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->min_rnr_timer = qp->r_min_rnr_timer;
855f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->port_num = qp->port_num;
856f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->timeout = qp->timeout;
857f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->retry_cnt = qp->s_retry_cnt;
858f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->rnr_retry = qp->s_rnr_retry_cnt;
859f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->alt_port_num = qp->alt_ah_attr.port_num;
860f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	attr->alt_timeout = qp->alt_timeout;
861f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
862f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_attr->event_handler = qp->ibqp.event_handler;
863f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_attr->qp_context = qp->ibqp.qp_context;
864f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_attr->send_cq = qp->ibqp.send_cq;
865f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_attr->recv_cq = qp->ibqp.recv_cq;
866f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_attr->srq = qp->ibqp.srq;
867f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_attr->cap = attr->cap;
868f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->s_flags & QIB_S_SIGNAL_REQ_WR)
869f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		init_attr->sq_sig_type = IB_SIGNAL_REQ_WR;
870f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
871f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		init_attr->sq_sig_type = IB_SIGNAL_ALL_WR;
872f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_attr->qp_type = qp->ibqp.qp_type;
873f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_attr->port_num = qp->port_num;
874f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return 0;
875f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
876f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
877f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
878f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_compute_aeth - compute the AETH (syndrome + MSN)
879f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @qp: the queue pair to compute the AETH for
880f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
881f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Returns the AETH.
882f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
883f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell__be32 qib_compute_aeth(struct qib_qp *qp)
884f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
885f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 aeth = qp->r_msn & QIB_MSN_MASK;
886f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
887f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->ibqp.srq) {
888f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
889f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Shared receive queues don't generate credits.
890f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Set the credit field to the invalid value.
891f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
892f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		aeth |= QIB_AETH_CREDIT_INVAL << QIB_AETH_CREDIT_SHIFT;
893f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
894f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 min, max, x;
895f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 credits;
896f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		struct qib_rwq *wq = qp->r_rq.wq;
897f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 head;
898f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 tail;
899f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
900f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* sanity check pointers before trusting them */
901f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		head = wq->head;
902f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (head >= qp->r_rq.size)
903f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			head = 0;
904f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tail = wq->tail;
905f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (tail >= qp->r_rq.size)
906f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			tail = 0;
907f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
908f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Compute the number of credits available (RWQEs).
909f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * XXX Not holding the r_rq.lock here so there is a small
910f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * chance that the pair of reads are not atomic.
911f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
912f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		credits = head - tail;
913f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if ((int)credits < 0)
914f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			credits += qp->r_rq.size;
915f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
916f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Binary search the credit table to find the code to
917f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * use.
918f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
919f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		min = 0;
920f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		max = 31;
921f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (;;) {
922f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			x = (min + max) / 2;
923f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (credit_table[x] == credits)
924f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
925f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (credit_table[x] > credits)
926f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				max = x;
927f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			else if (min == x)
928f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
929f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			else
930f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				min = x;
931f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
932f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		aeth |= x << QIB_AETH_CREDIT_SHIFT;
933f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
934f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return cpu_to_be32(aeth);
935f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
936f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
937f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
938f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_create_qp - create a queue pair for a device
939f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ibpd: the protection domain who's device we create the queue pair for
940f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @init_attr: the attributes of the queue pair
941f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @udata: user data for libibverbs.so
942f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
943f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Returns the queue pair on success, otherwise returns an errno.
944f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
945f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Called by the ib_create_qp() core verbs function.
946f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
947f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstruct ib_qp *qib_create_qp(struct ib_pd *ibpd,
948f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    struct ib_qp_init_attr *init_attr,
949f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    struct ib_udata *udata)
950f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
951f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_qp *qp;
952f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int err;
953f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_swqe *swq = NULL;
954f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_ibdev *dev;
955f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd;
956f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	size_t sz;
957f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	size_t sg_list_sz;
958f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct ib_qp *ret;
959f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
960f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (init_attr->cap.max_send_sge > ib_qib_max_sges ||
961f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	    init_attr->cap.max_send_wr > ib_qib_max_qp_wrs) {
962f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = ERR_PTR(-EINVAL);
963f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
964f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
965f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
966f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* Check receive queue parameters if no SRQ is specified. */
967f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!init_attr->srq) {
968f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (init_attr->cap.max_recv_sge > ib_qib_max_sges ||
969f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    init_attr->cap.max_recv_wr > ib_qib_max_qp_wrs) {
970f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = ERR_PTR(-EINVAL);
971f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
972f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
973f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (init_attr->cap.max_send_sge +
974f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    init_attr->cap.max_send_wr +
975f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    init_attr->cap.max_recv_sge +
976f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    init_attr->cap.max_recv_wr == 0) {
977f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = ERR_PTR(-EINVAL);
978f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
979f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
980f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
981f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
982f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (init_attr->qp_type) {
983f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPT_SMI:
984f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPT_GSI:
985f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (init_attr->port_num == 0 ||
986f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    init_attr->port_num > ibpd->device->phys_port_cnt) {
987f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = ERR_PTR(-EINVAL);
988f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
989f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
990f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPT_UC:
991f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPT_RC:
992f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_QPT_UD:
993f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sz = sizeof(struct qib_sge) *
994f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			init_attr->cap.max_send_sge +
995f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			sizeof(struct qib_swqe);
996f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		swq = vmalloc((init_attr->cap.max_send_wr + 1) * sz);
997f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (swq == NULL) {
998f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = ERR_PTR(-ENOMEM);
999f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
1000f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1001f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sz = sizeof(*qp);
1002f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sg_list_sz = 0;
1003f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (init_attr->srq) {
1004f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			struct qib_srq *srq = to_isrq(init_attr->srq);
1005f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1006f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (srq->rq.max_sge > 1)
1007f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				sg_list_sz = sizeof(*qp->r_sg_list) *
1008f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					(srq->rq.max_sge - 1);
1009f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else if (init_attr->cap.max_recv_sge > 1)
1010f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			sg_list_sz = sizeof(*qp->r_sg_list) *
1011f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				(init_attr->cap.max_recv_sge - 1);
1012f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp = kzalloc(sz + sg_list_sz, GFP_KERNEL);
1013f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!qp) {
1014f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = ERR_PTR(-ENOMEM);
1015f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail_swq;
1016f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1017f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (init_attr->srq)
1018f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			sz = 0;
1019f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else {
1020f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->r_rq.size = init_attr->cap.max_recv_wr + 1;
1021f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->r_rq.max_sge = init_attr->cap.max_recv_sge;
1022f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) +
1023f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				sizeof(struct qib_rwqe);
1024f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->r_rq.wq = vmalloc_user(sizeof(struct qib_rwq) +
1025f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						   qp->r_rq.size * sz);
1026f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (!qp->r_rq.wq) {
1027f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ret = ERR_PTR(-ENOMEM);
1028f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				goto bail_qp;
1029f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
1030f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1031f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1032f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1033f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * ib_create_qp() will initialize qp->ibqp
1034f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * except for qp->ibqp.qp_num.
1035f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1036f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_init(&qp->r_lock);
1037f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_init(&qp->s_lock);
1038f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_init(&qp->r_rq.lock);
1039f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		atomic_set(&qp->refcount, 0);
1040f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		init_waitqueue_head(&qp->wait);
1041f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		init_waitqueue_head(&qp->wait_dma);
1042f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		init_timer(&qp->s_timer);
1043f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_timer.data = (unsigned long)qp;
1044f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		INIT_WORK(&qp->s_work, qib_do_send);
1045f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		INIT_LIST_HEAD(&qp->iowait);
1046f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		INIT_LIST_HEAD(&qp->rspwait);
1047f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->state = IB_QPS_RESET;
1048f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_wq = swq;
1049f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_size = init_attr->cap.max_send_wr + 1;
1050f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_max_sge = init_attr->cap.max_send_sge;
1051f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (init_attr->sq_sig_type == IB_SIGNAL_REQ_WR)
1052f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->s_flags = QIB_S_SIGNAL_REQ_WR;
1053f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dev = to_idev(ibpd->device);
1054f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd = dd_from_dev(dev);
1055f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		err = alloc_qpn(dd, &dev->qpn_table, init_attr->qp_type,
1056f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				init_attr->port_num);
1057f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (err < 0) {
1058f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = ERR_PTR(err);
1059f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			vfree(qp->r_rq.wq);
1060f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail_qp;
1061f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1062f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->ibqp.qp_num = err;
1063f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->port_num = init_attr->port_num;
1064f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->processor_id = smp_processor_id();
1065f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_reset_qp(qp, init_attr->qp_type);
1066f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1067f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1068f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	default:
1069f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* Don't support raw QPs */
1070f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = ERR_PTR(-ENOSYS);
1071f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
1072f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1073f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1074f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_attr->cap.max_inline_data = 0;
1075f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1076f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1077f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Return the address of the RWQ as the offset to mmap.
1078f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * See qib_mmap() for details.
1079f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1080f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (udata && udata->outlen >= sizeof(__u64)) {
1081f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!qp->r_rq.wq) {
1082f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			__u64 offset = 0;
1083f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1084f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			err = ib_copy_to_udata(udata, &offset,
1085f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					       sizeof(offset));
1086f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (err) {
1087f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ret = ERR_PTR(err);
1088f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				goto bail_ip;
1089f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
1090f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else {
1091f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			u32 s = sizeof(struct qib_rwq) + qp->r_rq.size * sz;
1092f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1093f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->ip = qib_create_mmap_info(dev, s,
1094f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						      ibpd->uobject->context,
1095f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						      qp->r_rq.wq);
1096f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (!qp->ip) {
1097f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ret = ERR_PTR(-ENOMEM);
1098f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				goto bail_ip;
1099f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
1100f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1101f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			err = ib_copy_to_udata(udata, &(qp->ip->offset),
1102f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					       sizeof(qp->ip->offset));
1103f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (err) {
1104f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ret = ERR_PTR(err);
1105f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				goto bail_ip;
1106f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
1107f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1108f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1109f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1110f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock(&dev->n_qps_lock);
1111f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dev->n_qps_allocated == ib_qib_max_qps) {
1112f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock(&dev->n_qps_lock);
1113f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = ERR_PTR(-ENOMEM);
1114f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail_ip;
1115f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1116f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1117f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dev->n_qps_allocated++;
1118f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock(&dev->n_qps_lock);
1119f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1120f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->ip) {
1121f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irq(&dev->pending_lock);
1122f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		list_add(&qp->ip->pending_mmaps, &dev->pending_mmaps);
1123f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irq(&dev->pending_lock);
1124f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1125f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1126f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = &qp->ibqp;
1127f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	goto bail;
1128f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1129f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail_ip:
1130f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->ip)
1131f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		kref_put(&qp->ip->ref, qib_release_mmap_info);
1132f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
1133f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		vfree(qp->r_rq.wq);
1134f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	free_qpn(&dev->qpn_table, qp->ibqp.qp_num);
1135f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail_qp:
1136f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	kfree(qp);
1137f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail_swq:
1138f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	vfree(swq);
1139f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
1140f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
1141f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1142f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1143f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
1144f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_destroy_qp - destroy a queue pair
1145f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ibqp: the queue pair to destroy
1146f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1147f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Returns 0 on success.
1148f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1149f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Note that this can be called while the QP is actively sending or
1150f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * receiving!
1151f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1152f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellint qib_destroy_qp(struct ib_qp *ibqp)
1153f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1154f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_qp *qp = to_iqp(ibqp);
1155f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_ibdev *dev = to_idev(ibqp->device);
1156f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1157f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* Make sure HW and driver activity is stopped. */
1158f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irq(&qp->s_lock);
1159f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->state != IB_QPS_RESET) {
1160f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->state = IB_QPS_RESET;
1161f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock(&dev->pending_lock);
1162f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!list_empty(&qp->iowait))
1163f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			list_del_init(&qp->iowait);
1164f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock(&dev->pending_lock);
1165f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qp->s_flags &= ~(QIB_S_TIMER | QIB_S_ANY_WAIT);
1166f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irq(&qp->s_lock);
1167f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		cancel_work_sync(&qp->s_work);
1168f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		del_timer_sync(&qp->s_timer);
1169f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		wait_event(qp->wait_dma, !atomic_read(&qp->s_dma_busy));
1170f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qp->s_tx) {
1171f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_put_txreq(qp->s_tx);
1172f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->s_tx = NULL;
1173f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1174f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		remove_qp(dev, qp);
1175f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		wait_event(qp->wait, !atomic_read(&qp->refcount));
1176f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		clear_mr_refs(qp, 1);
1177f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
1178f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irq(&qp->s_lock);
1179f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1180f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* all user's cleaned up, mark it available */
1181f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	free_qpn(&dev->qpn_table, qp->ibqp.qp_num);
1182f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock(&dev->n_qps_lock);
1183f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dev->n_qps_allocated--;
1184f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock(&dev->n_qps_lock);
1185f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1186f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qp->ip)
1187f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		kref_put(&qp->ip->ref, qib_release_mmap_info);
1188f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
1189f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		vfree(qp->r_rq.wq);
1190f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	vfree(qp->s_wq);
1191f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	kfree(qp);
1192f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return 0;
1193f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1194f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1195f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
1196f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_init_qpn_table - initialize the QP number table for a device
1197f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @qpt: the QPN table
1198f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1199f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellvoid qib_init_qpn_table(struct qib_devdata *dd, struct qib_qpn_table *qpt)
1200f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1201f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_init(&qpt->lock);
1202f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qpt->last = 1;          /* start with QPN 2 */
1203f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qpt->nmaps = 1;
1204f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qpt->mask = dd->qpn_mask;
1205f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1206f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1207f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
1208f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_free_qpn_table - free the QP number table for a device
1209f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @qpt: the QPN table
1210f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1211f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellvoid qib_free_qpn_table(struct qib_qpn_table *qpt)
1212f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1213f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int i;
1214f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1215f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 0; i < ARRAY_SIZE(qpt->map); i++)
1216f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qpt->map[i].page)
1217f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			free_page((unsigned long) qpt->map[i].page);
1218f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1219f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1220f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
1221f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_get_credit - flush the send work queue of a QP
1222f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @qp: the qp who's send work queue to flush
1223f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @aeth: the Acknowledge Extended Transport Header
1224f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1225f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * The QP s_lock should be held.
1226f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1227f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellvoid qib_get_credit(struct qib_qp *qp, u32 aeth)
1228f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1229f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 credit = (aeth >> QIB_AETH_CREDIT_SHIFT) & QIB_AETH_CREDIT_MASK;
1230f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1231f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1232f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * If the credit is invalid, we can send
1233f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * as many packets as we like.  Otherwise, we have to
1234f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * honor the credit field.
1235f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1236f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (credit == QIB_AETH_CREDIT_INVAL) {
1237f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(qp->s_flags & QIB_S_UNLIMITED_CREDIT)) {
1238f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->s_flags |= QIB_S_UNLIMITED_CREDIT;
1239f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (qp->s_flags & QIB_S_WAIT_SSN_CREDIT) {
1240f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qp->s_flags &= ~QIB_S_WAIT_SSN_CREDIT;
1241f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_schedule_send(qp);
1242f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
1243f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1244f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (!(qp->s_flags & QIB_S_UNLIMITED_CREDIT)) {
1245f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* Compute new LSN (i.e., MSN + credit) */
1246f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		credit = (aeth + credit_table[credit]) & QIB_MSN_MASK;
1247f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qib_cmp24(credit, qp->s_lsn) > 0) {
1248f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qp->s_lsn = credit;
1249f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (qp->s_flags & QIB_S_WAIT_SSN_CREDIT) {
1250f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qp->s_flags &= ~QIB_S_WAIT_SSN_CREDIT;
1251f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_schedule_send(qp);
1252f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
1253f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1254f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1255f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1256