1 /* 2 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 3 * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. 4 * All rights reserved. 5 * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. 6 * 7 * This software is available to you under a choice of one of two 8 * licenses. You may choose to be licensed under the terms of the GNU 9 * General Public License (GPL) Version 2, available from the file 10 * COPYING in the main directory of this source tree, or the 11 * OpenIB.org BSD license below: 12 * 13 * Redistribution and use in source and binary forms, with or 14 * without modification, are permitted provided that the following 15 * conditions are met: 16 * 17 * - Redistributions of source code must retain the above 18 * copyright notice, this list of conditions and the following 19 * disclaimer. 20 * 21 * - Redistributions in binary form must reproduce the above 22 * copyright notice, this list of conditions and the following 23 * disclaimer in the documentation and/or other materials 24 * provided with the distribution. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 * SOFTWARE. 34 */ 35 36 #include <linux/sched.h> 37 #include <linux/pci.h> 38 #include <linux/errno.h> 39 #include <linux/kernel.h> 40 #include <linux/io.h> 41 #include <linux/slab.h> 42 #include <linux/mlx4/cmd.h> 43 #include <linux/mlx4/qp.h> 44 45 #include "mlx4.h" 46 #include "fw.h" 47 48 #define MLX4_MAC_VALID (1ull << 63) 49 #define MLX4_MAC_MASK 0x7fffffffffffffffULL 50 #define ETH_ALEN 6 51 52 struct mac_res { 53 struct list_head list; 54 u64 mac; 55 u8 port; 56 }; 57 58 struct res_common { 59 struct list_head list; 60 u32 res_id; 61 int owner; 62 int state; 63 int from_state; 64 int to_state; 65 int removing; 66 }; 67 68 enum { 69 RES_ANY_BUSY = 1 70 }; 71 72 struct res_gid { 73 struct list_head list; 74 u8 gid[16]; 75 enum mlx4_protocol prot; 76 enum mlx4_steer_type steer; 77 }; 78 79 enum res_qp_states { 80 RES_QP_BUSY = RES_ANY_BUSY, 81 82 /* QP number was allocated */ 83 RES_QP_RESERVED, 84 85 /* ICM memory for QP context was mapped */ 86 RES_QP_MAPPED, 87 88 /* QP is in hw ownership */ 89 RES_QP_HW 90 }; 91 92 static inline const char *qp_states_str(enum res_qp_states state) 93 { 94 switch (state) { 95 case RES_QP_BUSY: return "RES_QP_BUSY"; 96 case RES_QP_RESERVED: return "RES_QP_RESERVED"; 97 case RES_QP_MAPPED: return "RES_QP_MAPPED"; 98 case RES_QP_HW: return "RES_QP_HW"; 99 default: return "Unknown"; 100 } 101 } 102 103 struct res_qp { 104 struct res_common com; 105 struct res_mtt *mtt; 106 struct res_cq *rcq; 107 struct res_cq *scq; 108 struct res_srq *srq; 109 struct list_head mcg_list; 110 spinlock_t mcg_spl; 111 int local_qpn; 112 }; 113 114 enum res_mtt_states { 115 RES_MTT_BUSY = RES_ANY_BUSY, 116 RES_MTT_ALLOCATED, 117 }; 118 119 static inline const char *mtt_states_str(enum res_mtt_states state) 120 { 121 switch (state) { 122 case RES_MTT_BUSY: return "RES_MTT_BUSY"; 123 case RES_MTT_ALLOCATED: return "RES_MTT_ALLOCATED"; 124 default: return "Unknown"; 125 } 126 } 127 128 struct res_mtt { 129 struct res_common com; 130 int order; 131 atomic_t ref_count; 132 }; 133 134 enum res_mpt_states { 135 RES_MPT_BUSY = RES_ANY_BUSY, 136 RES_MPT_RESERVED, 137 RES_MPT_MAPPED, 138 RES_MPT_HW, 139 }; 140 141 struct res_mpt { 142 struct res_common com; 143 struct res_mtt *mtt; 144 int key; 145 }; 146 147 enum res_eq_states { 148 RES_EQ_BUSY = RES_ANY_BUSY, 149 RES_EQ_RESERVED, 150 RES_EQ_HW, 151 }; 152 153 struct res_eq { 154 struct res_common com; 155 struct res_mtt *mtt; 156 }; 157 158 enum res_cq_states { 159 RES_CQ_BUSY = RES_ANY_BUSY, 160 RES_CQ_ALLOCATED, 161 RES_CQ_HW, 162 }; 163 164 struct res_cq { 165 struct res_common com; 166 struct res_mtt *mtt; 167 atomic_t ref_count; 168 }; 169 170 enum res_srq_states { 171 RES_SRQ_BUSY = RES_ANY_BUSY, 172 RES_SRQ_ALLOCATED, 173 RES_SRQ_HW, 174 }; 175 176 static inline const char *srq_states_str(enum res_srq_states state) 177 { 178 switch (state) { 179 case RES_SRQ_BUSY: return "RES_SRQ_BUSY"; 180 case RES_SRQ_ALLOCATED: return "RES_SRQ_ALLOCATED"; 181 case RES_SRQ_HW: return "RES_SRQ_HW"; 182 default: return "Unknown"; 183 } 184 } 185 186 struct res_srq { 187 struct res_common com; 188 struct res_mtt *mtt; 189 struct res_cq *cq; 190 atomic_t ref_count; 191 }; 192 193 enum res_counter_states { 194 RES_COUNTER_BUSY = RES_ANY_BUSY, 195 RES_COUNTER_ALLOCATED, 196 }; 197 198 static inline const char *counter_states_str(enum res_counter_states state) 199 { 200 switch (state) { 201 case RES_COUNTER_BUSY: return "RES_COUNTER_BUSY"; 202 case RES_COUNTER_ALLOCATED: return "RES_COUNTER_ALLOCATED"; 203 default: return "Unknown"; 204 } 205 } 206 207 struct res_counter { 208 struct res_common com; 209 int port; 210 }; 211 212 /* For Debug uses */ 213 static const char *ResourceType(enum mlx4_resource rt) 214 { 215 switch (rt) { 216 case RES_QP: return "RES_QP"; 217 case RES_CQ: return "RES_CQ"; 218 case RES_SRQ: return "RES_SRQ"; 219 case RES_MPT: return "RES_MPT"; 220 case RES_MTT: return "RES_MTT"; 221 case RES_MAC: return "RES_MAC"; 222 case RES_EQ: return "RES_EQ"; 223 case RES_COUNTER: return "RES_COUNTER"; 224 default: return "Unknown resource type !!!"; 225 }; 226 } 227 228 int mlx4_init_resource_tracker(struct mlx4_dev *dev) 229 { 230 struct mlx4_priv *priv = mlx4_priv(dev); 231 int i; 232 int t; 233 234 priv->mfunc.master.res_tracker.slave_list = 235 kzalloc(dev->num_slaves * sizeof(struct slave_list), 236 GFP_KERNEL); 237 if (!priv->mfunc.master.res_tracker.slave_list) 238 return -ENOMEM; 239 240 for (i = 0 ; i < dev->num_slaves; i++) { 241 for (t = 0; t < MLX4_NUM_OF_RESOURCE_TYPE; ++t) 242 INIT_LIST_HEAD(&priv->mfunc.master.res_tracker. 243 slave_list[i].res_list[t]); 244 mutex_init(&priv->mfunc.master.res_tracker.slave_list[i].mutex); 245 } 246 247 mlx4_dbg(dev, "Started init_resource_tracker: %ld slaves\n", 248 dev->num_slaves); 249 for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) 250 INIT_RADIX_TREE(&priv->mfunc.master.res_tracker.res_tree[i], 251 GFP_ATOMIC|__GFP_NOWARN); 252 253 spin_lock_init(&priv->mfunc.master.res_tracker.lock); 254 return 0 ; 255 } 256 257 void mlx4_free_resource_tracker(struct mlx4_dev *dev) 258 { 259 struct mlx4_priv *priv = mlx4_priv(dev); 260 int i; 261 262 if (priv->mfunc.master.res_tracker.slave_list) { 263 for (i = 0 ; i < dev->num_slaves; i++) 264 mlx4_delete_all_resources_for_slave(dev, i); 265 266 kfree(priv->mfunc.master.res_tracker.slave_list); 267 } 268 } 269 270 static void update_ud_gid(struct mlx4_dev *dev, 271 struct mlx4_qp_context *qp_ctx, u8 slave) 272 { 273 u32 ts = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff; 274 275 if (MLX4_QP_ST_UD == ts) 276 qp_ctx->pri_path.mgid_index = 0x80 | slave; 277 278 mlx4_dbg(dev, "slave %d, new gid index: 0x%x ", 279 slave, qp_ctx->pri_path.mgid_index); 280 } 281 282 static int mpt_mask(struct mlx4_dev *dev) 283 { 284 return dev->caps.num_mpts - 1; 285 } 286 287 static void *find_res(struct mlx4_dev *dev, int res_id, 288 enum mlx4_resource type) 289 { 290 struct mlx4_priv *priv = mlx4_priv(dev); 291 292 return radix_tree_lookup(&priv->mfunc.master.res_tracker.res_tree[type], 293 res_id); 294 } 295 296 static int get_res(struct mlx4_dev *dev, int slave, int res_id, 297 enum mlx4_resource type, 298 void *res) 299 { 300 struct res_common *r; 301 int err = 0; 302 303 spin_lock_irq(mlx4_tlock(dev)); 304 r = find_res(dev, res_id, type); 305 if (!r) { 306 err = -ENONET; 307 goto exit; 308 } 309 310 if (r->state == RES_ANY_BUSY) { 311 err = -EBUSY; 312 goto exit; 313 } 314 315 if (r->owner != slave) { 316 err = -EPERM; 317 goto exit; 318 } 319 320 r->from_state = r->state; 321 r->state = RES_ANY_BUSY; 322 mlx4_dbg(dev, "res %s id 0x%x to busy\n", 323 ResourceType(type), r->res_id); 324 325 if (res) 326 *((struct res_common **)res) = r; 327 328 exit: 329 spin_unlock_irq(mlx4_tlock(dev)); 330 return err; 331 } 332 333 int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev, 334 enum mlx4_resource type, 335 int res_id, int *slave) 336 { 337 338 struct res_common *r; 339 int err = -ENOENT; 340 int id = res_id; 341 342 if (type == RES_QP) 343 id &= 0x7fffff; 344 spin_lock(mlx4_tlock(dev)); 345 346 r = find_res(dev, id, type); 347 if (r) { 348 *slave = r->owner; 349 err = 0; 350 } 351 spin_unlock(mlx4_tlock(dev)); 352 353 return err; 354 } 355 356 static void put_res(struct mlx4_dev *dev, int slave, int res_id, 357 enum mlx4_resource type) 358 { 359 struct res_common *r; 360 361 spin_lock_irq(mlx4_tlock(dev)); 362 r = find_res(dev, res_id, type); 363 if (r) 364 r->state = r->from_state; 365 spin_unlock_irq(mlx4_tlock(dev)); 366 } 367 368 static struct res_common *alloc_qp_tr(int id) 369 { 370 struct res_qp *ret; 371 372 ret = kzalloc(sizeof *ret, GFP_KERNEL); 373 if (!ret) 374 return NULL; 375 376 ret->com.res_id = id; 377 ret->com.state = RES_QP_RESERVED; 378 ret->local_qpn = id; 379 INIT_LIST_HEAD(&ret->mcg_list); 380 spin_lock_init(&ret->mcg_spl); 381 382 return &ret->com; 383 } 384 385 static struct res_common *alloc_mtt_tr(int id, int order) 386 { 387 struct res_mtt *ret; 388 389 ret = kzalloc(sizeof *ret, GFP_KERNEL); 390 if (!ret) 391 return NULL; 392 393 ret->com.res_id = id; 394 ret->order = order; 395 ret->com.state = RES_MTT_ALLOCATED; 396 atomic_set(&ret->ref_count, 0); 397 398 return &ret->com; 399 } 400 401 static struct res_common *alloc_mpt_tr(int id, int key) 402 { 403 struct res_mpt *ret; 404 405 ret = kzalloc(sizeof *ret, GFP_KERNEL); 406 if (!ret) 407 return NULL; 408 409 ret->com.res_id = id; 410 ret->com.state = RES_MPT_RESERVED; 411 ret->key = key; 412 413 return &ret->com; 414 } 415 416 static struct res_common *alloc_eq_tr(int id) 417 { 418 struct res_eq *ret; 419 420 ret = kzalloc(sizeof *ret, GFP_KERNEL); 421 if (!ret) 422 return NULL; 423 424 ret->com.res_id = id; 425 ret->com.state = RES_EQ_RESERVED; 426 427 return &ret->com; 428 } 429 430 static struct res_common *alloc_cq_tr(int id) 431 { 432 struct res_cq *ret; 433 434 ret = kzalloc(sizeof *ret, GFP_KERNEL); 435 if (!ret) 436 return NULL; 437 438 ret->com.res_id = id; 439 ret->com.state = RES_CQ_ALLOCATED; 440 atomic_set(&ret->ref_count, 0); 441 442 return &ret->com; 443 } 444 445 static struct res_common *alloc_srq_tr(int id) 446 { 447 struct res_srq *ret; 448 449 ret = kzalloc(sizeof *ret, GFP_KERNEL); 450 if (!ret) 451 return NULL; 452 453 ret->com.res_id = id; 454 ret->com.state = RES_SRQ_ALLOCATED; 455 atomic_set(&ret->ref_count, 0); 456 457 return &ret->com; 458 } 459 460 static struct res_common *alloc_counter_tr(int id) 461 { 462 struct res_counter *ret; 463 464 ret = kzalloc(sizeof *ret, GFP_KERNEL); 465 if (!ret) 466 return NULL; 467 468 ret->com.res_id = id; 469 ret->com.state = RES_COUNTER_ALLOCATED; 470 471 return &ret->com; 472 } 473 474 static struct res_common *alloc_tr(int id, enum mlx4_resource type, int slave, 475 int extra) 476 { 477 struct res_common *ret; 478 479 switch (type) { 480 case RES_QP: 481 ret = alloc_qp_tr(id); 482 break; 483 case RES_MPT: 484 ret = alloc_mpt_tr(id, extra); 485 break; 486 case RES_MTT: 487 ret = alloc_mtt_tr(id, extra); 488 break; 489 case RES_EQ: 490 ret = alloc_eq_tr(id); 491 break; 492 case RES_CQ: 493 ret = alloc_cq_tr(id); 494 break; 495 case RES_SRQ: 496 ret = alloc_srq_tr(id); 497 break; 498 case RES_MAC: 499 printk(KERN_ERR "implementation missing\n"); 500 return NULL; 501 case RES_COUNTER: 502 ret = alloc_counter_tr(id); 503 break; 504 505 default: 506 return NULL; 507 } 508 if (ret) 509 ret->owner = slave; 510 511 return ret; 512 } 513 514 static int add_res_range(struct mlx4_dev *dev, int slave, int base, int count, 515 enum mlx4_resource type, int extra) 516 { 517 int i; 518 int err; 519 struct mlx4_priv *priv = mlx4_priv(dev); 520 struct res_common **res_arr; 521 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 522 struct radix_tree_root *root = &tracker->res_tree[type]; 523 524 res_arr = kzalloc(count * sizeof *res_arr, GFP_KERNEL); 525 if (!res_arr) 526 return -ENOMEM; 527 528 for (i = 0; i < count; ++i) { 529 res_arr[i] = alloc_tr(base + i, type, slave, extra); 530 if (!res_arr[i]) { 531 for (--i; i >= 0; --i) 532 kfree(res_arr[i]); 533 534 kfree(res_arr); 535 return -ENOMEM; 536 } 537 } 538 539 spin_lock_irq(mlx4_tlock(dev)); 540 for (i = 0; i < count; ++i) { 541 if (find_res(dev, base + i, type)) { 542 err = -EEXIST; 543 goto undo; 544 } 545 err = radix_tree_insert(root, base + i, res_arr[i]); 546 if (err) 547 goto undo; 548 list_add_tail(&res_arr[i]->list, 549 &tracker->slave_list[slave].res_list[type]); 550 } 551 spin_unlock_irq(mlx4_tlock(dev)); 552 kfree(res_arr); 553 554 return 0; 555 556 undo: 557 for (--i; i >= base; --i) 558 radix_tree_delete(&tracker->res_tree[type], i); 559 560 spin_unlock_irq(mlx4_tlock(dev)); 561 562 for (i = 0; i < count; ++i) 563 kfree(res_arr[i]); 564 565 kfree(res_arr); 566 567 return err; 568 } 569 570 static int remove_qp_ok(struct res_qp *res) 571 { 572 if (res->com.state == RES_QP_BUSY) 573 return -EBUSY; 574 else if (res->com.state != RES_QP_RESERVED) 575 return -EPERM; 576 577 return 0; 578 } 579 580 static int remove_mtt_ok(struct res_mtt *res, int order) 581 { 582 if (res->com.state == RES_MTT_BUSY || 583 atomic_read(&res->ref_count)) { 584 printk(KERN_DEBUG "%s-%d: state %s, ref_count %d\n", 585 __func__, __LINE__, 586 mtt_states_str(res->com.state), 587 atomic_read(&res->ref_count)); 588 return -EBUSY; 589 } else if (res->com.state != RES_MTT_ALLOCATED) 590 return -EPERM; 591 else if (res->order != order) 592 return -EINVAL; 593 594 return 0; 595 } 596 597 static int remove_mpt_ok(struct res_mpt *res) 598 { 599 if (res->com.state == RES_MPT_BUSY) 600 return -EBUSY; 601 else if (res->com.state != RES_MPT_RESERVED) 602 return -EPERM; 603 604 return 0; 605 } 606 607 static int remove_eq_ok(struct res_eq *res) 608 { 609 if (res->com.state == RES_MPT_BUSY) 610 return -EBUSY; 611 else if (res->com.state != RES_MPT_RESERVED) 612 return -EPERM; 613 614 return 0; 615 } 616 617 static int remove_counter_ok(struct res_counter *res) 618 { 619 if (res->com.state == RES_COUNTER_BUSY) 620 return -EBUSY; 621 else if (res->com.state != RES_COUNTER_ALLOCATED) 622 return -EPERM; 623 624 return 0; 625 } 626 627 static int remove_cq_ok(struct res_cq *res) 628 { 629 if (res->com.state == RES_CQ_BUSY) 630 return -EBUSY; 631 else if (res->com.state != RES_CQ_ALLOCATED) 632 return -EPERM; 633 634 return 0; 635 } 636 637 static int remove_srq_ok(struct res_srq *res) 638 { 639 if (res->com.state == RES_SRQ_BUSY) 640 return -EBUSY; 641 else if (res->com.state != RES_SRQ_ALLOCATED) 642 return -EPERM; 643 644 return 0; 645 } 646 647 static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra) 648 { 649 switch (type) { 650 case RES_QP: 651 return remove_qp_ok((struct res_qp *)res); 652 case RES_CQ: 653 return remove_cq_ok((struct res_cq *)res); 654 case RES_SRQ: 655 return remove_srq_ok((struct res_srq *)res); 656 case RES_MPT: 657 return remove_mpt_ok((struct res_mpt *)res); 658 case RES_MTT: 659 return remove_mtt_ok((struct res_mtt *)res, extra); 660 case RES_MAC: 661 return -ENOSYS; 662 case RES_EQ: 663 return remove_eq_ok((struct res_eq *)res); 664 case RES_COUNTER: 665 return remove_counter_ok((struct res_counter *)res); 666 default: 667 return -EINVAL; 668 } 669 } 670 671 static int rem_res_range(struct mlx4_dev *dev, int slave, int base, int count, 672 enum mlx4_resource type, int extra) 673 { 674 int i; 675 int err; 676 struct mlx4_priv *priv = mlx4_priv(dev); 677 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 678 struct res_common *r; 679 680 spin_lock_irq(mlx4_tlock(dev)); 681 for (i = base; i < base + count; ++i) { 682 r = radix_tree_lookup(&tracker->res_tree[type], i); 683 if (!r) { 684 err = -ENOENT; 685 goto out; 686 } 687 if (r->owner != slave) { 688 err = -EPERM; 689 goto out; 690 } 691 err = remove_ok(r, type, extra); 692 if (err) 693 goto out; 694 } 695 696 for (i = base; i < base + count; ++i) { 697 r = radix_tree_lookup(&tracker->res_tree[type], i); 698 radix_tree_delete(&tracker->res_tree[type], i); 699 list_del(&r->list); 700 kfree(r); 701 } 702 err = 0; 703 704 out: 705 spin_unlock_irq(mlx4_tlock(dev)); 706 707 return err; 708 } 709 710 static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn, 711 enum res_qp_states state, struct res_qp **qp, 712 int alloc) 713 { 714 struct mlx4_priv *priv = mlx4_priv(dev); 715 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 716 struct res_qp *r; 717 int err = 0; 718 719 spin_lock_irq(mlx4_tlock(dev)); 720 r = radix_tree_lookup(&tracker->res_tree[RES_QP], qpn); 721 if (!r) 722 err = -ENOENT; 723 else if (r->com.owner != slave) 724 err = -EPERM; 725 else { 726 switch (state) { 727 case RES_QP_BUSY: 728 mlx4_dbg(dev, "%s: failed RES_QP, 0x%x\n", 729 __func__, r->com.res_id); 730 err = -EBUSY; 731 break; 732 733 case RES_QP_RESERVED: 734 if (r->com.state == RES_QP_MAPPED && !alloc) 735 break; 736 737 mlx4_dbg(dev, "failed RES_QP, 0x%x\n", r->com.res_id); 738 err = -EINVAL; 739 break; 740 741 case RES_QP_MAPPED: 742 if ((r->com.state == RES_QP_RESERVED && alloc) || 743 r->com.state == RES_QP_HW) 744 break; 745 else { 746 mlx4_dbg(dev, "failed RES_QP, 0x%x\n", 747 r->com.res_id); 748 err = -EINVAL; 749 } 750 751 break; 752 753 case RES_QP_HW: 754 if (r->com.state != RES_QP_MAPPED) 755 err = -EINVAL; 756 break; 757 default: 758 err = -EINVAL; 759 } 760 761 if (!err) { 762 r->com.from_state = r->com.state; 763 r->com.to_state = state; 764 r->com.state = RES_QP_BUSY; 765 if (qp) 766 *qp = (struct res_qp *)r; 767 } 768 } 769 770 spin_unlock_irq(mlx4_tlock(dev)); 771 772 return err; 773 } 774 775 static int mr_res_start_move_to(struct mlx4_dev *dev, int slave, int index, 776 enum res_mpt_states state, struct res_mpt **mpt) 777 { 778 struct mlx4_priv *priv = mlx4_priv(dev); 779 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 780 struct res_mpt *r; 781 int err = 0; 782 783 spin_lock_irq(mlx4_tlock(dev)); 784 r = radix_tree_lookup(&tracker->res_tree[RES_MPT], index); 785 if (!r) 786 err = -ENOENT; 787 else if (r->com.owner != slave) 788 err = -EPERM; 789 else { 790 switch (state) { 791 case RES_MPT_BUSY: 792 err = -EINVAL; 793 break; 794 795 case RES_MPT_RESERVED: 796 if (r->com.state != RES_MPT_MAPPED) 797 err = -EINVAL; 798 break; 799 800 case RES_MPT_MAPPED: 801 if (r->com.state != RES_MPT_RESERVED && 802 r->com.state != RES_MPT_HW) 803 err = -EINVAL; 804 break; 805 806 case RES_MPT_HW: 807 if (r->com.state != RES_MPT_MAPPED) 808 err = -EINVAL; 809 break; 810 default: 811 err = -EINVAL; 812 } 813 814 if (!err) { 815 r->com.from_state = r->com.state; 816 r->com.to_state = state; 817 r->com.state = RES_MPT_BUSY; 818 if (mpt) 819 *mpt = (struct res_mpt *)r; 820 } 821 } 822 823 spin_unlock_irq(mlx4_tlock(dev)); 824 825 return err; 826 } 827 828 static int eq_res_start_move_to(struct mlx4_dev *dev, int slave, int index, 829 enum res_eq_states state, struct res_eq **eq) 830 { 831 struct mlx4_priv *priv = mlx4_priv(dev); 832 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 833 struct res_eq *r; 834 int err = 0; 835 836 spin_lock_irq(mlx4_tlock(dev)); 837 r = radix_tree_lookup(&tracker->res_tree[RES_EQ], index); 838 if (!r) 839 err = -ENOENT; 840 else if (r->com.owner != slave) 841 err = -EPERM; 842 else { 843 switch (state) { 844 case RES_EQ_BUSY: 845 err = -EINVAL; 846 break; 847 848 case RES_EQ_RESERVED: 849 if (r->com.state != RES_EQ_HW) 850 err = -EINVAL; 851 break; 852 853 case RES_EQ_HW: 854 if (r->com.state != RES_EQ_RESERVED) 855 err = -EINVAL; 856 break; 857 858 default: 859 err = -EINVAL; 860 } 861 862 if (!err) { 863 r->com.from_state = r->com.state; 864 r->com.to_state = state; 865 r->com.state = RES_EQ_BUSY; 866 if (eq) 867 *eq = r; 868 } 869 } 870 871 spin_unlock_irq(mlx4_tlock(dev)); 872 873 return err; 874 } 875 876 static int cq_res_start_move_to(struct mlx4_dev *dev, int slave, int cqn, 877 enum res_cq_states state, struct res_cq **cq) 878 { 879 struct mlx4_priv *priv = mlx4_priv(dev); 880 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 881 struct res_cq *r; 882 int err; 883 884 spin_lock_irq(mlx4_tlock(dev)); 885 r = radix_tree_lookup(&tracker->res_tree[RES_CQ], cqn); 886 if (!r) 887 err = -ENOENT; 888 else if (r->com.owner != slave) 889 err = -EPERM; 890 else { 891 switch (state) { 892 case RES_CQ_BUSY: 893 err = -EBUSY; 894 break; 895 896 case RES_CQ_ALLOCATED: 897 if (r->com.state != RES_CQ_HW) 898 err = -EINVAL; 899 else if (atomic_read(&r->ref_count)) 900 err = -EBUSY; 901 else 902 err = 0; 903 break; 904 905 case RES_CQ_HW: 906 if (r->com.state != RES_CQ_ALLOCATED) 907 err = -EINVAL; 908 else 909 err = 0; 910 break; 911 912 default: 913 err = -EINVAL; 914 } 915 916 if (!err) { 917 r->com.from_state = r->com.state; 918 r->com.to_state = state; 919 r->com.state = RES_CQ_BUSY; 920 if (cq) 921 *cq = r; 922 } 923 } 924 925 spin_unlock_irq(mlx4_tlock(dev)); 926 927 return err; 928 } 929 930 static int srq_res_start_move_to(struct mlx4_dev *dev, int slave, int index, 931 enum res_cq_states state, struct res_srq **srq) 932 { 933 struct mlx4_priv *priv = mlx4_priv(dev); 934 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 935 struct res_srq *r; 936 int err = 0; 937 938 spin_lock_irq(mlx4_tlock(dev)); 939 r = radix_tree_lookup(&tracker->res_tree[RES_SRQ], index); 940 if (!r) 941 err = -ENOENT; 942 else if (r->com.owner != slave) 943 err = -EPERM; 944 else { 945 switch (state) { 946 case RES_SRQ_BUSY: 947 err = -EINVAL; 948 break; 949 950 case RES_SRQ_ALLOCATED: 951 if (r->com.state != RES_SRQ_HW) 952 err = -EINVAL; 953 else if (atomic_read(&r->ref_count)) 954 err = -EBUSY; 955 break; 956 957 case RES_SRQ_HW: 958 if (r->com.state != RES_SRQ_ALLOCATED) 959 err = -EINVAL; 960 break; 961 962 default: 963 err = -EINVAL; 964 } 965 966 if (!err) { 967 r->com.from_state = r->com.state; 968 r->com.to_state = state; 969 r->com.state = RES_SRQ_BUSY; 970 if (srq) 971 *srq = r; 972 } 973 } 974 975 spin_unlock_irq(mlx4_tlock(dev)); 976 977 return err; 978 } 979 980 static void res_abort_move(struct mlx4_dev *dev, int slave, 981 enum mlx4_resource type, int id) 982 { 983 struct mlx4_priv *priv = mlx4_priv(dev); 984 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 985 struct res_common *r; 986 987 spin_lock_irq(mlx4_tlock(dev)); 988 r = radix_tree_lookup(&tracker->res_tree[type], id); 989 if (r && (r->owner == slave)) 990 r->state = r->from_state; 991 spin_unlock_irq(mlx4_tlock(dev)); 992 } 993 994 static void res_end_move(struct mlx4_dev *dev, int slave, 995 enum mlx4_resource type, int id) 996 { 997 struct mlx4_priv *priv = mlx4_priv(dev); 998 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 999 struct res_common *r; 1000 1001 spin_lock_irq(mlx4_tlock(dev)); 1002 r = radix_tree_lookup(&tracker->res_tree[type], id); 1003 if (r && (r->owner == slave)) 1004 r->state = r->to_state; 1005 spin_unlock_irq(mlx4_tlock(dev)); 1006 } 1007 1008 static int valid_reserved(struct mlx4_dev *dev, int slave, int qpn) 1009 { 1010 return mlx4_is_qp_reserved(dev, qpn); 1011 } 1012 1013 static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1014 u64 in_param, u64 *out_param) 1015 { 1016 int err; 1017 int count; 1018 int align; 1019 int base; 1020 int qpn; 1021 1022 switch (op) { 1023 case RES_OP_RESERVE: 1024 count = get_param_l(&in_param); 1025 align = get_param_h(&in_param); 1026 err = __mlx4_qp_reserve_range(dev, count, align, &base); 1027 if (err) 1028 return err; 1029 1030 err = add_res_range(dev, slave, base, count, RES_QP, 0); 1031 if (err) { 1032 __mlx4_qp_release_range(dev, base, count); 1033 return err; 1034 } 1035 set_param_l(out_param, base); 1036 break; 1037 case RES_OP_MAP_ICM: 1038 qpn = get_param_l(&in_param) & 0x7fffff; 1039 if (valid_reserved(dev, slave, qpn)) { 1040 err = add_res_range(dev, slave, qpn, 1, RES_QP, 0); 1041 if (err) 1042 return err; 1043 } 1044 1045 err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED, 1046 NULL, 1); 1047 if (err) 1048 return err; 1049 1050 if (!valid_reserved(dev, slave, qpn)) { 1051 err = __mlx4_qp_alloc_icm(dev, qpn); 1052 if (err) { 1053 res_abort_move(dev, slave, RES_QP, qpn); 1054 return err; 1055 } 1056 } 1057 1058 res_end_move(dev, slave, RES_QP, qpn); 1059 break; 1060 1061 default: 1062 err = -EINVAL; 1063 break; 1064 } 1065 return err; 1066 } 1067 1068 static int mtt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1069 u64 in_param, u64 *out_param) 1070 { 1071 int err = -EINVAL; 1072 int base; 1073 int order; 1074 1075 if (op != RES_OP_RESERVE_AND_MAP) 1076 return err; 1077 1078 order = get_param_l(&in_param); 1079 base = __mlx4_alloc_mtt_range(dev, order); 1080 if (base == -1) 1081 return -ENOMEM; 1082 1083 err = add_res_range(dev, slave, base, 1, RES_MTT, order); 1084 if (err) 1085 __mlx4_free_mtt_range(dev, base, order); 1086 else 1087 set_param_l(out_param, base); 1088 1089 return err; 1090 } 1091 1092 static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1093 u64 in_param, u64 *out_param) 1094 { 1095 int err = -EINVAL; 1096 int index; 1097 int id; 1098 struct res_mpt *mpt; 1099 1100 switch (op) { 1101 case RES_OP_RESERVE: 1102 index = __mlx4_mr_reserve(dev); 1103 if (index == -1) 1104 break; 1105 id = index & mpt_mask(dev); 1106 1107 err = add_res_range(dev, slave, id, 1, RES_MPT, index); 1108 if (err) { 1109 __mlx4_mr_release(dev, index); 1110 break; 1111 } 1112 set_param_l(out_param, index); 1113 break; 1114 case RES_OP_MAP_ICM: 1115 index = get_param_l(&in_param); 1116 id = index & mpt_mask(dev); 1117 err = mr_res_start_move_to(dev, slave, id, 1118 RES_MPT_MAPPED, &mpt); 1119 if (err) 1120 return err; 1121 1122 err = __mlx4_mr_alloc_icm(dev, mpt->key); 1123 if (err) { 1124 res_abort_move(dev, slave, RES_MPT, id); 1125 return err; 1126 } 1127 1128 res_end_move(dev, slave, RES_MPT, id); 1129 break; 1130 } 1131 return err; 1132 } 1133 1134 static int cq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1135 u64 in_param, u64 *out_param) 1136 { 1137 int cqn; 1138 int err; 1139 1140 switch (op) { 1141 case RES_OP_RESERVE_AND_MAP: 1142 err = __mlx4_cq_alloc_icm(dev, &cqn); 1143 if (err) 1144 break; 1145 1146 err = add_res_range(dev, slave, cqn, 1, RES_CQ, 0); 1147 if (err) { 1148 __mlx4_cq_free_icm(dev, cqn); 1149 break; 1150 } 1151 1152 set_param_l(out_param, cqn); 1153 break; 1154 1155 default: 1156 err = -EINVAL; 1157 } 1158 1159 return err; 1160 } 1161 1162 static int srq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1163 u64 in_param, u64 *out_param) 1164 { 1165 int srqn; 1166 int err; 1167 1168 switch (op) { 1169 case RES_OP_RESERVE_AND_MAP: 1170 err = __mlx4_srq_alloc_icm(dev, &srqn); 1171 if (err) 1172 break; 1173 1174 err = add_res_range(dev, slave, srqn, 1, RES_SRQ, 0); 1175 if (err) { 1176 __mlx4_srq_free_icm(dev, srqn); 1177 break; 1178 } 1179 1180 set_param_l(out_param, srqn); 1181 break; 1182 1183 default: 1184 err = -EINVAL; 1185 } 1186 1187 return err; 1188 } 1189 1190 static int mac_add_to_slave(struct mlx4_dev *dev, int slave, u64 mac, int port) 1191 { 1192 struct mlx4_priv *priv = mlx4_priv(dev); 1193 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 1194 struct mac_res *res; 1195 1196 res = kzalloc(sizeof *res, GFP_KERNEL); 1197 if (!res) 1198 return -ENOMEM; 1199 res->mac = mac; 1200 res->port = (u8) port; 1201 list_add_tail(&res->list, 1202 &tracker->slave_list[slave].res_list[RES_MAC]); 1203 return 0; 1204 } 1205 1206 static void mac_del_from_slave(struct mlx4_dev *dev, int slave, u64 mac, 1207 int port) 1208 { 1209 struct mlx4_priv *priv = mlx4_priv(dev); 1210 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 1211 struct list_head *mac_list = 1212 &tracker->slave_list[slave].res_list[RES_MAC]; 1213 struct mac_res *res, *tmp; 1214 1215 list_for_each_entry_safe(res, tmp, mac_list, list) { 1216 if (res->mac == mac && res->port == (u8) port) { 1217 list_del(&res->list); 1218 kfree(res); 1219 break; 1220 } 1221 } 1222 } 1223 1224 static void rem_slave_macs(struct mlx4_dev *dev, int slave) 1225 { 1226 struct mlx4_priv *priv = mlx4_priv(dev); 1227 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 1228 struct list_head *mac_list = 1229 &tracker->slave_list[slave].res_list[RES_MAC]; 1230 struct mac_res *res, *tmp; 1231 1232 list_for_each_entry_safe(res, tmp, mac_list, list) { 1233 list_del(&res->list); 1234 __mlx4_unregister_mac(dev, res->port, res->mac); 1235 kfree(res); 1236 } 1237 } 1238 1239 static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1240 u64 in_param, u64 *out_param) 1241 { 1242 int err = -EINVAL; 1243 int port; 1244 u64 mac; 1245 1246 if (op != RES_OP_RESERVE_AND_MAP) 1247 return err; 1248 1249 port = get_param_l(out_param); 1250 mac = in_param; 1251 1252 err = __mlx4_register_mac(dev, port, mac); 1253 if (err >= 0) { 1254 set_param_l(out_param, err); 1255 err = 0; 1256 } 1257 1258 if (!err) { 1259 err = mac_add_to_slave(dev, slave, mac, port); 1260 if (err) 1261 __mlx4_unregister_mac(dev, port, mac); 1262 } 1263 return err; 1264 } 1265 1266 static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1267 u64 in_param, u64 *out_param) 1268 { 1269 return 0; 1270 } 1271 1272 int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, 1273 struct mlx4_vhcr *vhcr, 1274 struct mlx4_cmd_mailbox *inbox, 1275 struct mlx4_cmd_mailbox *outbox, 1276 struct mlx4_cmd_info *cmd) 1277 { 1278 int err; 1279 int alop = vhcr->op_modifier; 1280 1281 switch (vhcr->in_modifier) { 1282 case RES_QP: 1283 err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop, 1284 vhcr->in_param, &vhcr->out_param); 1285 break; 1286 1287 case RES_MTT: 1288 err = mtt_alloc_res(dev, slave, vhcr->op_modifier, alop, 1289 vhcr->in_param, &vhcr->out_param); 1290 break; 1291 1292 case RES_MPT: 1293 err = mpt_alloc_res(dev, slave, vhcr->op_modifier, alop, 1294 vhcr->in_param, &vhcr->out_param); 1295 break; 1296 1297 case RES_CQ: 1298 err = cq_alloc_res(dev, slave, vhcr->op_modifier, alop, 1299 vhcr->in_param, &vhcr->out_param); 1300 break; 1301 1302 case RES_SRQ: 1303 err = srq_alloc_res(dev, slave, vhcr->op_modifier, alop, 1304 vhcr->in_param, &vhcr->out_param); 1305 break; 1306 1307 case RES_MAC: 1308 err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop, 1309 vhcr->in_param, &vhcr->out_param); 1310 break; 1311 1312 case RES_VLAN: 1313 err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop, 1314 vhcr->in_param, &vhcr->out_param); 1315 break; 1316 1317 default: 1318 err = -EINVAL; 1319 break; 1320 } 1321 1322 return err; 1323 } 1324 1325 static int qp_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1326 u64 in_param) 1327 { 1328 int err; 1329 int count; 1330 int base; 1331 int qpn; 1332 1333 switch (op) { 1334 case RES_OP_RESERVE: 1335 base = get_param_l(&in_param) & 0x7fffff; 1336 count = get_param_h(&in_param); 1337 err = rem_res_range(dev, slave, base, count, RES_QP, 0); 1338 if (err) 1339 break; 1340 __mlx4_qp_release_range(dev, base, count); 1341 break; 1342 case RES_OP_MAP_ICM: 1343 qpn = get_param_l(&in_param) & 0x7fffff; 1344 err = qp_res_start_move_to(dev, slave, qpn, RES_QP_RESERVED, 1345 NULL, 0); 1346 if (err) 1347 return err; 1348 1349 if (!valid_reserved(dev, slave, qpn)) 1350 __mlx4_qp_free_icm(dev, qpn); 1351 1352 res_end_move(dev, slave, RES_QP, qpn); 1353 1354 if (valid_reserved(dev, slave, qpn)) 1355 err = rem_res_range(dev, slave, qpn, 1, RES_QP, 0); 1356 break; 1357 default: 1358 err = -EINVAL; 1359 break; 1360 } 1361 return err; 1362 } 1363 1364 static int mtt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1365 u64 in_param, u64 *out_param) 1366 { 1367 int err = -EINVAL; 1368 int base; 1369 int order; 1370 1371 if (op != RES_OP_RESERVE_AND_MAP) 1372 return err; 1373 1374 base = get_param_l(&in_param); 1375 order = get_param_h(&in_param); 1376 err = rem_res_range(dev, slave, base, 1, RES_MTT, order); 1377 if (!err) 1378 __mlx4_free_mtt_range(dev, base, order); 1379 return err; 1380 } 1381 1382 static int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1383 u64 in_param) 1384 { 1385 int err = -EINVAL; 1386 int index; 1387 int id; 1388 struct res_mpt *mpt; 1389 1390 switch (op) { 1391 case RES_OP_RESERVE: 1392 index = get_param_l(&in_param); 1393 id = index & mpt_mask(dev); 1394 err = get_res(dev, slave, id, RES_MPT, &mpt); 1395 if (err) 1396 break; 1397 index = mpt->key; 1398 put_res(dev, slave, id, RES_MPT); 1399 1400 err = rem_res_range(dev, slave, id, 1, RES_MPT, 0); 1401 if (err) 1402 break; 1403 __mlx4_mr_release(dev, index); 1404 break; 1405 case RES_OP_MAP_ICM: 1406 index = get_param_l(&in_param); 1407 id = index & mpt_mask(dev); 1408 err = mr_res_start_move_to(dev, slave, id, 1409 RES_MPT_RESERVED, &mpt); 1410 if (err) 1411 return err; 1412 1413 __mlx4_mr_free_icm(dev, mpt->key); 1414 res_end_move(dev, slave, RES_MPT, id); 1415 return err; 1416 break; 1417 default: 1418 err = -EINVAL; 1419 break; 1420 } 1421 return err; 1422 } 1423 1424 static int cq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1425 u64 in_param, u64 *out_param) 1426 { 1427 int cqn; 1428 int err; 1429 1430 switch (op) { 1431 case RES_OP_RESERVE_AND_MAP: 1432 cqn = get_param_l(&in_param); 1433 err = rem_res_range(dev, slave, cqn, 1, RES_CQ, 0); 1434 if (err) 1435 break; 1436 1437 __mlx4_cq_free_icm(dev, cqn); 1438 break; 1439 1440 default: 1441 err = -EINVAL; 1442 break; 1443 } 1444 1445 return err; 1446 } 1447 1448 static int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1449 u64 in_param, u64 *out_param) 1450 { 1451 int srqn; 1452 int err; 1453 1454 switch (op) { 1455 case RES_OP_RESERVE_AND_MAP: 1456 srqn = get_param_l(&in_param); 1457 err = rem_res_range(dev, slave, srqn, 1, RES_SRQ, 0); 1458 if (err) 1459 break; 1460 1461 __mlx4_srq_free_icm(dev, srqn); 1462 break; 1463 1464 default: 1465 err = -EINVAL; 1466 break; 1467 } 1468 1469 return err; 1470 } 1471 1472 static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1473 u64 in_param, u64 *out_param) 1474 { 1475 int port; 1476 int err = 0; 1477 1478 switch (op) { 1479 case RES_OP_RESERVE_AND_MAP: 1480 port = get_param_l(out_param); 1481 mac_del_from_slave(dev, slave, in_param, port); 1482 __mlx4_unregister_mac(dev, port, in_param); 1483 break; 1484 default: 1485 err = -EINVAL; 1486 break; 1487 } 1488 1489 return err; 1490 1491 } 1492 1493 static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1494 u64 in_param, u64 *out_param) 1495 { 1496 return 0; 1497 } 1498 1499 int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, 1500 struct mlx4_vhcr *vhcr, 1501 struct mlx4_cmd_mailbox *inbox, 1502 struct mlx4_cmd_mailbox *outbox, 1503 struct mlx4_cmd_info *cmd) 1504 { 1505 int err = -EINVAL; 1506 int alop = vhcr->op_modifier; 1507 1508 switch (vhcr->in_modifier) { 1509 case RES_QP: 1510 err = qp_free_res(dev, slave, vhcr->op_modifier, alop, 1511 vhcr->in_param); 1512 break; 1513 1514 case RES_MTT: 1515 err = mtt_free_res(dev, slave, vhcr->op_modifier, alop, 1516 vhcr->in_param, &vhcr->out_param); 1517 break; 1518 1519 case RES_MPT: 1520 err = mpt_free_res(dev, slave, vhcr->op_modifier, alop, 1521 vhcr->in_param); 1522 break; 1523 1524 case RES_CQ: 1525 err = cq_free_res(dev, slave, vhcr->op_modifier, alop, 1526 vhcr->in_param, &vhcr->out_param); 1527 break; 1528 1529 case RES_SRQ: 1530 err = srq_free_res(dev, slave, vhcr->op_modifier, alop, 1531 vhcr->in_param, &vhcr->out_param); 1532 break; 1533 1534 case RES_MAC: 1535 err = mac_free_res(dev, slave, vhcr->op_modifier, alop, 1536 vhcr->in_param, &vhcr->out_param); 1537 break; 1538 1539 case RES_VLAN: 1540 err = vlan_free_res(dev, slave, vhcr->op_modifier, alop, 1541 vhcr->in_param, &vhcr->out_param); 1542 break; 1543 1544 default: 1545 break; 1546 } 1547 return err; 1548 } 1549 1550 /* ugly but other choices are uglier */ 1551 static int mr_phys_mpt(struct mlx4_mpt_entry *mpt) 1552 { 1553 return (be32_to_cpu(mpt->flags) >> 9) & 1; 1554 } 1555 1556 static int mr_get_mtt_addr(struct mlx4_mpt_entry *mpt) 1557 { 1558 return (int)be64_to_cpu(mpt->mtt_addr) & 0xfffffff8; 1559 } 1560 1561 static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt) 1562 { 1563 return be32_to_cpu(mpt->mtt_sz); 1564 } 1565 1566 static int qp_get_mtt_addr(struct mlx4_qp_context *qpc) 1567 { 1568 return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8; 1569 } 1570 1571 static int srq_get_mtt_addr(struct mlx4_srq_context *srqc) 1572 { 1573 return be32_to_cpu(srqc->mtt_base_addr_l) & 0xfffffff8; 1574 } 1575 1576 static int qp_get_mtt_size(struct mlx4_qp_context *qpc) 1577 { 1578 int page_shift = (qpc->log_page_size & 0x3f) + 12; 1579 int log_sq_size = (qpc->sq_size_stride >> 3) & 0xf; 1580 int log_sq_sride = qpc->sq_size_stride & 7; 1581 int log_rq_size = (qpc->rq_size_stride >> 3) & 0xf; 1582 int log_rq_stride = qpc->rq_size_stride & 7; 1583 int srq = (be32_to_cpu(qpc->srqn) >> 24) & 1; 1584 int rss = (be32_to_cpu(qpc->flags) >> 13) & 1; 1585 int xrc = (be32_to_cpu(qpc->local_qpn) >> 23) & 1; 1586 int sq_size; 1587 int rq_size; 1588 int total_pages; 1589 int total_mem; 1590 int page_offset = (be32_to_cpu(qpc->params2) >> 6) & 0x3f; 1591 1592 sq_size = 1 << (log_sq_size + log_sq_sride + 4); 1593 rq_size = (srq|rss|xrc) ? 0 : (1 << (log_rq_size + log_rq_stride + 4)); 1594 total_mem = sq_size + rq_size; 1595 total_pages = 1596 roundup_pow_of_two((total_mem + (page_offset << 6)) >> 1597 page_shift); 1598 1599 return total_pages; 1600 } 1601 1602 static int check_mtt_range(struct mlx4_dev *dev, int slave, int start, 1603 int size, struct res_mtt *mtt) 1604 { 1605 int res_start = mtt->com.res_id; 1606 int res_size = (1 << mtt->order); 1607 1608 if (start < res_start || start + size > res_start + res_size) 1609 return -EPERM; 1610 return 0; 1611 } 1612 1613 int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave, 1614 struct mlx4_vhcr *vhcr, 1615 struct mlx4_cmd_mailbox *inbox, 1616 struct mlx4_cmd_mailbox *outbox, 1617 struct mlx4_cmd_info *cmd) 1618 { 1619 int err; 1620 int index = vhcr->in_modifier; 1621 struct res_mtt *mtt; 1622 struct res_mpt *mpt; 1623 int mtt_base = mr_get_mtt_addr(inbox->buf) / dev->caps.mtt_entry_sz; 1624 int phys; 1625 int id; 1626 1627 id = index & mpt_mask(dev); 1628 err = mr_res_start_move_to(dev, slave, id, RES_MPT_HW, &mpt); 1629 if (err) 1630 return err; 1631 1632 phys = mr_phys_mpt(inbox->buf); 1633 if (!phys) { 1634 err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); 1635 if (err) 1636 goto ex_abort; 1637 1638 err = check_mtt_range(dev, slave, mtt_base, 1639 mr_get_mtt_size(inbox->buf), mtt); 1640 if (err) 1641 goto ex_put; 1642 1643 mpt->mtt = mtt; 1644 } 1645 1646 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 1647 if (err) 1648 goto ex_put; 1649 1650 if (!phys) { 1651 atomic_inc(&mtt->ref_count); 1652 put_res(dev, slave, mtt->com.res_id, RES_MTT); 1653 } 1654 1655 res_end_move(dev, slave, RES_MPT, id); 1656 return 0; 1657 1658 ex_put: 1659 if (!phys) 1660 put_res(dev, slave, mtt->com.res_id, RES_MTT); 1661 ex_abort: 1662 res_abort_move(dev, slave, RES_MPT, id); 1663 1664 return err; 1665 } 1666 1667 int mlx4_HW2SW_MPT_wrapper(struct mlx4_dev *dev, int slave, 1668 struct mlx4_vhcr *vhcr, 1669 struct mlx4_cmd_mailbox *inbox, 1670 struct mlx4_cmd_mailbox *outbox, 1671 struct mlx4_cmd_info *cmd) 1672 { 1673 int err; 1674 int index = vhcr->in_modifier; 1675 struct res_mpt *mpt; 1676 int id; 1677 1678 id = index & mpt_mask(dev); 1679 err = mr_res_start_move_to(dev, slave, id, RES_MPT_MAPPED, &mpt); 1680 if (err) 1681 return err; 1682 1683 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 1684 if (err) 1685 goto ex_abort; 1686 1687 if (mpt->mtt) 1688 atomic_dec(&mpt->mtt->ref_count); 1689 1690 res_end_move(dev, slave, RES_MPT, id); 1691 return 0; 1692 1693 ex_abort: 1694 res_abort_move(dev, slave, RES_MPT, id); 1695 1696 return err; 1697 } 1698 1699 int mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave, 1700 struct mlx4_vhcr *vhcr, 1701 struct mlx4_cmd_mailbox *inbox, 1702 struct mlx4_cmd_mailbox *outbox, 1703 struct mlx4_cmd_info *cmd) 1704 { 1705 int err; 1706 int index = vhcr->in_modifier; 1707 struct res_mpt *mpt; 1708 int id; 1709 1710 id = index & mpt_mask(dev); 1711 err = get_res(dev, slave, id, RES_MPT, &mpt); 1712 if (err) 1713 return err; 1714 1715 if (mpt->com.from_state != RES_MPT_HW) { 1716 err = -EBUSY; 1717 goto out; 1718 } 1719 1720 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 1721 1722 out: 1723 put_res(dev, slave, id, RES_MPT); 1724 return err; 1725 } 1726 1727 static int qp_get_rcqn(struct mlx4_qp_context *qpc) 1728 { 1729 return be32_to_cpu(qpc->cqn_recv) & 0xffffff; 1730 } 1731 1732 static int qp_get_scqn(struct mlx4_qp_context *qpc) 1733 { 1734 return be32_to_cpu(qpc->cqn_send) & 0xffffff; 1735 } 1736 1737 static u32 qp_get_srqn(struct mlx4_qp_context *qpc) 1738 { 1739 return be32_to_cpu(qpc->srqn) & 0x1ffffff; 1740 } 1741 1742 int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, 1743 struct mlx4_vhcr *vhcr, 1744 struct mlx4_cmd_mailbox *inbox, 1745 struct mlx4_cmd_mailbox *outbox, 1746 struct mlx4_cmd_info *cmd) 1747 { 1748 int err; 1749 int qpn = vhcr->in_modifier & 0x7fffff; 1750 struct res_mtt *mtt; 1751 struct res_qp *qp; 1752 struct mlx4_qp_context *qpc = inbox->buf + 8; 1753 int mtt_base = qp_get_mtt_addr(qpc) / dev->caps.mtt_entry_sz; 1754 int mtt_size = qp_get_mtt_size(qpc); 1755 struct res_cq *rcq; 1756 struct res_cq *scq; 1757 int rcqn = qp_get_rcqn(qpc); 1758 int scqn = qp_get_scqn(qpc); 1759 u32 srqn = qp_get_srqn(qpc) & 0xffffff; 1760 int use_srq = (qp_get_srqn(qpc) >> 24) & 1; 1761 struct res_srq *srq; 1762 int local_qpn = be32_to_cpu(qpc->local_qpn) & 0xffffff; 1763 1764 err = qp_res_start_move_to(dev, slave, qpn, RES_QP_HW, &qp, 0); 1765 if (err) 1766 return err; 1767 qp->local_qpn = local_qpn; 1768 1769 err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); 1770 if (err) 1771 goto ex_abort; 1772 1773 err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt); 1774 if (err) 1775 goto ex_put_mtt; 1776 1777 err = get_res(dev, slave, rcqn, RES_CQ, &rcq); 1778 if (err) 1779 goto ex_put_mtt; 1780 1781 if (scqn != rcqn) { 1782 err = get_res(dev, slave, scqn, RES_CQ, &scq); 1783 if (err) 1784 goto ex_put_rcq; 1785 } else 1786 scq = rcq; 1787 1788 if (use_srq) { 1789 err = get_res(dev, slave, srqn, RES_SRQ, &srq); 1790 if (err) 1791 goto ex_put_scq; 1792 } 1793 1794 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 1795 if (err) 1796 goto ex_put_srq; 1797 atomic_inc(&mtt->ref_count); 1798 qp->mtt = mtt; 1799 atomic_inc(&rcq->ref_count); 1800 qp->rcq = rcq; 1801 atomic_inc(&scq->ref_count); 1802 qp->scq = scq; 1803 1804 if (scqn != rcqn) 1805 put_res(dev, slave, scqn, RES_CQ); 1806 1807 if (use_srq) { 1808 atomic_inc(&srq->ref_count); 1809 put_res(dev, slave, srqn, RES_SRQ); 1810 qp->srq = srq; 1811 } 1812 put_res(dev, slave, rcqn, RES_CQ); 1813 put_res(dev, slave, mtt_base, RES_MTT); 1814 res_end_move(dev, slave, RES_QP, qpn); 1815 1816 return 0; 1817 1818 ex_put_srq: 1819 if (use_srq) 1820 put_res(dev, slave, srqn, RES_SRQ); 1821 ex_put_scq: 1822 if (scqn != rcqn) 1823 put_res(dev, slave, scqn, RES_CQ); 1824 ex_put_rcq: 1825 put_res(dev, slave, rcqn, RES_CQ); 1826 ex_put_mtt: 1827 put_res(dev, slave, mtt_base, RES_MTT); 1828 ex_abort: 1829 res_abort_move(dev, slave, RES_QP, qpn); 1830 1831 return err; 1832 } 1833 1834 static int eq_get_mtt_addr(struct mlx4_eq_context *eqc) 1835 { 1836 return be32_to_cpu(eqc->mtt_base_addr_l) & 0xfffffff8; 1837 } 1838 1839 static int eq_get_mtt_size(struct mlx4_eq_context *eqc) 1840 { 1841 int log_eq_size = eqc->log_eq_size & 0x1f; 1842 int page_shift = (eqc->log_page_size & 0x3f) + 12; 1843 1844 if (log_eq_size + 5 < page_shift) 1845 return 1; 1846 1847 return 1 << (log_eq_size + 5 - page_shift); 1848 } 1849 1850 static int cq_get_mtt_addr(struct mlx4_cq_context *cqc) 1851 { 1852 return be32_to_cpu(cqc->mtt_base_addr_l) & 0xfffffff8; 1853 } 1854 1855 static int cq_get_mtt_size(struct mlx4_cq_context *cqc) 1856 { 1857 int log_cq_size = (be32_to_cpu(cqc->logsize_usrpage) >> 24) & 0x1f; 1858 int page_shift = (cqc->log_page_size & 0x3f) + 12; 1859 1860 if (log_cq_size + 5 < page_shift) 1861 return 1; 1862 1863 return 1 << (log_cq_size + 5 - page_shift); 1864 } 1865 1866 int mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave, 1867 struct mlx4_vhcr *vhcr, 1868 struct mlx4_cmd_mailbox *inbox, 1869 struct mlx4_cmd_mailbox *outbox, 1870 struct mlx4_cmd_info *cmd) 1871 { 1872 int err; 1873 int eqn = vhcr->in_modifier; 1874 int res_id = (slave << 8) | eqn; 1875 struct mlx4_eq_context *eqc = inbox->buf; 1876 int mtt_base = eq_get_mtt_addr(eqc) / dev->caps.mtt_entry_sz; 1877 int mtt_size = eq_get_mtt_size(eqc); 1878 struct res_eq *eq; 1879 struct res_mtt *mtt; 1880 1881 err = add_res_range(dev, slave, res_id, 1, RES_EQ, 0); 1882 if (err) 1883 return err; 1884 err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_HW, &eq); 1885 if (err) 1886 goto out_add; 1887 1888 err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); 1889 if (err) 1890 goto out_move; 1891 1892 err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt); 1893 if (err) 1894 goto out_put; 1895 1896 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 1897 if (err) 1898 goto out_put; 1899 1900 atomic_inc(&mtt->ref_count); 1901 eq->mtt = mtt; 1902 put_res(dev, slave, mtt->com.res_id, RES_MTT); 1903 res_end_move(dev, slave, RES_EQ, res_id); 1904 return 0; 1905 1906 out_put: 1907 put_res(dev, slave, mtt->com.res_id, RES_MTT); 1908 out_move: 1909 res_abort_move(dev, slave, RES_EQ, res_id); 1910 out_add: 1911 rem_res_range(dev, slave, res_id, 1, RES_EQ, 0); 1912 return err; 1913 } 1914 1915 static int get_containing_mtt(struct mlx4_dev *dev, int slave, int start, 1916 int len, struct res_mtt **res) 1917 { 1918 struct mlx4_priv *priv = mlx4_priv(dev); 1919 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 1920 struct res_mtt *mtt; 1921 int err = -EINVAL; 1922 1923 spin_lock_irq(mlx4_tlock(dev)); 1924 list_for_each_entry(mtt, &tracker->slave_list[slave].res_list[RES_MTT], 1925 com.list) { 1926 if (!check_mtt_range(dev, slave, start, len, mtt)) { 1927 *res = mtt; 1928 mtt->com.from_state = mtt->com.state; 1929 mtt->com.state = RES_MTT_BUSY; 1930 err = 0; 1931 break; 1932 } 1933 } 1934 spin_unlock_irq(mlx4_tlock(dev)); 1935 1936 return err; 1937 } 1938 1939 int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave, 1940 struct mlx4_vhcr *vhcr, 1941 struct mlx4_cmd_mailbox *inbox, 1942 struct mlx4_cmd_mailbox *outbox, 1943 struct mlx4_cmd_info *cmd) 1944 { 1945 struct mlx4_mtt mtt; 1946 __be64 *page_list = inbox->buf; 1947 u64 *pg_list = (u64 *)page_list; 1948 int i; 1949 struct res_mtt *rmtt = NULL; 1950 int start = be64_to_cpu(page_list[0]); 1951 int npages = vhcr->in_modifier; 1952 int err; 1953 1954 err = get_containing_mtt(dev, slave, start, npages, &rmtt); 1955 if (err) 1956 return err; 1957 1958 /* Call the SW implementation of write_mtt: 1959 * - Prepare a dummy mtt struct 1960 * - Translate inbox contents to simple addresses in host endianess */ 1961 mtt.offset = 0; /* TBD this is broken but I don't handle it since 1962 we don't really use it */ 1963 mtt.order = 0; 1964 mtt.page_shift = 0; 1965 for (i = 0; i < npages; ++i) 1966 pg_list[i + 2] = (be64_to_cpu(page_list[i + 2]) & ~1ULL); 1967 1968 err = __mlx4_write_mtt(dev, &mtt, be64_to_cpu(page_list[0]), npages, 1969 ((u64 *)page_list + 2)); 1970 1971 if (rmtt) 1972 put_res(dev, slave, rmtt->com.res_id, RES_MTT); 1973 1974 return err; 1975 } 1976 1977 int mlx4_HW2SW_EQ_wrapper(struct mlx4_dev *dev, int slave, 1978 struct mlx4_vhcr *vhcr, 1979 struct mlx4_cmd_mailbox *inbox, 1980 struct mlx4_cmd_mailbox *outbox, 1981 struct mlx4_cmd_info *cmd) 1982 { 1983 int eqn = vhcr->in_modifier; 1984 int res_id = eqn | (slave << 8); 1985 struct res_eq *eq; 1986 int err; 1987 1988 err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_RESERVED, &eq); 1989 if (err) 1990 return err; 1991 1992 err = get_res(dev, slave, eq->mtt->com.res_id, RES_MTT, NULL); 1993 if (err) 1994 goto ex_abort; 1995 1996 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 1997 if (err) 1998 goto ex_put; 1999 2000 atomic_dec(&eq->mtt->ref_count); 2001 put_res(dev, slave, eq->mtt->com.res_id, RES_MTT); 2002 res_end_move(dev, slave, RES_EQ, res_id); 2003 rem_res_range(dev, slave, res_id, 1, RES_EQ, 0); 2004 2005 return 0; 2006 2007 ex_put: 2008 put_res(dev, slave, eq->mtt->com.res_id, RES_MTT); 2009 ex_abort: 2010 res_abort_move(dev, slave, RES_EQ, res_id); 2011 2012 return err; 2013 } 2014 2015 int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe) 2016 { 2017 struct mlx4_priv *priv = mlx4_priv(dev); 2018 struct mlx4_slave_event_eq_info *event_eq; 2019 struct mlx4_cmd_mailbox *mailbox; 2020 u32 in_modifier = 0; 2021 int err; 2022 int res_id; 2023 struct res_eq *req; 2024 2025 if (!priv->mfunc.master.slave_state) 2026 return -EINVAL; 2027 2028 event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type]; 2029 2030 /* Create the event only if the slave is registered */ 2031 if (event_eq->eqn < 0) 2032 return 0; 2033 2034 mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]); 2035 res_id = (slave << 8) | event_eq->eqn; 2036 err = get_res(dev, slave, res_id, RES_EQ, &req); 2037 if (err) 2038 goto unlock; 2039 2040 if (req->com.from_state != RES_EQ_HW) { 2041 err = -EINVAL; 2042 goto put; 2043 } 2044 2045 mailbox = mlx4_alloc_cmd_mailbox(dev); 2046 if (IS_ERR(mailbox)) { 2047 err = PTR_ERR(mailbox); 2048 goto put; 2049 } 2050 2051 if (eqe->type == MLX4_EVENT_TYPE_CMD) { 2052 ++event_eq->token; 2053 eqe->event.cmd.token = cpu_to_be16(event_eq->token); 2054 } 2055 2056 memcpy(mailbox->buf, (u8 *) eqe, 28); 2057 2058 in_modifier = (slave & 0xff) | ((event_eq->eqn & 0xff) << 16); 2059 2060 err = mlx4_cmd(dev, mailbox->dma, in_modifier, 0, 2061 MLX4_CMD_GEN_EQE, MLX4_CMD_TIME_CLASS_B, 2062 MLX4_CMD_NATIVE); 2063 2064 put_res(dev, slave, res_id, RES_EQ); 2065 mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]); 2066 mlx4_free_cmd_mailbox(dev, mailbox); 2067 return err; 2068 2069 put: 2070 put_res(dev, slave, res_id, RES_EQ); 2071 2072 unlock: 2073 mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]); 2074 return err; 2075 } 2076 2077 int mlx4_QUERY_EQ_wrapper(struct mlx4_dev *dev, int slave, 2078 struct mlx4_vhcr *vhcr, 2079 struct mlx4_cmd_mailbox *inbox, 2080 struct mlx4_cmd_mailbox *outbox, 2081 struct mlx4_cmd_info *cmd) 2082 { 2083 int eqn = vhcr->in_modifier; 2084 int res_id = eqn | (slave << 8); 2085 struct res_eq *eq; 2086 int err; 2087 2088 err = get_res(dev, slave, res_id, RES_EQ, &eq); 2089 if (err) 2090 return err; 2091 2092 if (eq->com.from_state != RES_EQ_HW) { 2093 err = -EINVAL; 2094 goto ex_put; 2095 } 2096 2097 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2098 2099 ex_put: 2100 put_res(dev, slave, res_id, RES_EQ); 2101 return err; 2102 } 2103 2104 int mlx4_SW2HW_CQ_wrapper(struct mlx4_dev *dev, int slave, 2105 struct mlx4_vhcr *vhcr, 2106 struct mlx4_cmd_mailbox *inbox, 2107 struct mlx4_cmd_mailbox *outbox, 2108 struct mlx4_cmd_info *cmd) 2109 { 2110 int err; 2111 int cqn = vhcr->in_modifier; 2112 struct mlx4_cq_context *cqc = inbox->buf; 2113 int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz; 2114 struct res_cq *cq; 2115 struct res_mtt *mtt; 2116 2117 err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_HW, &cq); 2118 if (err) 2119 return err; 2120 err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); 2121 if (err) 2122 goto out_move; 2123 err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt); 2124 if (err) 2125 goto out_put; 2126 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2127 if (err) 2128 goto out_put; 2129 atomic_inc(&mtt->ref_count); 2130 cq->mtt = mtt; 2131 put_res(dev, slave, mtt->com.res_id, RES_MTT); 2132 res_end_move(dev, slave, RES_CQ, cqn); 2133 return 0; 2134 2135 out_put: 2136 put_res(dev, slave, mtt->com.res_id, RES_MTT); 2137 out_move: 2138 res_abort_move(dev, slave, RES_CQ, cqn); 2139 return err; 2140 } 2141 2142 int mlx4_HW2SW_CQ_wrapper(struct mlx4_dev *dev, int slave, 2143 struct mlx4_vhcr *vhcr, 2144 struct mlx4_cmd_mailbox *inbox, 2145 struct mlx4_cmd_mailbox *outbox, 2146 struct mlx4_cmd_info *cmd) 2147 { 2148 int err; 2149 int cqn = vhcr->in_modifier; 2150 struct res_cq *cq; 2151 2152 err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_ALLOCATED, &cq); 2153 if (err) 2154 return err; 2155 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2156 if (err) 2157 goto out_move; 2158 atomic_dec(&cq->mtt->ref_count); 2159 res_end_move(dev, slave, RES_CQ, cqn); 2160 return 0; 2161 2162 out_move: 2163 res_abort_move(dev, slave, RES_CQ, cqn); 2164 return err; 2165 } 2166 2167 int mlx4_QUERY_CQ_wrapper(struct mlx4_dev *dev, int slave, 2168 struct mlx4_vhcr *vhcr, 2169 struct mlx4_cmd_mailbox *inbox, 2170 struct mlx4_cmd_mailbox *outbox, 2171 struct mlx4_cmd_info *cmd) 2172 { 2173 int cqn = vhcr->in_modifier; 2174 struct res_cq *cq; 2175 int err; 2176 2177 err = get_res(dev, slave, cqn, RES_CQ, &cq); 2178 if (err) 2179 return err; 2180 2181 if (cq->com.from_state != RES_CQ_HW) 2182 goto ex_put; 2183 2184 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2185 ex_put: 2186 put_res(dev, slave, cqn, RES_CQ); 2187 2188 return err; 2189 } 2190 2191 static int handle_resize(struct mlx4_dev *dev, int slave, 2192 struct mlx4_vhcr *vhcr, 2193 struct mlx4_cmd_mailbox *inbox, 2194 struct mlx4_cmd_mailbox *outbox, 2195 struct mlx4_cmd_info *cmd, 2196 struct res_cq *cq) 2197 { 2198 int err; 2199 struct res_mtt *orig_mtt; 2200 struct res_mtt *mtt; 2201 struct mlx4_cq_context *cqc = inbox->buf; 2202 int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz; 2203 2204 err = get_res(dev, slave, cq->mtt->com.res_id, RES_MTT, &orig_mtt); 2205 if (err) 2206 return err; 2207 2208 if (orig_mtt != cq->mtt) { 2209 err = -EINVAL; 2210 goto ex_put; 2211 } 2212 2213 err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); 2214 if (err) 2215 goto ex_put; 2216 2217 err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt); 2218 if (err) 2219 goto ex_put1; 2220 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2221 if (err) 2222 goto ex_put1; 2223 atomic_dec(&orig_mtt->ref_count); 2224 put_res(dev, slave, orig_mtt->com.res_id, RES_MTT); 2225 atomic_inc(&mtt->ref_count); 2226 cq->mtt = mtt; 2227 put_res(dev, slave, mtt->com.res_id, RES_MTT); 2228 return 0; 2229 2230 ex_put1: 2231 put_res(dev, slave, mtt->com.res_id, RES_MTT); 2232 ex_put: 2233 put_res(dev, slave, orig_mtt->com.res_id, RES_MTT); 2234 2235 return err; 2236 2237 } 2238 2239 int mlx4_MODIFY_CQ_wrapper(struct mlx4_dev *dev, int slave, 2240 struct mlx4_vhcr *vhcr, 2241 struct mlx4_cmd_mailbox *inbox, 2242 struct mlx4_cmd_mailbox *outbox, 2243 struct mlx4_cmd_info *cmd) 2244 { 2245 int cqn = vhcr->in_modifier; 2246 struct res_cq *cq; 2247 int err; 2248 2249 err = get_res(dev, slave, cqn, RES_CQ, &cq); 2250 if (err) 2251 return err; 2252 2253 if (cq->com.from_state != RES_CQ_HW) 2254 goto ex_put; 2255 2256 if (vhcr->op_modifier == 0) { 2257 err = handle_resize(dev, slave, vhcr, inbox, outbox, cmd, cq); 2258 goto ex_put; 2259 } 2260 2261 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2262 ex_put: 2263 put_res(dev, slave, cqn, RES_CQ); 2264 2265 return err; 2266 } 2267 2268 static int srq_get_mtt_size(struct mlx4_srq_context *srqc) 2269 { 2270 int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf; 2271 int log_rq_stride = srqc->logstride & 7; 2272 int page_shift = (srqc->log_page_size & 0x3f) + 12; 2273 2274 if (log_srq_size + log_rq_stride + 4 < page_shift) 2275 return 1; 2276 2277 return 1 << (log_srq_size + log_rq_stride + 4 - page_shift); 2278 } 2279 2280 int mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave, 2281 struct mlx4_vhcr *vhcr, 2282 struct mlx4_cmd_mailbox *inbox, 2283 struct mlx4_cmd_mailbox *outbox, 2284 struct mlx4_cmd_info *cmd) 2285 { 2286 int err; 2287 int srqn = vhcr->in_modifier; 2288 struct res_mtt *mtt; 2289 struct res_srq *srq; 2290 struct mlx4_srq_context *srqc = inbox->buf; 2291 int mtt_base = srq_get_mtt_addr(srqc) / dev->caps.mtt_entry_sz; 2292 2293 if (srqn != (be32_to_cpu(srqc->state_logsize_srqn) & 0xffffff)) 2294 return -EINVAL; 2295 2296 err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_HW, &srq); 2297 if (err) 2298 return err; 2299 err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); 2300 if (err) 2301 goto ex_abort; 2302 err = check_mtt_range(dev, slave, mtt_base, srq_get_mtt_size(srqc), 2303 mtt); 2304 if (err) 2305 goto ex_put_mtt; 2306 2307 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2308 if (err) 2309 goto ex_put_mtt; 2310 2311 atomic_inc(&mtt->ref_count); 2312 srq->mtt = mtt; 2313 put_res(dev, slave, mtt->com.res_id, RES_MTT); 2314 res_end_move(dev, slave, RES_SRQ, srqn); 2315 return 0; 2316 2317 ex_put_mtt: 2318 put_res(dev, slave, mtt->com.res_id, RES_MTT); 2319 ex_abort: 2320 res_abort_move(dev, slave, RES_SRQ, srqn); 2321 2322 return err; 2323 } 2324 2325 int mlx4_HW2SW_SRQ_wrapper(struct mlx4_dev *dev, int slave, 2326 struct mlx4_vhcr *vhcr, 2327 struct mlx4_cmd_mailbox *inbox, 2328 struct mlx4_cmd_mailbox *outbox, 2329 struct mlx4_cmd_info *cmd) 2330 { 2331 int err; 2332 int srqn = vhcr->in_modifier; 2333 struct res_srq *srq; 2334 2335 err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_ALLOCATED, &srq); 2336 if (err) 2337 return err; 2338 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2339 if (err) 2340 goto ex_abort; 2341 atomic_dec(&srq->mtt->ref_count); 2342 if (srq->cq) 2343 atomic_dec(&srq->cq->ref_count); 2344 res_end_move(dev, slave, RES_SRQ, srqn); 2345 2346 return 0; 2347 2348 ex_abort: 2349 res_abort_move(dev, slave, RES_SRQ, srqn); 2350 2351 return err; 2352 } 2353 2354 int mlx4_QUERY_SRQ_wrapper(struct mlx4_dev *dev, int slave, 2355 struct mlx4_vhcr *vhcr, 2356 struct mlx4_cmd_mailbox *inbox, 2357 struct mlx4_cmd_mailbox *outbox, 2358 struct mlx4_cmd_info *cmd) 2359 { 2360 int err; 2361 int srqn = vhcr->in_modifier; 2362 struct res_srq *srq; 2363 2364 err = get_res(dev, slave, srqn, RES_SRQ, &srq); 2365 if (err) 2366 return err; 2367 if (srq->com.from_state != RES_SRQ_HW) { 2368 err = -EBUSY; 2369 goto out; 2370 } 2371 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2372 out: 2373 put_res(dev, slave, srqn, RES_SRQ); 2374 return err; 2375 } 2376 2377 int mlx4_ARM_SRQ_wrapper(struct mlx4_dev *dev, int slave, 2378 struct mlx4_vhcr *vhcr, 2379 struct mlx4_cmd_mailbox *inbox, 2380 struct mlx4_cmd_mailbox *outbox, 2381 struct mlx4_cmd_info *cmd) 2382 { 2383 int err; 2384 int srqn = vhcr->in_modifier; 2385 struct res_srq *srq; 2386 2387 err = get_res(dev, slave, srqn, RES_SRQ, &srq); 2388 if (err) 2389 return err; 2390 2391 if (srq->com.from_state != RES_SRQ_HW) { 2392 err = -EBUSY; 2393 goto out; 2394 } 2395 2396 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2397 out: 2398 put_res(dev, slave, srqn, RES_SRQ); 2399 return err; 2400 } 2401 2402 int mlx4_GEN_QP_wrapper(struct mlx4_dev *dev, int slave, 2403 struct mlx4_vhcr *vhcr, 2404 struct mlx4_cmd_mailbox *inbox, 2405 struct mlx4_cmd_mailbox *outbox, 2406 struct mlx4_cmd_info *cmd) 2407 { 2408 int err; 2409 int qpn = vhcr->in_modifier & 0x7fffff; 2410 struct res_qp *qp; 2411 2412 err = get_res(dev, slave, qpn, RES_QP, &qp); 2413 if (err) 2414 return err; 2415 if (qp->com.from_state != RES_QP_HW) { 2416 err = -EBUSY; 2417 goto out; 2418 } 2419 2420 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2421 out: 2422 put_res(dev, slave, qpn, RES_QP); 2423 return err; 2424 } 2425 2426 int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, 2427 struct mlx4_vhcr *vhcr, 2428 struct mlx4_cmd_mailbox *inbox, 2429 struct mlx4_cmd_mailbox *outbox, 2430 struct mlx4_cmd_info *cmd) 2431 { 2432 struct mlx4_qp_context *qpc = inbox->buf + 8; 2433 2434 update_ud_gid(dev, qpc, (u8)slave); 2435 2436 return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2437 } 2438 2439 int mlx4_2RST_QP_wrapper(struct mlx4_dev *dev, int slave, 2440 struct mlx4_vhcr *vhcr, 2441 struct mlx4_cmd_mailbox *inbox, 2442 struct mlx4_cmd_mailbox *outbox, 2443 struct mlx4_cmd_info *cmd) 2444 { 2445 int err; 2446 int qpn = vhcr->in_modifier & 0x7fffff; 2447 struct res_qp *qp; 2448 2449 err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED, &qp, 0); 2450 if (err) 2451 return err; 2452 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2453 if (err) 2454 goto ex_abort; 2455 2456 atomic_dec(&qp->mtt->ref_count); 2457 atomic_dec(&qp->rcq->ref_count); 2458 atomic_dec(&qp->scq->ref_count); 2459 if (qp->srq) 2460 atomic_dec(&qp->srq->ref_count); 2461 res_end_move(dev, slave, RES_QP, qpn); 2462 return 0; 2463 2464 ex_abort: 2465 res_abort_move(dev, slave, RES_QP, qpn); 2466 2467 return err; 2468 } 2469 2470 static struct res_gid *find_gid(struct mlx4_dev *dev, int slave, 2471 struct res_qp *rqp, u8 *gid) 2472 { 2473 struct res_gid *res; 2474 2475 list_for_each_entry(res, &rqp->mcg_list, list) { 2476 if (!memcmp(res->gid, gid, 16)) 2477 return res; 2478 } 2479 return NULL; 2480 } 2481 2482 static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp, 2483 u8 *gid, enum mlx4_protocol prot, 2484 enum mlx4_steer_type steer) 2485 { 2486 struct res_gid *res; 2487 int err; 2488 2489 res = kzalloc(sizeof *res, GFP_KERNEL); 2490 if (!res) 2491 return -ENOMEM; 2492 2493 spin_lock_irq(&rqp->mcg_spl); 2494 if (find_gid(dev, slave, rqp, gid)) { 2495 kfree(res); 2496 err = -EEXIST; 2497 } else { 2498 memcpy(res->gid, gid, 16); 2499 res->prot = prot; 2500 res->steer = steer; 2501 list_add_tail(&res->list, &rqp->mcg_list); 2502 err = 0; 2503 } 2504 spin_unlock_irq(&rqp->mcg_spl); 2505 2506 return err; 2507 } 2508 2509 static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp, 2510 u8 *gid, enum mlx4_protocol prot, 2511 enum mlx4_steer_type steer) 2512 { 2513 struct res_gid *res; 2514 int err; 2515 2516 spin_lock_irq(&rqp->mcg_spl); 2517 res = find_gid(dev, slave, rqp, gid); 2518 if (!res || res->prot != prot || res->steer != steer) 2519 err = -EINVAL; 2520 else { 2521 list_del(&res->list); 2522 kfree(res); 2523 err = 0; 2524 } 2525 spin_unlock_irq(&rqp->mcg_spl); 2526 2527 return err; 2528 } 2529 2530 int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, 2531 struct mlx4_vhcr *vhcr, 2532 struct mlx4_cmd_mailbox *inbox, 2533 struct mlx4_cmd_mailbox *outbox, 2534 struct mlx4_cmd_info *cmd) 2535 { 2536 struct mlx4_qp qp; /* dummy for calling attach/detach */ 2537 u8 *gid = inbox->buf; 2538 enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7; 2539 int err, err1; 2540 int qpn; 2541 struct res_qp *rqp; 2542 int attach = vhcr->op_modifier; 2543 int block_loopback = vhcr->in_modifier >> 31; 2544 u8 steer_type_mask = 2; 2545 enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1; 2546 2547 qpn = vhcr->in_modifier & 0xffffff; 2548 err = get_res(dev, slave, qpn, RES_QP, &rqp); 2549 if (err) 2550 return err; 2551 2552 qp.qpn = qpn; 2553 if (attach) { 2554 err = add_mcg_res(dev, slave, rqp, gid, prot, type); 2555 if (err) 2556 goto ex_put; 2557 2558 err = mlx4_qp_attach_common(dev, &qp, gid, 2559 block_loopback, prot, type); 2560 if (err) 2561 goto ex_rem; 2562 } else { 2563 err = rem_mcg_res(dev, slave, rqp, gid, prot, type); 2564 if (err) 2565 goto ex_put; 2566 err = mlx4_qp_detach_common(dev, &qp, gid, prot, type); 2567 } 2568 2569 put_res(dev, slave, qpn, RES_QP); 2570 return 0; 2571 2572 ex_rem: 2573 /* ignore error return below, already in error */ 2574 err1 = rem_mcg_res(dev, slave, rqp, gid, prot, type); 2575 ex_put: 2576 put_res(dev, slave, qpn, RES_QP); 2577 2578 return err; 2579 } 2580 2581 enum { 2582 BUSY_MAX_RETRIES = 10 2583 }; 2584 2585 int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave, 2586 struct mlx4_vhcr *vhcr, 2587 struct mlx4_cmd_mailbox *inbox, 2588 struct mlx4_cmd_mailbox *outbox, 2589 struct mlx4_cmd_info *cmd) 2590 { 2591 int err; 2592 int index = vhcr->in_modifier & 0xffff; 2593 2594 err = get_res(dev, slave, index, RES_COUNTER, NULL); 2595 if (err) 2596 return err; 2597 2598 err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); 2599 put_res(dev, slave, index, RES_COUNTER); 2600 return err; 2601 } 2602 2603 static void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp) 2604 { 2605 struct res_gid *rgid; 2606 struct res_gid *tmp; 2607 int err; 2608 struct mlx4_qp qp; /* dummy for calling attach/detach */ 2609 2610 list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) { 2611 qp.qpn = rqp->local_qpn; 2612 err = mlx4_qp_detach_common(dev, &qp, rgid->gid, rgid->prot, 2613 rgid->steer); 2614 list_del(&rgid->list); 2615 kfree(rgid); 2616 } 2617 } 2618 2619 static int _move_all_busy(struct mlx4_dev *dev, int slave, 2620 enum mlx4_resource type, int print) 2621 { 2622 struct mlx4_priv *priv = mlx4_priv(dev); 2623 struct mlx4_resource_tracker *tracker = 2624 &priv->mfunc.master.res_tracker; 2625 struct list_head *rlist = &tracker->slave_list[slave].res_list[type]; 2626 struct res_common *r; 2627 struct res_common *tmp; 2628 int busy; 2629 2630 busy = 0; 2631 spin_lock_irq(mlx4_tlock(dev)); 2632 list_for_each_entry_safe(r, tmp, rlist, list) { 2633 if (r->owner == slave) { 2634 if (!r->removing) { 2635 if (r->state == RES_ANY_BUSY) { 2636 if (print) 2637 mlx4_dbg(dev, 2638 "%s id 0x%x is busy\n", 2639 ResourceType(type), 2640 r->res_id); 2641 ++busy; 2642 } else { 2643 r->from_state = r->state; 2644 r->state = RES_ANY_BUSY; 2645 r->removing = 1; 2646 } 2647 } 2648 } 2649 } 2650 spin_unlock_irq(mlx4_tlock(dev)); 2651 2652 return busy; 2653 } 2654 2655 static int move_all_busy(struct mlx4_dev *dev, int slave, 2656 enum mlx4_resource type) 2657 { 2658 unsigned long begin; 2659 int busy; 2660 2661 begin = jiffies; 2662 do { 2663 busy = _move_all_busy(dev, slave, type, 0); 2664 if (time_after(jiffies, begin + 5 * HZ)) 2665 break; 2666 if (busy) 2667 cond_resched(); 2668 } while (busy); 2669 2670 if (busy) 2671 busy = _move_all_busy(dev, slave, type, 1); 2672 2673 return busy; 2674 } 2675 static void rem_slave_qps(struct mlx4_dev *dev, int slave) 2676 { 2677 struct mlx4_priv *priv = mlx4_priv(dev); 2678 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 2679 struct list_head *qp_list = 2680 &tracker->slave_list[slave].res_list[RES_QP]; 2681 struct res_qp *qp; 2682 struct res_qp *tmp; 2683 int state; 2684 u64 in_param; 2685 int qpn; 2686 int err; 2687 2688 err = move_all_busy(dev, slave, RES_QP); 2689 if (err) 2690 mlx4_warn(dev, "rem_slave_qps: Could not move all qps to busy" 2691 "for slave %d\n", slave); 2692 2693 spin_lock_irq(mlx4_tlock(dev)); 2694 list_for_each_entry_safe(qp, tmp, qp_list, com.list) { 2695 spin_unlock_irq(mlx4_tlock(dev)); 2696 if (qp->com.owner == slave) { 2697 qpn = qp->com.res_id; 2698 detach_qp(dev, slave, qp); 2699 state = qp->com.from_state; 2700 while (state != 0) { 2701 switch (state) { 2702 case RES_QP_RESERVED: 2703 spin_lock_irq(mlx4_tlock(dev)); 2704 radix_tree_delete(&tracker->res_tree[RES_QP], 2705 qp->com.res_id); 2706 list_del(&qp->com.list); 2707 spin_unlock_irq(mlx4_tlock(dev)); 2708 kfree(qp); 2709 state = 0; 2710 break; 2711 case RES_QP_MAPPED: 2712 if (!valid_reserved(dev, slave, qpn)) 2713 __mlx4_qp_free_icm(dev, qpn); 2714 state = RES_QP_RESERVED; 2715 break; 2716 case RES_QP_HW: 2717 in_param = slave; 2718 err = mlx4_cmd(dev, in_param, 2719 qp->local_qpn, 2, 2720 MLX4_CMD_2RST_QP, 2721 MLX4_CMD_TIME_CLASS_A, 2722 MLX4_CMD_NATIVE); 2723 if (err) 2724 mlx4_dbg(dev, "rem_slave_qps: failed" 2725 " to move slave %d qpn %d to" 2726 " reset\n", slave, 2727 qp->local_qpn); 2728 atomic_dec(&qp->rcq->ref_count); 2729 atomic_dec(&qp->scq->ref_count); 2730 atomic_dec(&qp->mtt->ref_count); 2731 if (qp->srq) 2732 atomic_dec(&qp->srq->ref_count); 2733 state = RES_QP_MAPPED; 2734 break; 2735 default: 2736 state = 0; 2737 } 2738 } 2739 } 2740 spin_lock_irq(mlx4_tlock(dev)); 2741 } 2742 spin_unlock_irq(mlx4_tlock(dev)); 2743 } 2744 2745 static void rem_slave_srqs(struct mlx4_dev *dev, int slave) 2746 { 2747 struct mlx4_priv *priv = mlx4_priv(dev); 2748 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 2749 struct list_head *srq_list = 2750 &tracker->slave_list[slave].res_list[RES_SRQ]; 2751 struct res_srq *srq; 2752 struct res_srq *tmp; 2753 int state; 2754 u64 in_param; 2755 LIST_HEAD(tlist); 2756 int srqn; 2757 int err; 2758 2759 err = move_all_busy(dev, slave, RES_SRQ); 2760 if (err) 2761 mlx4_warn(dev, "rem_slave_srqs: Could not move all srqs to " 2762 "busy for slave %d\n", slave); 2763 2764 spin_lock_irq(mlx4_tlock(dev)); 2765 list_for_each_entry_safe(srq, tmp, srq_list, com.list) { 2766 spin_unlock_irq(mlx4_tlock(dev)); 2767 if (srq->com.owner == slave) { 2768 srqn = srq->com.res_id; 2769 state = srq->com.from_state; 2770 while (state != 0) { 2771 switch (state) { 2772 case RES_SRQ_ALLOCATED: 2773 __mlx4_srq_free_icm(dev, srqn); 2774 spin_lock_irq(mlx4_tlock(dev)); 2775 radix_tree_delete(&tracker->res_tree[RES_SRQ], 2776 srqn); 2777 list_del(&srq->com.list); 2778 spin_unlock_irq(mlx4_tlock(dev)); 2779 kfree(srq); 2780 state = 0; 2781 break; 2782 2783 case RES_SRQ_HW: 2784 in_param = slave; 2785 err = mlx4_cmd(dev, in_param, srqn, 1, 2786 MLX4_CMD_HW2SW_SRQ, 2787 MLX4_CMD_TIME_CLASS_A, 2788 MLX4_CMD_NATIVE); 2789 if (err) 2790 mlx4_dbg(dev, "rem_slave_srqs: failed" 2791 " to move slave %d srq %d to" 2792 " SW ownership\n", 2793 slave, srqn); 2794 2795 atomic_dec(&srq->mtt->ref_count); 2796 if (srq->cq) 2797 atomic_dec(&srq->cq->ref_count); 2798 state = RES_SRQ_ALLOCATED; 2799 break; 2800 2801 default: 2802 state = 0; 2803 } 2804 } 2805 } 2806 spin_lock_irq(mlx4_tlock(dev)); 2807 } 2808 spin_unlock_irq(mlx4_tlock(dev)); 2809 } 2810 2811 static void rem_slave_cqs(struct mlx4_dev *dev, int slave) 2812 { 2813 struct mlx4_priv *priv = mlx4_priv(dev); 2814 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 2815 struct list_head *cq_list = 2816 &tracker->slave_list[slave].res_list[RES_CQ]; 2817 struct res_cq *cq; 2818 struct res_cq *tmp; 2819 int state; 2820 u64 in_param; 2821 LIST_HEAD(tlist); 2822 int cqn; 2823 int err; 2824 2825 err = move_all_busy(dev, slave, RES_CQ); 2826 if (err) 2827 mlx4_warn(dev, "rem_slave_cqs: Could not move all cqs to " 2828 "busy for slave %d\n", slave); 2829 2830 spin_lock_irq(mlx4_tlock(dev)); 2831 list_for_each_entry_safe(cq, tmp, cq_list, com.list) { 2832 spin_unlock_irq(mlx4_tlock(dev)); 2833 if (cq->com.owner == slave && !atomic_read(&cq->ref_count)) { 2834 cqn = cq->com.res_id; 2835 state = cq->com.from_state; 2836 while (state != 0) { 2837 switch (state) { 2838 case RES_CQ_ALLOCATED: 2839 __mlx4_cq_free_icm(dev, cqn); 2840 spin_lock_irq(mlx4_tlock(dev)); 2841 radix_tree_delete(&tracker->res_tree[RES_CQ], 2842 cqn); 2843 list_del(&cq->com.list); 2844 spin_unlock_irq(mlx4_tlock(dev)); 2845 kfree(cq); 2846 state = 0; 2847 break; 2848 2849 case RES_CQ_HW: 2850 in_param = slave; 2851 err = mlx4_cmd(dev, in_param, cqn, 1, 2852 MLX4_CMD_HW2SW_CQ, 2853 MLX4_CMD_TIME_CLASS_A, 2854 MLX4_CMD_NATIVE); 2855 if (err) 2856 mlx4_dbg(dev, "rem_slave_cqs: failed" 2857 " to move slave %d cq %d to" 2858 " SW ownership\n", 2859 slave, cqn); 2860 atomic_dec(&cq->mtt->ref_count); 2861 state = RES_CQ_ALLOCATED; 2862 break; 2863 2864 default: 2865 state = 0; 2866 } 2867 } 2868 } 2869 spin_lock_irq(mlx4_tlock(dev)); 2870 } 2871 spin_unlock_irq(mlx4_tlock(dev)); 2872 } 2873 2874 static void rem_slave_mrs(struct mlx4_dev *dev, int slave) 2875 { 2876 struct mlx4_priv *priv = mlx4_priv(dev); 2877 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 2878 struct list_head *mpt_list = 2879 &tracker->slave_list[slave].res_list[RES_MPT]; 2880 struct res_mpt *mpt; 2881 struct res_mpt *tmp; 2882 int state; 2883 u64 in_param; 2884 LIST_HEAD(tlist); 2885 int mptn; 2886 int err; 2887 2888 err = move_all_busy(dev, slave, RES_MPT); 2889 if (err) 2890 mlx4_warn(dev, "rem_slave_mrs: Could not move all mpts to " 2891 "busy for slave %d\n", slave); 2892 2893 spin_lock_irq(mlx4_tlock(dev)); 2894 list_for_each_entry_safe(mpt, tmp, mpt_list, com.list) { 2895 spin_unlock_irq(mlx4_tlock(dev)); 2896 if (mpt->com.owner == slave) { 2897 mptn = mpt->com.res_id; 2898 state = mpt->com.from_state; 2899 while (state != 0) { 2900 switch (state) { 2901 case RES_MPT_RESERVED: 2902 __mlx4_mr_release(dev, mpt->key); 2903 spin_lock_irq(mlx4_tlock(dev)); 2904 radix_tree_delete(&tracker->res_tree[RES_MPT], 2905 mptn); 2906 list_del(&mpt->com.list); 2907 spin_unlock_irq(mlx4_tlock(dev)); 2908 kfree(mpt); 2909 state = 0; 2910 break; 2911 2912 case RES_MPT_MAPPED: 2913 __mlx4_mr_free_icm(dev, mpt->key); 2914 state = RES_MPT_RESERVED; 2915 break; 2916 2917 case RES_MPT_HW: 2918 in_param = slave; 2919 err = mlx4_cmd(dev, in_param, mptn, 0, 2920 MLX4_CMD_HW2SW_MPT, 2921 MLX4_CMD_TIME_CLASS_A, 2922 MLX4_CMD_NATIVE); 2923 if (err) 2924 mlx4_dbg(dev, "rem_slave_mrs: failed" 2925 " to move slave %d mpt %d to" 2926 " SW ownership\n", 2927 slave, mptn); 2928 if (mpt->mtt) 2929 atomic_dec(&mpt->mtt->ref_count); 2930 state = RES_MPT_MAPPED; 2931 break; 2932 default: 2933 state = 0; 2934 } 2935 } 2936 } 2937 spin_lock_irq(mlx4_tlock(dev)); 2938 } 2939 spin_unlock_irq(mlx4_tlock(dev)); 2940 } 2941 2942 static void rem_slave_mtts(struct mlx4_dev *dev, int slave) 2943 { 2944 struct mlx4_priv *priv = mlx4_priv(dev); 2945 struct mlx4_resource_tracker *tracker = 2946 &priv->mfunc.master.res_tracker; 2947 struct list_head *mtt_list = 2948 &tracker->slave_list[slave].res_list[RES_MTT]; 2949 struct res_mtt *mtt; 2950 struct res_mtt *tmp; 2951 int state; 2952 LIST_HEAD(tlist); 2953 int base; 2954 int err; 2955 2956 err = move_all_busy(dev, slave, RES_MTT); 2957 if (err) 2958 mlx4_warn(dev, "rem_slave_mtts: Could not move all mtts to " 2959 "busy for slave %d\n", slave); 2960 2961 spin_lock_irq(mlx4_tlock(dev)); 2962 list_for_each_entry_safe(mtt, tmp, mtt_list, com.list) { 2963 spin_unlock_irq(mlx4_tlock(dev)); 2964 if (mtt->com.owner == slave) { 2965 base = mtt->com.res_id; 2966 state = mtt->com.from_state; 2967 while (state != 0) { 2968 switch (state) { 2969 case RES_MTT_ALLOCATED: 2970 __mlx4_free_mtt_range(dev, base, 2971 mtt->order); 2972 spin_lock_irq(mlx4_tlock(dev)); 2973 radix_tree_delete(&tracker->res_tree[RES_MTT], 2974 base); 2975 list_del(&mtt->com.list); 2976 spin_unlock_irq(mlx4_tlock(dev)); 2977 kfree(mtt); 2978 state = 0; 2979 break; 2980 2981 default: 2982 state = 0; 2983 } 2984 } 2985 } 2986 spin_lock_irq(mlx4_tlock(dev)); 2987 } 2988 spin_unlock_irq(mlx4_tlock(dev)); 2989 } 2990 2991 static void rem_slave_eqs(struct mlx4_dev *dev, int slave) 2992 { 2993 struct mlx4_priv *priv = mlx4_priv(dev); 2994 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 2995 struct list_head *eq_list = 2996 &tracker->slave_list[slave].res_list[RES_EQ]; 2997 struct res_eq *eq; 2998 struct res_eq *tmp; 2999 int err; 3000 int state; 3001 LIST_HEAD(tlist); 3002 int eqn; 3003 struct mlx4_cmd_mailbox *mailbox; 3004 3005 err = move_all_busy(dev, slave, RES_EQ); 3006 if (err) 3007 mlx4_warn(dev, "rem_slave_eqs: Could not move all eqs to " 3008 "busy for slave %d\n", slave); 3009 3010 spin_lock_irq(mlx4_tlock(dev)); 3011 list_for_each_entry_safe(eq, tmp, eq_list, com.list) { 3012 spin_unlock_irq(mlx4_tlock(dev)); 3013 if (eq->com.owner == slave) { 3014 eqn = eq->com.res_id; 3015 state = eq->com.from_state; 3016 while (state != 0) { 3017 switch (state) { 3018 case RES_EQ_RESERVED: 3019 spin_lock_irq(mlx4_tlock(dev)); 3020 radix_tree_delete(&tracker->res_tree[RES_EQ], 3021 eqn); 3022 list_del(&eq->com.list); 3023 spin_unlock_irq(mlx4_tlock(dev)); 3024 kfree(eq); 3025 state = 0; 3026 break; 3027 3028 case RES_EQ_HW: 3029 mailbox = mlx4_alloc_cmd_mailbox(dev); 3030 if (IS_ERR(mailbox)) { 3031 cond_resched(); 3032 continue; 3033 } 3034 err = mlx4_cmd_box(dev, slave, 0, 3035 eqn & 0xff, 0, 3036 MLX4_CMD_HW2SW_EQ, 3037 MLX4_CMD_TIME_CLASS_A, 3038 MLX4_CMD_NATIVE); 3039 mlx4_dbg(dev, "rem_slave_eqs: failed" 3040 " to move slave %d eqs %d to" 3041 " SW ownership\n", slave, eqn); 3042 mlx4_free_cmd_mailbox(dev, mailbox); 3043 if (!err) { 3044 atomic_dec(&eq->mtt->ref_count); 3045 state = RES_EQ_RESERVED; 3046 } 3047 break; 3048 3049 default: 3050 state = 0; 3051 } 3052 } 3053 } 3054 spin_lock_irq(mlx4_tlock(dev)); 3055 } 3056 spin_unlock_irq(mlx4_tlock(dev)); 3057 } 3058 3059 void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) 3060 { 3061 struct mlx4_priv *priv = mlx4_priv(dev); 3062 3063 mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); 3064 /*VLAN*/ 3065 rem_slave_macs(dev, slave); 3066 rem_slave_qps(dev, slave); 3067 rem_slave_srqs(dev, slave); 3068 rem_slave_cqs(dev, slave); 3069 rem_slave_mrs(dev, slave); 3070 rem_slave_eqs(dev, slave); 3071 rem_slave_mtts(dev, slave); 3072 mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); 3073 } 3074