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

Configure Feed

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

at v2.6.31-rc4 365 lines 9.0 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 %pI6 is %04x\n", gid, *hash); 122 123 *index = *hash; 124 *prev = -1; 125 126 do { 127 err = mlx4_READ_MCG(dev, *index, mgm_mailbox); 128 if (err) 129 return err; 130 131 if (!memcmp(mgm->gid, zero_gid, 16)) { 132 if (*index != *hash) { 133 mlx4_err(dev, "Found zero MGID in AMGM.\n"); 134 err = -EINVAL; 135 } 136 return err; 137 } 138 139 if (!memcmp(mgm->gid, gid, 16)) 140 return err; 141 142 *prev = *index; 143 *index = be32_to_cpu(mgm->next_gid_index) >> 6; 144 } while (*index); 145 146 *index = -1; 147 return err; 148} 149 150int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 151 int block_mcast_loopback) 152{ 153 struct mlx4_priv *priv = mlx4_priv(dev); 154 struct mlx4_cmd_mailbox *mailbox; 155 struct mlx4_mgm *mgm; 156 u32 members_count; 157 u16 hash; 158 int index, prev; 159 int link = 0; 160 int i; 161 int err; 162 163 mailbox = mlx4_alloc_cmd_mailbox(dev); 164 if (IS_ERR(mailbox)) 165 return PTR_ERR(mailbox); 166 mgm = mailbox->buf; 167 168 mutex_lock(&priv->mcg_table.mutex); 169 170 err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); 171 if (err) 172 goto out; 173 174 if (index != -1) { 175 if (!memcmp(mgm->gid, zero_gid, 16)) 176 memcpy(mgm->gid, gid, 16); 177 } else { 178 link = 1; 179 180 index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap); 181 if (index == -1) { 182 mlx4_err(dev, "No AMGM entries left\n"); 183 err = -ENOMEM; 184 goto out; 185 } 186 index += dev->caps.num_mgms; 187 188 memset(mgm, 0, sizeof *mgm); 189 memcpy(mgm->gid, gid, 16); 190 } 191 192 members_count = be32_to_cpu(mgm->members_count); 193 if (members_count == MLX4_QP_PER_MGM) { 194 mlx4_err(dev, "MGM at index %x is full.\n", index); 195 err = -ENOMEM; 196 goto out; 197 } 198 199 for (i = 0; i < members_count; ++i) 200 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) { 201 mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn); 202 err = 0; 203 goto out; 204 } 205 206 if (block_mcast_loopback) 207 mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) | 208 (1U << MGM_BLCK_LB_BIT)); 209 else 210 mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK); 211 212 mgm->members_count = cpu_to_be32(members_count); 213 214 err = mlx4_WRITE_MCG(dev, index, mailbox); 215 if (err) 216 goto out; 217 218 if (!link) 219 goto out; 220 221 err = mlx4_READ_MCG(dev, prev, mailbox); 222 if (err) 223 goto out; 224 225 mgm->next_gid_index = cpu_to_be32(index << 6); 226 227 err = mlx4_WRITE_MCG(dev, prev, mailbox); 228 if (err) 229 goto out; 230 231out: 232 if (err && link && index != -1) { 233 if (index < dev->caps.num_mgms) 234 mlx4_warn(dev, "Got AMGM index %d < %d", 235 index, dev->caps.num_mgms); 236 else 237 mlx4_bitmap_free(&priv->mcg_table.bitmap, 238 index - dev->caps.num_mgms); 239 } 240 mutex_unlock(&priv->mcg_table.mutex); 241 242 mlx4_free_cmd_mailbox(dev, mailbox); 243 return err; 244} 245EXPORT_SYMBOL_GPL(mlx4_multicast_attach); 246 247int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) 248{ 249 struct mlx4_priv *priv = mlx4_priv(dev); 250 struct mlx4_cmd_mailbox *mailbox; 251 struct mlx4_mgm *mgm; 252 u32 members_count; 253 u16 hash; 254 int prev, index; 255 int i, loc; 256 int err; 257 258 mailbox = mlx4_alloc_cmd_mailbox(dev); 259 if (IS_ERR(mailbox)) 260 return PTR_ERR(mailbox); 261 mgm = mailbox->buf; 262 263 mutex_lock(&priv->mcg_table.mutex); 264 265 err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); 266 if (err) 267 goto out; 268 269 if (index == -1) { 270 mlx4_err(dev, "MGID %pI6 not found\n", gid); 271 err = -EINVAL; 272 goto out; 273 } 274 275 members_count = be32_to_cpu(mgm->members_count); 276 for (loc = -1, i = 0; i < members_count; ++i) 277 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) 278 loc = i; 279 280 if (loc == -1) { 281 mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn); 282 err = -EINVAL; 283 goto out; 284 } 285 286 287 mgm->members_count = cpu_to_be32(--members_count); 288 mgm->qp[loc] = mgm->qp[i - 1]; 289 mgm->qp[i - 1] = 0; 290 291 if (i != 1) { 292 err = mlx4_WRITE_MCG(dev, index, mailbox); 293 goto out; 294 } 295 296 if (prev == -1) { 297 /* Remove entry from MGM */ 298 int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6; 299 if (amgm_index) { 300 err = mlx4_READ_MCG(dev, amgm_index, mailbox); 301 if (err) 302 goto out; 303 } else 304 memset(mgm->gid, 0, 16); 305 306 err = mlx4_WRITE_MCG(dev, index, mailbox); 307 if (err) 308 goto out; 309 310 if (amgm_index) { 311 if (amgm_index < dev->caps.num_mgms) 312 mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d", 313 index, amgm_index, dev->caps.num_mgms); 314 else 315 mlx4_bitmap_free(&priv->mcg_table.bitmap, 316 amgm_index - dev->caps.num_mgms); 317 } 318 } else { 319 /* Remove entry from AMGM */ 320 int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; 321 err = mlx4_READ_MCG(dev, prev, mailbox); 322 if (err) 323 goto out; 324 325 mgm->next_gid_index = cpu_to_be32(cur_next_index << 6); 326 327 err = mlx4_WRITE_MCG(dev, prev, mailbox); 328 if (err) 329 goto out; 330 331 if (index < dev->caps.num_mgms) 332 mlx4_warn(dev, "entry %d had next AMGM index %d < %d", 333 prev, index, dev->caps.num_mgms); 334 else 335 mlx4_bitmap_free(&priv->mcg_table.bitmap, 336 index - dev->caps.num_mgms); 337 } 338 339out: 340 mutex_unlock(&priv->mcg_table.mutex); 341 342 mlx4_free_cmd_mailbox(dev, mailbox); 343 return err; 344} 345EXPORT_SYMBOL_GPL(mlx4_multicast_detach); 346 347int mlx4_init_mcg_table(struct mlx4_dev *dev) 348{ 349 struct mlx4_priv *priv = mlx4_priv(dev); 350 int err; 351 352 err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms, 353 dev->caps.num_amgms - 1, 0, 0); 354 if (err) 355 return err; 356 357 mutex_init(&priv->mcg_table.mutex); 358 359 return 0; 360} 361 362void mlx4_cleanup_mcg_table(struct mlx4_dev *dev) 363{ 364 mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap); 365}