11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2004 Topspin Communications. All rights reserved. 3cd4e8fb49d2326364971a56f5a4b664a976f3712Tom Duffy * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software is available to you under a choice of one of two 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * licenses. You may choose to be licensed under the terms of the GNU 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * General Public License (GPL) Version 2, available from the file 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * COPYING in the main directory of this source tree, or the 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OpenIB.org BSD license below: 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Redistribution and use in source and binary forms, with or 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without modification, are permitted provided that the following 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * conditions are met: 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Redistributions of source code must retain the above 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copyright notice, this list of conditions and the following 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * disclaimer. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Redistributions in binary form must reproduce the above 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copyright notice, this list of conditions and the following 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * disclaimer in the documentation and/or other materials 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * provided with the distribution. 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SOFTWARE. 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 344e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/string.h> 354e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/slab.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37a4d61e84804f3b14cc35c5e2af768a07c0f64ef6Roland Dreier#include <rdma/ib_verbs.h> 38a4d61e84804f3b14cc35c5e2af768a07c0f64ef6Roland Dreier#include <rdma/ib_cache.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mthca_dev.h" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgensteinenum { 43bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein MTHCA_RATE_TAVOR_FULL = 0, 44bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein MTHCA_RATE_TAVOR_1X = 1, 45bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein MTHCA_RATE_TAVOR_4X = 2, 46bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein MTHCA_RATE_TAVOR_1X_DDR = 3 47bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein}; 48bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 49bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgensteinenum { 50bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein MTHCA_RATE_MEMFREE_FULL = 0, 51bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein MTHCA_RATE_MEMFREE_QUARTER = 1, 52bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein MTHCA_RATE_MEMFREE_EIGHTH = 2, 53bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein MTHCA_RATE_MEMFREE_HALF = 3 54bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein}; 55bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mthca_av { 5797f52eb438be7caebe026421545619d8a0c1398aSean Hefty __be32 port_pd; 5897f52eb438be7caebe026421545619d8a0c1398aSean Hefty u8 reserved1; 5997f52eb438be7caebe026421545619d8a0c1398aSean Hefty u8 g_slid; 6097f52eb438be7caebe026421545619d8a0c1398aSean Hefty __be16 dlid; 6197f52eb438be7caebe026421545619d8a0c1398aSean Hefty u8 reserved2; 6297f52eb438be7caebe026421545619d8a0c1398aSean Hefty u8 gid_index; 6397f52eb438be7caebe026421545619d8a0c1398aSean Hefty u8 msg_sr; 6497f52eb438be7caebe026421545619d8a0c1398aSean Hefty u8 hop_limit; 6597f52eb438be7caebe026421545619d8a0c1398aSean Hefty __be32 sl_tclass_flowlabel; 6697f52eb438be7caebe026421545619d8a0c1398aSean Hefty __be32 dgid[4]; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 69bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgensteinstatic enum ib_rate memfree_rate_to_ib(u8 mthca_rate, u8 port_rate) 70bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein{ 71bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein switch (mthca_rate) { 72bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case MTHCA_RATE_MEMFREE_EIGHTH: 73bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return mult_to_ib_rate(port_rate >> 3); 74bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case MTHCA_RATE_MEMFREE_QUARTER: 75bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return mult_to_ib_rate(port_rate >> 2); 76bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case MTHCA_RATE_MEMFREE_HALF: 77bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return mult_to_ib_rate(port_rate >> 1); 78bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case MTHCA_RATE_MEMFREE_FULL: 79bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein default: 80bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return mult_to_ib_rate(port_rate); 81bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein } 82bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein} 83bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 84bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgensteinstatic enum ib_rate tavor_rate_to_ib(u8 mthca_rate, u8 port_rate) 85bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein{ 86bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein switch (mthca_rate) { 87bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case MTHCA_RATE_TAVOR_1X: return IB_RATE_2_5_GBPS; 88bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case MTHCA_RATE_TAVOR_1X_DDR: return IB_RATE_5_GBPS; 89bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case MTHCA_RATE_TAVOR_4X: return IB_RATE_10_GBPS; 90b046a04e162dc7f468700a0817acda0321b2b3aeJack Morgenstein default: return mult_to_ib_rate(port_rate); 91bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein } 92bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein} 93bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 94bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgensteinenum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port) 95bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein{ 96bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein if (mthca_is_memfree(dev)) { 97bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein /* Handle old Arbel FW */ 98bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein if (dev->limits.stat_rate_support == 0x3 && mthca_rate) 99bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return IB_RATE_2_5_GBPS; 100bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 101bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return memfree_rate_to_ib(mthca_rate, dev->rate[port - 1]); 102bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein } else 103bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return tavor_rate_to_ib(mthca_rate, dev->rate[port - 1]); 104bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein} 105bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 106bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgensteinstatic u8 ib_rate_to_memfree(u8 req_rate, u8 cur_rate) 107bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein{ 108bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein if (cur_rate <= req_rate) 109bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return 0; 110bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 111bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein /* 112bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein * Inter-packet delay (IPD) to get from rate X down to a rate 113bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein * no more than Y is (X - 1) / Y. 114bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein */ 115bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein switch ((cur_rate - 1) / req_rate) { 116bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case 0: return MTHCA_RATE_MEMFREE_FULL; 117bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case 1: return MTHCA_RATE_MEMFREE_HALF; 118bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case 2: /* fall through */ 119bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case 3: return MTHCA_RATE_MEMFREE_QUARTER; 120bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein default: return MTHCA_RATE_MEMFREE_EIGHTH; 121bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein } 122bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein} 123bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 124bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgensteinstatic u8 ib_rate_to_tavor(u8 static_rate) 125bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein{ 126bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein switch (static_rate) { 127bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case IB_RATE_2_5_GBPS: return MTHCA_RATE_TAVOR_1X; 128bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case IB_RATE_5_GBPS: return MTHCA_RATE_TAVOR_1X_DDR; 129bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein case IB_RATE_10_GBPS: return MTHCA_RATE_TAVOR_4X; 130bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein default: return MTHCA_RATE_TAVOR_FULL; 131bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein } 132bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein} 133bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 134bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgensteinu8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port) 135bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein{ 136bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein u8 rate; 137bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 138bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein if (!static_rate || ib_rate_to_mult(static_rate) >= dev->rate[port - 1]) 139bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return 0; 140bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 141bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein if (mthca_is_memfree(dev)) 142bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein rate = ib_rate_to_memfree(ib_rate_to_mult(static_rate), 143bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein dev->rate[port - 1]); 144bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein else 145bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein rate = ib_rate_to_tavor(static_rate); 146bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 147bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein if (!(dev->limits.stat_rate_support & (1 << rate))) 148bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein rate = 1; 149bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 150bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein return rate; 151bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein} 152bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mthca_create_ah(struct mthca_dev *dev, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mthca_pd *pd, 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ib_ah_attr *ah_attr, 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mthca_ah *ah) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 index = -1; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mthca_av *av = NULL; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah->type = MTHCA_AH_PCI_POOL; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 163d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier if (mthca_is_memfree(dev)) { 1648df8a34de60f8e51c87e5c145679f1a896133199Roland Dreier ah->av = kmalloc(sizeof *ah->av, GFP_ATOMIC); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ah->av) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah->type = MTHCA_AH_KMALLOC; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av = ah->av; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!atomic_read(&pd->sqp_count) && 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) { 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds index = mthca_alloc(&dev->av_table.alloc); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fall back to allocate in host memory */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (index == -1) 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto on_hca_fail; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1788df8a34de60f8e51c87e5c145679f1a896133199Roland Dreier av = kmalloc(sizeof *av, GFP_ATOMIC); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!av) 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto on_hca_fail; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah->type = MTHCA_AH_ON_HCA; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah->avdma = dev->av_table.ddr_av_base + 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds index * MTHCA_AV_SIZE; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldson_hca_fail: 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ah->type == MTHCA_AH_PCI_POOL) { 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah->av = pci_pool_alloc(dev->av_table.pool, 19054e6ecb23951b195d02433a741c7f7cb0b796c78Christoph Lameter GFP_ATOMIC, &ah->avdma); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ah->av) 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av = ah->av; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah->key = pd->ntmr.ibmr.lkey; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(av, 0, MTHCA_AV_SIZE); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->port_pd = cpu_to_be32(pd->pd_num | (ah_attr->port_num << 24)); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->g_slid = ah_attr->src_path_bits; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->dlid = cpu_to_be16(ah_attr->dlid); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->msg_sr = (3 << 4) | /* 2K message */ 205bf6a9e31cfa768ce0a8e18474b3ca808641d9243Jack Morgenstein mthca_get_rate(dev, ah_attr->static_rate, ah_attr->port_num); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ah_attr->ah_flags & IB_AH_GRH) { 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->g_slid |= 0x80; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->gid_index = (ah_attr->port_num - 1) * dev->limits.gid_table_len + 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah_attr->grh.sgid_index; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->hop_limit = ah_attr->grh.hop_limit; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->sl_tclass_flowlabel |= 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_to_be32((ah_attr->grh.traffic_class << 20) | 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah_attr->grh.flow_label); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(av->dgid, ah_attr->grh.dgid.raw, 16); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Arbel workaround -- low byte of GID must be 2 */ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av->dgid[3] = cpu_to_be32(2); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (0) { 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int j; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mthca_dbg(dev, "Created UDAV at %p/%08lx:\n", 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av, (unsigned long) ah->avdma); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = 0; j < 8; ++j) 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG " [%2x] %08x\n", 22897f52eb438be7caebe026421545619d8a0c1398aSean Hefty j * 4, be32_to_cpu(((__be32 *) av)[j])); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ah->type == MTHCA_AH_ON_HCA) { 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_toio(dev->av_table.av_map + index * MTHCA_AV_SIZE, 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av, MTHCA_AV_SIZE); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(av); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ah->type) { 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MTHCA_AH_ON_HCA: 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mthca_free(&dev->av_table.alloc, 2452fa5e2ebbe2d81f741ba7bed9e07dc38cc734625Roland Dreier (ah->avdma - dev->av_table.ddr_av_base) / 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MTHCA_AV_SIZE); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MTHCA_AH_PCI_POOL: 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_pool_free(dev->av_table.pool, ah->av, ah->avdma); 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MTHCA_AH_KMALLOC: 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ah->av); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2619eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkinint mthca_ah_grh_present(struct mthca_ah *ah) 2629eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin{ 2639eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin return !!(ah->av->g_slid & 0x80); 2649eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin} 2659eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ib_ud_header *header) 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ah->type == MTHCA_AH_ON_HCA) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->lrh.destination_lid = ah->av->dlid; 27497f52eb438be7caebe026421545619d8a0c1398aSean Hefty header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); 2759eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin if (mthca_ah_grh_present(ah)) { 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->grh.traffic_class = 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds header->grh.flow_label = 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah->av->sl_tclass_flowlabel & cpu_to_be32(0xfffff); 2803f37cae6944de9d380c83f717f73d91ec6255d98Rolf Manderscheid header->grh.hop_limit = ah->av->hop_limit; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ib_get_cached_gid(&dev->ib_dev, 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds be32_to_cpu(ah->av->port_pd) >> 24, 283f9e61929e5e1dacc2afefbde6abc3e6571ca2887Michael S. Tsirkin ah->av->gid_index % dev->limits.gid_table_len, 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &header->grh.source_gid); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(header->grh.destination_gid.raw, 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ah->av->dgid, 16); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgensteinint mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr) 2931d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein{ 2941d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein struct mthca_ah *ah = to_mah(ibah); 2951d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein struct mthca_dev *dev = to_mdev(ibah->device); 2961d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein 2971d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein /* Only implement for MAD and memfree ah for now. */ 2981d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein if (ah->type == MTHCA_AH_ON_HCA) 2991d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein return -ENOSYS; 3001d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein 3011d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein memset(attr, 0, sizeof *attr); 3021d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein attr->dlid = be16_to_cpu(ah->av->dlid); 3031d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein attr->sl = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; 3041d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein attr->port_num = be32_to_cpu(ah->av->port_pd) >> 24; 3052290d2c9f51d7ee2f45adee79b4d9e080ca15d36Jack Morgenstein attr->static_rate = mthca_rate_to_ib(dev, ah->av->msg_sr & 0x7, 3062290d2c9f51d7ee2f45adee79b4d9e080ca15d36Jack Morgenstein attr->port_num); 3072290d2c9f51d7ee2f45adee79b4d9e080ca15d36Jack Morgenstein attr->src_path_bits = ah->av->g_slid & 0x7F; 3081d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein attr->ah_flags = mthca_ah_grh_present(ah) ? IB_AH_GRH : 0; 3091d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein 3101d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein if (attr->ah_flags) { 3111d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein attr->grh.traffic_class = 3121d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20; 3131d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein attr->grh.flow_label = 3141d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein be32_to_cpu(ah->av->sl_tclass_flowlabel) & 0xfffff; 3151d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein attr->grh.hop_limit = ah->av->hop_limit; 3161d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein attr->grh.sgid_index = ah->av->gid_index & 3171d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein (dev->limits.gid_table_len - 1); 3181d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein memcpy(attr->grh.dgid.raw, ah->av->dgid, 16); 3191d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein } 3201d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein 3211d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein return 0; 3221d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein} 3231d89b1ae6c203bc68a3f424be144abcdf62773c9Jack Morgenstein 324f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreierint mthca_init_av_table(struct mthca_dev *dev) 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 328d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier if (mthca_is_memfree(dev)) 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = mthca_alloc_init(&dev->av_table.alloc, 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->av_table.num_ddr_avs, 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->av_table.num_ddr_avs - 1, 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0); 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->av_table.pool = pci_pool_create("mthca_av", dev->pdev, 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MTHCA_AV_SIZE, 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MTHCA_AV_SIZE, 0); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->av_table.pool) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_free_alloc; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) { 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->av_table.av_map = ioremap(pci_resource_start(dev->pdev, 4) + 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->av_table.ddr_av_base - 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->ddr_start, 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->av_table.num_ddr_avs * 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MTHCA_AV_SIZE); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->av_table.av_map) 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_free_pool; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->av_table.av_map = NULL; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_free_pool: 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_pool_destroy(dev->av_table.pool); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_free_alloc: 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mthca_alloc_cleanup(&dev->av_table.alloc); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 365e1f7868c80947d40ef8e1fd37323d939a9bf311cRoland Dreiervoid mthca_cleanup_av_table(struct mthca_dev *dev) 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 367d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier if (mthca_is_memfree(dev)) 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->av_table.av_map) 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(dev->av_table.av_map); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_pool_destroy(dev->av_table.pool); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mthca_alloc_cleanup(&dev->av_table.alloc); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 375