Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.27-rc2 384 lines 9.7 kB view raw
1/* 2 * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. 3 * Copyright (c) 2007, 2008 Mellanox Technologies. 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/init.h> 35#include <linux/string.h> 36#include <linux/slab.h> 37 38#include <linux/mlx4/cmd.h> 39 40#include "mlx4.h" 41 42#define MGM_QPN_MASK 0x00FFFFFF 43#define MGM_BLCK_LB_BIT 30 44 45struct mlx4_mgm { 46 __be32 next_gid_index; 47 __be32 members_count; 48 u32 reserved[2]; 49 u8 gid[16]; 50 __be32 qp[MLX4_QP_PER_MGM]; 51}; 52 53static const u8 zero_gid[16]; /* automatically initialized to 0 */ 54 55static int mlx4_READ_MCG(struct mlx4_dev *dev, int index, 56 struct mlx4_cmd_mailbox *mailbox) 57{ 58 return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG, 59 MLX4_CMD_TIME_CLASS_A); 60} 61 62static int mlx4_WRITE_MCG(struct mlx4_dev *dev, int index, 63 struct mlx4_cmd_mailbox *mailbox) 64{ 65 return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG, 66 MLX4_CMD_TIME_CLASS_A); 67} 68 69static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, 70 u16 *hash) 71{ 72 u64 imm; 73 int err; 74 75 err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, 0, MLX4_CMD_MGID_HASH, 76 MLX4_CMD_TIME_CLASS_A); 77 78 if (!err) 79 *hash = imm; 80 81 return err; 82} 83 84/* 85 * Caller must hold MCG table semaphore. gid and mgm parameters must 86 * be properly aligned for command interface. 87 * 88 * Returns 0 unless a firmware command error occurs. 89 * 90 * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1 91 * and *mgm holds MGM entry. 92 * 93 * if GID is found in AMGM, *index = index in AMGM, *prev = index of 94 * previous entry in hash chain and *mgm holds AMGM entry. 95 * 96 * If no AMGM exists for given gid, *index = -1, *prev = index of last 97 * entry in hash chain and *mgm holds end of hash chain. 98 */ 99static int find_mgm(struct mlx4_dev *dev, 100 u8 *gid, struct mlx4_cmd_mailbox *mgm_mailbox, 101 u16 *hash, int *prev, int *index) 102{ 103 struct mlx4_cmd_mailbox *mailbox; 104 struct mlx4_mgm *mgm = mgm_mailbox->buf; 105 u8 *mgid; 106 int err; 107 108 mailbox = mlx4_alloc_cmd_mailbox(dev); 109 if (IS_ERR(mailbox)) 110 return -ENOMEM; 111 mgid = mailbox->buf; 112 113 memcpy(mgid, gid, 16); 114 115 err = mlx4_MGID_HASH(dev, mailbox, hash); 116 mlx4_free_cmd_mailbox(dev, mailbox); 117 if (err) 118 return err; 119 120 if (0) 121 mlx4_dbg(dev, "Hash for %04x:%04x:%04x:%04x:" 122 "%04x:%04x:%04x:%04x is %04x\n", 123 be16_to_cpu(((__be16 *) gid)[0]), 124 be16_to_cpu(((__be16 *) gid)[1]), 125 be16_to_cpu(((__be16 *) gid)[2]), 126 be16_to_cpu(((__be16 *) gid)[3]), 127 be16_to_cpu(((__be16 *) gid)[4]), 128 be16_to_cpu(((__be16 *) gid)[5]), 129 be16_to_cpu(((__be16 *) gid)[6]), 130 be16_to_cpu(((__be16 *) gid)[7]), 131 *hash); 132 133 *index = *hash; 134 *prev = -1; 135 136 do { 137 err = mlx4_READ_MCG(dev, *index, mgm_mailbox); 138 if (err) 139 return err; 140 141 if (!memcmp(mgm->gid, zero_gid, 16)) { 142 if (*index != *hash) { 143 mlx4_err(dev, "Found zero MGID in AMGM.\n"); 144 err = -EINVAL; 145 } 146 return err; 147 } 148 149 if (!memcmp(mgm->gid, gid, 16)) 150 return err; 151 152 *prev = *index; 153 *index = be32_to_cpu(mgm->next_gid_index) >> 6; 154 } while (*index); 155 156 *index = -1; 157 return err; 158} 159 160int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 161 int block_mcast_loopback) 162{ 163 struct mlx4_priv *priv = mlx4_priv(dev); 164 struct mlx4_cmd_mailbox *mailbox; 165 struct mlx4_mgm *mgm; 166 u32 members_count; 167 u16 hash; 168 int index, prev; 169 int link = 0; 170 int i; 171 int err; 172 173 mailbox = mlx4_alloc_cmd_mailbox(dev); 174 if (IS_ERR(mailbox)) 175 return PTR_ERR(mailbox); 176 mgm = mailbox->buf; 177 178 mutex_lock(&priv->mcg_table.mutex); 179 180 err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); 181 if (err) 182 goto out; 183 184 if (index != -1) { 185 if (!memcmp(mgm->gid, zero_gid, 16)) 186 memcpy(mgm->gid, gid, 16); 187 } else { 188 link = 1; 189 190 index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap); 191 if (index == -1) { 192 mlx4_err(dev, "No AMGM entries left\n"); 193 err = -ENOMEM; 194 goto out; 195 } 196 index += dev->caps.num_mgms; 197 198 memset(mgm, 0, sizeof *mgm); 199 memcpy(mgm->gid, gid, 16); 200 } 201 202 members_count = be32_to_cpu(mgm->members_count); 203 if (members_count == MLX4_QP_PER_MGM) { 204 mlx4_err(dev, "MGM at index %x is full.\n", index); 205 err = -ENOMEM; 206 goto out; 207 } 208 209 for (i = 0; i < members_count; ++i) 210 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) { 211 mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn); 212 err = 0; 213 goto out; 214 } 215 216 if (block_mcast_loopback) 217 mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) | 218 (1 << MGM_BLCK_LB_BIT)); 219 else 220 mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK); 221 222 mgm->members_count = cpu_to_be32(members_count); 223 224 err = mlx4_WRITE_MCG(dev, index, mailbox); 225 if (err) 226 goto out; 227 228 if (!link) 229 goto out; 230 231 err = mlx4_READ_MCG(dev, prev, mailbox); 232 if (err) 233 goto out; 234 235 mgm->next_gid_index = cpu_to_be32(index << 6); 236 237 err = mlx4_WRITE_MCG(dev, prev, mailbox); 238 if (err) 239 goto out; 240 241out: 242 if (err && link && index != -1) { 243 if (index < dev->caps.num_mgms) 244 mlx4_warn(dev, "Got AMGM index %d < %d", 245 index, dev->caps.num_mgms); 246 else 247 mlx4_bitmap_free(&priv->mcg_table.bitmap, 248 index - dev->caps.num_mgms); 249 } 250 mutex_unlock(&priv->mcg_table.mutex); 251 252 mlx4_free_cmd_mailbox(dev, mailbox); 253 return err; 254} 255EXPORT_SYMBOL_GPL(mlx4_multicast_attach); 256 257int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) 258{ 259 struct mlx4_priv *priv = mlx4_priv(dev); 260 struct mlx4_cmd_mailbox *mailbox; 261 struct mlx4_mgm *mgm; 262 u32 members_count; 263 u16 hash; 264 int prev, index; 265 int i, loc; 266 int err; 267 268 mailbox = mlx4_alloc_cmd_mailbox(dev); 269 if (IS_ERR(mailbox)) 270 return PTR_ERR(mailbox); 271 mgm = mailbox->buf; 272 273 mutex_lock(&priv->mcg_table.mutex); 274 275 err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); 276 if (err) 277 goto out; 278 279 if (index == -1) { 280 mlx4_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " 281 "not found\n", 282 be16_to_cpu(((__be16 *) gid)[0]), 283 be16_to_cpu(((__be16 *) gid)[1]), 284 be16_to_cpu(((__be16 *) gid)[2]), 285 be16_to_cpu(((__be16 *) gid)[3]), 286 be16_to_cpu(((__be16 *) gid)[4]), 287 be16_to_cpu(((__be16 *) gid)[5]), 288 be16_to_cpu(((__be16 *) gid)[6]), 289 be16_to_cpu(((__be16 *) gid)[7])); 290 err = -EINVAL; 291 goto out; 292 } 293 294 members_count = be32_to_cpu(mgm->members_count); 295 for (loc = -1, i = 0; i < members_count; ++i) 296 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) 297 loc = i; 298 299 if (loc == -1) { 300 mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn); 301 err = -EINVAL; 302 goto out; 303 } 304 305 306 mgm->members_count = cpu_to_be32(--members_count); 307 mgm->qp[loc] = mgm->qp[i - 1]; 308 mgm->qp[i - 1] = 0; 309 310 if (i != 1) { 311 err = mlx4_WRITE_MCG(dev, index, mailbox); 312 goto out; 313 } 314 315 if (prev == -1) { 316 /* Remove entry from MGM */ 317 int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6; 318 if (amgm_index) { 319 err = mlx4_READ_MCG(dev, amgm_index, mailbox); 320 if (err) 321 goto out; 322 } else 323 memset(mgm->gid, 0, 16); 324 325 err = mlx4_WRITE_MCG(dev, index, mailbox); 326 if (err) 327 goto out; 328 329 if (amgm_index) { 330 if (amgm_index < dev->caps.num_mgms) 331 mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d", 332 index, amgm_index, dev->caps.num_mgms); 333 else 334 mlx4_bitmap_free(&priv->mcg_table.bitmap, 335 amgm_index - dev->caps.num_mgms); 336 } 337 } else { 338 /* Remove entry from AMGM */ 339 int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; 340 err = mlx4_READ_MCG(dev, prev, mailbox); 341 if (err) 342 goto out; 343 344 mgm->next_gid_index = cpu_to_be32(cur_next_index << 6); 345 346 err = mlx4_WRITE_MCG(dev, prev, mailbox); 347 if (err) 348 goto out; 349 350 if (index < dev->caps.num_mgms) 351 mlx4_warn(dev, "entry %d had next AMGM index %d < %d", 352 prev, index, dev->caps.num_mgms); 353 else 354 mlx4_bitmap_free(&priv->mcg_table.bitmap, 355 index - dev->caps.num_mgms); 356 } 357 358out: 359 mutex_unlock(&priv->mcg_table.mutex); 360 361 mlx4_free_cmd_mailbox(dev, mailbox); 362 return err; 363} 364EXPORT_SYMBOL_GPL(mlx4_multicast_detach); 365 366int mlx4_init_mcg_table(struct mlx4_dev *dev) 367{ 368 struct mlx4_priv *priv = mlx4_priv(dev); 369 int err; 370 371 err = mlx4_bitmap_init(&priv->mcg_table.bitmap, 372 dev->caps.num_amgms, dev->caps.num_amgms - 1, 0); 373 if (err) 374 return err; 375 376 mutex_init(&priv->mcg_table.mutex); 377 378 return 0; 379} 380 381void mlx4_cleanup_mcg_table(struct mlx4_dev *dev) 382{ 383 mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap); 384}