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/string.h> 35 #include <linux/etherdevice.h> 36 37 #include <linux/mlx4/cmd.h> 38 #include <linux/export.h> 39 40 #include "mlx4.h" 41 42 #define MGM_QPN_MASK 0x00FFFFFF 43 #define MGM_BLCK_LB_BIT 30 44 45 static const u8 zero_gid[16]; /* automatically initialized to 0 */ 46 47 struct mlx4_mgm { 48 __be32 next_gid_index; 49 __be32 members_count; 50 u32 reserved[2]; 51 u8 gid[16]; 52 __be32 qp[MLX4_MAX_QP_PER_MGM]; 53 }; 54 55 int mlx4_get_mgm_entry_size(struct mlx4_dev *dev) 56 { 57 return min((1 << mlx4_log_num_mgm_entry_size), MLX4_MAX_MGM_ENTRY_SIZE); 58 } 59 60 int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) 61 { 62 return 4 * (mlx4_get_mgm_entry_size(dev) / 16 - 2); 63 } 64 65 static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index, 66 struct mlx4_cmd_mailbox *mailbox) 67 { 68 return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG, 69 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 70 } 71 72 static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index, 73 struct mlx4_cmd_mailbox *mailbox) 74 { 75 return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG, 76 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 77 } 78 79 static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 port, u8 steer, 80 struct mlx4_cmd_mailbox *mailbox) 81 { 82 u32 in_mod; 83 84 in_mod = (u32) port << 16 | steer << 1; 85 return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1, 86 MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A, 87 MLX4_CMD_NATIVE); 88 } 89 90 static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, 91 u16 *hash, u8 op_mod) 92 { 93 u64 imm; 94 int err; 95 96 err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod, 97 MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A, 98 MLX4_CMD_NATIVE); 99 100 if (!err) 101 *hash = imm; 102 103 return err; 104 } 105 106 static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, 107 enum mlx4_steer_type steer, 108 u32 qpn) 109 { 110 struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num]; 111 struct mlx4_promisc_qp *pqp; 112 113 list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { 114 if (pqp->qpn == qpn) 115 return pqp; 116 } 117 /* not found */ 118 return NULL; 119 } 120 121 /* 122 * Add new entry to steering data structure. 123 * All promisc QPs should be added as well 124 */ 125 static int new_steering_entry(struct mlx4_dev *dev, u8 port, 126 enum mlx4_steer_type steer, 127 unsigned int index, u32 qpn) 128 { 129 struct mlx4_steer *s_steer; 130 struct mlx4_cmd_mailbox *mailbox; 131 struct mlx4_mgm *mgm; 132 u32 members_count; 133 struct mlx4_steer_index *new_entry; 134 struct mlx4_promisc_qp *pqp; 135 struct mlx4_promisc_qp *dqp = NULL; 136 u32 prot; 137 int err; 138 139 s_steer = &mlx4_priv(dev)->steer[0]; 140 new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL); 141 if (!new_entry) 142 return -ENOMEM; 143 144 INIT_LIST_HEAD(&new_entry->duplicates); 145 new_entry->index = index; 146 list_add_tail(&new_entry->list, &s_steer->steer_entries[steer]); 147 148 /* If the given qpn is also a promisc qp, 149 * it should be inserted to duplicates list 150 */ 151 pqp = get_promisc_qp(dev, 0, steer, qpn); 152 if (pqp) { 153 dqp = kmalloc(sizeof *dqp, GFP_KERNEL); 154 if (!dqp) { 155 err = -ENOMEM; 156 goto out_alloc; 157 } 158 dqp->qpn = qpn; 159 list_add_tail(&dqp->list, &new_entry->duplicates); 160 } 161 162 /* if no promisc qps for this vep, we are done */ 163 if (list_empty(&s_steer->promisc_qps[steer])) 164 return 0; 165 166 /* now need to add all the promisc qps to the new 167 * steering entry, as they should also receive the packets 168 * destined to this address */ 169 mailbox = mlx4_alloc_cmd_mailbox(dev); 170 if (IS_ERR(mailbox)) { 171 err = -ENOMEM; 172 goto out_alloc; 173 } 174 mgm = mailbox->buf; 175 176 err = mlx4_READ_ENTRY(dev, index, mailbox); 177 if (err) 178 goto out_mailbox; 179 180 members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 181 prot = be32_to_cpu(mgm->members_count) >> 30; 182 list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { 183 /* don't add already existing qpn */ 184 if (pqp->qpn == qpn) 185 continue; 186 if (members_count == dev->caps.num_qp_per_mgm) { 187 /* out of space */ 188 err = -ENOMEM; 189 goto out_mailbox; 190 } 191 192 /* add the qpn */ 193 mgm->qp[members_count++] = cpu_to_be32(pqp->qpn & MGM_QPN_MASK); 194 } 195 /* update the qps count and update the entry with all the promisc qps*/ 196 mgm->members_count = cpu_to_be32(members_count | (prot << 30)); 197 err = mlx4_WRITE_ENTRY(dev, index, mailbox); 198 199 out_mailbox: 200 mlx4_free_cmd_mailbox(dev, mailbox); 201 if (!err) 202 return 0; 203 out_alloc: 204 if (dqp) { 205 list_del(&dqp->list); 206 kfree(dqp); 207 } 208 list_del(&new_entry->list); 209 kfree(new_entry); 210 return err; 211 } 212 213 /* update the data structures with existing steering entry */ 214 static int existing_steering_entry(struct mlx4_dev *dev, u8 port, 215 enum mlx4_steer_type steer, 216 unsigned int index, u32 qpn) 217 { 218 struct mlx4_steer *s_steer; 219 struct mlx4_steer_index *tmp_entry, *entry = NULL; 220 struct mlx4_promisc_qp *pqp; 221 struct mlx4_promisc_qp *dqp; 222 223 s_steer = &mlx4_priv(dev)->steer[0]; 224 225 pqp = get_promisc_qp(dev, 0, steer, qpn); 226 if (!pqp) 227 return 0; /* nothing to do */ 228 229 list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) { 230 if (tmp_entry->index == index) { 231 entry = tmp_entry; 232 break; 233 } 234 } 235 if (unlikely(!entry)) { 236 mlx4_warn(dev, "Steering entry at index %x is not registered\n", index); 237 return -EINVAL; 238 } 239 240 /* the given qpn is listed as a promisc qpn 241 * we need to add it as a duplicate to this entry 242 * for future references */ 243 list_for_each_entry(dqp, &entry->duplicates, list) { 244 if (qpn == pqp->qpn) 245 return 0; /* qp is already duplicated */ 246 } 247 248 /* add the qp as a duplicate on this index */ 249 dqp = kmalloc(sizeof *dqp, GFP_KERNEL); 250 if (!dqp) 251 return -ENOMEM; 252 dqp->qpn = qpn; 253 list_add_tail(&dqp->list, &entry->duplicates); 254 255 return 0; 256 } 257 258 /* Check whether a qpn is a duplicate on steering entry 259 * If so, it should not be removed from mgm */ 260 static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, 261 enum mlx4_steer_type steer, 262 unsigned int index, u32 qpn) 263 { 264 struct mlx4_steer *s_steer; 265 struct mlx4_steer_index *tmp_entry, *entry = NULL; 266 struct mlx4_promisc_qp *dqp, *tmp_dqp; 267 268 s_steer = &mlx4_priv(dev)->steer[0]; 269 270 /* if qp is not promisc, it cannot be duplicated */ 271 if (!get_promisc_qp(dev, 0, steer, qpn)) 272 return false; 273 274 /* The qp is promisc qp so it is a duplicate on this index 275 * Find the index entry, and remove the duplicate */ 276 list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) { 277 if (tmp_entry->index == index) { 278 entry = tmp_entry; 279 break; 280 } 281 } 282 if (unlikely(!entry)) { 283 mlx4_warn(dev, "Steering entry for index %x is not registered\n", index); 284 return false; 285 } 286 list_for_each_entry_safe(dqp, tmp_dqp, &entry->duplicates, list) { 287 if (dqp->qpn == qpn) { 288 list_del(&dqp->list); 289 kfree(dqp); 290 } 291 } 292 return true; 293 } 294 295 /* I a steering entry contains only promisc QPs, it can be removed. */ 296 static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, 297 enum mlx4_steer_type steer, 298 unsigned int index, u32 tqpn) 299 { 300 struct mlx4_steer *s_steer; 301 struct mlx4_cmd_mailbox *mailbox; 302 struct mlx4_mgm *mgm; 303 struct mlx4_steer_index *entry = NULL, *tmp_entry; 304 u32 qpn; 305 u32 members_count; 306 bool ret = false; 307 int i; 308 309 s_steer = &mlx4_priv(dev)->steer[0]; 310 311 mailbox = mlx4_alloc_cmd_mailbox(dev); 312 if (IS_ERR(mailbox)) 313 return false; 314 mgm = mailbox->buf; 315 316 if (mlx4_READ_ENTRY(dev, index, mailbox)) 317 goto out; 318 members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 319 for (i = 0; i < members_count; i++) { 320 qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; 321 if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) { 322 /* the qp is not promisc, the entry can't be removed */ 323 goto out; 324 } 325 } 326 /* All the qps currently registered for this entry are promiscuous, 327 * Checking for duplicates */ 328 ret = true; 329 list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) { 330 if (entry->index == index) { 331 if (list_empty(&entry->duplicates)) { 332 list_del(&entry->list); 333 kfree(entry); 334 } else { 335 /* This entry contains duplicates so it shouldn't be removed */ 336 ret = false; 337 goto out; 338 } 339 } 340 } 341 342 out: 343 mlx4_free_cmd_mailbox(dev, mailbox); 344 return ret; 345 } 346 347 static int add_promisc_qp(struct mlx4_dev *dev, u8 port, 348 enum mlx4_steer_type steer, u32 qpn) 349 { 350 struct mlx4_steer *s_steer; 351 struct mlx4_cmd_mailbox *mailbox; 352 struct mlx4_mgm *mgm; 353 struct mlx4_steer_index *entry; 354 struct mlx4_promisc_qp *pqp; 355 struct mlx4_promisc_qp *dqp; 356 u32 members_count; 357 u32 prot; 358 int i; 359 bool found; 360 int last_index; 361 int err; 362 struct mlx4_priv *priv = mlx4_priv(dev); 363 364 s_steer = &mlx4_priv(dev)->steer[0]; 365 366 mutex_lock(&priv->mcg_table.mutex); 367 368 if (get_promisc_qp(dev, 0, steer, qpn)) { 369 err = 0; /* Noting to do, already exists */ 370 goto out_mutex; 371 } 372 373 pqp = kmalloc(sizeof *pqp, GFP_KERNEL); 374 if (!pqp) { 375 err = -ENOMEM; 376 goto out_mutex; 377 } 378 pqp->qpn = qpn; 379 380 mailbox = mlx4_alloc_cmd_mailbox(dev); 381 if (IS_ERR(mailbox)) { 382 err = -ENOMEM; 383 goto out_alloc; 384 } 385 mgm = mailbox->buf; 386 387 /* the promisc qp needs to be added for each one of the steering 388 * entries, if it already exists, needs to be added as a duplicate 389 * for this entry */ 390 list_for_each_entry(entry, &s_steer->steer_entries[steer], list) { 391 err = mlx4_READ_ENTRY(dev, entry->index, mailbox); 392 if (err) 393 goto out_mailbox; 394 395 members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 396 prot = be32_to_cpu(mgm->members_count) >> 30; 397 found = false; 398 for (i = 0; i < members_count; i++) { 399 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) { 400 /* Entry already exists, add to duplicates */ 401 dqp = kmalloc(sizeof *dqp, GFP_KERNEL); 402 if (!dqp) 403 goto out_mailbox; 404 dqp->qpn = qpn; 405 list_add_tail(&dqp->list, &entry->duplicates); 406 found = true; 407 } 408 } 409 if (!found) { 410 /* Need to add the qpn to mgm */ 411 if (members_count == dev->caps.num_qp_per_mgm) { 412 /* entry is full */ 413 err = -ENOMEM; 414 goto out_mailbox; 415 } 416 mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK); 417 mgm->members_count = cpu_to_be32(members_count | (prot << 30)); 418 err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox); 419 if (err) 420 goto out_mailbox; 421 } 422 last_index = entry->index; 423 } 424 425 /* add the new qpn to list of promisc qps */ 426 list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]); 427 /* now need to add all the promisc qps to default entry */ 428 memset(mgm, 0, sizeof *mgm); 429 members_count = 0; 430 list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) 431 mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); 432 mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); 433 434 err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox); 435 if (err) 436 goto out_list; 437 438 mlx4_free_cmd_mailbox(dev, mailbox); 439 mutex_unlock(&priv->mcg_table.mutex); 440 return 0; 441 442 out_list: 443 list_del(&pqp->list); 444 out_mailbox: 445 mlx4_free_cmd_mailbox(dev, mailbox); 446 out_alloc: 447 kfree(pqp); 448 out_mutex: 449 mutex_unlock(&priv->mcg_table.mutex); 450 return err; 451 } 452 453 static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, 454 enum mlx4_steer_type steer, u32 qpn) 455 { 456 struct mlx4_priv *priv = mlx4_priv(dev); 457 struct mlx4_steer *s_steer; 458 struct mlx4_cmd_mailbox *mailbox; 459 struct mlx4_mgm *mgm; 460 struct mlx4_steer_index *entry; 461 struct mlx4_promisc_qp *pqp; 462 struct mlx4_promisc_qp *dqp; 463 u32 members_count; 464 bool found; 465 bool back_to_list = false; 466 int loc, i; 467 int err; 468 469 s_steer = &mlx4_priv(dev)->steer[0]; 470 mutex_lock(&priv->mcg_table.mutex); 471 472 pqp = get_promisc_qp(dev, 0, steer, qpn); 473 if (unlikely(!pqp)) { 474 mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); 475 /* nothing to do */ 476 err = 0; 477 goto out_mutex; 478 } 479 480 /*remove from list of promisc qps */ 481 list_del(&pqp->list); 482 483 /* set the default entry not to include the removed one */ 484 mailbox = mlx4_alloc_cmd_mailbox(dev); 485 if (IS_ERR(mailbox)) { 486 err = -ENOMEM; 487 back_to_list = true; 488 goto out_list; 489 } 490 mgm = mailbox->buf; 491 memset(mgm, 0, sizeof *mgm); 492 members_count = 0; 493 list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) 494 mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); 495 mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); 496 497 err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox); 498 if (err) 499 goto out_mailbox; 500 501 /* remove the qp from all the steering entries*/ 502 list_for_each_entry(entry, &s_steer->steer_entries[steer], list) { 503 found = false; 504 list_for_each_entry(dqp, &entry->duplicates, list) { 505 if (dqp->qpn == qpn) { 506 found = true; 507 break; 508 } 509 } 510 if (found) { 511 /* a duplicate, no need to change the mgm, 512 * only update the duplicates list */ 513 list_del(&dqp->list); 514 kfree(dqp); 515 } else { 516 err = mlx4_READ_ENTRY(dev, entry->index, mailbox); 517 if (err) 518 goto out_mailbox; 519 members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 520 for (loc = -1, i = 0; i < members_count; ++i) 521 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) 522 loc = i; 523 524 mgm->members_count = cpu_to_be32(--members_count | 525 (MLX4_PROT_ETH << 30)); 526 mgm->qp[loc] = mgm->qp[i - 1]; 527 mgm->qp[i - 1] = 0; 528 529 err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox); 530 if (err) 531 goto out_mailbox; 532 } 533 534 } 535 536 out_mailbox: 537 mlx4_free_cmd_mailbox(dev, mailbox); 538 out_list: 539 if (back_to_list) 540 list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]); 541 else 542 kfree(pqp); 543 out_mutex: 544 mutex_unlock(&priv->mcg_table.mutex); 545 return err; 546 } 547 548 /* 549 * Caller must hold MCG table semaphore. gid and mgm parameters must 550 * be properly aligned for command interface. 551 * 552 * Returns 0 unless a firmware command error occurs. 553 * 554 * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1 555 * and *mgm holds MGM entry. 556 * 557 * if GID is found in AMGM, *index = index in AMGM, *prev = index of 558 * previous entry in hash chain and *mgm holds AMGM entry. 559 * 560 * If no AMGM exists for given gid, *index = -1, *prev = index of last 561 * entry in hash chain and *mgm holds end of hash chain. 562 */ 563 static int find_entry(struct mlx4_dev *dev, u8 port, 564 u8 *gid, enum mlx4_protocol prot, 565 enum mlx4_steer_type steer, 566 struct mlx4_cmd_mailbox *mgm_mailbox, 567 u16 *hash, int *prev, int *index) 568 { 569 struct mlx4_cmd_mailbox *mailbox; 570 struct mlx4_mgm *mgm = mgm_mailbox->buf; 571 u8 *mgid; 572 int err; 573 u8 op_mod = (prot == MLX4_PROT_ETH) ? 574 !!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) : 0; 575 576 mailbox = mlx4_alloc_cmd_mailbox(dev); 577 if (IS_ERR(mailbox)) 578 return -ENOMEM; 579 mgid = mailbox->buf; 580 581 memcpy(mgid, gid, 16); 582 583 err = mlx4_GID_HASH(dev, mailbox, hash, op_mod); 584 mlx4_free_cmd_mailbox(dev, mailbox); 585 if (err) 586 return err; 587 588 if (0) 589 mlx4_dbg(dev, "Hash for %pI6 is %04x\n", gid, *hash); 590 591 *index = *hash; 592 *prev = -1; 593 594 do { 595 err = mlx4_READ_ENTRY(dev, *index, mgm_mailbox); 596 if (err) 597 return err; 598 599 if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) { 600 if (*index != *hash) { 601 mlx4_err(dev, "Found zero MGID in AMGM.\n"); 602 err = -EINVAL; 603 } 604 return err; 605 } 606 607 if (!memcmp(mgm->gid, gid, 16) && 608 be32_to_cpu(mgm->members_count) >> 30 == prot) 609 return err; 610 611 *prev = *index; 612 *index = be32_to_cpu(mgm->next_gid_index) >> 6; 613 } while (*index); 614 615 *index = -1; 616 return err; 617 } 618 619 int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 620 int block_mcast_loopback, enum mlx4_protocol prot, 621 enum mlx4_steer_type steer) 622 { 623 struct mlx4_priv *priv = mlx4_priv(dev); 624 struct mlx4_cmd_mailbox *mailbox; 625 struct mlx4_mgm *mgm; 626 u32 members_count; 627 u16 hash; 628 int index, prev; 629 int link = 0; 630 int i; 631 int err; 632 u8 port = gid[5]; 633 u8 new_entry = 0; 634 635 mailbox = mlx4_alloc_cmd_mailbox(dev); 636 if (IS_ERR(mailbox)) 637 return PTR_ERR(mailbox); 638 mgm = mailbox->buf; 639 640 mutex_lock(&priv->mcg_table.mutex); 641 err = find_entry(dev, port, gid, prot, steer, 642 mailbox, &hash, &prev, &index); 643 if (err) 644 goto out; 645 646 if (index != -1) { 647 if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) { 648 new_entry = 1; 649 memcpy(mgm->gid, gid, 16); 650 } 651 } else { 652 link = 1; 653 654 index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap); 655 if (index == -1) { 656 mlx4_err(dev, "No AMGM entries left\n"); 657 err = -ENOMEM; 658 goto out; 659 } 660 index += dev->caps.num_mgms; 661 662 new_entry = 1; 663 memset(mgm, 0, sizeof *mgm); 664 memcpy(mgm->gid, gid, 16); 665 } 666 667 members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 668 if (members_count == dev->caps.num_qp_per_mgm) { 669 mlx4_err(dev, "MGM at index %x is full.\n", index); 670 err = -ENOMEM; 671 goto out; 672 } 673 674 for (i = 0; i < members_count; ++i) 675 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) { 676 mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn); 677 err = 0; 678 goto out; 679 } 680 681 if (block_mcast_loopback) 682 mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) | 683 (1U << MGM_BLCK_LB_BIT)); 684 else 685 mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK); 686 687 mgm->members_count = cpu_to_be32(members_count | (u32) prot << 30); 688 689 err = mlx4_WRITE_ENTRY(dev, index, mailbox); 690 if (err) 691 goto out; 692 693 if (!link) 694 goto out; 695 696 err = mlx4_READ_ENTRY(dev, prev, mailbox); 697 if (err) 698 goto out; 699 700 mgm->next_gid_index = cpu_to_be32(index << 6); 701 702 err = mlx4_WRITE_ENTRY(dev, prev, mailbox); 703 if (err) 704 goto out; 705 706 out: 707 if (prot == MLX4_PROT_ETH) { 708 /* manage the steering entry for promisc mode */ 709 if (new_entry) 710 new_steering_entry(dev, port, steer, index, qp->qpn); 711 else 712 existing_steering_entry(dev, port, steer, 713 index, qp->qpn); 714 } 715 if (err && link && index != -1) { 716 if (index < dev->caps.num_mgms) 717 mlx4_warn(dev, "Got AMGM index %d < %d", 718 index, dev->caps.num_mgms); 719 else 720 mlx4_bitmap_free(&priv->mcg_table.bitmap, 721 index - dev->caps.num_mgms); 722 } 723 mutex_unlock(&priv->mcg_table.mutex); 724 725 mlx4_free_cmd_mailbox(dev, mailbox); 726 return err; 727 } 728 729 int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 730 enum mlx4_protocol prot, enum mlx4_steer_type steer) 731 { 732 struct mlx4_priv *priv = mlx4_priv(dev); 733 struct mlx4_cmd_mailbox *mailbox; 734 struct mlx4_mgm *mgm; 735 u32 members_count; 736 u16 hash; 737 int prev, index; 738 int i, loc; 739 int err; 740 u8 port = gid[5]; 741 bool removed_entry = false; 742 743 mailbox = mlx4_alloc_cmd_mailbox(dev); 744 if (IS_ERR(mailbox)) 745 return PTR_ERR(mailbox); 746 mgm = mailbox->buf; 747 748 mutex_lock(&priv->mcg_table.mutex); 749 750 err = find_entry(dev, port, gid, prot, steer, 751 mailbox, &hash, &prev, &index); 752 if (err) 753 goto out; 754 755 if (index == -1) { 756 mlx4_err(dev, "MGID %pI6 not found\n", gid); 757 err = -EINVAL; 758 goto out; 759 } 760 761 /* if this pq is also a promisc qp, it shouldn't be removed */ 762 if (prot == MLX4_PROT_ETH && 763 check_duplicate_entry(dev, port, steer, index, qp->qpn)) 764 goto out; 765 766 members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 767 for (loc = -1, i = 0; i < members_count; ++i) 768 if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) 769 loc = i; 770 771 if (loc == -1) { 772 mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn); 773 err = -EINVAL; 774 goto out; 775 } 776 777 778 mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30); 779 mgm->qp[loc] = mgm->qp[i - 1]; 780 mgm->qp[i - 1] = 0; 781 782 if (prot == MLX4_PROT_ETH) 783 removed_entry = can_remove_steering_entry(dev, port, steer, 784 index, qp->qpn); 785 if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) { 786 err = mlx4_WRITE_ENTRY(dev, index, mailbox); 787 goto out; 788 } 789 790 /* We are going to delete the entry, members count should be 0 */ 791 mgm->members_count = cpu_to_be32((u32) prot << 30); 792 793 if (prev == -1) { 794 /* Remove entry from MGM */ 795 int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6; 796 if (amgm_index) { 797 err = mlx4_READ_ENTRY(dev, amgm_index, mailbox); 798 if (err) 799 goto out; 800 } else 801 memset(mgm->gid, 0, 16); 802 803 err = mlx4_WRITE_ENTRY(dev, index, mailbox); 804 if (err) 805 goto out; 806 807 if (amgm_index) { 808 if (amgm_index < dev->caps.num_mgms) 809 mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d", 810 index, amgm_index, dev->caps.num_mgms); 811 else 812 mlx4_bitmap_free(&priv->mcg_table.bitmap, 813 amgm_index - dev->caps.num_mgms); 814 } 815 } else { 816 /* Remove entry from AMGM */ 817 int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; 818 err = mlx4_READ_ENTRY(dev, prev, mailbox); 819 if (err) 820 goto out; 821 822 mgm->next_gid_index = cpu_to_be32(cur_next_index << 6); 823 824 err = mlx4_WRITE_ENTRY(dev, prev, mailbox); 825 if (err) 826 goto out; 827 828 if (index < dev->caps.num_mgms) 829 mlx4_warn(dev, "entry %d had next AMGM index %d < %d", 830 prev, index, dev->caps.num_mgms); 831 else 832 mlx4_bitmap_free(&priv->mcg_table.bitmap, 833 index - dev->caps.num_mgms); 834 } 835 836 out: 837 mutex_unlock(&priv->mcg_table.mutex); 838 839 mlx4_free_cmd_mailbox(dev, mailbox); 840 return err; 841 } 842 843 static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp, 844 u8 gid[16], u8 attach, u8 block_loopback, 845 enum mlx4_protocol prot) 846 { 847 struct mlx4_cmd_mailbox *mailbox; 848 int err = 0; 849 int qpn; 850 851 if (!mlx4_is_mfunc(dev)) 852 return -EBADF; 853 854 mailbox = mlx4_alloc_cmd_mailbox(dev); 855 if (IS_ERR(mailbox)) 856 return PTR_ERR(mailbox); 857 858 memcpy(mailbox->buf, gid, 16); 859 qpn = qp->qpn; 860 qpn |= (prot << 28); 861 if (attach && block_loopback) 862 qpn |= (1 << 31); 863 864 err = mlx4_cmd(dev, mailbox->dma, qpn, attach, 865 MLX4_CMD_QP_ATTACH, MLX4_CMD_TIME_CLASS_A, 866 MLX4_CMD_WRAPPED); 867 868 mlx4_free_cmd_mailbox(dev, mailbox); 869 return err; 870 } 871 872 int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 873 int block_mcast_loopback, enum mlx4_protocol prot) 874 { 875 enum mlx4_steer_type steer; 876 877 steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER; 878 879 if (prot == MLX4_PROT_ETH && 880 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) 881 return 0; 882 883 if (prot == MLX4_PROT_ETH) 884 gid[7] |= (steer << 1); 885 886 if (mlx4_is_mfunc(dev)) 887 return mlx4_QP_ATTACH(dev, qp, gid, 1, 888 block_mcast_loopback, prot); 889 890 return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback, 891 prot, steer); 892 } 893 EXPORT_SYMBOL_GPL(mlx4_multicast_attach); 894 895 int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 896 enum mlx4_protocol prot) 897 { 898 enum mlx4_steer_type steer; 899 900 steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER; 901 902 if (prot == MLX4_PROT_ETH && 903 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) 904 return 0; 905 906 if (prot == MLX4_PROT_ETH) 907 gid[7] |= (steer << 1); 908 909 if (mlx4_is_mfunc(dev)) 910 return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); 911 912 return mlx4_qp_detach_common(dev, qp, gid, prot, steer); 913 } 914 EXPORT_SYMBOL_GPL(mlx4_multicast_detach); 915 916 int mlx4_unicast_attach(struct mlx4_dev *dev, 917 struct mlx4_qp *qp, u8 gid[16], 918 int block_mcast_loopback, enum mlx4_protocol prot) 919 { 920 if (prot == MLX4_PROT_ETH && 921 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) 922 return 0; 923 924 if (prot == MLX4_PROT_ETH) 925 gid[7] |= (MLX4_UC_STEER << 1); 926 927 if (mlx4_is_mfunc(dev)) 928 return mlx4_QP_ATTACH(dev, qp, gid, 1, 929 block_mcast_loopback, prot); 930 931 return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback, 932 prot, MLX4_UC_STEER); 933 } 934 EXPORT_SYMBOL_GPL(mlx4_unicast_attach); 935 936 int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, 937 u8 gid[16], enum mlx4_protocol prot) 938 { 939 if (prot == MLX4_PROT_ETH && 940 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) 941 return 0; 942 943 if (prot == MLX4_PROT_ETH) 944 gid[7] |= (MLX4_UC_STEER << 1); 945 946 if (mlx4_is_mfunc(dev)) 947 return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); 948 949 return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_UC_STEER); 950 } 951 EXPORT_SYMBOL_GPL(mlx4_unicast_detach); 952 953 int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave, 954 struct mlx4_vhcr *vhcr, 955 struct mlx4_cmd_mailbox *inbox, 956 struct mlx4_cmd_mailbox *outbox, 957 struct mlx4_cmd_info *cmd) 958 { 959 u32 qpn = (u32) vhcr->in_param & 0xffffffff; 960 u8 port = vhcr->in_param >> 62; 961 enum mlx4_steer_type steer = vhcr->in_modifier; 962 963 /* Promiscuous unicast is not allowed in mfunc */ 964 if (mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER) 965 return 0; 966 967 if (vhcr->op_modifier) 968 return add_promisc_qp(dev, port, steer, qpn); 969 else 970 return remove_promisc_qp(dev, port, steer, qpn); 971 } 972 973 static int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn, 974 enum mlx4_steer_type steer, u8 add, u8 port) 975 { 976 return mlx4_cmd(dev, (u64) qpn | (u64) port << 62, (u32) steer, add, 977 MLX4_CMD_PROMISC, MLX4_CMD_TIME_CLASS_A, 978 MLX4_CMD_WRAPPED); 979 } 980 981 int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) 982 { 983 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) 984 return 0; 985 986 if (mlx4_is_mfunc(dev)) 987 return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port); 988 989 return add_promisc_qp(dev, port, MLX4_MC_STEER, qpn); 990 } 991 EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add); 992 993 int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) 994 { 995 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) 996 return 0; 997 998 if (mlx4_is_mfunc(dev)) 999 return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port); 1000 1001 return remove_promisc_qp(dev, port, MLX4_MC_STEER, qpn); 1002 } 1003 EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove); 1004 1005 int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) 1006 { 1007 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) 1008 return 0; 1009 1010 if (mlx4_is_mfunc(dev)) 1011 return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port); 1012 1013 return add_promisc_qp(dev, port, MLX4_UC_STEER, qpn); 1014 } 1015 EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add); 1016 1017 int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) 1018 { 1019 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) 1020 return 0; 1021 1022 if (mlx4_is_mfunc(dev)) 1023 return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port); 1024 1025 return remove_promisc_qp(dev, port, MLX4_UC_STEER, qpn); 1026 } 1027 EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove); 1028 1029 int mlx4_init_mcg_table(struct mlx4_dev *dev) 1030 { 1031 struct mlx4_priv *priv = mlx4_priv(dev); 1032 int err; 1033 1034 err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms, 1035 dev->caps.num_amgms - 1, 0, 0); 1036 if (err) 1037 return err; 1038 1039 mutex_init(&priv->mcg_table.mutex); 1040 1041 return 0; 1042 } 1043 1044 void mlx4_cleanup_mcg_table(struct mlx4_dev *dev) 1045 { 1046 mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap); 1047 } 1048