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