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