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