1 /* 2 * Copyright (c) 2004 Topspin Communications. All rights reserved. 3 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34 #include <linux/string.h> 35 #include <linux/slab.h> 36 37 #include <rdma/ib_verbs.h> 38 #include <rdma/ib_cache.h> 39 40 #include "mthca_dev.h" 41 42 enum { 43 MTHCA_RATE_TAVOR_FULL = 0, 44 MTHCA_RATE_TAVOR_1X = 1, 45 MTHCA_RATE_TAVOR_4X = 2, 46 MTHCA_RATE_TAVOR_1X_DDR = 3 47 }; 48 49 enum { 50 MTHCA_RATE_MEMFREE_FULL = 0, 51 MTHCA_RATE_MEMFREE_QUARTER = 1, 52 MTHCA_RATE_MEMFREE_EIGHTH = 2, 53 MTHCA_RATE_MEMFREE_HALF = 3 54 }; 55 56 struct mthca_av { 57 __be32 port_pd; 58 u8 reserved1; 59 u8 g_slid; 60 __be16 dlid; 61 u8 reserved2; 62 u8 gid_index; 63 u8 msg_sr; 64 u8 hop_limit; 65 __be32 sl_tclass_flowlabel; 66 __be32 dgid[4]; 67 }; 68 69 static enum ib_rate memfree_rate_to_ib(u8 mthca_rate, u8 port_rate) 70 { 71 switch (mthca_rate) { 72 case MTHCA_RATE_MEMFREE_EIGHTH: 73 return mult_to_ib_rate(port_rate >> 3); 74 case MTHCA_RATE_MEMFREE_QUARTER: 75 return mult_to_ib_rate(port_rate >> 2); 76 case MTHCA_RATE_MEMFREE_HALF: 77 return mult_to_ib_rate(port_rate >> 1); 78 case MTHCA_RATE_MEMFREE_FULL: 79 default: 80 return mult_to_ib_rate(port_rate); 81 } 82 } 83 84 static enum ib_rate tavor_rate_to_ib(u8 mthca_rate, u8 port_rate) 85 { 86 switch (mthca_rate) { 87 case MTHCA_RATE_TAVOR_1X: return IB_RATE_2_5_GBPS; 88 case MTHCA_RATE_TAVOR_1X_DDR: return IB_RATE_5_GBPS; 89 case MTHCA_RATE_TAVOR_4X: return IB_RATE_10_GBPS; 90 default: return mult_to_ib_rate(port_rate); 91 } 92 } 93 94 enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port) 95 { 96 if (mthca_is_memfree(dev)) { 97 /* Handle old Arbel FW */ 98 if (dev->limits.stat_rate_support == 0x3 && mthca_rate) 99 return IB_RATE_2_5_GBPS; 100 101 return memfree_rate_to_ib(mthca_rate, dev->rate[port - 1]); 102 } else 103 return tavor_rate_to_ib(mthca_rate, dev->rate[port - 1]); 104 } 105 106 static u8 ib_rate_to_memfree(u8 req_rate, u8 cur_rate) 107 { 108 if (cur_rate <= req_rate) 109 return 0; 110 111 /* 112 * Inter-packet delay (IPD) to get from rate X down to a rate 113 * no more than Y is (X - 1) / Y. 114 */ 115 switch ((cur_rate - 1) / req_rate) { 116 case 0: return MTHCA_RATE_MEMFREE_FULL; 117 case 1: return MTHCA_RATE_MEMFREE_HALF; 118 case 2: /* fall through */ 119 case 3: return MTHCA_RATE_MEMFREE_QUARTER; 120 default: return MTHCA_RATE_MEMFREE_EIGHTH; 121 } 122 } 123 124 static u8 ib_rate_to_tavor(u8 static_rate) 125 { 126 switch (static_rate) { 127 case IB_RATE_2_5_GBPS: return MTHCA_RATE_TAVOR_1X; 128 case IB_RATE_5_GBPS: return MTHCA_RATE_TAVOR_1X_DDR; 129 case IB_RATE_10_GBPS: return MTHCA_RATE_TAVOR_4X; 130 default: return MTHCA_RATE_TAVOR_FULL; 131 } 132 } 133 134 u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port) 135 { 136 u8 rate; 137 138 if (!static_rate || ib_rate_to_mult(static_rate) >= dev->rate[port - 1]) 139 return 0; 140 141 if (mthca_is_memfree(dev)) 142 rate = ib_rate_to_memfree(ib_rate_to_mult(static_rate), 143 dev->rate[port - 1]); 144 else 145 rate = ib_rate_to_tavor(static_rate); 146 147 if (!(dev->limits.stat_rate_support & (1 << rate))) 148 rate = 1; 149 150 return rate; 151 } 152 153 int mthca_create_ah(struct mthca_dev *dev, 154 struct mthca_pd *pd, 155 struct rdma_ah_attr *ah_attr, 156 struct mthca_ah *ah) 157 { 158 u32 index = -1; 159 struct mthca_av *av = NULL; 160 161 ah->type = MTHCA_AH_PCI_POOL; 162 163 if (mthca_is_memfree(dev)) { 164 ah->av = kmalloc(sizeof *ah->av, GFP_ATOMIC); 165 if (!ah->av) 166 return -ENOMEM; 167 168 ah->type = MTHCA_AH_KMALLOC; 169 av = ah->av; 170 } else if (!atomic_read(&pd->sqp_count) && 171 !(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) { 172 index = mthca_alloc(&dev->av_table.alloc); 173 174 /* fall back to allocate in host memory */ 175 if (index == -1) 176 goto on_hca_fail; 177 178 av = kmalloc(sizeof *av, GFP_ATOMIC); 179 if (!av) 180 goto on_hca_fail; 181 182 ah->type = MTHCA_AH_ON_HCA; 183 ah->avdma = dev->av_table.ddr_av_base + 184 index * MTHCA_AV_SIZE; 185 } 186 187 on_hca_fail: 188 if (ah->type == MTHCA_AH_PCI_POOL) { 189 ah->av = pci_pool_alloc(dev->av_table.pool, 190 GFP_ATOMIC, &ah->avdma); 191 if (!ah->av) 192 return -ENOMEM; 193 194 av = ah->av; 195 } 196 197 ah->key = pd->ntmr.ibmr.lkey; 198 199 memset(av, 0, MTHCA_AV_SIZE); 200 201 av->port_pd = cpu_to_be32(pd->pd_num | 202 (rdma_ah_get_port_num(ah_attr) << 24)); 203 av->g_slid = rdma_ah_get_path_bits(ah_attr); 204 av->dlid = cpu_to_be16(rdma_ah_get_dlid(ah_attr)); 205 av->msg_sr = (3 << 4) | /* 2K message */ 206 mthca_get_rate(dev, rdma_ah_get_static_rate(ah_attr), 207 rdma_ah_get_port_num(ah_attr)); 208 av->sl_tclass_flowlabel = cpu_to_be32(rdma_ah_get_sl(ah_attr) << 28); 209 if (rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH) { 210 const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr); 211 212 av->g_slid |= 0x80; 213 av->gid_index = (rdma_ah_get_port_num(ah_attr) - 1) * 214 dev->limits.gid_table_len + 215 grh->sgid_index; 216 av->hop_limit = grh->hop_limit; 217 av->sl_tclass_flowlabel |= 218 cpu_to_be32((grh->traffic_class << 20) | 219 grh->flow_label); 220 memcpy(av->dgid, grh->dgid.raw, 16); 221 } else { 222 /* Arbel workaround -- low byte of GID must be 2 */ 223 av->dgid[3] = cpu_to_be32(2); 224 } 225 226 if (0) { 227 int j; 228 229 mthca_dbg(dev, "Created UDAV at %p/%08lx:\n", 230 av, (unsigned long) ah->avdma); 231 for (j = 0; j < 8; ++j) 232 printk(KERN_DEBUG " [%2x] %08x\n", 233 j * 4, be32_to_cpu(((__be32 *) av)[j])); 234 } 235 236 if (ah->type == MTHCA_AH_ON_HCA) { 237 memcpy_toio(dev->av_table.av_map + index * MTHCA_AV_SIZE, 238 av, MTHCA_AV_SIZE); 239 kfree(av); 240 } 241 242 return 0; 243 } 244 245 int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah) 246 { 247 switch (ah->type) { 248 case MTHCA_AH_ON_HCA: 249 mthca_free(&dev->av_table.alloc, 250 (ah->avdma - dev->av_table.ddr_av_base) / 251 MTHCA_AV_SIZE); 252 break; 253 254 case MTHCA_AH_PCI_POOL: 255 pci_pool_free(dev->av_table.pool, ah->av, ah->avdma); 256 break; 257 258 case MTHCA_AH_KMALLOC: 259 kfree(ah->av); 260 break; 261 } 262 263 return 0; 264 } 265 266 int mthca_ah_grh_present(struct mthca_ah *ah) 267 { 268 return !!(ah->av->g_slid & 0x80); 269 } 270 271 int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, 272 struct ib_ud_header *header) 273 { 274 if (ah->type == MTHCA_AH_ON_HCA) 275 return -EINVAL; 276 277 header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; 278 header->lrh.destination_lid = ah->av->dlid; 279 header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); 280 if (mthca_ah_grh_present(ah)) { 281 header->grh.traffic_class = 282 (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; 283 header->grh.flow_label = 284 ah->av->sl_tclass_flowlabel & cpu_to_be32(0xfffff); 285 header->grh.hop_limit = ah->av->hop_limit; 286 header->grh.source_gid = ah->ibah.sgid_attr->gid; 287 memcpy(header->grh.destination_gid.raw, 288 ah->av->dgid, 16); 289 } 290 291 return 0; 292 } 293 294 int mthca_ah_query(struct ib_ah *ibah, struct rdma_ah_attr *attr) 295 { 296 struct mthca_ah *ah = to_mah(ibah); 297 struct mthca_dev *dev = to_mdev(ibah->device); 298 u8 port_num = be32_to_cpu(ah->av->port_pd) >> 24; 299 300 /* Only implement for MAD and memfree ah for now. */ 301 if (ah->type == MTHCA_AH_ON_HCA) 302 return -ENOSYS; 303 304 memset(attr, 0, sizeof *attr); 305 attr->type = ibah->type; 306 rdma_ah_set_dlid(attr, be16_to_cpu(ah->av->dlid)); 307 rdma_ah_set_sl(attr, be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28); 308 rdma_ah_set_port_num(attr, port_num); 309 rdma_ah_set_static_rate(attr, 310 mthca_rate_to_ib(dev, ah->av->msg_sr & 0x7, port_num)); 311 rdma_ah_set_path_bits(attr, ah->av->g_slid & 0x7F); 312 if (mthca_ah_grh_present(ah)) { 313 u32 tc_fl = be32_to_cpu(ah->av->sl_tclass_flowlabel); 314 315 rdma_ah_set_grh(attr, NULL, 316 tc_fl & 0xfffff, 317 ah->av->gid_index & 318 (dev->limits.gid_table_len - 1), 319 ah->av->hop_limit, 320 tc_fl >> 20); 321 rdma_ah_set_dgid_raw(attr, ah->av->dgid); 322 } 323 324 return 0; 325 } 326 327 int mthca_init_av_table(struct mthca_dev *dev) 328 { 329 int err; 330 331 if (mthca_is_memfree(dev)) 332 return 0; 333 334 err = mthca_alloc_init(&dev->av_table.alloc, 335 dev->av_table.num_ddr_avs, 336 dev->av_table.num_ddr_avs - 1, 337 0); 338 if (err) 339 return err; 340 341 dev->av_table.pool = pci_pool_create("mthca_av", dev->pdev, 342 MTHCA_AV_SIZE, 343 MTHCA_AV_SIZE, 0); 344 if (!dev->av_table.pool) 345 goto out_free_alloc; 346 347 if (!(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) { 348 dev->av_table.av_map = ioremap(pci_resource_start(dev->pdev, 4) + 349 dev->av_table.ddr_av_base - 350 dev->ddr_start, 351 dev->av_table.num_ddr_avs * 352 MTHCA_AV_SIZE); 353 if (!dev->av_table.av_map) 354 goto out_free_pool; 355 } else 356 dev->av_table.av_map = NULL; 357 358 return 0; 359 360 out_free_pool: 361 pci_pool_destroy(dev->av_table.pool); 362 363 out_free_alloc: 364 mthca_alloc_cleanup(&dev->av_table.alloc); 365 return -ENOMEM; 366 } 367 368 void mthca_cleanup_av_table(struct mthca_dev *dev) 369 { 370 if (mthca_is_memfree(dev)) 371 return; 372 373 if (dev->av_table.av_map) 374 iounmap(dev->av_table.av_map); 375 pci_pool_destroy(dev->av_table.pool); 376 mthca_alloc_cleanup(&dev->av_table.alloc); 377 } 378