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