mlx4_resource_tracker.c revision 255932
1255932Salfred/*
2255932Salfred * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
3255932Salfred * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies.
4255932Salfred * All rights reserved.
5255932Salfred * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc.  All rights reserved.
6255932Salfred *
7255932Salfred * This software is available to you under a choice of one of two
8255932Salfred * licenses.  You may choose to be licensed under the terms of the GNU
9255932Salfred * General Public License (GPL) Version 2, available from the file
10255932Salfred * COPYING in the main directory of this source tree, or the
11255932Salfred * OpenIB.org BSD license below:
12255932Salfred *
13255932Salfred *     Redistribution and use in source and binary forms, with or
14255932Salfred *     without modification, are permitted provided that the following
15255932Salfred *     conditions are met:
16255932Salfred *
17255932Salfred *      - Redistributions of source code must retain the above
18255932Salfred *        copyright notice, this list of conditions and the following
19255932Salfred *        disclaimer.
20255932Salfred *
21255932Salfred *      - Redistributions in binary form must reproduce the above
22255932Salfred *        copyright notice, this list of conditions and the following
23255932Salfred *        disclaimer in the documentation and/or other materials
24255932Salfred *        provided with the distribution.
25255932Salfred *
26255932Salfred * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27255932Salfred * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28255932Salfred * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29255932Salfred * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30255932Salfred * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31255932Salfred * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32255932Salfred * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33255932Salfred * SOFTWARE.
34255932Salfred */
35255932Salfred
36255932Salfred#include <linux/sched.h>
37255932Salfred#include <linux/pci.h>
38255932Salfred#include <linux/errno.h>
39255932Salfred#include <linux/kernel.h>
40255932Salfred#include <linux/io.h>
41255932Salfred#include <linux/slab.h>
42255932Salfred#include <linux/mlx4/cmd.h>
43255932Salfred#include <linux/mlx4/qp.h>
44255932Salfred#include <linux/if_ether.h>
45255932Salfred#include <linux/compat.h>
46255932Salfred
47255932Salfred#include "mlx4.h"
48255932Salfred#include "fw.h"
49255932Salfred
50255932Salfred#define MLX4_MAC_VALID		(1ull << 63)
51255932Salfred
52255932Salfredstruct mac_res {
53255932Salfred	struct list_head list;
54255932Salfred	u64 mac;
55255932Salfred	int ref_count;
56255932Salfred	u8 smac_index;
57255932Salfred	u8 port;
58255932Salfred};
59255932Salfred
60255932Salfredstruct vlan_res {
61255932Salfred	struct list_head list;
62255932Salfred	u16 vlan;
63255932Salfred	int ref_count;
64255932Salfred	int vlan_index;
65255932Salfred	u8 port;
66255932Salfred};
67255932Salfred
68255932Salfredstruct res_common {
69255932Salfred	struct list_head	list;
70255932Salfred	struct rb_node		node;
71255932Salfred	u64		        res_id;
72255932Salfred	int			owner;
73255932Salfred	int			state;
74255932Salfred	int			from_state;
75255932Salfred	int			to_state;
76255932Salfred	int			removing;
77255932Salfred};
78255932Salfred
79255932Salfredenum {
80255932Salfred	RES_ANY_BUSY = 1
81255932Salfred};
82255932Salfred
83255932Salfredstruct res_gid {
84255932Salfred	struct list_head	list;
85255932Salfred	u8			gid[16];
86255932Salfred	enum mlx4_protocol	prot;
87255932Salfred	enum mlx4_steer_type	steer;
88255932Salfred};
89255932Salfred
90255932Salfredenum res_qp_states {
91255932Salfred	RES_QP_BUSY = RES_ANY_BUSY,
92255932Salfred
93255932Salfred	/* QP number was allocated */
94255932Salfred	RES_QP_RESERVED,
95255932Salfred
96255932Salfred	/* ICM memory for QP context was mapped */
97255932Salfred	RES_QP_MAPPED,
98255932Salfred
99255932Salfred	/* QP is in hw ownership */
100255932Salfred	RES_QP_HW
101255932Salfred};
102255932Salfred
103255932Salfredstruct res_qp {
104255932Salfred	struct res_common	com;
105255932Salfred	struct res_mtt	       *mtt;
106255932Salfred	struct res_cq	       *rcq;
107255932Salfred	struct res_cq	       *scq;
108255932Salfred	struct res_srq	       *srq;
109255932Salfred	struct list_head	mcg_list;
110255932Salfred	spinlock_t		mcg_spl;
111255932Salfred	int			local_qpn;
112255932Salfred};
113255932Salfred
114255932Salfredenum res_mtt_states {
115255932Salfred	RES_MTT_BUSY = RES_ANY_BUSY,
116255932Salfred	RES_MTT_ALLOCATED,
117255932Salfred};
118255932Salfred
119255932Salfredstatic inline const char *mtt_states_str(enum res_mtt_states state)
120255932Salfred{
121255932Salfred	switch (state) {
122255932Salfred	case RES_MTT_BUSY: return "RES_MTT_BUSY";
123255932Salfred	case RES_MTT_ALLOCATED: return "RES_MTT_ALLOCATED";
124255932Salfred	default: return "Unknown";
125255932Salfred	}
126255932Salfred}
127255932Salfred
128255932Salfredstruct res_mtt {
129255932Salfred	struct res_common	com;
130255932Salfred	int			order;
131255932Salfred	atomic_t		ref_count;
132255932Salfred};
133255932Salfred
134255932Salfredenum res_mpt_states {
135255932Salfred	RES_MPT_BUSY = RES_ANY_BUSY,
136255932Salfred	RES_MPT_RESERVED,
137255932Salfred	RES_MPT_MAPPED,
138255932Salfred	RES_MPT_HW,
139255932Salfred};
140255932Salfred
141255932Salfredstruct res_mpt {
142255932Salfred	struct res_common	com;
143255932Salfred	struct res_mtt	       *mtt;
144255932Salfred	int			key;
145255932Salfred};
146255932Salfred
147255932Salfredenum res_eq_states {
148255932Salfred	RES_EQ_BUSY = RES_ANY_BUSY,
149255932Salfred	RES_EQ_RESERVED,
150255932Salfred	RES_EQ_HW,
151255932Salfred};
152255932Salfred
153255932Salfredstruct res_eq {
154255932Salfred	struct res_common	com;
155255932Salfred	struct res_mtt	       *mtt;
156255932Salfred};
157255932Salfred
158255932Salfredenum res_cq_states {
159255932Salfred	RES_CQ_BUSY = RES_ANY_BUSY,
160255932Salfred	RES_CQ_ALLOCATED,
161255932Salfred	RES_CQ_HW,
162255932Salfred};
163255932Salfred
164255932Salfredstruct res_cq {
165255932Salfred	struct res_common	com;
166255932Salfred	struct res_mtt	       *mtt;
167255932Salfred	atomic_t		ref_count;
168255932Salfred};
169255932Salfred
170255932Salfredenum res_srq_states {
171255932Salfred	RES_SRQ_BUSY = RES_ANY_BUSY,
172255932Salfred	RES_SRQ_ALLOCATED,
173255932Salfred	RES_SRQ_HW,
174255932Salfred};
175255932Salfred
176255932Salfredstruct res_srq {
177255932Salfred	struct res_common	com;
178255932Salfred	struct res_mtt	       *mtt;
179255932Salfred	struct res_cq	       *cq;
180255932Salfred	atomic_t		ref_count;
181255932Salfred};
182255932Salfred
183255932Salfredenum res_counter_states {
184255932Salfred	RES_COUNTER_BUSY = RES_ANY_BUSY,
185255932Salfred	RES_COUNTER_ALLOCATED,
186255932Salfred};
187255932Salfred
188255932Salfredstruct res_counter {
189255932Salfred	struct res_common	com;
190255932Salfred	int			port;
191255932Salfred};
192255932Salfred
193255932Salfredenum res_xrcdn_states {
194255932Salfred	RES_XRCD_BUSY = RES_ANY_BUSY,
195255932Salfred	RES_XRCD_ALLOCATED,
196255932Salfred};
197255932Salfred
198255932Salfredstruct res_xrcdn {
199255932Salfred	struct res_common	com;
200255932Salfred	int			port;
201255932Salfred};
202255932Salfred
203255932Salfredenum res_fs_rule_states {
204255932Salfred	RES_FS_RULE_BUSY = RES_ANY_BUSY,
205255932Salfred	RES_FS_RULE_ALLOCATED,
206255932Salfred};
207255932Salfred
208255932Salfredstruct res_fs_rule {
209255932Salfred	struct res_common	com;
210255932Salfred};
211255932Salfred
212255932Salfredstatic int mlx4_is_eth(struct mlx4_dev *dev, int port)
213255932Salfred{
214255932Salfred	return dev->caps.port_mask[port] == MLX4_PORT_TYPE_IB ? 0 : 1;
215255932Salfred}
216255932Salfred
217255932Salfredstatic void *res_tracker_lookup(struct rb_root *root, u64 res_id)
218255932Salfred{
219255932Salfred	struct rb_node *node = root->rb_node;
220255932Salfred
221255932Salfred	while (node) {
222255932Salfred		struct res_common *res = container_of(node, struct res_common,
223255932Salfred						      node);
224255932Salfred
225255932Salfred		if (res_id < res->res_id)
226255932Salfred			node = node->rb_left;
227255932Salfred		else if (res_id > res->res_id)
228255932Salfred			node = node->rb_right;
229255932Salfred		else
230255932Salfred			return res;
231255932Salfred	}
232255932Salfred	return NULL;
233255932Salfred}
234255932Salfred
235255932Salfredstatic int res_tracker_insert(struct rb_root *root, struct res_common *res)
236255932Salfred{
237255932Salfred	struct rb_node **new = &(root->rb_node), *parent = NULL;
238255932Salfred
239255932Salfred	/* Figure out where to put new node */
240255932Salfred	while (*new) {
241255932Salfred		struct res_common *this = container_of(*new, struct res_common,
242255932Salfred						       node);
243255932Salfred
244255932Salfred		parent = *new;
245255932Salfred		if (res->res_id < this->res_id)
246255932Salfred			new = &((*new)->rb_left);
247255932Salfred		else if (res->res_id > this->res_id)
248255932Salfred			new = &((*new)->rb_right);
249255932Salfred		else
250255932Salfred			return -EEXIST;
251255932Salfred	}
252255932Salfred
253255932Salfred	/* Add new node and rebalance tree. */
254255932Salfred	rb_link_node(&res->node, parent, new);
255255932Salfred	rb_insert_color(&res->node, root);
256255932Salfred
257255932Salfred	return 0;
258255932Salfred}
259255932Salfred
260255932Salfredenum qp_transition {
261255932Salfred	QP_TRANS_INIT2RTR,
262255932Salfred	QP_TRANS_RTR2RTS,
263255932Salfred	QP_TRANS_RTS2RTS,
264255932Salfred	QP_TRANS_SQERR2RTS,
265255932Salfred	QP_TRANS_SQD2SQD,
266255932Salfred	QP_TRANS_SQD2RTS
267255932Salfred};
268255932Salfred
269255932Salfred/* For Debug uses */
270255932Salfredstatic const char *ResourceType(enum mlx4_resource rt)
271255932Salfred{
272255932Salfred	switch (rt) {
273255932Salfred	case RES_QP: return "RES_QP";
274255932Salfred	case RES_CQ: return "RES_CQ";
275255932Salfred	case RES_SRQ: return "RES_SRQ";
276255932Salfred	case RES_MPT: return "RES_MPT";
277255932Salfred	case RES_MTT: return "RES_MTT";
278255932Salfred	case RES_MAC: return  "RES_MAC";
279255932Salfred	case RES_VLAN: return  "RES_VLAN";
280255932Salfred	case RES_EQ: return "RES_EQ";
281255932Salfred	case RES_COUNTER: return "RES_COUNTER";
282255932Salfred	case RES_FS_RULE: return "RES_FS_RULE";
283255932Salfred	case RES_XRCD: return "RES_XRCD";
284255932Salfred	default: return "Unknown resource type !!!";
285255932Salfred	};
286255932Salfred}
287255932Salfred
288255932Salfredstatic void rem_slave_vlans(struct mlx4_dev *dev, int slave);
289255932Salfredstatic inline int mlx4_grant_resource(struct mlx4_dev *dev, int slave,
290255932Salfred				      enum mlx4_resource res_type, int count,
291255932Salfred				      int port)
292255932Salfred{
293255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
294255932Salfred	struct resource_allocator *res_alloc =
295255932Salfred		&priv->mfunc.master.res_tracker.res_alloc[res_type];
296255932Salfred	int err = -EINVAL;
297255932Salfred	int allocated, free, reserved, guaranteed, from_free;
298255932Salfred
299255932Salfred	spin_lock(&res_alloc->alloc_lock);
300255932Salfred	allocated = (port > 0) ?
301255932Salfred		res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] :
302255932Salfred		res_alloc->allocated[slave];
303255932Salfred	free = (port > 0) ? res_alloc->res_port_free[port - 1] :
304255932Salfred		res_alloc->res_free;
305255932Salfred	reserved = (port > 0) ? res_alloc->res_port_rsvd[port - 1] :
306255932Salfred		res_alloc->res_reserved;
307255932Salfred	guaranteed = res_alloc->guaranteed[slave];
308255932Salfred
309255932Salfred	if (allocated + count > res_alloc->quota[slave])
310255932Salfred		goto out;
311255932Salfred
312255932Salfred	if (allocated + count <= guaranteed) {
313255932Salfred		err = 0;
314255932Salfred	} else {
315255932Salfred		/* portion may need to be obtained from free area */
316255932Salfred		if (guaranteed - allocated > 0)
317255932Salfred			from_free = count - (guaranteed - allocated);
318255932Salfred		else
319255932Salfred			from_free = count;
320255932Salfred
321255932Salfred		if (free - from_free > reserved)
322255932Salfred			err = 0;
323255932Salfred	}
324255932Salfred
325255932Salfred	if (!err) {
326255932Salfred		/* grant the request */
327255932Salfred		if (port > 0) {
328255932Salfred			res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] += count;
329255932Salfred			res_alloc->res_port_free[port - 1] -= count;
330255932Salfred		} else {
331255932Salfred			res_alloc->allocated[slave] += count;
332255932Salfred			res_alloc->res_free -= count;
333255932Salfred		}
334255932Salfred	}
335255932Salfred
336255932Salfredout:
337255932Salfred	spin_unlock(&res_alloc->alloc_lock);
338255932Salfred	return err;
339255932Salfred
340255932Salfred}
341255932Salfred
342255932Salfredstatic inline void mlx4_release_resource(struct mlx4_dev *dev, int slave,
343255932Salfred				    enum mlx4_resource res_type, int count,
344255932Salfred				    int port)
345255932Salfred{
346255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
347255932Salfred	struct resource_allocator *res_alloc =
348255932Salfred		&priv->mfunc.master.res_tracker.res_alloc[res_type];
349255932Salfred
350255932Salfred	spin_lock(&res_alloc->alloc_lock);
351255932Salfred	if (port > 0) {
352255932Salfred		res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] -= count;
353255932Salfred		res_alloc->res_port_free[port - 1] += count;
354255932Salfred	} else {
355255932Salfred		res_alloc->allocated[slave] -= count;
356255932Salfred		res_alloc->res_free += count;
357255932Salfred	}
358255932Salfred
359255932Salfred	spin_unlock(&res_alloc->alloc_lock);
360255932Salfred	return;
361255932Salfred}
362255932Salfred
363255932Salfredstatic inline void initialize_res_quotas(struct mlx4_dev *dev,
364255932Salfred					 struct resource_allocator *res_alloc,
365255932Salfred					 enum mlx4_resource res_type,
366255932Salfred					 int vf, int num_instances)
367255932Salfred{
368255932Salfred	res_alloc->guaranteed[vf] = num_instances / (2 * (dev->num_vfs + 1));
369255932Salfred	res_alloc->quota[vf] = (num_instances / 2) + res_alloc->guaranteed[vf];
370255932Salfred	if (vf == mlx4_master_func_num(dev)) {
371255932Salfred		res_alloc->res_free = num_instances;
372255932Salfred		if (res_type == RES_MTT) {
373255932Salfred			/* reserved mtts will be taken out of the PF allocation */
374255932Salfred			res_alloc->res_free += dev->caps.reserved_mtts;
375255932Salfred			res_alloc->guaranteed[vf] += dev->caps.reserved_mtts;
376255932Salfred			res_alloc->quota[vf] += dev->caps.reserved_mtts;
377255932Salfred		}
378255932Salfred	}
379255932Salfred}
380255932Salfred
381255932Salfredvoid mlx4_init_quotas(struct mlx4_dev *dev)
382255932Salfred{
383255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
384255932Salfred	int pf;
385255932Salfred
386255932Salfred	/* quotas for VFs are initialized in mlx4_slave_cap */
387255932Salfred	if (mlx4_is_slave(dev))
388255932Salfred		return;
389255932Salfred
390255932Salfred	if (!mlx4_is_mfunc(dev)) {
391255932Salfred		dev->quotas.qp = dev->caps.num_qps - dev->caps.reserved_qps -
392255932Salfred			mlx4_num_reserved_sqps(dev);
393255932Salfred		dev->quotas.cq = dev->caps.num_cqs - dev->caps.reserved_cqs;
394255932Salfred		dev->quotas.srq = dev->caps.num_srqs - dev->caps.reserved_srqs;
395255932Salfred		dev->quotas.mtt = dev->caps.num_mtts - dev->caps.reserved_mtts;
396255932Salfred		dev->quotas.mpt = dev->caps.num_mpts - dev->caps.reserved_mrws;
397255932Salfred		return;
398255932Salfred	}
399255932Salfred
400255932Salfred	pf = mlx4_master_func_num(dev);
401255932Salfred	dev->quotas.qp =
402255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[pf];
403255932Salfred	dev->quotas.cq =
404255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[pf];
405255932Salfred	dev->quotas.srq =
406255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[pf];
407255932Salfred	dev->quotas.mtt =
408255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[pf];
409255932Salfred	dev->quotas.mpt =
410255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[pf];
411255932Salfred}
412255932Salfredint mlx4_init_resource_tracker(struct mlx4_dev *dev)
413255932Salfred{
414255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
415255932Salfred	int i, j;
416255932Salfred	int t;
417255932Salfred
418255932Salfred	priv->mfunc.master.res_tracker.slave_list =
419255932Salfred		kzalloc(dev->num_slaves * sizeof(struct slave_list),
420255932Salfred			GFP_KERNEL);
421255932Salfred	if (!priv->mfunc.master.res_tracker.slave_list)
422255932Salfred		return -ENOMEM;
423255932Salfred
424255932Salfred	for (i = 0 ; i < dev->num_slaves; i++) {
425255932Salfred		for (t = 0; t < MLX4_NUM_OF_RESOURCE_TYPE; ++t)
426255932Salfred			INIT_LIST_HEAD(&priv->mfunc.master.res_tracker.
427255932Salfred				       slave_list[i].res_list[t]);
428255932Salfred		mutex_init(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
429255932Salfred	}
430255932Salfred
431255932Salfred	mlx4_dbg(dev, "Started init_resource_tracker: %ld slaves\n",
432255932Salfred		 dev->num_slaves);
433255932Salfred	for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++)
434255932Salfred		priv->mfunc.master.res_tracker.res_tree[i] = RB_ROOT;
435255932Salfred
436255932Salfred	for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
437255932Salfred		struct resource_allocator *res_alloc =
438255932Salfred			&priv->mfunc.master.res_tracker.res_alloc[i];
439255932Salfred		res_alloc->quota = kmalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL);
440255932Salfred		res_alloc->guaranteed = kmalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL);
441255932Salfred		if (i == RES_MAC || i == RES_VLAN)
442255932Salfred			res_alloc->allocated = kzalloc(MLX4_MAX_PORTS *
443255932Salfred						       (dev->num_vfs + 1) * sizeof(int),
444255932Salfred							GFP_KERNEL);
445255932Salfred		else
446255932Salfred			res_alloc->allocated = kzalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL);
447255932Salfred
448255932Salfred		if (!res_alloc->quota || !res_alloc->guaranteed ||
449255932Salfred		    !res_alloc->allocated)
450255932Salfred			goto no_mem_err;
451255932Salfred
452255932Salfred		spin_lock_init(&res_alloc->alloc_lock);
453255932Salfred		for (t = 0; t < dev->num_vfs + 1; t++) {
454255932Salfred			switch (i) {
455255932Salfred			case RES_QP:
456255932Salfred				initialize_res_quotas(dev, res_alloc, RES_QP,
457255932Salfred						      t, dev->caps.num_qps -
458255932Salfred						      dev->caps.reserved_qps -
459255932Salfred						      mlx4_num_reserved_sqps(dev));
460255932Salfred				break;
461255932Salfred			case RES_CQ:
462255932Salfred				initialize_res_quotas(dev, res_alloc, RES_CQ,
463255932Salfred						      t, dev->caps.num_cqs -
464255932Salfred						      dev->caps.reserved_cqs);
465255932Salfred				break;
466255932Salfred			case RES_SRQ:
467255932Salfred				initialize_res_quotas(dev, res_alloc, RES_SRQ,
468255932Salfred						      t, dev->caps.num_srqs -
469255932Salfred						      dev->caps.reserved_srqs);
470255932Salfred				break;
471255932Salfred			case RES_MPT:
472255932Salfred				initialize_res_quotas(dev, res_alloc, RES_MPT,
473255932Salfred						      t, dev->caps.num_mpts -
474255932Salfred						      dev->caps.reserved_mrws);
475255932Salfred				break;
476255932Salfred			case RES_MTT:
477255932Salfred				initialize_res_quotas(dev, res_alloc, RES_MTT,
478255932Salfred						      t, dev->caps.num_mtts -
479255932Salfred						      dev->caps.reserved_mtts);
480255932Salfred				break;
481255932Salfred			case RES_MAC:
482255932Salfred				if (t == mlx4_master_func_num(dev)) {
483255932Salfred					res_alloc->quota[t] =
484255932Salfred						MLX4_MAX_MAC_NUM - 2 * dev->num_vfs;
485255932Salfred					res_alloc->guaranteed[t] = res_alloc->quota[t];
486255932Salfred					for (j = 0; j < MLX4_MAX_PORTS; j++)
487255932Salfred						res_alloc->res_port_free[j] = MLX4_MAX_MAC_NUM;
488255932Salfred				} else {
489255932Salfred					res_alloc->quota[t] = 2;
490255932Salfred					res_alloc->guaranteed[t] = 2;
491255932Salfred				}
492255932Salfred				break;
493255932Salfred			case RES_VLAN:
494255932Salfred				if (t == mlx4_master_func_num(dev)) {
495255932Salfred					res_alloc->quota[t] = MLX4_MAX_VLAN_NUM;
496255932Salfred					res_alloc->guaranteed[t] = MLX4_MAX_VLAN_NUM / 2;
497255932Salfred					for (j = 0; j < MLX4_MAX_PORTS; j++)
498255932Salfred						res_alloc->res_port_free[j] =
499255932Salfred							res_alloc->quota[t];
500255932Salfred				} else {
501255932Salfred					res_alloc->quota[t] = MLX4_MAX_VLAN_NUM / 2;
502255932Salfred					res_alloc->guaranteed[t] = 0;
503255932Salfred				}
504255932Salfred				break;
505255932Salfred			case RES_COUNTER:
506255932Salfred				res_alloc->quota[t] = dev->caps.max_counters;
507255932Salfred				res_alloc->guaranteed[t] = 0;
508255932Salfred				if (t == mlx4_master_func_num(dev))
509255932Salfred					res_alloc->res_free = res_alloc->quota[t];
510255932Salfred				break;
511255932Salfred			default:
512255932Salfred				break;
513255932Salfred			}
514255932Salfred			if (i == RES_MAC || i == RES_VLAN) {
515255932Salfred				for (j = 0; j < MLX4_MAX_PORTS; j++)
516255932Salfred					res_alloc->res_port_rsvd[j] +=
517255932Salfred						res_alloc->guaranteed[t];
518255932Salfred			} else {
519255932Salfred				res_alloc->res_reserved += res_alloc->guaranteed[t];
520255932Salfred			}
521255932Salfred		}
522255932Salfred	}
523255932Salfred	spin_lock_init(&priv->mfunc.master.res_tracker.lock);
524255932Salfred	return 0;
525255932Salfred
526255932Salfredno_mem_err:
527255932Salfred	for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
528255932Salfred		kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated);
529255932Salfred		priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL;
530255932Salfred		kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed);
531255932Salfred		priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL;
532255932Salfred		kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota);
533255932Salfred		priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL;
534255932Salfred	}
535255932Salfred	return -ENOMEM;
536255932Salfred}
537255932Salfred
538255932Salfredvoid mlx4_free_resource_tracker(struct mlx4_dev *dev,
539255932Salfred				enum mlx4_res_tracker_free_type type)
540255932Salfred{
541255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
542255932Salfred	int i;
543255932Salfred
544255932Salfred	if (priv->mfunc.master.res_tracker.slave_list) {
545255932Salfred		if (type != RES_TR_FREE_STRUCTS_ONLY) {
546255932Salfred			for (i = 0; i < dev->num_slaves; i++) {
547255932Salfred				if (type == RES_TR_FREE_ALL ||
548255932Salfred				    dev->caps.function != i)
549255932Salfred					mlx4_delete_all_resources_for_slave(dev, i);
550255932Salfred			}
551255932Salfred			/* free master's vlans */
552255932Salfred			i = dev->caps.function;
553255932Salfred			mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
554255932Salfred			rem_slave_vlans(dev, i);
555255932Salfred			mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
556255932Salfred		}
557255932Salfred
558255932Salfred		if (type != RES_TR_FREE_SLAVES_ONLY) {
559255932Salfred			for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
560255932Salfred				kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated);
561255932Salfred				priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL;
562255932Salfred				kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed);
563255932Salfred				priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL;
564255932Salfred				kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota);
565255932Salfred				priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL;
566255932Salfred			}
567255932Salfred			kfree(priv->mfunc.master.res_tracker.slave_list);
568255932Salfred			priv->mfunc.master.res_tracker.slave_list = NULL;
569255932Salfred		}
570255932Salfred	}
571255932Salfred}
572255932Salfred
573255932Salfredstatic void update_pkey_index(struct mlx4_dev *dev, int slave,
574255932Salfred			      struct mlx4_cmd_mailbox *inbox)
575255932Salfred{
576255932Salfred	u8 sched = *(u8 *)(inbox->buf + 64);
577255932Salfred	u8 orig_index = *(u8 *)(inbox->buf + 35);
578255932Salfred	u8 new_index;
579255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
580255932Salfred	int port;
581255932Salfred
582255932Salfred	port = (sched >> 6 & 1) + 1;
583255932Salfred
584255932Salfred	new_index = priv->virt2phys_pkey[slave][port - 1][orig_index];
585255932Salfred	*(u8 *)(inbox->buf + 35) = new_index;
586255932Salfred}
587255932Salfred
588255932Salfredstatic void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
589255932Salfred		       u8 slave)
590255932Salfred{
591255932Salfred	struct mlx4_qp_context	*qp_ctx = inbox->buf + 8;
592255932Salfred	enum mlx4_qp_optpar	optpar = be32_to_cpu(*(__be32 *) inbox->buf);
593255932Salfred	u32			ts = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff;
594255932Salfred	int port;
595255932Salfred
596255932Salfred	if (MLX4_QP_ST_UD == ts) {
597255932Salfred		port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
598255932Salfred		if (mlx4_is_eth(dev, port))
599255932Salfred			qp_ctx->pri_path.mgid_index = mlx4_get_base_gid_ix(dev, slave) | 0x80;
600255932Salfred		else
601255932Salfred			qp_ctx->pri_path.mgid_index = 0x80 | slave;
602255932Salfred
603255932Salfred	} else if (MLX4_QP_ST_RC == ts || MLX4_QP_ST_UC == ts) {
604255932Salfred		if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH) {
605255932Salfred			port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
606255932Salfred			if (mlx4_is_eth(dev, port)) {
607255932Salfred				qp_ctx->pri_path.mgid_index += mlx4_get_base_gid_ix(dev, slave);
608255932Salfred				qp_ctx->pri_path.mgid_index &= 0x7f;
609255932Salfred			} else {
610255932Salfred				qp_ctx->pri_path.mgid_index = slave & 0x7F;
611255932Salfred			}
612255932Salfred		}
613255932Salfred		if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) {
614255932Salfred			port = (qp_ctx->alt_path.sched_queue >> 6 & 1) + 1;
615255932Salfred			if (mlx4_is_eth(dev, port)) {
616255932Salfred				qp_ctx->alt_path.mgid_index += mlx4_get_base_gid_ix(dev, slave);
617255932Salfred				qp_ctx->alt_path.mgid_index &= 0x7f;
618255932Salfred			} else {
619255932Salfred				qp_ctx->alt_path.mgid_index = slave & 0x7F;
620255932Salfred			}
621255932Salfred		}
622255932Salfred	}
623255932Salfred}
624255932Salfred
625255932Salfredstatic int update_vport_qp_param(struct mlx4_dev *dev,
626255932Salfred				 struct mlx4_cmd_mailbox *inbox,
627255932Salfred				 u8 slave)
628255932Salfred{
629255932Salfred	struct mlx4_qp_context	*qpc = inbox->buf + 8;
630255932Salfred	struct mlx4_vport_oper_state *vp_oper;
631255932Salfred	struct mlx4_priv *priv;
632255932Salfred	u32 qp_type;
633255932Salfred	int port;
634255932Salfred
635255932Salfred	port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1;
636255932Salfred	priv = mlx4_priv(dev);
637255932Salfred	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
638255932Salfred
639255932Salfred	if (MLX4_VGT != vp_oper->state.default_vlan) {
640255932Salfred		qp_type	= (be32_to_cpu(qpc->flags) >> 16) & 0xff;
641255932Salfred		if (MLX4_QP_ST_RC == qp_type)
642255932Salfred			return -EINVAL;
643255932Salfred
644255932Salfred		qpc->srqn |= cpu_to_be32(1 << 25); /*set cqe vlan mask */
645255932Salfred		qpc->pri_path.vlan_index = vp_oper->vlan_idx;
646255932Salfred		qpc->pri_path.fl = 1 << 6; /* set cv bit*/
647255932Salfred		qpc->pri_path.feup |= 1 << 3; /* set fvl bit */
648255932Salfred		qpc->pri_path.sched_queue &= 0xC7;
649255932Salfred		qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3;
650255932Salfred		mlx4_dbg(dev, "qp %d  port %d Q 0x%x set vlan to %d vidx %d feup %x fl %x\n",
651255932Salfred			 be32_to_cpu(qpc->local_qpn) & 0xffffff, port,
652255932Salfred			 (int)(qpc->pri_path.sched_queue), vp_oper->state.default_vlan,
653255932Salfred			 vp_oper->vlan_idx, (int)(qpc->pri_path.feup),
654255932Salfred			 (int)(qpc->pri_path.fl));
655255932Salfred	}
656255932Salfred	if (vp_oper->state.spoofchk) {
657255932Salfred		qpc->pri_path.feup |= 1 << 5; /* set fsm bit */;
658255932Salfred		qpc->pri_path.grh_mylmc = (0x80 & qpc->pri_path.grh_mylmc) + vp_oper->mac_idx;
659255932Salfred		mlx4_dbg(dev, "spoof qp %d  port %d feup  0x%x, myLmc 0x%x mindx %d\n",
660255932Salfred			 be32_to_cpu(qpc->local_qpn) & 0xffffff, port,
661255932Salfred			 (int)qpc->pri_path.feup, (int)qpc->pri_path.grh_mylmc,
662255932Salfred			 vp_oper->mac_idx);
663255932Salfred	}
664255932Salfred	return 0;
665255932Salfred}
666255932Salfred
667255932Salfredstatic int mpt_mask(struct mlx4_dev *dev)
668255932Salfred{
669255932Salfred	return dev->caps.num_mpts - 1;
670255932Salfred}
671255932Salfred
672255932Salfredstatic void *find_res(struct mlx4_dev *dev, int res_id,
673255932Salfred		      enum mlx4_resource type)
674255932Salfred{
675255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
676255932Salfred
677255932Salfred	return res_tracker_lookup(&priv->mfunc.master.res_tracker.res_tree[type],
678255932Salfred				  res_id);
679255932Salfred}
680255932Salfred
681255932Salfredstatic int get_res(struct mlx4_dev *dev, int slave, u64 res_id,
682255932Salfred		   enum mlx4_resource type,
683255932Salfred		   void *res)
684255932Salfred{
685255932Salfred	struct res_common *r;
686255932Salfred	int err = 0;
687255932Salfred
688255932Salfred	spin_lock_irq(mlx4_tlock(dev));
689255932Salfred	r = find_res(dev, res_id, type);
690255932Salfred	if (!r) {
691255932Salfred		err = -ENOENT;
692255932Salfred		goto exit;
693255932Salfred	}
694255932Salfred
695255932Salfred	if (r->state == RES_ANY_BUSY) {
696255932Salfred		err = -EBUSY;
697255932Salfred		goto exit;
698255932Salfred	}
699255932Salfred
700255932Salfred	if (r->owner != slave) {
701255932Salfred		err = -EPERM;
702255932Salfred		goto exit;
703255932Salfred	}
704255932Salfred
705255932Salfred	r->from_state = r->state;
706255932Salfred	r->state = RES_ANY_BUSY;
707255932Salfred
708255932Salfred	if (res)
709255932Salfred		*((struct res_common **)res) = r;
710255932Salfred
711255932Salfredexit:
712255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
713255932Salfred	return err;
714255932Salfred}
715255932Salfred
716255932Salfredint mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,
717255932Salfred				    enum mlx4_resource type,
718255932Salfred				    u64 res_id, int *slave)
719255932Salfred{
720255932Salfred
721255932Salfred	struct res_common *r;
722255932Salfred	int err = -ENOENT;
723255932Salfred	int id = res_id;
724255932Salfred
725255932Salfred	if (type == RES_QP)
726255932Salfred		id &= 0x7fffff;
727255932Salfred	spin_lock(mlx4_tlock(dev));
728255932Salfred
729255932Salfred	r = find_res(dev, id, type);
730255932Salfred	if (r) {
731255932Salfred		*slave = r->owner;
732255932Salfred		err = 0;
733255932Salfred	}
734255932Salfred	spin_unlock(mlx4_tlock(dev));
735255932Salfred
736255932Salfred	return err;
737255932Salfred}
738255932Salfred
739255932Salfredstatic void put_res(struct mlx4_dev *dev, int slave, u64 res_id,
740255932Salfred		    enum mlx4_resource type)
741255932Salfred{
742255932Salfred	struct res_common *r;
743255932Salfred
744255932Salfred	spin_lock_irq(mlx4_tlock(dev));
745255932Salfred	r = find_res(dev, res_id, type);
746255932Salfred	if (r)
747255932Salfred		r->state = r->from_state;
748255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
749255932Salfred}
750255932Salfred
751255932Salfredstatic struct res_common *alloc_qp_tr(int id)
752255932Salfred{
753255932Salfred	struct res_qp *ret;
754255932Salfred
755255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
756255932Salfred	if (!ret)
757255932Salfred		return NULL;
758255932Salfred
759255932Salfred	ret->com.res_id = id;
760255932Salfred	ret->com.state = RES_QP_RESERVED;
761255932Salfred	ret->local_qpn = id;
762255932Salfred	INIT_LIST_HEAD(&ret->mcg_list);
763255932Salfred	spin_lock_init(&ret->mcg_spl);
764255932Salfred
765255932Salfred	return &ret->com;
766255932Salfred}
767255932Salfred
768255932Salfredstatic struct res_common *alloc_mtt_tr(int id, int order)
769255932Salfred{
770255932Salfred	struct res_mtt *ret;
771255932Salfred
772255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
773255932Salfred	if (!ret)
774255932Salfred		return NULL;
775255932Salfred
776255932Salfred	ret->com.res_id = id;
777255932Salfred	ret->order = order;
778255932Salfred	ret->com.state = RES_MTT_ALLOCATED;
779255932Salfred	atomic_set(&ret->ref_count, 0);
780255932Salfred
781255932Salfred	return &ret->com;
782255932Salfred}
783255932Salfred
784255932Salfredstatic struct res_common *alloc_mpt_tr(int id, int key)
785255932Salfred{
786255932Salfred	struct res_mpt *ret;
787255932Salfred
788255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
789255932Salfred	if (!ret)
790255932Salfred		return NULL;
791255932Salfred
792255932Salfred	ret->com.res_id = id;
793255932Salfred	ret->com.state = RES_MPT_RESERVED;
794255932Salfred	ret->key = key;
795255932Salfred
796255932Salfred	return &ret->com;
797255932Salfred}
798255932Salfred
799255932Salfredstatic struct res_common *alloc_eq_tr(int id)
800255932Salfred{
801255932Salfred	struct res_eq *ret;
802255932Salfred
803255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
804255932Salfred	if (!ret)
805255932Salfred		return NULL;
806255932Salfred
807255932Salfred	ret->com.res_id = id;
808255932Salfred	ret->com.state = RES_EQ_RESERVED;
809255932Salfred
810255932Salfred	return &ret->com;
811255932Salfred}
812255932Salfred
813255932Salfredstatic struct res_common *alloc_cq_tr(int id)
814255932Salfred{
815255932Salfred	struct res_cq *ret;
816255932Salfred
817255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
818255932Salfred	if (!ret)
819255932Salfred		return NULL;
820255932Salfred
821255932Salfred	ret->com.res_id = id;
822255932Salfred	ret->com.state = RES_CQ_ALLOCATED;
823255932Salfred	atomic_set(&ret->ref_count, 0);
824255932Salfred
825255932Salfred	return &ret->com;
826255932Salfred}
827255932Salfred
828255932Salfredstatic struct res_common *alloc_srq_tr(int id)
829255932Salfred{
830255932Salfred	struct res_srq *ret;
831255932Salfred
832255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
833255932Salfred	if (!ret)
834255932Salfred		return NULL;
835255932Salfred
836255932Salfred	ret->com.res_id = id;
837255932Salfred	ret->com.state = RES_SRQ_ALLOCATED;
838255932Salfred	atomic_set(&ret->ref_count, 0);
839255932Salfred
840255932Salfred	return &ret->com;
841255932Salfred}
842255932Salfred
843255932Salfredstatic struct res_common *alloc_counter_tr(int id)
844255932Salfred{
845255932Salfred	struct res_counter *ret;
846255932Salfred
847255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
848255932Salfred	if (!ret)
849255932Salfred		return NULL;
850255932Salfred
851255932Salfred	ret->com.res_id = id;
852255932Salfred	ret->com.state = RES_COUNTER_ALLOCATED;
853255932Salfred
854255932Salfred	return &ret->com;
855255932Salfred}
856255932Salfred
857255932Salfredstatic struct res_common *alloc_xrcdn_tr(int id)
858255932Salfred{
859255932Salfred	struct res_xrcdn *ret;
860255932Salfred
861255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
862255932Salfred	if (!ret)
863255932Salfred		return NULL;
864255932Salfred
865255932Salfred	ret->com.res_id = id;
866255932Salfred	ret->com.state = RES_XRCD_ALLOCATED;
867255932Salfred
868255932Salfred	return &ret->com;
869255932Salfred}
870255932Salfred
871255932Salfredstatic struct res_common *alloc_fs_rule_tr(u64 id)
872255932Salfred{
873255932Salfred	struct res_fs_rule *ret;
874255932Salfred
875255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
876255932Salfred	if (!ret)
877255932Salfred		return NULL;
878255932Salfred
879255932Salfred	ret->com.res_id = id;
880255932Salfred	ret->com.state = RES_FS_RULE_ALLOCATED;
881255932Salfred
882255932Salfred	return &ret->com;
883255932Salfred}
884255932Salfred
885255932Salfredstatic struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave,
886255932Salfred				   int extra)
887255932Salfred{
888255932Salfred	struct res_common *ret;
889255932Salfred
890255932Salfred	switch (type) {
891255932Salfred	case RES_QP:
892255932Salfred		ret = alloc_qp_tr(id);
893255932Salfred		break;
894255932Salfred	case RES_MPT:
895255932Salfred		ret = alloc_mpt_tr(id, extra);
896255932Salfred		break;
897255932Salfred	case RES_MTT:
898255932Salfred		ret = alloc_mtt_tr(id, extra);
899255932Salfred		break;
900255932Salfred	case RES_EQ:
901255932Salfred		ret = alloc_eq_tr(id);
902255932Salfred		break;
903255932Salfred	case RES_CQ:
904255932Salfred		ret = alloc_cq_tr(id);
905255932Salfred		break;
906255932Salfred	case RES_SRQ:
907255932Salfred		ret = alloc_srq_tr(id);
908255932Salfred		break;
909255932Salfred	case RES_MAC:
910255932Salfred		printk(KERN_ERR "implementation missing\n");
911255932Salfred		return NULL;
912255932Salfred	case RES_COUNTER:
913255932Salfred		ret = alloc_counter_tr(id);
914255932Salfred		break;
915255932Salfred	case RES_XRCD:
916255932Salfred		ret = alloc_xrcdn_tr(id);
917255932Salfred		break;
918255932Salfred	case RES_FS_RULE:
919255932Salfred		ret = alloc_fs_rule_tr(id);
920255932Salfred		break;
921255932Salfred	default:
922255932Salfred		return NULL;
923255932Salfred	}
924255932Salfred	if (ret)
925255932Salfred		ret->owner = slave;
926255932Salfred
927255932Salfred	return ret;
928255932Salfred}
929255932Salfred
930255932Salfredstatic int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
931255932Salfred			 enum mlx4_resource type, int extra)
932255932Salfred{
933255932Salfred	int i;
934255932Salfred	int err;
935255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
936255932Salfred	struct res_common **res_arr;
937255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
938255932Salfred	struct rb_root *root = &tracker->res_tree[type];
939255932Salfred
940255932Salfred	res_arr = kzalloc(count * sizeof *res_arr, GFP_KERNEL);
941255932Salfred	if (!res_arr)
942255932Salfred		return -ENOMEM;
943255932Salfred
944255932Salfred	for (i = 0; i < count; ++i) {
945255932Salfred		res_arr[i] = alloc_tr(base + i, type, slave, extra);
946255932Salfred		if (!res_arr[i]) {
947255932Salfred			for (--i; i >= 0; --i)
948255932Salfred				kfree(res_arr[i]);
949255932Salfred
950255932Salfred			kfree(res_arr);
951255932Salfred			return -ENOMEM;
952255932Salfred		}
953255932Salfred	}
954255932Salfred
955255932Salfred	spin_lock_irq(mlx4_tlock(dev));
956255932Salfred	for (i = 0; i < count; ++i) {
957255932Salfred		if (find_res(dev, base + i, type)) {
958255932Salfred			err = -EEXIST;
959255932Salfred			goto undo;
960255932Salfred		}
961255932Salfred		err = res_tracker_insert(root, res_arr[i]);
962255932Salfred		if (err)
963255932Salfred			goto undo;
964255932Salfred		list_add_tail(&res_arr[i]->list,
965255932Salfred			      &tracker->slave_list[slave].res_list[type]);
966255932Salfred	}
967255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
968255932Salfred	kfree(res_arr);
969255932Salfred
970255932Salfred	return 0;
971255932Salfred
972255932Salfredundo:
973255932Salfred	for (--i; i >= base; --i)
974255932Salfred		rb_erase(&res_arr[i]->node, root);
975255932Salfred
976255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
977255932Salfred
978255932Salfred	for (i = 0; i < count; ++i)
979255932Salfred		kfree(res_arr[i]);
980255932Salfred
981255932Salfred	kfree(res_arr);
982255932Salfred
983255932Salfred	return err;
984255932Salfred}
985255932Salfred
986255932Salfredstatic int remove_qp_ok(struct res_qp *res)
987255932Salfred{
988255932Salfred	if (res->com.state == RES_QP_BUSY)
989255932Salfred		return -EBUSY;
990255932Salfred	else if (res->com.state != RES_QP_RESERVED)
991255932Salfred		return -EPERM;
992255932Salfred
993255932Salfred	return 0;
994255932Salfred}
995255932Salfred
996255932Salfredstatic int remove_mtt_ok(struct res_mtt *res, int order)
997255932Salfred{
998255932Salfred	if (res->com.state == RES_MTT_BUSY ||
999255932Salfred	    atomic_read(&res->ref_count)) {
1000255932Salfred		printk(KERN_DEBUG "%s-%d: state %s, ref_count %d\n",
1001255932Salfred		       __func__, __LINE__,
1002255932Salfred		       mtt_states_str(res->com.state),
1003255932Salfred		       atomic_read(&res->ref_count));
1004255932Salfred		return -EBUSY;
1005255932Salfred	} else if (res->com.state != RES_MTT_ALLOCATED)
1006255932Salfred		return -EPERM;
1007255932Salfred	else if (res->order != order)
1008255932Salfred		return -EINVAL;
1009255932Salfred
1010255932Salfred	return 0;
1011255932Salfred}
1012255932Salfred
1013255932Salfredstatic int remove_mpt_ok(struct res_mpt *res)
1014255932Salfred{
1015255932Salfred	if (res->com.state == RES_MPT_BUSY)
1016255932Salfred		return -EBUSY;
1017255932Salfred	else if (res->com.state != RES_MPT_RESERVED)
1018255932Salfred		return -EPERM;
1019255932Salfred
1020255932Salfred	return 0;
1021255932Salfred}
1022255932Salfred
1023255932Salfredstatic int remove_eq_ok(struct res_eq *res)
1024255932Salfred{
1025255932Salfred	if (res->com.state == RES_MPT_BUSY)
1026255932Salfred		return -EBUSY;
1027255932Salfred	else if (res->com.state != RES_MPT_RESERVED)
1028255932Salfred		return -EPERM;
1029255932Salfred
1030255932Salfred	return 0;
1031255932Salfred}
1032255932Salfred
1033255932Salfredstatic int remove_counter_ok(struct res_counter *res)
1034255932Salfred{
1035255932Salfred	if (res->com.state == RES_COUNTER_BUSY)
1036255932Salfred		return -EBUSY;
1037255932Salfred	else if (res->com.state != RES_COUNTER_ALLOCATED)
1038255932Salfred		return -EPERM;
1039255932Salfred
1040255932Salfred	return 0;
1041255932Salfred}
1042255932Salfred
1043255932Salfredstatic int remove_xrcdn_ok(struct res_xrcdn *res)
1044255932Salfred{
1045255932Salfred	if (res->com.state == RES_XRCD_BUSY)
1046255932Salfred		return -EBUSY;
1047255932Salfred	else if (res->com.state != RES_XRCD_ALLOCATED)
1048255932Salfred		return -EPERM;
1049255932Salfred
1050255932Salfred	return 0;
1051255932Salfred}
1052255932Salfred
1053255932Salfredstatic int remove_fs_rule_ok(struct res_fs_rule *res)
1054255932Salfred{
1055255932Salfred	if (res->com.state == RES_FS_RULE_BUSY)
1056255932Salfred		return -EBUSY;
1057255932Salfred	else if (res->com.state != RES_FS_RULE_ALLOCATED)
1058255932Salfred		return -EPERM;
1059255932Salfred
1060255932Salfred	return 0;
1061255932Salfred}
1062255932Salfred
1063255932Salfredstatic int remove_cq_ok(struct res_cq *res)
1064255932Salfred{
1065255932Salfred	if (res->com.state == RES_CQ_BUSY)
1066255932Salfred		return -EBUSY;
1067255932Salfred	else if (res->com.state != RES_CQ_ALLOCATED)
1068255932Salfred		return -EPERM;
1069255932Salfred
1070255932Salfred	return 0;
1071255932Salfred}
1072255932Salfred
1073255932Salfredstatic int remove_srq_ok(struct res_srq *res)
1074255932Salfred{
1075255932Salfred	if (res->com.state == RES_SRQ_BUSY)
1076255932Salfred		return -EBUSY;
1077255932Salfred	else if (res->com.state != RES_SRQ_ALLOCATED)
1078255932Salfred		return -EPERM;
1079255932Salfred
1080255932Salfred	return 0;
1081255932Salfred}
1082255932Salfred
1083255932Salfredstatic int remove_ok(struct res_common *res, enum mlx4_resource type, int extra)
1084255932Salfred{
1085255932Salfred	switch (type) {
1086255932Salfred	case RES_QP:
1087255932Salfred		return remove_qp_ok((struct res_qp *)res);
1088255932Salfred	case RES_CQ:
1089255932Salfred		return remove_cq_ok((struct res_cq *)res);
1090255932Salfred	case RES_SRQ:
1091255932Salfred		return remove_srq_ok((struct res_srq *)res);
1092255932Salfred	case RES_MPT:
1093255932Salfred		return remove_mpt_ok((struct res_mpt *)res);
1094255932Salfred	case RES_MTT:
1095255932Salfred		return remove_mtt_ok((struct res_mtt *)res, extra);
1096255932Salfred	case RES_MAC:
1097255932Salfred		return -ENOSYS;
1098255932Salfred	case RES_EQ:
1099255932Salfred		return remove_eq_ok((struct res_eq *)res);
1100255932Salfred	case RES_COUNTER:
1101255932Salfred		return remove_counter_ok((struct res_counter *)res);
1102255932Salfred	case RES_XRCD:
1103255932Salfred		return remove_xrcdn_ok((struct res_xrcdn *)res);
1104255932Salfred	case RES_FS_RULE:
1105255932Salfred		return remove_fs_rule_ok((struct res_fs_rule *)res);
1106255932Salfred	default:
1107255932Salfred		return -EINVAL;
1108255932Salfred	}
1109255932Salfred}
1110255932Salfred
1111255932Salfredstatic int rem_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
1112255932Salfred			 enum mlx4_resource type, int extra)
1113255932Salfred{
1114255932Salfred	u64 i;
1115255932Salfred	int err;
1116255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1117255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1118255932Salfred	struct res_common *r;
1119255932Salfred
1120255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1121255932Salfred	for (i = base; i < base + count; ++i) {
1122255932Salfred		r = res_tracker_lookup(&tracker->res_tree[type], i);
1123255932Salfred		if (!r) {
1124255932Salfred			err = -ENOENT;
1125255932Salfred			goto out;
1126255932Salfred		}
1127255932Salfred		if (r->owner != slave) {
1128255932Salfred			err = -EPERM;
1129255932Salfred			goto out;
1130255932Salfred		}
1131255932Salfred		err = remove_ok(r, type, extra);
1132255932Salfred		if (err)
1133255932Salfred			goto out;
1134255932Salfred	}
1135255932Salfred
1136255932Salfred	for (i = base; i < base + count; ++i) {
1137255932Salfred		r = res_tracker_lookup(&tracker->res_tree[type], i);
1138255932Salfred		rb_erase(&r->node, &tracker->res_tree[type]);
1139255932Salfred		list_del(&r->list);
1140255932Salfred		kfree(r);
1141255932Salfred	}
1142255932Salfred	err = 0;
1143255932Salfred
1144255932Salfredout:
1145255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1146255932Salfred
1147255932Salfred	return err;
1148255932Salfred}
1149255932Salfred
1150255932Salfredstatic int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn,
1151255932Salfred				enum res_qp_states state, struct res_qp **qp,
1152255932Salfred				int alloc)
1153255932Salfred{
1154255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1155255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1156255932Salfred	struct res_qp *r;
1157255932Salfred	int err = 0;
1158255932Salfred
1159255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1160255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_QP], qpn);
1161255932Salfred	if (!r)
1162255932Salfred		err = -ENOENT;
1163255932Salfred	else if (r->com.owner != slave)
1164255932Salfred		err = -EPERM;
1165255932Salfred	else {
1166255932Salfred		switch (state) {
1167255932Salfred		case RES_QP_BUSY:
1168255932Salfred			mlx4_dbg(dev, "%s: failed RES_QP, 0x%llx\n",
1169255932Salfred				 __func__, r->com.res_id);
1170255932Salfred			err = -EBUSY;
1171255932Salfred			break;
1172255932Salfred
1173255932Salfred		case RES_QP_RESERVED:
1174255932Salfred			if (r->com.state == RES_QP_MAPPED && !alloc)
1175255932Salfred				break;
1176255932Salfred
1177255932Salfred			mlx4_dbg(dev, "failed RES_QP, 0x%llx\n", r->com.res_id);
1178255932Salfred			err = -EINVAL;
1179255932Salfred			break;
1180255932Salfred
1181255932Salfred		case RES_QP_MAPPED:
1182255932Salfred			if ((r->com.state == RES_QP_RESERVED && alloc) ||
1183255932Salfred			    r->com.state == RES_QP_HW)
1184255932Salfred				break;
1185255932Salfred			else {
1186255932Salfred				mlx4_dbg(dev, "failed RES_QP, 0x%llx\n",
1187255932Salfred					  r->com.res_id);
1188255932Salfred				err = -EINVAL;
1189255932Salfred			}
1190255932Salfred
1191255932Salfred			break;
1192255932Salfred
1193255932Salfred		case RES_QP_HW:
1194255932Salfred			if (r->com.state != RES_QP_MAPPED)
1195255932Salfred				err = -EINVAL;
1196255932Salfred			break;
1197255932Salfred		default:
1198255932Salfred			err = -EINVAL;
1199255932Salfred		}
1200255932Salfred
1201255932Salfred		if (!err) {
1202255932Salfred			r->com.from_state = r->com.state;
1203255932Salfred			r->com.to_state = state;
1204255932Salfred			r->com.state = RES_QP_BUSY;
1205255932Salfred			if (qp)
1206255932Salfred				*qp = r;
1207255932Salfred		}
1208255932Salfred	}
1209255932Salfred
1210255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1211255932Salfred
1212255932Salfred	return err;
1213255932Salfred}
1214255932Salfred
1215255932Salfredstatic int mr_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
1216255932Salfred				enum res_mpt_states state, struct res_mpt **mpt)
1217255932Salfred{
1218255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1219255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1220255932Salfred	struct res_mpt *r;
1221255932Salfred	int err = 0;
1222255932Salfred
1223255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1224255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_MPT], index);
1225255932Salfred	if (!r)
1226255932Salfred		err = -ENOENT;
1227255932Salfred	else if (r->com.owner != slave)
1228255932Salfred		err = -EPERM;
1229255932Salfred	else {
1230255932Salfred		switch (state) {
1231255932Salfred		case RES_MPT_BUSY:
1232255932Salfred			err = -EINVAL;
1233255932Salfred			break;
1234255932Salfred
1235255932Salfred		case RES_MPT_RESERVED:
1236255932Salfred			if (r->com.state != RES_MPT_MAPPED)
1237255932Salfred				err = -EINVAL;
1238255932Salfred			break;
1239255932Salfred
1240255932Salfred		case RES_MPT_MAPPED:
1241255932Salfred			if (r->com.state != RES_MPT_RESERVED &&
1242255932Salfred			    r->com.state != RES_MPT_HW)
1243255932Salfred				err = -EINVAL;
1244255932Salfred			break;
1245255932Salfred
1246255932Salfred		case RES_MPT_HW:
1247255932Salfred			if (r->com.state != RES_MPT_MAPPED)
1248255932Salfred				err = -EINVAL;
1249255932Salfred			break;
1250255932Salfred		default:
1251255932Salfred			err = -EINVAL;
1252255932Salfred		}
1253255932Salfred
1254255932Salfred		if (!err) {
1255255932Salfred			r->com.from_state = r->com.state;
1256255932Salfred			r->com.to_state = state;
1257255932Salfred			r->com.state = RES_MPT_BUSY;
1258255932Salfred			if (mpt)
1259255932Salfred				*mpt = r;
1260255932Salfred		}
1261255932Salfred	}
1262255932Salfred
1263255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1264255932Salfred
1265255932Salfred	return err;
1266255932Salfred}
1267255932Salfred
1268255932Salfredstatic int eq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
1269255932Salfred				enum res_eq_states state, struct res_eq **eq)
1270255932Salfred{
1271255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1272255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1273255932Salfred	struct res_eq *r;
1274255932Salfred	int err = 0;
1275255932Salfred
1276255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1277255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_EQ], index);
1278255932Salfred	if (!r)
1279255932Salfred		err = -ENOENT;
1280255932Salfred	else if (r->com.owner != slave)
1281255932Salfred		err = -EPERM;
1282255932Salfred	else {
1283255932Salfred		switch (state) {
1284255932Salfred		case RES_EQ_BUSY:
1285255932Salfred			err = -EINVAL;
1286255932Salfred			break;
1287255932Salfred
1288255932Salfred		case RES_EQ_RESERVED:
1289255932Salfred			if (r->com.state != RES_EQ_HW)
1290255932Salfred				err = -EINVAL;
1291255932Salfred			break;
1292255932Salfred
1293255932Salfred		case RES_EQ_HW:
1294255932Salfred			if (r->com.state != RES_EQ_RESERVED)
1295255932Salfred				err = -EINVAL;
1296255932Salfred			break;
1297255932Salfred
1298255932Salfred		default:
1299255932Salfred			err = -EINVAL;
1300255932Salfred		}
1301255932Salfred
1302255932Salfred		if (!err) {
1303255932Salfred			r->com.from_state = r->com.state;
1304255932Salfred			r->com.to_state = state;
1305255932Salfred			r->com.state = RES_EQ_BUSY;
1306255932Salfred			if (eq)
1307255932Salfred				*eq = r;
1308255932Salfred		}
1309255932Salfred	}
1310255932Salfred
1311255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1312255932Salfred
1313255932Salfred	return err;
1314255932Salfred}
1315255932Salfred
1316255932Salfredstatic int cq_res_start_move_to(struct mlx4_dev *dev, int slave, int cqn,
1317255932Salfred				enum res_cq_states state, struct res_cq **cq)
1318255932Salfred{
1319255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1320255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1321255932Salfred	struct res_cq *r;
1322255932Salfred	int err;
1323255932Salfred
1324255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1325255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_CQ], cqn);
1326255932Salfred	if (!r)
1327255932Salfred		err = -ENOENT;
1328255932Salfred	else if (r->com.owner != slave)
1329255932Salfred		err = -EPERM;
1330255932Salfred	else {
1331255932Salfred		switch (state) {
1332255932Salfred		case RES_CQ_BUSY:
1333255932Salfred			err = -EBUSY;
1334255932Salfred			break;
1335255932Salfred
1336255932Salfred		case RES_CQ_ALLOCATED:
1337255932Salfred			if (r->com.state != RES_CQ_HW)
1338255932Salfred				err = -EINVAL;
1339255932Salfred			else if (atomic_read(&r->ref_count))
1340255932Salfred				err = -EBUSY;
1341255932Salfred			else
1342255932Salfred				err = 0;
1343255932Salfred			break;
1344255932Salfred
1345255932Salfred		case RES_CQ_HW:
1346255932Salfred			if (r->com.state != RES_CQ_ALLOCATED)
1347255932Salfred				err = -EINVAL;
1348255932Salfred			else
1349255932Salfred				err = 0;
1350255932Salfred			break;
1351255932Salfred
1352255932Salfred		default:
1353255932Salfred			err = -EINVAL;
1354255932Salfred		}
1355255932Salfred
1356255932Salfred		if (!err) {
1357255932Salfred			r->com.from_state = r->com.state;
1358255932Salfred			r->com.to_state = state;
1359255932Salfred			r->com.state = RES_CQ_BUSY;
1360255932Salfred			if (cq)
1361255932Salfred				*cq = r;
1362255932Salfred		}
1363255932Salfred	}
1364255932Salfred
1365255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1366255932Salfred
1367255932Salfred	return err;
1368255932Salfred}
1369255932Salfred
1370255932Salfredstatic int srq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
1371255932Salfred				 enum res_srq_states state, struct res_srq **srq)
1372255932Salfred{
1373255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1374255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1375255932Salfred	struct res_srq *r;
1376255932Salfred	int err = 0;
1377255932Salfred
1378255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1379255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_SRQ], index);
1380255932Salfred	if (!r)
1381255932Salfred		err = -ENOENT;
1382255932Salfred	else if (r->com.owner != slave)
1383255932Salfred		err = -EPERM;
1384255932Salfred	else {
1385255932Salfred		switch (state) {
1386255932Salfred		case RES_SRQ_BUSY:
1387255932Salfred			err = -EINVAL;
1388255932Salfred			break;
1389255932Salfred
1390255932Salfred		case RES_SRQ_ALLOCATED:
1391255932Salfred			if (r->com.state != RES_SRQ_HW)
1392255932Salfred				err = -EINVAL;
1393255932Salfred			else if (atomic_read(&r->ref_count))
1394255932Salfred				err = -EBUSY;
1395255932Salfred			break;
1396255932Salfred
1397255932Salfred		case RES_SRQ_HW:
1398255932Salfred			if (r->com.state != RES_SRQ_ALLOCATED)
1399255932Salfred				err = -EINVAL;
1400255932Salfred			break;
1401255932Salfred
1402255932Salfred		default:
1403255932Salfred			err = -EINVAL;
1404255932Salfred		}
1405255932Salfred
1406255932Salfred		if (!err) {
1407255932Salfred			r->com.from_state = r->com.state;
1408255932Salfred			r->com.to_state = state;
1409255932Salfred			r->com.state = RES_SRQ_BUSY;
1410255932Salfred			if (srq)
1411255932Salfred				*srq = r;
1412255932Salfred		}
1413255932Salfred	}
1414255932Salfred
1415255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1416255932Salfred
1417255932Salfred	return err;
1418255932Salfred}
1419255932Salfred
1420255932Salfredstatic void res_abort_move(struct mlx4_dev *dev, int slave,
1421255932Salfred			   enum mlx4_resource type, int id)
1422255932Salfred{
1423255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1424255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1425255932Salfred	struct res_common *r;
1426255932Salfred
1427255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1428255932Salfred	r = res_tracker_lookup(&tracker->res_tree[type], id);
1429255932Salfred	if (r && (r->owner == slave))
1430255932Salfred		r->state = r->from_state;
1431255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1432255932Salfred}
1433255932Salfred
1434255932Salfredstatic void res_end_move(struct mlx4_dev *dev, int slave,
1435255932Salfred			 enum mlx4_resource type, int id)
1436255932Salfred{
1437255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1438255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1439255932Salfred	struct res_common *r;
1440255932Salfred
1441255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1442255932Salfred	r = res_tracker_lookup(&tracker->res_tree[type], id);
1443255932Salfred	if (r && (r->owner == slave))
1444255932Salfred		r->state = r->to_state;
1445255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1446255932Salfred}
1447255932Salfred
1448255932Salfredstatic int valid_reserved(struct mlx4_dev *dev, int slave, int qpn)
1449255932Salfred{
1450255932Salfred	return mlx4_is_qp_reserved(dev, qpn) &&
1451255932Salfred		(mlx4_is_master(dev) || mlx4_is_guest_proxy(dev, slave, qpn));
1452255932Salfred}
1453255932Salfred
1454255932Salfredstatic int fw_reserved(struct mlx4_dev *dev, int qpn)
1455255932Salfred{
1456255932Salfred	return qpn < dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW];
1457255932Salfred}
1458255932Salfred
1459255932Salfredstatic int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1460255932Salfred			u64 in_param, u64 *out_param)
1461255932Salfred{
1462255932Salfred	int err;
1463255932Salfred	int count;
1464255932Salfred	int align;
1465255932Salfred	int base;
1466255932Salfred	int qpn;
1467255932Salfred	u8 bf_qp;
1468255932Salfred
1469255932Salfred	switch (op) {
1470255932Salfred	case RES_OP_RESERVE:
1471255932Salfred		count = get_param_l(&in_param) & 0xffffff;
1472255932Salfred		bf_qp = get_param_l(&in_param) >> 31;
1473255932Salfred		align = get_param_h(&in_param);
1474255932Salfred		err = mlx4_grant_resource(dev, slave, RES_QP, count, 0);
1475255932Salfred		if (err)
1476255932Salfred			return err;
1477255932Salfred
1478255932Salfred		err = __mlx4_qp_reserve_range(dev, count, align, &base, bf_qp);
1479255932Salfred		if (err) {
1480255932Salfred			mlx4_release_resource(dev, slave, RES_QP, count, 0);
1481255932Salfred			return err;
1482255932Salfred		}
1483255932Salfred
1484255932Salfred		err = add_res_range(dev, slave, base, count, RES_QP, 0);
1485255932Salfred		if (err) {
1486255932Salfred			mlx4_release_resource(dev, slave, RES_QP, count, 0);
1487255932Salfred			__mlx4_qp_release_range(dev, base, count);
1488255932Salfred			return err;
1489255932Salfred		}
1490255932Salfred		set_param_l(out_param, base);
1491255932Salfred		break;
1492255932Salfred	case RES_OP_MAP_ICM:
1493255932Salfred		qpn = get_param_l(&in_param) & 0x7fffff;
1494255932Salfred		if (valid_reserved(dev, slave, qpn)) {
1495255932Salfred			err = add_res_range(dev, slave, qpn, 1, RES_QP, 0);
1496255932Salfred			if (err)
1497255932Salfred				return err;
1498255932Salfred		}
1499255932Salfred
1500255932Salfred		err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED,
1501255932Salfred					   NULL, 1);
1502255932Salfred		if (err)
1503255932Salfred			return err;
1504255932Salfred
1505255932Salfred		if (!fw_reserved(dev, qpn)) {
1506255932Salfred			err = __mlx4_qp_alloc_icm(dev, qpn);
1507255932Salfred			if (err) {
1508255932Salfred				res_abort_move(dev, slave, RES_QP, qpn);
1509255932Salfred				return err;
1510255932Salfred			}
1511255932Salfred		}
1512255932Salfred
1513255932Salfred		res_end_move(dev, slave, RES_QP, qpn);
1514255932Salfred		break;
1515255932Salfred
1516255932Salfred	default:
1517255932Salfred		err = -EINVAL;
1518255932Salfred		break;
1519255932Salfred	}
1520255932Salfred	return err;
1521255932Salfred}
1522255932Salfred
1523255932Salfredstatic int mtt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1524255932Salfred			 u64 in_param, u64 *out_param)
1525255932Salfred{
1526255932Salfred	int err = -EINVAL;
1527255932Salfred	int base;
1528255932Salfred	int order;
1529255932Salfred
1530255932Salfred	if (op != RES_OP_RESERVE_AND_MAP)
1531255932Salfred		return err;
1532255932Salfred
1533255932Salfred	order = get_param_l(&in_param);
1534255932Salfred
1535255932Salfred	err = mlx4_grant_resource(dev, slave, RES_MTT, 1 << order, 0);
1536255932Salfred	if (err)
1537255932Salfred		return err;
1538255932Salfred
1539255932Salfred	base = __mlx4_alloc_mtt_range(dev, order);
1540255932Salfred	if (base == -1) {
1541255932Salfred		mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);
1542255932Salfred		return -ENOMEM;
1543255932Salfred	}
1544255932Salfred
1545255932Salfred	err = add_res_range(dev, slave, base, 1, RES_MTT, order);
1546255932Salfred	if (err) {
1547255932Salfred		mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);
1548255932Salfred		__mlx4_free_mtt_range(dev, base, order);
1549255932Salfred	} else
1550255932Salfred		set_param_l(out_param, base);
1551255932Salfred
1552255932Salfred	return err;
1553255932Salfred}
1554255932Salfred
1555255932Salfredstatic int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1556255932Salfred			 u64 in_param, u64 *out_param)
1557255932Salfred{
1558255932Salfred	int err = -EINVAL;
1559255932Salfred	int index;
1560255932Salfred	int id;
1561255932Salfred	struct res_mpt *mpt;
1562255932Salfred
1563255932Salfred	switch (op) {
1564255932Salfred	case RES_OP_RESERVE:
1565255932Salfred		err = mlx4_grant_resource(dev, slave, RES_MPT, 1, 0);
1566255932Salfred		if (err)
1567255932Salfred			break;
1568255932Salfred
1569255932Salfred		index = __mlx4_mr_reserve(dev);
1570255932Salfred		if (index == -1) {
1571255932Salfred			mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
1572255932Salfred			break;
1573255932Salfred		}
1574255932Salfred		id = index & mpt_mask(dev);
1575255932Salfred
1576255932Salfred		err = add_res_range(dev, slave, id, 1, RES_MPT, index);
1577255932Salfred		if (err) {
1578255932Salfred			mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
1579255932Salfred			__mlx4_mr_release(dev, index);
1580255932Salfred			break;
1581255932Salfred		}
1582255932Salfred		set_param_l(out_param, index);
1583255932Salfred		break;
1584255932Salfred	case RES_OP_MAP_ICM:
1585255932Salfred		index = get_param_l(&in_param);
1586255932Salfred		id = index & mpt_mask(dev);
1587255932Salfred		err = mr_res_start_move_to(dev, slave, id,
1588255932Salfred					   RES_MPT_MAPPED, &mpt);
1589255932Salfred		if (err)
1590255932Salfred			return err;
1591255932Salfred
1592255932Salfred		err = __mlx4_mr_alloc_icm(dev, mpt->key);
1593255932Salfred		if (err) {
1594255932Salfred			res_abort_move(dev, slave, RES_MPT, id);
1595255932Salfred			return err;
1596255932Salfred		}
1597255932Salfred
1598255932Salfred		res_end_move(dev, slave, RES_MPT, id);
1599255932Salfred		break;
1600255932Salfred	}
1601255932Salfred	return err;
1602255932Salfred}
1603255932Salfred
1604255932Salfredstatic int cq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1605255932Salfred			u64 in_param, u64 *out_param)
1606255932Salfred{
1607255932Salfred	int cqn;
1608255932Salfred	int err;
1609255932Salfred
1610255932Salfred	switch (op) {
1611255932Salfred	case RES_OP_RESERVE_AND_MAP:
1612255932Salfred		err = mlx4_grant_resource(dev, slave, RES_CQ, 1, 0);
1613255932Salfred		if (err)
1614255932Salfred			break;
1615255932Salfred
1616255932Salfred		err = __mlx4_cq_alloc_icm(dev, &cqn);
1617255932Salfred		if (err) {
1618255932Salfred			mlx4_release_resource(dev, slave, RES_CQ, 1, 0);
1619255932Salfred			break;
1620255932Salfred		}
1621255932Salfred
1622255932Salfred		err = add_res_range(dev, slave, cqn, 1, RES_CQ, 0);
1623255932Salfred		if (err) {
1624255932Salfred			mlx4_release_resource(dev, slave, RES_CQ, 1, 0);
1625255932Salfred			__mlx4_cq_free_icm(dev, cqn);
1626255932Salfred			break;
1627255932Salfred		}
1628255932Salfred
1629255932Salfred		set_param_l(out_param, cqn);
1630255932Salfred		break;
1631255932Salfred
1632255932Salfred	default:
1633255932Salfred		err = -EINVAL;
1634255932Salfred	}
1635255932Salfred
1636255932Salfred	return err;
1637255932Salfred}
1638255932Salfred
1639255932Salfredstatic int srq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1640255932Salfred			 u64 in_param, u64 *out_param)
1641255932Salfred{
1642255932Salfred	int srqn;
1643255932Salfred	int err;
1644255932Salfred
1645255932Salfred	switch (op) {
1646255932Salfred	case RES_OP_RESERVE_AND_MAP:
1647255932Salfred		err = mlx4_grant_resource(dev, slave, RES_SRQ, 1, 0);
1648255932Salfred		if (err)
1649255932Salfred			break;
1650255932Salfred
1651255932Salfred		err = __mlx4_srq_alloc_icm(dev, &srqn);
1652255932Salfred		if (err) {
1653255932Salfred			mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);
1654255932Salfred			break;
1655255932Salfred		}
1656255932Salfred
1657255932Salfred		err = add_res_range(dev, slave, srqn, 1, RES_SRQ, 0);
1658255932Salfred		if (err) {
1659255932Salfred			mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);
1660255932Salfred			__mlx4_srq_free_icm(dev, srqn);
1661255932Salfred			break;
1662255932Salfred		}
1663255932Salfred
1664255932Salfred		set_param_l(out_param, srqn);
1665255932Salfred		break;
1666255932Salfred
1667255932Salfred	default:
1668255932Salfred		err = -EINVAL;
1669255932Salfred	}
1670255932Salfred
1671255932Salfred	return err;
1672255932Salfred}
1673255932Salfred
1674255932Salfredstatic int mac_find_smac_ix_in_slave(struct mlx4_dev *dev, int slave, int port,
1675255932Salfred				     u8 smac_index, u64 *mac)
1676255932Salfred{
1677255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1678255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1679255932Salfred	struct list_head *mac_list =
1680255932Salfred		&tracker->slave_list[slave].res_list[RES_MAC];
1681255932Salfred	struct mac_res *res, *tmp;
1682255932Salfred
1683255932Salfred	list_for_each_entry_safe(res, tmp, mac_list, list) {
1684255932Salfred		if (res->smac_index == smac_index && res->port == (u8) port) {
1685255932Salfred			*mac = res->mac;
1686255932Salfred			return 0;
1687255932Salfred		}
1688255932Salfred	}
1689255932Salfred	return -ENOENT;
1690255932Salfred}
1691255932Salfred
1692255932Salfredstatic int mac_add_to_slave(struct mlx4_dev *dev, int slave, u64 mac, int port, u8 smac_index)
1693255932Salfred{
1694255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1695255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1696255932Salfred	struct list_head *mac_list =
1697255932Salfred		&tracker->slave_list[slave].res_list[RES_MAC];
1698255932Salfred	struct mac_res *res, *tmp;
1699255932Salfred
1700255932Salfred	list_for_each_entry_safe(res, tmp, mac_list, list) {
1701255932Salfred		if (res->mac == mac && res->port == (u8) port) {
1702255932Salfred			/* mac found. update ref count */
1703255932Salfred			++res->ref_count;
1704255932Salfred			return 0;
1705255932Salfred		}
1706255932Salfred	}
1707255932Salfred
1708255932Salfred	if (mlx4_grant_resource(dev, slave, RES_MAC, 1, port))
1709255932Salfred		return -EINVAL;
1710255932Salfred	res = kzalloc(sizeof *res, GFP_KERNEL);
1711255932Salfred	if (!res) {
1712255932Salfred		mlx4_release_resource(dev, slave, RES_MAC, 1, port);
1713255932Salfred		return -ENOMEM;
1714255932Salfred	}
1715255932Salfred	res->mac = mac;
1716255932Salfred	res->port = (u8) port;
1717255932Salfred	res->smac_index = smac_index;
1718255932Salfred	res->ref_count = 1;
1719255932Salfred	list_add_tail(&res->list,
1720255932Salfred		      &tracker->slave_list[slave].res_list[RES_MAC]);
1721255932Salfred	return 0;
1722255932Salfred}
1723255932Salfred
1724255932Salfred
1725255932Salfredstatic void mac_del_from_slave(struct mlx4_dev *dev, int slave, u64 mac,
1726255932Salfred			       int port)
1727255932Salfred{
1728255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1729255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1730255932Salfred	struct list_head *mac_list =
1731255932Salfred		&tracker->slave_list[slave].res_list[RES_MAC];
1732255932Salfred	struct mac_res *res, *tmp;
1733255932Salfred
1734255932Salfred	list_for_each_entry_safe(res, tmp, mac_list, list) {
1735255932Salfred		if (res->mac == mac && res->port == (u8) port) {
1736255932Salfred			if (!--res->ref_count) {
1737255932Salfred				list_del(&res->list);
1738255932Salfred				mlx4_release_resource(dev, slave, RES_MAC, 1, port);
1739255932Salfred				kfree(res);
1740255932Salfred			}
1741255932Salfred			break;
1742255932Salfred		}
1743255932Salfred	}
1744255932Salfred}
1745255932Salfred
1746255932Salfredstatic void rem_slave_macs(struct mlx4_dev *dev, int slave)
1747255932Salfred{
1748255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1749255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1750255932Salfred	struct list_head *mac_list =
1751255932Salfred		&tracker->slave_list[slave].res_list[RES_MAC];
1752255932Salfred	struct mac_res *res, *tmp;
1753255932Salfred	int i;
1754255932Salfred
1755255932Salfred	list_for_each_entry_safe(res, tmp, mac_list, list) {
1756255932Salfred		list_del(&res->list);
1757255932Salfred		/* dereference the mac the num times the slave referenced it */
1758255932Salfred		for (i = 0; i < res->ref_count; i++)
1759255932Salfred			__mlx4_unregister_mac(dev, res->port, res->mac);
1760255932Salfred		mlx4_release_resource(dev, slave, RES_MAC, 1, res->port);
1761255932Salfred		kfree(res);
1762255932Salfred	}
1763255932Salfred}
1764255932Salfred
1765255932Salfredstatic int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1766255932Salfred			 u64 in_param, u64 *out_param, int in_port)
1767255932Salfred{
1768255932Salfred	int err = -EINVAL;
1769255932Salfred	int port;
1770255932Salfred	u64 mac;
1771255932Salfred	u8 smac_index = 0;
1772255932Salfred
1773255932Salfred	if (op != RES_OP_RESERVE_AND_MAP)
1774255932Salfred		return err;
1775255932Salfred
1776255932Salfred	port = !in_port ? get_param_l(out_param) : in_port;
1777255932Salfred	mac = in_param;
1778255932Salfred
1779255932Salfred	err = __mlx4_register_mac(dev, port, mac);
1780255932Salfred	if (err >= 0) {
1781255932Salfred		smac_index = err;
1782255932Salfred		set_param_l(out_param, err);
1783255932Salfred		err = 0;
1784255932Salfred	}
1785255932Salfred
1786255932Salfred	if (!err) {
1787255932Salfred		err = mac_add_to_slave(dev, slave, mac, port, smac_index);
1788255932Salfred		if (err)
1789255932Salfred			__mlx4_unregister_mac(dev, port, mac);
1790255932Salfred	}
1791255932Salfred	return err;
1792255932Salfred}
1793255932Salfred
1794255932Salfredstatic int vlan_add_to_slave(struct mlx4_dev *dev, int slave, u16 vlan,
1795255932Salfred			     int port, int vlan_index)
1796255932Salfred{
1797255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1798255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1799255932Salfred	struct list_head *vlan_list =
1800255932Salfred		&tracker->slave_list[slave].res_list[RES_VLAN];
1801255932Salfred	struct vlan_res *res, *tmp;
1802255932Salfred
1803255932Salfred	list_for_each_entry_safe(res, tmp, vlan_list, list) {
1804255932Salfred		if (res->vlan == vlan && res->port == (u8) port) {
1805255932Salfred			/* vlan found. update ref count */
1806255932Salfred			++res->ref_count;
1807255932Salfred			return 0;
1808255932Salfred		}
1809255932Salfred	}
1810255932Salfred
1811255932Salfred	if (mlx4_grant_resource(dev, slave, RES_VLAN, 1, port))
1812255932Salfred		return -EINVAL;
1813255932Salfred	res = kzalloc(sizeof(*res), GFP_KERNEL);
1814255932Salfred	if (!res) {
1815255932Salfred		mlx4_release_resource(dev, slave, RES_VLAN, 1, port);
1816255932Salfred		return -ENOMEM;
1817255932Salfred	}
1818255932Salfred	res->vlan = vlan;
1819255932Salfred	res->port = (u8) port;
1820255932Salfred	res->vlan_index = vlan_index;
1821255932Salfred	res->ref_count = 1;
1822255932Salfred	list_add_tail(&res->list,
1823255932Salfred		      &tracker->slave_list[slave].res_list[RES_VLAN]);
1824255932Salfred	return 0;
1825255932Salfred}
1826255932Salfred
1827255932Salfred
1828255932Salfredstatic void vlan_del_from_slave(struct mlx4_dev *dev, int slave, u16 vlan,
1829255932Salfred				int port)
1830255932Salfred{
1831255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1832255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1833255932Salfred	struct list_head *vlan_list =
1834255932Salfred		&tracker->slave_list[slave].res_list[RES_VLAN];
1835255932Salfred	struct vlan_res *res, *tmp;
1836255932Salfred
1837255932Salfred	list_for_each_entry_safe(res, tmp, vlan_list, list) {
1838255932Salfred		if (res->vlan == vlan && res->port == (u8) port) {
1839255932Salfred			if (!--res->ref_count) {
1840255932Salfred				list_del(&res->list);
1841255932Salfred				mlx4_release_resource(dev, slave, RES_VLAN,
1842255932Salfred						      1, port);
1843255932Salfred				kfree(res);
1844255932Salfred			}
1845255932Salfred			break;
1846255932Salfred		}
1847255932Salfred	}
1848255932Salfred}
1849255932Salfred
1850255932Salfredstatic void rem_slave_vlans(struct mlx4_dev *dev, int slave)
1851255932Salfred{
1852255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1853255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1854255932Salfred	struct list_head *vlan_list =
1855255932Salfred		&tracker->slave_list[slave].res_list[RES_VLAN];
1856255932Salfred	struct vlan_res *res, *tmp;
1857255932Salfred	int i;
1858255932Salfred
1859255932Salfred	list_for_each_entry_safe(res, tmp, vlan_list, list) {
1860255932Salfred		list_del(&res->list);
1861255932Salfred		/* dereference the vlan the num times the slave referenced it */
1862255932Salfred		for (i = 0; i < res->ref_count; i++)
1863255932Salfred			__mlx4_unregister_vlan(dev, res->port, res->vlan);
1864255932Salfred		mlx4_release_resource(dev, slave, RES_VLAN, 1, res->port);
1865255932Salfred		kfree(res);
1866255932Salfred	}
1867255932Salfred}
1868255932Salfred
1869255932Salfredstatic int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1870255932Salfred			  u64 in_param, u64 *out_param, int port)
1871255932Salfred{
1872255932Salfred	int err = -EINVAL;
1873255932Salfred	u16 vlan;
1874255932Salfred	int vlan_index;
1875255932Salfred
1876255932Salfred	if (!port)
1877255932Salfred		return err;
1878255932Salfred
1879255932Salfred	if (op != RES_OP_RESERVE_AND_MAP)
1880255932Salfred		return err;
1881255932Salfred
1882255932Salfred	vlan = (u16) in_param;
1883255932Salfred
1884255932Salfred	err = __mlx4_register_vlan(dev, port, vlan, &vlan_index);
1885255932Salfred	if (!err) {
1886255932Salfred		set_param_l(out_param, (u32) vlan_index);
1887255932Salfred		err = vlan_add_to_slave(dev, slave, vlan, port, vlan_index);
1888255932Salfred		if (err)
1889255932Salfred			__mlx4_unregister_vlan(dev, port, vlan);
1890255932Salfred	}
1891255932Salfred	return err;
1892255932Salfred}
1893255932Salfred
1894255932Salfredstatic int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1895255932Salfred			     u64 in_param, u64 *out_param)
1896255932Salfred{
1897255932Salfred	u32 index;
1898255932Salfred	int err;
1899255932Salfred
1900255932Salfred	if (op != RES_OP_RESERVE)
1901255932Salfred		return -EINVAL;
1902255932Salfred
1903255932Salfred	err = mlx4_grant_resource(dev, slave, RES_COUNTER, 1, 0);
1904255932Salfred	if (err)
1905255932Salfred		return err;
1906255932Salfred
1907255932Salfred	err = __mlx4_counter_alloc(dev, &index);
1908255932Salfred	if (err) {
1909255932Salfred		mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);
1910255932Salfred		return err;
1911255932Salfred	}
1912255932Salfred
1913255932Salfred	err = add_res_range(dev, slave, index, 1, RES_COUNTER, 0);
1914255932Salfred	if (err) {
1915255932Salfred		__mlx4_counter_free(dev, index);
1916255932Salfred		mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);
1917255932Salfred	} else {
1918255932Salfred		set_param_l(out_param, index);
1919255932Salfred	}
1920255932Salfred
1921255932Salfred	return err;
1922255932Salfred}
1923255932Salfred
1924255932Salfredstatic int xrcdn_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1925255932Salfred			   u64 in_param, u64 *out_param)
1926255932Salfred{
1927255932Salfred	u32 xrcdn;
1928255932Salfred	int err;
1929255932Salfred
1930255932Salfred	if (op != RES_OP_RESERVE)
1931255932Salfred		return -EINVAL;
1932255932Salfred
1933255932Salfred	err = __mlx4_xrcd_alloc(dev, &xrcdn);
1934255932Salfred	if (err)
1935255932Salfred		return err;
1936255932Salfred
1937255932Salfred	err = add_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
1938255932Salfred	if (err)
1939255932Salfred		__mlx4_xrcd_free(dev, xrcdn);
1940255932Salfred	else
1941255932Salfred		set_param_l(out_param, xrcdn);
1942255932Salfred
1943255932Salfred	return err;
1944255932Salfred}
1945255932Salfred
1946255932Salfredint mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
1947255932Salfred			   struct mlx4_vhcr *vhcr,
1948255932Salfred			   struct mlx4_cmd_mailbox *inbox,
1949255932Salfred			   struct mlx4_cmd_mailbox *outbox,
1950255932Salfred			   struct mlx4_cmd_info *cmd)
1951255932Salfred{
1952255932Salfred	int err;
1953255932Salfred	int alop = vhcr->op_modifier;
1954255932Salfred
1955255932Salfred	switch (vhcr->in_modifier & 0xFF) {
1956255932Salfred	case RES_QP:
1957255932Salfred		err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop,
1958255932Salfred				   vhcr->in_param, &vhcr->out_param);
1959255932Salfred		break;
1960255932Salfred
1961255932Salfred	case RES_MTT:
1962255932Salfred		err = mtt_alloc_res(dev, slave, vhcr->op_modifier, alop,
1963255932Salfred				    vhcr->in_param, &vhcr->out_param);
1964255932Salfred		break;
1965255932Salfred
1966255932Salfred	case RES_MPT:
1967255932Salfred		err = mpt_alloc_res(dev, slave, vhcr->op_modifier, alop,
1968255932Salfred				    vhcr->in_param, &vhcr->out_param);
1969255932Salfred		break;
1970255932Salfred
1971255932Salfred	case RES_CQ:
1972255932Salfred		err = cq_alloc_res(dev, slave, vhcr->op_modifier, alop,
1973255932Salfred				   vhcr->in_param, &vhcr->out_param);
1974255932Salfred		break;
1975255932Salfred
1976255932Salfred	case RES_SRQ:
1977255932Salfred		err = srq_alloc_res(dev, slave, vhcr->op_modifier, alop,
1978255932Salfred				    vhcr->in_param, &vhcr->out_param);
1979255932Salfred		break;
1980255932Salfred
1981255932Salfred	case RES_MAC:
1982255932Salfred		err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop,
1983255932Salfred				    vhcr->in_param, &vhcr->out_param,
1984255932Salfred				    (vhcr->in_modifier >> 8) & 0xFF);
1985255932Salfred		break;
1986255932Salfred
1987255932Salfred	case RES_VLAN:
1988255932Salfred		err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop,
1989255932Salfred				     vhcr->in_param, &vhcr->out_param,
1990255932Salfred				     (vhcr->in_modifier >> 8) & 0xFF);
1991255932Salfred		break;
1992255932Salfred
1993255932Salfred	case RES_COUNTER:
1994255932Salfred		err = counter_alloc_res(dev, slave, vhcr->op_modifier, alop,
1995255932Salfred					vhcr->in_param, &vhcr->out_param);
1996255932Salfred		break;
1997255932Salfred
1998255932Salfred	case RES_XRCD:
1999255932Salfred		err = xrcdn_alloc_res(dev, slave, vhcr->op_modifier, alop,
2000255932Salfred				      vhcr->in_param, &vhcr->out_param);
2001255932Salfred		break;
2002255932Salfred
2003255932Salfred	default:
2004255932Salfred		err = -EINVAL;
2005255932Salfred		break;
2006255932Salfred	}
2007255932Salfred
2008255932Salfred	return err;
2009255932Salfred}
2010255932Salfred
2011255932Salfredstatic int qp_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2012255932Salfred		       u64 in_param)
2013255932Salfred{
2014255932Salfred	int err;
2015255932Salfred	int count;
2016255932Salfred	int base;
2017255932Salfred	int qpn;
2018255932Salfred
2019255932Salfred	switch (op) {
2020255932Salfred	case RES_OP_RESERVE:
2021255932Salfred		base = get_param_l(&in_param) & 0x7fffff;
2022255932Salfred		count = get_param_h(&in_param);
2023255932Salfred		err = rem_res_range(dev, slave, base, count, RES_QP, 0);
2024255932Salfred		if (err)
2025255932Salfred			break;
2026255932Salfred		mlx4_release_resource(dev, slave, RES_QP, count, 0);
2027255932Salfred		__mlx4_qp_release_range(dev, base, count);
2028255932Salfred		break;
2029255932Salfred	case RES_OP_MAP_ICM:
2030255932Salfred		qpn = get_param_l(&in_param) & 0x7fffff;
2031255932Salfred		err = qp_res_start_move_to(dev, slave, qpn, RES_QP_RESERVED,
2032255932Salfred					   NULL, 0);
2033255932Salfred		if (err)
2034255932Salfred			return err;
2035255932Salfred
2036255932Salfred		if (!fw_reserved(dev, qpn))
2037255932Salfred			__mlx4_qp_free_icm(dev, qpn);
2038255932Salfred
2039255932Salfred		res_end_move(dev, slave, RES_QP, qpn);
2040255932Salfred
2041255932Salfred		if (valid_reserved(dev, slave, qpn))
2042255932Salfred			err = rem_res_range(dev, slave, qpn, 1, RES_QP, 0);
2043255932Salfred		break;
2044255932Salfred	default:
2045255932Salfred		err = -EINVAL;
2046255932Salfred		break;
2047255932Salfred	}
2048255932Salfred	return err;
2049255932Salfred}
2050255932Salfred
2051255932Salfredstatic int mtt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2052255932Salfred			u64 in_param, u64 *out_param)
2053255932Salfred{
2054255932Salfred	int err = -EINVAL;
2055255932Salfred	int base;
2056255932Salfred	int order;
2057255932Salfred
2058255932Salfred	if (op != RES_OP_RESERVE_AND_MAP)
2059255932Salfred		return err;
2060255932Salfred
2061255932Salfred	base = get_param_l(&in_param);
2062255932Salfred	order = get_param_h(&in_param);
2063255932Salfred	err = rem_res_range(dev, slave, base, 1, RES_MTT, order);
2064255932Salfred	if (!err) {
2065255932Salfred		mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);
2066255932Salfred		__mlx4_free_mtt_range(dev, base, order);
2067255932Salfred	}
2068255932Salfred	return err;
2069255932Salfred}
2070255932Salfred
2071255932Salfredstatic int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2072255932Salfred			u64 in_param)
2073255932Salfred{
2074255932Salfred	int err = -EINVAL;
2075255932Salfred	int index;
2076255932Salfred	int id;
2077255932Salfred	struct res_mpt *mpt;
2078255932Salfred
2079255932Salfred	switch (op) {
2080255932Salfred	case RES_OP_RESERVE:
2081255932Salfred		index = get_param_l(&in_param);
2082255932Salfred		id = index & mpt_mask(dev);
2083255932Salfred		err = get_res(dev, slave, id, RES_MPT, &mpt);
2084255932Salfred		if (err)
2085255932Salfred			break;
2086255932Salfred		index = mpt->key;
2087255932Salfred		put_res(dev, slave, id, RES_MPT);
2088255932Salfred
2089255932Salfred		err = rem_res_range(dev, slave, id, 1, RES_MPT, 0);
2090255932Salfred		if (err)
2091255932Salfred			break;
2092255932Salfred		mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
2093255932Salfred		__mlx4_mr_release(dev, index);
2094255932Salfred		break;
2095255932Salfred	case RES_OP_MAP_ICM:
2096255932Salfred			index = get_param_l(&in_param);
2097255932Salfred			id = index & mpt_mask(dev);
2098255932Salfred			err = mr_res_start_move_to(dev, slave, id,
2099255932Salfred						   RES_MPT_RESERVED, &mpt);
2100255932Salfred			if (err)
2101255932Salfred				return err;
2102255932Salfred
2103255932Salfred			__mlx4_mr_free_icm(dev, mpt->key);
2104255932Salfred			res_end_move(dev, slave, RES_MPT, id);
2105255932Salfred			return err;
2106255932Salfred		break;
2107255932Salfred	default:
2108255932Salfred		err = -EINVAL;
2109255932Salfred		break;
2110255932Salfred	}
2111255932Salfred	return err;
2112255932Salfred}
2113255932Salfred
2114255932Salfredstatic int cq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2115255932Salfred		       u64 in_param, u64 *out_param)
2116255932Salfred{
2117255932Salfred	int cqn;
2118255932Salfred	int err;
2119255932Salfred
2120255932Salfred	switch (op) {
2121255932Salfred	case RES_OP_RESERVE_AND_MAP:
2122255932Salfred		cqn = get_param_l(&in_param);
2123255932Salfred		err = rem_res_range(dev, slave, cqn, 1, RES_CQ, 0);
2124255932Salfred		if (err)
2125255932Salfred			break;
2126255932Salfred
2127255932Salfred		mlx4_release_resource(dev, slave, RES_CQ, 1, 0);
2128255932Salfred		__mlx4_cq_free_icm(dev, cqn);
2129255932Salfred		break;
2130255932Salfred
2131255932Salfred	default:
2132255932Salfred		err = -EINVAL;
2133255932Salfred		break;
2134255932Salfred	}
2135255932Salfred
2136255932Salfred	return err;
2137255932Salfred}
2138255932Salfred
2139255932Salfredstatic int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2140255932Salfred			u64 in_param, u64 *out_param)
2141255932Salfred{
2142255932Salfred	int srqn;
2143255932Salfred	int err;
2144255932Salfred
2145255932Salfred	switch (op) {
2146255932Salfred	case RES_OP_RESERVE_AND_MAP:
2147255932Salfred		srqn = get_param_l(&in_param);
2148255932Salfred		err = rem_res_range(dev, slave, srqn, 1, RES_SRQ, 0);
2149255932Salfred		if (err)
2150255932Salfred			break;
2151255932Salfred
2152255932Salfred		mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);
2153255932Salfred		__mlx4_srq_free_icm(dev, srqn);
2154255932Salfred		break;
2155255932Salfred
2156255932Salfred	default:
2157255932Salfred		err = -EINVAL;
2158255932Salfred		break;
2159255932Salfred	}
2160255932Salfred
2161255932Salfred	return err;
2162255932Salfred}
2163255932Salfred
2164255932Salfredstatic int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2165255932Salfred			    u64 in_param, u64 *out_param, int in_port)
2166255932Salfred{
2167255932Salfred	int port;
2168255932Salfred	int err = 0;
2169255932Salfred
2170255932Salfred	switch (op) {
2171255932Salfred	case RES_OP_RESERVE_AND_MAP:
2172255932Salfred		port = !in_port ? get_param_l(out_param) : in_port;
2173255932Salfred		mac_del_from_slave(dev, slave, in_param, port);
2174255932Salfred		__mlx4_unregister_mac(dev, port, in_param);
2175255932Salfred		break;
2176255932Salfred	default:
2177255932Salfred		err = -EINVAL;
2178255932Salfred		break;
2179255932Salfred	}
2180255932Salfred
2181255932Salfred	return err;
2182255932Salfred
2183255932Salfred}
2184255932Salfred
2185255932Salfredstatic int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2186255932Salfred			    u64 in_param, u64 *out_param, int port)
2187255932Salfred{
2188255932Salfred	int err = 0;
2189255932Salfred
2190255932Salfred	switch (op) {
2191255932Salfred	case RES_OP_RESERVE_AND_MAP:
2192255932Salfred		if (!port)
2193255932Salfred			return -EINVAL;
2194255932Salfred		vlan_del_from_slave(dev, slave, in_param, port);
2195255932Salfred		__mlx4_unregister_vlan(dev, port, in_param);
2196255932Salfred		break;
2197255932Salfred	default:
2198255932Salfred		err = -EINVAL;
2199255932Salfred		break;
2200255932Salfred	}
2201255932Salfred
2202255932Salfred	return err;
2203255932Salfred}
2204255932Salfred
2205255932Salfredstatic int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2206255932Salfred			    u64 in_param, u64 *out_param)
2207255932Salfred{
2208255932Salfred	int index;
2209255932Salfred	int err;
2210255932Salfred
2211255932Salfred	if (op != RES_OP_RESERVE)
2212255932Salfred		return -EINVAL;
2213255932Salfred
2214255932Salfred	index = get_param_l(&in_param);
2215255932Salfred	err = rem_res_range(dev, slave, index, 1, RES_COUNTER, 0);
2216255932Salfred	if (err)
2217255932Salfred		return err;
2218255932Salfred
2219255932Salfred	__mlx4_counter_free(dev, index);
2220255932Salfred	mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);
2221255932Salfred
2222255932Salfred	return err;
2223255932Salfred}
2224255932Salfred
2225255932Salfredstatic int xrcdn_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2226255932Salfred			  u64 in_param, u64 *out_param)
2227255932Salfred{
2228255932Salfred	int xrcdn;
2229255932Salfred	int err;
2230255932Salfred
2231255932Salfred	if (op != RES_OP_RESERVE)
2232255932Salfred		return -EINVAL;
2233255932Salfred
2234255932Salfred	xrcdn = get_param_l(&in_param);
2235255932Salfred	err = rem_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
2236255932Salfred	if (err)
2237255932Salfred		return err;
2238255932Salfred
2239255932Salfred	__mlx4_xrcd_free(dev, xrcdn);
2240255932Salfred
2241255932Salfred	return err;
2242255932Salfred}
2243255932Salfred
2244255932Salfredint mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
2245255932Salfred			  struct mlx4_vhcr *vhcr,
2246255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2247255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2248255932Salfred			  struct mlx4_cmd_info *cmd)
2249255932Salfred{
2250255932Salfred	int err = -EINVAL;
2251255932Salfred	int alop = vhcr->op_modifier;
2252255932Salfred
2253255932Salfred	switch (vhcr->in_modifier & 0xFF) {
2254255932Salfred	case RES_QP:
2255255932Salfred		err = qp_free_res(dev, slave, vhcr->op_modifier, alop,
2256255932Salfred				  vhcr->in_param);
2257255932Salfred		break;
2258255932Salfred
2259255932Salfred	case RES_MTT:
2260255932Salfred		err = mtt_free_res(dev, slave, vhcr->op_modifier, alop,
2261255932Salfred				   vhcr->in_param, &vhcr->out_param);
2262255932Salfred		break;
2263255932Salfred
2264255932Salfred	case RES_MPT:
2265255932Salfred		err = mpt_free_res(dev, slave, vhcr->op_modifier, alop,
2266255932Salfred				   vhcr->in_param);
2267255932Salfred		break;
2268255932Salfred
2269255932Salfred	case RES_CQ:
2270255932Salfred		err = cq_free_res(dev, slave, vhcr->op_modifier, alop,
2271255932Salfred				  vhcr->in_param, &vhcr->out_param);
2272255932Salfred		break;
2273255932Salfred
2274255932Salfred	case RES_SRQ:
2275255932Salfred		err = srq_free_res(dev, slave, vhcr->op_modifier, alop,
2276255932Salfred				   vhcr->in_param, &vhcr->out_param);
2277255932Salfred		break;
2278255932Salfred
2279255932Salfred	case RES_MAC:
2280255932Salfred		err = mac_free_res(dev, slave, vhcr->op_modifier, alop,
2281255932Salfred				   vhcr->in_param, &vhcr->out_param,
2282255932Salfred				   (vhcr->in_modifier >> 8) & 0xFF);
2283255932Salfred		break;
2284255932Salfred
2285255932Salfred	case RES_VLAN:
2286255932Salfred		err = vlan_free_res(dev, slave, vhcr->op_modifier, alop,
2287255932Salfred				    vhcr->in_param, &vhcr->out_param,
2288255932Salfred				    (vhcr->in_modifier >> 8) & 0xFF);
2289255932Salfred		break;
2290255932Salfred
2291255932Salfred	case RES_COUNTER:
2292255932Salfred		err = counter_free_res(dev, slave, vhcr->op_modifier, alop,
2293255932Salfred				       vhcr->in_param, &vhcr->out_param);
2294255932Salfred		break;
2295255932Salfred
2296255932Salfred	case RES_XRCD:
2297255932Salfred		err = xrcdn_free_res(dev, slave, vhcr->op_modifier, alop,
2298255932Salfred				     vhcr->in_param, &vhcr->out_param);
2299255932Salfred
2300255932Salfred	default:
2301255932Salfred		break;
2302255932Salfred	}
2303255932Salfred	return err;
2304255932Salfred}
2305255932Salfred
2306255932Salfred/* ugly but other choices are uglier */
2307255932Salfredstatic int mr_phys_mpt(struct mlx4_mpt_entry *mpt)
2308255932Salfred{
2309255932Salfred	return (be32_to_cpu(mpt->flags) >> 9) & 1;
2310255932Salfred}
2311255932Salfred
2312255932Salfredstatic int mr_get_mtt_addr(struct mlx4_mpt_entry *mpt)
2313255932Salfred{
2314255932Salfred	return (int)be64_to_cpu(mpt->mtt_addr) & 0xfffffff8;
2315255932Salfred}
2316255932Salfred
2317255932Salfredstatic int mr_get_mtt_size(struct mlx4_mpt_entry *mpt)
2318255932Salfred{
2319255932Salfred	return be32_to_cpu(mpt->mtt_sz);
2320255932Salfred}
2321255932Salfred
2322255932Salfredstatic int qp_get_mtt_addr(struct mlx4_qp_context *qpc)
2323255932Salfred{
2324255932Salfred	return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;
2325255932Salfred}
2326255932Salfred
2327255932Salfredstatic int srq_get_mtt_addr(struct mlx4_srq_context *srqc)
2328255932Salfred{
2329255932Salfred	return be32_to_cpu(srqc->mtt_base_addr_l) & 0xfffffff8;
2330255932Salfred}
2331255932Salfred
2332255932Salfredstatic int qp_get_mtt_size(struct mlx4_qp_context *qpc)
2333255932Salfred{
2334255932Salfred	int page_shift = (qpc->log_page_size & 0x3f) + 12;
2335255932Salfred	int log_sq_size = (qpc->sq_size_stride >> 3) & 0xf;
2336255932Salfred	int log_sq_sride = qpc->sq_size_stride & 7;
2337255932Salfred	int log_rq_size = (qpc->rq_size_stride >> 3) & 0xf;
2338255932Salfred	int log_rq_stride = qpc->rq_size_stride & 7;
2339255932Salfred	int srq = (be32_to_cpu(qpc->srqn) >> 24) & 1;
2340255932Salfred	int rss = (be32_to_cpu(qpc->flags) >> 13) & 1;
2341255932Salfred	int xrc = (be32_to_cpu(qpc->local_qpn) >> 23) & 1;
2342255932Salfred	int sq_size;
2343255932Salfred	int rq_size;
2344255932Salfred	int total_pages;
2345255932Salfred	int total_mem;
2346255932Salfred	int page_offset = (be32_to_cpu(qpc->params2) >> 6) & 0x3f;
2347255932Salfred
2348255932Salfred	sq_size = 1 << (log_sq_size + log_sq_sride + 4);
2349255932Salfred	rq_size = (srq|rss|xrc) ? 0 : (1 << (log_rq_size + log_rq_stride + 4));
2350255932Salfred	total_mem = sq_size + rq_size;
2351255932Salfred	total_pages =
2352255932Salfred		roundup_pow_of_two((total_mem + (page_offset << 6)) >>
2353255932Salfred				   page_shift);
2354255932Salfred
2355255932Salfred	return total_pages;
2356255932Salfred}
2357255932Salfred
2358255932Salfredstatic int check_mtt_range(struct mlx4_dev *dev, int slave, int start,
2359255932Salfred			   int size, struct res_mtt *mtt)
2360255932Salfred{
2361255932Salfred	int res_start = mtt->com.res_id;
2362255932Salfred	int res_size = (1 << mtt->order);
2363255932Salfred
2364255932Salfred	if (start < res_start || start + size > res_start + res_size)
2365255932Salfred		return -EPERM;
2366255932Salfred	return 0;
2367255932Salfred}
2368255932Salfred
2369255932Salfredint mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,
2370255932Salfred			   struct mlx4_vhcr *vhcr,
2371255932Salfred			   struct mlx4_cmd_mailbox *inbox,
2372255932Salfred			   struct mlx4_cmd_mailbox *outbox,
2373255932Salfred			   struct mlx4_cmd_info *cmd)
2374255932Salfred{
2375255932Salfred	int err;
2376255932Salfred	int index = vhcr->in_modifier;
2377255932Salfred	struct res_mtt *mtt;
2378255932Salfred	struct res_mpt *mpt;
2379255932Salfred	int mtt_base = mr_get_mtt_addr(inbox->buf) / dev->caps.mtt_entry_sz;
2380255932Salfred	int phys;
2381255932Salfred	int id;
2382255932Salfred
2383255932Salfred	id = index & mpt_mask(dev);
2384255932Salfred	err = mr_res_start_move_to(dev, slave, id, RES_MPT_HW, &mpt);
2385255932Salfred	if (err)
2386255932Salfred		return err;
2387255932Salfred
2388255932Salfred	phys = mr_phys_mpt(inbox->buf);
2389255932Salfred	if (!phys) {
2390255932Salfred		err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
2391255932Salfred		if (err)
2392255932Salfred			goto ex_abort;
2393255932Salfred
2394255932Salfred		err = check_mtt_range(dev, slave, mtt_base,
2395255932Salfred				      mr_get_mtt_size(inbox->buf), mtt);
2396255932Salfred		if (err)
2397255932Salfred			goto ex_put;
2398255932Salfred
2399255932Salfred		mpt->mtt = mtt;
2400255932Salfred	}
2401255932Salfred
2402255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2403255932Salfred	if (err)
2404255932Salfred		goto ex_put;
2405255932Salfred
2406255932Salfred	if (!phys) {
2407255932Salfred		atomic_inc(&mtt->ref_count);
2408255932Salfred		put_res(dev, slave, mtt->com.res_id, RES_MTT);
2409255932Salfred	}
2410255932Salfred
2411255932Salfred	res_end_move(dev, slave, RES_MPT, id);
2412255932Salfred	return 0;
2413255932Salfred
2414255932Salfredex_put:
2415255932Salfred	if (!phys)
2416255932Salfred		put_res(dev, slave, mtt->com.res_id, RES_MTT);
2417255932Salfredex_abort:
2418255932Salfred	res_abort_move(dev, slave, RES_MPT, id);
2419255932Salfred
2420255932Salfred	return err;
2421255932Salfred}
2422255932Salfred
2423255932Salfredint mlx4_HW2SW_MPT_wrapper(struct mlx4_dev *dev, int slave,
2424255932Salfred			   struct mlx4_vhcr *vhcr,
2425255932Salfred			   struct mlx4_cmd_mailbox *inbox,
2426255932Salfred			   struct mlx4_cmd_mailbox *outbox,
2427255932Salfred			   struct mlx4_cmd_info *cmd)
2428255932Salfred{
2429255932Salfred	int err;
2430255932Salfred	int index = vhcr->in_modifier;
2431255932Salfred	struct res_mpt *mpt;
2432255932Salfred	int id;
2433255932Salfred
2434255932Salfred	id = index & mpt_mask(dev);
2435255932Salfred	err = mr_res_start_move_to(dev, slave, id, RES_MPT_MAPPED, &mpt);
2436255932Salfred	if (err)
2437255932Salfred		return err;
2438255932Salfred
2439255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2440255932Salfred	if (err)
2441255932Salfred		goto ex_abort;
2442255932Salfred
2443255932Salfred	if (mpt->mtt)
2444255932Salfred		atomic_dec(&mpt->mtt->ref_count);
2445255932Salfred
2446255932Salfred	res_end_move(dev, slave, RES_MPT, id);
2447255932Salfred	return 0;
2448255932Salfred
2449255932Salfredex_abort:
2450255932Salfred	res_abort_move(dev, slave, RES_MPT, id);
2451255932Salfred
2452255932Salfred	return err;
2453255932Salfred}
2454255932Salfred
2455255932Salfredint mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave,
2456255932Salfred			   struct mlx4_vhcr *vhcr,
2457255932Salfred			   struct mlx4_cmd_mailbox *inbox,
2458255932Salfred			   struct mlx4_cmd_mailbox *outbox,
2459255932Salfred			   struct mlx4_cmd_info *cmd)
2460255932Salfred{
2461255932Salfred	int err;
2462255932Salfred	int index = vhcr->in_modifier;
2463255932Salfred	struct res_mpt *mpt;
2464255932Salfred	int id;
2465255932Salfred
2466255932Salfred	id = index & mpt_mask(dev);
2467255932Salfred	err = get_res(dev, slave, id, RES_MPT, &mpt);
2468255932Salfred	if (err)
2469255932Salfred		return err;
2470255932Salfred
2471255932Salfred	if (mpt->com.from_state != RES_MPT_HW) {
2472255932Salfred		err = -EBUSY;
2473255932Salfred		goto out;
2474255932Salfred	}
2475255932Salfred
2476255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2477255932Salfred
2478255932Salfredout:
2479255932Salfred	put_res(dev, slave, id, RES_MPT);
2480255932Salfred	return err;
2481255932Salfred}
2482255932Salfred
2483255932Salfredstatic int qp_get_rcqn(struct mlx4_qp_context *qpc)
2484255932Salfred{
2485255932Salfred	return be32_to_cpu(qpc->cqn_recv) & 0xffffff;
2486255932Salfred}
2487255932Salfred
2488255932Salfredstatic int qp_get_scqn(struct mlx4_qp_context *qpc)
2489255932Salfred{
2490255932Salfred	return be32_to_cpu(qpc->cqn_send) & 0xffffff;
2491255932Salfred}
2492255932Salfred
2493255932Salfredstatic u32 qp_get_srqn(struct mlx4_qp_context *qpc)
2494255932Salfred{
2495255932Salfred	return be32_to_cpu(qpc->srqn) & 0x1ffffff;
2496255932Salfred}
2497255932Salfred
2498255932Salfredstatic void adjust_proxy_tun_qkey(struct mlx4_dev *dev, struct mlx4_vhcr *vhcr,
2499255932Salfred				  struct mlx4_qp_context *context)
2500255932Salfred{
2501255932Salfred	u32 qpn = vhcr->in_modifier & 0xffffff;
2502255932Salfred	u32 qkey = 0;
2503255932Salfred
2504255932Salfred	if (mlx4_get_parav_qkey(dev, qpn, &qkey))
2505255932Salfred		return;
2506255932Salfred
2507255932Salfred	/* adjust qkey in qp context */
2508255932Salfred	context->qkey = cpu_to_be32(qkey);
2509255932Salfred}
2510255932Salfred
2511255932Salfredint mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
2512255932Salfred			     struct mlx4_vhcr *vhcr,
2513255932Salfred			     struct mlx4_cmd_mailbox *inbox,
2514255932Salfred			     struct mlx4_cmd_mailbox *outbox,
2515255932Salfred			     struct mlx4_cmd_info *cmd)
2516255932Salfred{
2517255932Salfred	int err;
2518255932Salfred	int qpn = vhcr->in_modifier & 0x7fffff;
2519255932Salfred	struct res_mtt *mtt;
2520255932Salfred	struct res_qp *qp;
2521255932Salfred	struct mlx4_qp_context *qpc = inbox->buf + 8;
2522255932Salfred	int mtt_base = qp_get_mtt_addr(qpc) / dev->caps.mtt_entry_sz;
2523255932Salfred	int mtt_size = qp_get_mtt_size(qpc);
2524255932Salfred	struct res_cq *rcq;
2525255932Salfred	struct res_cq *scq;
2526255932Salfred	int rcqn = qp_get_rcqn(qpc);
2527255932Salfred	int scqn = qp_get_scqn(qpc);
2528255932Salfred	u32 srqn = qp_get_srqn(qpc) & 0xffffff;
2529255932Salfred	int use_srq = (qp_get_srqn(qpc) >> 24) & 1;
2530255932Salfred	struct res_srq *srq;
2531255932Salfred	int local_qpn = be32_to_cpu(qpc->local_qpn) & 0xffffff;
2532255932Salfred
2533255932Salfred	err = qp_res_start_move_to(dev, slave, qpn, RES_QP_HW, &qp, 0);
2534255932Salfred	if (err)
2535255932Salfred		return err;
2536255932Salfred	qp->local_qpn = local_qpn;
2537255932Salfred
2538255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
2539255932Salfred	if (err)
2540255932Salfred		goto ex_abort;
2541255932Salfred
2542255932Salfred	err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt);
2543255932Salfred	if (err)
2544255932Salfred		goto ex_put_mtt;
2545255932Salfred
2546255932Salfred	err = get_res(dev, slave, rcqn, RES_CQ, &rcq);
2547255932Salfred	if (err)
2548255932Salfred		goto ex_put_mtt;
2549255932Salfred
2550255932Salfred	if (scqn != rcqn) {
2551255932Salfred		err = get_res(dev, slave, scqn, RES_CQ, &scq);
2552255932Salfred		if (err)
2553255932Salfred			goto ex_put_rcq;
2554255932Salfred	} else
2555255932Salfred		scq = rcq;
2556255932Salfred
2557255932Salfred	if (use_srq) {
2558255932Salfred		err = get_res(dev, slave, srqn, RES_SRQ, &srq);
2559255932Salfred		if (err)
2560255932Salfred			goto ex_put_scq;
2561255932Salfred	}
2562255932Salfred
2563255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, qpc);
2564255932Salfred	update_pkey_index(dev, slave, inbox);
2565255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2566255932Salfred	if (err)
2567255932Salfred		goto ex_put_srq;
2568255932Salfred	atomic_inc(&mtt->ref_count);
2569255932Salfred	qp->mtt = mtt;
2570255932Salfred	atomic_inc(&rcq->ref_count);
2571255932Salfred	qp->rcq = rcq;
2572255932Salfred	atomic_inc(&scq->ref_count);
2573255932Salfred	qp->scq = scq;
2574255932Salfred
2575255932Salfred	if (scqn != rcqn)
2576255932Salfred		put_res(dev, slave, scqn, RES_CQ);
2577255932Salfred
2578255932Salfred	if (use_srq) {
2579255932Salfred		atomic_inc(&srq->ref_count);
2580255932Salfred		put_res(dev, slave, srqn, RES_SRQ);
2581255932Salfred		qp->srq = srq;
2582255932Salfred	}
2583255932Salfred	put_res(dev, slave, rcqn, RES_CQ);
2584255932Salfred	put_res(dev, slave, mtt_base, RES_MTT);
2585255932Salfred	res_end_move(dev, slave, RES_QP, qpn);
2586255932Salfred
2587255932Salfred	return 0;
2588255932Salfred
2589255932Salfredex_put_srq:
2590255932Salfred	if (use_srq)
2591255932Salfred		put_res(dev, slave, srqn, RES_SRQ);
2592255932Salfredex_put_scq:
2593255932Salfred	if (scqn != rcqn)
2594255932Salfred		put_res(dev, slave, scqn, RES_CQ);
2595255932Salfredex_put_rcq:
2596255932Salfred	put_res(dev, slave, rcqn, RES_CQ);
2597255932Salfredex_put_mtt:
2598255932Salfred	put_res(dev, slave, mtt_base, RES_MTT);
2599255932Salfredex_abort:
2600255932Salfred	res_abort_move(dev, slave, RES_QP, qpn);
2601255932Salfred
2602255932Salfred	return err;
2603255932Salfred}
2604255932Salfred
2605255932Salfredstatic int eq_get_mtt_addr(struct mlx4_eq_context *eqc)
2606255932Salfred{
2607255932Salfred	return be32_to_cpu(eqc->mtt_base_addr_l) & 0xfffffff8;
2608255932Salfred}
2609255932Salfred
2610255932Salfredstatic int eq_get_mtt_size(struct mlx4_eq_context *eqc)
2611255932Salfred{
2612255932Salfred	int log_eq_size = eqc->log_eq_size & 0x1f;
2613255932Salfred	int page_shift = (eqc->log_page_size & 0x3f) + 12;
2614255932Salfred
2615255932Salfred	if (log_eq_size + 5 < page_shift)
2616255932Salfred		return 1;
2617255932Salfred
2618255932Salfred	return 1 << (log_eq_size + 5 - page_shift);
2619255932Salfred}
2620255932Salfred
2621255932Salfredstatic int cq_get_mtt_addr(struct mlx4_cq_context *cqc)
2622255932Salfred{
2623255932Salfred	return be32_to_cpu(cqc->mtt_base_addr_l) & 0xfffffff8;
2624255932Salfred}
2625255932Salfred
2626255932Salfredstatic int cq_get_mtt_size(struct mlx4_cq_context *cqc)
2627255932Salfred{
2628255932Salfred	int log_cq_size = (be32_to_cpu(cqc->logsize_usrpage) >> 24) & 0x1f;
2629255932Salfred	int page_shift = (cqc->log_page_size & 0x3f) + 12;
2630255932Salfred
2631255932Salfred	if (log_cq_size + 5 < page_shift)
2632255932Salfred		return 1;
2633255932Salfred
2634255932Salfred	return 1 << (log_cq_size + 5 - page_shift);
2635255932Salfred}
2636255932Salfred
2637255932Salfredint mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave,
2638255932Salfred			  struct mlx4_vhcr *vhcr,
2639255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2640255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2641255932Salfred			  struct mlx4_cmd_info *cmd)
2642255932Salfred{
2643255932Salfred	int err;
2644255932Salfred	int eqn = vhcr->in_modifier;
2645255932Salfred	int res_id = (slave << 8) | eqn;
2646255932Salfred	struct mlx4_eq_context *eqc = inbox->buf;
2647255932Salfred	int mtt_base = eq_get_mtt_addr(eqc) / dev->caps.mtt_entry_sz;
2648255932Salfred	int mtt_size = eq_get_mtt_size(eqc);
2649255932Salfred	struct res_eq *eq;
2650255932Salfred	struct res_mtt *mtt;
2651255932Salfred
2652255932Salfred	err = add_res_range(dev, slave, res_id, 1, RES_EQ, 0);
2653255932Salfred	if (err)
2654255932Salfred		return err;
2655255932Salfred	err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_HW, &eq);
2656255932Salfred	if (err)
2657255932Salfred		goto out_add;
2658255932Salfred
2659255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
2660255932Salfred	if (err)
2661255932Salfred		goto out_move;
2662255932Salfred
2663255932Salfred	err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt);
2664255932Salfred	if (err)
2665255932Salfred		goto out_put;
2666255932Salfred
2667255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2668255932Salfred	if (err)
2669255932Salfred		goto out_put;
2670255932Salfred
2671255932Salfred	atomic_inc(&mtt->ref_count);
2672255932Salfred	eq->mtt = mtt;
2673255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
2674255932Salfred	res_end_move(dev, slave, RES_EQ, res_id);
2675255932Salfred	return 0;
2676255932Salfred
2677255932Salfredout_put:
2678255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
2679255932Salfredout_move:
2680255932Salfred	res_abort_move(dev, slave, RES_EQ, res_id);
2681255932Salfredout_add:
2682255932Salfred	rem_res_range(dev, slave, res_id, 1, RES_EQ, 0);
2683255932Salfred	return err;
2684255932Salfred}
2685255932Salfred
2686255932Salfredstatic int get_containing_mtt(struct mlx4_dev *dev, int slave, int start,
2687255932Salfred			      int len, struct res_mtt **res)
2688255932Salfred{
2689255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
2690255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
2691255932Salfred	struct res_mtt *mtt;
2692255932Salfred	int err = -EINVAL;
2693255932Salfred
2694255932Salfred	spin_lock_irq(mlx4_tlock(dev));
2695255932Salfred	list_for_each_entry(mtt, &tracker->slave_list[slave].res_list[RES_MTT],
2696255932Salfred			    com.list) {
2697255932Salfred		if (!check_mtt_range(dev, slave, start, len, mtt)) {
2698255932Salfred			*res = mtt;
2699255932Salfred			mtt->com.from_state = mtt->com.state;
2700255932Salfred			mtt->com.state = RES_MTT_BUSY;
2701255932Salfred			err = 0;
2702255932Salfred			break;
2703255932Salfred		}
2704255932Salfred	}
2705255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
2706255932Salfred
2707255932Salfred	return err;
2708255932Salfred}
2709255932Salfred
2710255932Salfredstatic int verify_qp_parameters(struct mlx4_dev *dev,
2711255932Salfred				struct mlx4_cmd_mailbox *inbox,
2712255932Salfred				enum qp_transition transition, u8 slave)
2713255932Salfred{
2714255932Salfred	u32			qp_type;
2715255932Salfred	struct mlx4_qp_context	*qp_ctx;
2716255932Salfred	enum mlx4_qp_optpar	optpar;
2717255932Salfred	int port;
2718255932Salfred	int num_gids;
2719255932Salfred
2720255932Salfred	qp_ctx  = inbox->buf + 8;
2721255932Salfred	qp_type	= (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff;
2722255932Salfred	optpar	= be32_to_cpu(*(__be32 *) inbox->buf);
2723255932Salfred
2724255932Salfred	switch (qp_type) {
2725255932Salfred	case MLX4_QP_ST_RC:
2726255932Salfred	case MLX4_QP_ST_UC:
2727255932Salfred		switch (transition) {
2728255932Salfred		case QP_TRANS_INIT2RTR:
2729255932Salfred		case QP_TRANS_RTR2RTS:
2730255932Salfred		case QP_TRANS_RTS2RTS:
2731255932Salfred		case QP_TRANS_SQD2SQD:
2732255932Salfred		case QP_TRANS_SQD2RTS:
2733255932Salfred			if (slave != mlx4_master_func_num(dev))
2734255932Salfred				if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH) {
2735255932Salfred					port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
2736255932Salfred					if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB)
2737255932Salfred						num_gids = mlx4_get_slave_num_gids(dev, slave);
2738255932Salfred					else
2739255932Salfred						num_gids = 1;
2740255932Salfred					if (qp_ctx->pri_path.mgid_index >= num_gids)
2741255932Salfred						return -EINVAL;
2742255932Salfred				}
2743255932Salfred				if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) {
2744255932Salfred					port = (qp_ctx->alt_path.sched_queue >> 6 & 1) + 1;
2745255932Salfred					if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB)
2746255932Salfred						num_gids = mlx4_get_slave_num_gids(dev, slave);
2747255932Salfred					else
2748255932Salfred						num_gids = 1;
2749255932Salfred					if (qp_ctx->alt_path.mgid_index >= num_gids)
2750255932Salfred						return -EINVAL;
2751255932Salfred				}
2752255932Salfred			break;
2753255932Salfred		default:
2754255932Salfred			break;
2755255932Salfred		}
2756255932Salfred
2757255932Salfred		break;
2758255932Salfred	default:
2759255932Salfred		break;
2760255932Salfred	}
2761255932Salfred
2762255932Salfred	return 0;
2763255932Salfred}
2764255932Salfred
2765255932Salfredint mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave,
2766255932Salfred			   struct mlx4_vhcr *vhcr,
2767255932Salfred			   struct mlx4_cmd_mailbox *inbox,
2768255932Salfred			   struct mlx4_cmd_mailbox *outbox,
2769255932Salfred			   struct mlx4_cmd_info *cmd)
2770255932Salfred{
2771255932Salfred	struct mlx4_mtt mtt;
2772255932Salfred	__be64 *page_list = inbox->buf;
2773255932Salfred	u64 *pg_list = (u64 *)page_list;
2774255932Salfred	int i;
2775255932Salfred	struct res_mtt *rmtt = NULL;
2776255932Salfred	int start = be64_to_cpu(page_list[0]);
2777255932Salfred	int npages = vhcr->in_modifier;
2778255932Salfred	int err;
2779255932Salfred
2780255932Salfred	err = get_containing_mtt(dev, slave, start, npages, &rmtt);
2781255932Salfred	if (err)
2782255932Salfred		return err;
2783255932Salfred
2784255932Salfred	/* Call the SW implementation of write_mtt:
2785255932Salfred	 * - Prepare a dummy mtt struct
2786255932Salfred	 * - Translate inbox contents to simple addresses in host endianess */
2787255932Salfred	mtt.offset = 0;  /* TBD this is broken but I don't handle it since
2788255932Salfred			    we don't really use it */
2789255932Salfred	mtt.order = 0;
2790255932Salfred	mtt.page_shift = 0;
2791255932Salfred	for (i = 0; i < npages; ++i)
2792255932Salfred		pg_list[i + 2] = (be64_to_cpu(page_list[i + 2]) & ~1ULL);
2793255932Salfred
2794255932Salfred	err = __mlx4_write_mtt(dev, &mtt, be64_to_cpu(page_list[0]), npages,
2795255932Salfred			       ((u64 *)page_list + 2));
2796255932Salfred
2797255932Salfred	if (rmtt)
2798255932Salfred		put_res(dev, slave, rmtt->com.res_id, RES_MTT);
2799255932Salfred
2800255932Salfred	return err;
2801255932Salfred}
2802255932Salfred
2803255932Salfredint mlx4_HW2SW_EQ_wrapper(struct mlx4_dev *dev, int slave,
2804255932Salfred			  struct mlx4_vhcr *vhcr,
2805255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2806255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2807255932Salfred			  struct mlx4_cmd_info *cmd)
2808255932Salfred{
2809255932Salfred	int eqn = vhcr->in_modifier;
2810255932Salfred	int res_id = eqn | (slave << 8);
2811255932Salfred	struct res_eq *eq;
2812255932Salfred	int err;
2813255932Salfred
2814255932Salfred	err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_RESERVED, &eq);
2815255932Salfred	if (err)
2816255932Salfred		return err;
2817255932Salfred
2818255932Salfred	err = get_res(dev, slave, eq->mtt->com.res_id, RES_MTT, NULL);
2819255932Salfred	if (err)
2820255932Salfred		goto ex_abort;
2821255932Salfred
2822255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2823255932Salfred	if (err)
2824255932Salfred		goto ex_put;
2825255932Salfred
2826255932Salfred	atomic_dec(&eq->mtt->ref_count);
2827255932Salfred	put_res(dev, slave, eq->mtt->com.res_id, RES_MTT);
2828255932Salfred	res_end_move(dev, slave, RES_EQ, res_id);
2829255932Salfred	rem_res_range(dev, slave, res_id, 1, RES_EQ, 0);
2830255932Salfred
2831255932Salfred	return 0;
2832255932Salfred
2833255932Salfredex_put:
2834255932Salfred	put_res(dev, slave, eq->mtt->com.res_id, RES_MTT);
2835255932Salfredex_abort:
2836255932Salfred	res_abort_move(dev, slave, RES_EQ, res_id);
2837255932Salfred
2838255932Salfred	return err;
2839255932Salfred}
2840255932Salfred
2841255932Salfredint mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe)
2842255932Salfred{
2843255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
2844255932Salfred	struct mlx4_slave_event_eq_info *event_eq;
2845255932Salfred	struct mlx4_cmd_mailbox *mailbox;
2846255932Salfred	u32 in_modifier = 0;
2847255932Salfred	int err;
2848255932Salfred	int res_id;
2849255932Salfred	struct res_eq *req;
2850255932Salfred
2851255932Salfred	if (!priv->mfunc.master.slave_state)
2852255932Salfred		return -EINVAL;
2853255932Salfred
2854255932Salfred	event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type];
2855255932Salfred
2856255932Salfred	/* Create the event only if the slave is registered */
2857255932Salfred	if (event_eq->eqn < 0)
2858255932Salfred		return 0;
2859255932Salfred
2860255932Salfred	mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]);
2861255932Salfred	res_id = (slave << 8) | event_eq->eqn;
2862255932Salfred	err = get_res(dev, slave, res_id, RES_EQ, &req);
2863255932Salfred	if (err)
2864255932Salfred		goto unlock;
2865255932Salfred
2866255932Salfred	if (req->com.from_state != RES_EQ_HW) {
2867255932Salfred		err = -EINVAL;
2868255932Salfred		goto put;
2869255932Salfred	}
2870255932Salfred
2871255932Salfred	mailbox = mlx4_alloc_cmd_mailbox(dev);
2872255932Salfred	if (IS_ERR(mailbox)) {
2873255932Salfred		err = PTR_ERR(mailbox);
2874255932Salfred		goto put;
2875255932Salfred	}
2876255932Salfred
2877255932Salfred	if (eqe->type == MLX4_EVENT_TYPE_CMD) {
2878255932Salfred		++event_eq->token;
2879255932Salfred		eqe->event.cmd.token = cpu_to_be16(event_eq->token);
2880255932Salfred	}
2881255932Salfred
2882255932Salfred	memcpy(mailbox->buf, (u8 *) eqe, 28);
2883255932Salfred
2884255932Salfred	in_modifier = (slave & 0xff) | ((event_eq->eqn & 0xff) << 16);
2885255932Salfred
2886255932Salfred	err = mlx4_cmd(dev, mailbox->dma, in_modifier, 0,
2887255932Salfred		       MLX4_CMD_GEN_EQE, MLX4_CMD_TIME_CLASS_B,
2888255932Salfred		       MLX4_CMD_NATIVE);
2889255932Salfred
2890255932Salfred	put_res(dev, slave, res_id, RES_EQ);
2891255932Salfred	mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]);
2892255932Salfred	mlx4_free_cmd_mailbox(dev, mailbox);
2893255932Salfred	return err;
2894255932Salfred
2895255932Salfredput:
2896255932Salfred	put_res(dev, slave, res_id, RES_EQ);
2897255932Salfred
2898255932Salfredunlock:
2899255932Salfred	mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]);
2900255932Salfred	return err;
2901255932Salfred}
2902255932Salfred
2903255932Salfredint mlx4_QUERY_EQ_wrapper(struct mlx4_dev *dev, int slave,
2904255932Salfred			  struct mlx4_vhcr *vhcr,
2905255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2906255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2907255932Salfred			  struct mlx4_cmd_info *cmd)
2908255932Salfred{
2909255932Salfred	int eqn = vhcr->in_modifier;
2910255932Salfred	int res_id = eqn | (slave << 8);
2911255932Salfred	struct res_eq *eq;
2912255932Salfred	int err;
2913255932Salfred
2914255932Salfred	err = get_res(dev, slave, res_id, RES_EQ, &eq);
2915255932Salfred	if (err)
2916255932Salfred		return err;
2917255932Salfred
2918255932Salfred	if (eq->com.from_state != RES_EQ_HW) {
2919255932Salfred		err = -EINVAL;
2920255932Salfred		goto ex_put;
2921255932Salfred	}
2922255932Salfred
2923255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2924255932Salfred
2925255932Salfredex_put:
2926255932Salfred	put_res(dev, slave, res_id, RES_EQ);
2927255932Salfred	return err;
2928255932Salfred}
2929255932Salfred
2930255932Salfredint mlx4_SW2HW_CQ_wrapper(struct mlx4_dev *dev, int slave,
2931255932Salfred			  struct mlx4_vhcr *vhcr,
2932255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2933255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2934255932Salfred			  struct mlx4_cmd_info *cmd)
2935255932Salfred{
2936255932Salfred	int err;
2937255932Salfred	int cqn = vhcr->in_modifier;
2938255932Salfred	struct mlx4_cq_context *cqc = inbox->buf;
2939255932Salfred	int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz;
2940255932Salfred	struct res_cq *cq;
2941255932Salfred	struct res_mtt *mtt;
2942255932Salfred
2943255932Salfred	err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_HW, &cq);
2944255932Salfred	if (err)
2945255932Salfred		return err;
2946255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
2947255932Salfred	if (err)
2948255932Salfred		goto out_move;
2949255932Salfred	err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt);
2950255932Salfred	if (err)
2951255932Salfred		goto out_put;
2952255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2953255932Salfred	if (err)
2954255932Salfred		goto out_put;
2955255932Salfred	atomic_inc(&mtt->ref_count);
2956255932Salfred	cq->mtt = mtt;
2957255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
2958255932Salfred	res_end_move(dev, slave, RES_CQ, cqn);
2959255932Salfred	return 0;
2960255932Salfred
2961255932Salfredout_put:
2962255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
2963255932Salfredout_move:
2964255932Salfred	res_abort_move(dev, slave, RES_CQ, cqn);
2965255932Salfred	return err;
2966255932Salfred}
2967255932Salfred
2968255932Salfredint mlx4_HW2SW_CQ_wrapper(struct mlx4_dev *dev, int slave,
2969255932Salfred			  struct mlx4_vhcr *vhcr,
2970255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2971255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2972255932Salfred			  struct mlx4_cmd_info *cmd)
2973255932Salfred{
2974255932Salfred	int err;
2975255932Salfred	int cqn = vhcr->in_modifier;
2976255932Salfred	struct res_cq *cq;
2977255932Salfred
2978255932Salfred	err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_ALLOCATED, &cq);
2979255932Salfred	if (err)
2980255932Salfred		return err;
2981255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2982255932Salfred	if (err)
2983255932Salfred		goto out_move;
2984255932Salfred	atomic_dec(&cq->mtt->ref_count);
2985255932Salfred	res_end_move(dev, slave, RES_CQ, cqn);
2986255932Salfred	return 0;
2987255932Salfred
2988255932Salfredout_move:
2989255932Salfred	res_abort_move(dev, slave, RES_CQ, cqn);
2990255932Salfred	return err;
2991255932Salfred}
2992255932Salfred
2993255932Salfredint mlx4_QUERY_CQ_wrapper(struct mlx4_dev *dev, int slave,
2994255932Salfred			  struct mlx4_vhcr *vhcr,
2995255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2996255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2997255932Salfred			  struct mlx4_cmd_info *cmd)
2998255932Salfred{
2999255932Salfred	int cqn = vhcr->in_modifier;
3000255932Salfred	struct res_cq *cq;
3001255932Salfred	int err;
3002255932Salfred
3003255932Salfred	err = get_res(dev, slave, cqn, RES_CQ, &cq);
3004255932Salfred	if (err)
3005255932Salfred		return err;
3006255932Salfred
3007255932Salfred	if (cq->com.from_state != RES_CQ_HW)
3008255932Salfred		goto ex_put;
3009255932Salfred
3010255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3011255932Salfredex_put:
3012255932Salfred	put_res(dev, slave, cqn, RES_CQ);
3013255932Salfred
3014255932Salfred	return err;
3015255932Salfred}
3016255932Salfred
3017255932Salfredstatic int handle_resize(struct mlx4_dev *dev, int slave,
3018255932Salfred			 struct mlx4_vhcr *vhcr,
3019255932Salfred			 struct mlx4_cmd_mailbox *inbox,
3020255932Salfred			 struct mlx4_cmd_mailbox *outbox,
3021255932Salfred			 struct mlx4_cmd_info *cmd,
3022255932Salfred			 struct res_cq *cq)
3023255932Salfred{
3024255932Salfred	int err;
3025255932Salfred	struct res_mtt *orig_mtt;
3026255932Salfred	struct res_mtt *mtt;
3027255932Salfred	struct mlx4_cq_context *cqc = inbox->buf;
3028255932Salfred	int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz;
3029255932Salfred
3030255932Salfred	err = get_res(dev, slave, cq->mtt->com.res_id, RES_MTT, &orig_mtt);
3031255932Salfred	if (err)
3032255932Salfred		return err;
3033255932Salfred
3034255932Salfred	if (orig_mtt != cq->mtt) {
3035255932Salfred		err = -EINVAL;
3036255932Salfred		goto ex_put;
3037255932Salfred	}
3038255932Salfred
3039255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
3040255932Salfred	if (err)
3041255932Salfred		goto ex_put;
3042255932Salfred
3043255932Salfred	err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt);
3044255932Salfred	if (err)
3045255932Salfred		goto ex_put1;
3046255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3047255932Salfred	if (err)
3048255932Salfred		goto ex_put1;
3049255932Salfred	atomic_dec(&orig_mtt->ref_count);
3050255932Salfred	put_res(dev, slave, orig_mtt->com.res_id, RES_MTT);
3051255932Salfred	atomic_inc(&mtt->ref_count);
3052255932Salfred	cq->mtt = mtt;
3053255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3054255932Salfred	return 0;
3055255932Salfred
3056255932Salfredex_put1:
3057255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3058255932Salfredex_put:
3059255932Salfred	put_res(dev, slave, orig_mtt->com.res_id, RES_MTT);
3060255932Salfred
3061255932Salfred	return err;
3062255932Salfred
3063255932Salfred}
3064255932Salfred
3065255932Salfredint mlx4_MODIFY_CQ_wrapper(struct mlx4_dev *dev, int slave,
3066255932Salfred			   struct mlx4_vhcr *vhcr,
3067255932Salfred			   struct mlx4_cmd_mailbox *inbox,
3068255932Salfred			   struct mlx4_cmd_mailbox *outbox,
3069255932Salfred			   struct mlx4_cmd_info *cmd)
3070255932Salfred{
3071255932Salfred	int cqn = vhcr->in_modifier;
3072255932Salfred	struct res_cq *cq;
3073255932Salfred	int err;
3074255932Salfred
3075255932Salfred	err = get_res(dev, slave, cqn, RES_CQ, &cq);
3076255932Salfred	if (err)
3077255932Salfred		return err;
3078255932Salfred
3079255932Salfred	if (cq->com.from_state != RES_CQ_HW)
3080255932Salfred		goto ex_put;
3081255932Salfred
3082255932Salfred	if (vhcr->op_modifier == 0) {
3083255932Salfred		err = handle_resize(dev, slave, vhcr, inbox, outbox, cmd, cq);
3084255932Salfred		goto ex_put;
3085255932Salfred	}
3086255932Salfred
3087255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3088255932Salfredex_put:
3089255932Salfred	put_res(dev, slave, cqn, RES_CQ);
3090255932Salfred
3091255932Salfred	return err;
3092255932Salfred}
3093255932Salfred
3094255932Salfredstatic int srq_get_mtt_size(struct mlx4_srq_context *srqc)
3095255932Salfred{
3096255932Salfred	int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf;
3097255932Salfred	int log_rq_stride = srqc->logstride & 7;
3098255932Salfred	int page_shift = (srqc->log_page_size & 0x3f) + 12;
3099255932Salfred
3100255932Salfred	if (log_srq_size + log_rq_stride + 4 < page_shift)
3101255932Salfred		return 1;
3102255932Salfred
3103255932Salfred	return 1 << (log_srq_size + log_rq_stride + 4 - page_shift);
3104255932Salfred}
3105255932Salfred
3106255932Salfredint mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
3107255932Salfred			   struct mlx4_vhcr *vhcr,
3108255932Salfred			   struct mlx4_cmd_mailbox *inbox,
3109255932Salfred			   struct mlx4_cmd_mailbox *outbox,
3110255932Salfred			   struct mlx4_cmd_info *cmd)
3111255932Salfred{
3112255932Salfred	int err;
3113255932Salfred	int srqn = vhcr->in_modifier;
3114255932Salfred	struct res_mtt *mtt;
3115255932Salfred	struct res_srq *srq;
3116255932Salfred	struct mlx4_srq_context *srqc = inbox->buf;
3117255932Salfred	int mtt_base = srq_get_mtt_addr(srqc) / dev->caps.mtt_entry_sz;
3118255932Salfred
3119255932Salfred	if (srqn != (be32_to_cpu(srqc->state_logsize_srqn) & 0xffffff))
3120255932Salfred		return -EINVAL;
3121255932Salfred
3122255932Salfred	err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_HW, &srq);
3123255932Salfred	if (err)
3124255932Salfred		return err;
3125255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
3126255932Salfred	if (err)
3127255932Salfred		goto ex_abort;
3128255932Salfred	err = check_mtt_range(dev, slave, mtt_base, srq_get_mtt_size(srqc),
3129255932Salfred			      mtt);
3130255932Salfred	if (err)
3131255932Salfred		goto ex_put_mtt;
3132255932Salfred
3133255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3134255932Salfred	if (err)
3135255932Salfred		goto ex_put_mtt;
3136255932Salfred
3137255932Salfred	atomic_inc(&mtt->ref_count);
3138255932Salfred	srq->mtt = mtt;
3139255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3140255932Salfred	res_end_move(dev, slave, RES_SRQ, srqn);
3141255932Salfred	return 0;
3142255932Salfred
3143255932Salfredex_put_mtt:
3144255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3145255932Salfredex_abort:
3146255932Salfred	res_abort_move(dev, slave, RES_SRQ, srqn);
3147255932Salfred
3148255932Salfred	return err;
3149255932Salfred}
3150255932Salfred
3151255932Salfredint mlx4_HW2SW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
3152255932Salfred			   struct mlx4_vhcr *vhcr,
3153255932Salfred			   struct mlx4_cmd_mailbox *inbox,
3154255932Salfred			   struct mlx4_cmd_mailbox *outbox,
3155255932Salfred			   struct mlx4_cmd_info *cmd)
3156255932Salfred{
3157255932Salfred	int err;
3158255932Salfred	int srqn = vhcr->in_modifier;
3159255932Salfred	struct res_srq *srq;
3160255932Salfred
3161255932Salfred	err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_ALLOCATED, &srq);
3162255932Salfred	if (err)
3163255932Salfred		return err;
3164255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3165255932Salfred	if (err)
3166255932Salfred		goto ex_abort;
3167255932Salfred	atomic_dec(&srq->mtt->ref_count);
3168255932Salfred	if (srq->cq)
3169255932Salfred		atomic_dec(&srq->cq->ref_count);
3170255932Salfred	res_end_move(dev, slave, RES_SRQ, srqn);
3171255932Salfred
3172255932Salfred	return 0;
3173255932Salfred
3174255932Salfredex_abort:
3175255932Salfred	res_abort_move(dev, slave, RES_SRQ, srqn);
3176255932Salfred
3177255932Salfred	return err;
3178255932Salfred}
3179255932Salfred
3180255932Salfredint mlx4_QUERY_SRQ_wrapper(struct mlx4_dev *dev, int slave,
3181255932Salfred			   struct mlx4_vhcr *vhcr,
3182255932Salfred			   struct mlx4_cmd_mailbox *inbox,
3183255932Salfred			   struct mlx4_cmd_mailbox *outbox,
3184255932Salfred			   struct mlx4_cmd_info *cmd)
3185255932Salfred{
3186255932Salfred	int err;
3187255932Salfred	int srqn = vhcr->in_modifier;
3188255932Salfred	struct res_srq *srq;
3189255932Salfred
3190255932Salfred	err = get_res(dev, slave, srqn, RES_SRQ, &srq);
3191255932Salfred	if (err)
3192255932Salfred		return err;
3193255932Salfred	if (srq->com.from_state != RES_SRQ_HW) {
3194255932Salfred		err = -EBUSY;
3195255932Salfred		goto out;
3196255932Salfred	}
3197255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3198255932Salfredout:
3199255932Salfred	put_res(dev, slave, srqn, RES_SRQ);
3200255932Salfred	return err;
3201255932Salfred}
3202255932Salfred
3203255932Salfredint mlx4_ARM_SRQ_wrapper(struct mlx4_dev *dev, int slave,
3204255932Salfred			 struct mlx4_vhcr *vhcr,
3205255932Salfred			 struct mlx4_cmd_mailbox *inbox,
3206255932Salfred			 struct mlx4_cmd_mailbox *outbox,
3207255932Salfred			 struct mlx4_cmd_info *cmd)
3208255932Salfred{
3209255932Salfred	int err;
3210255932Salfred	int srqn = vhcr->in_modifier;
3211255932Salfred	struct res_srq *srq;
3212255932Salfred
3213255932Salfred	err = get_res(dev, slave, srqn, RES_SRQ, &srq);
3214255932Salfred	if (err)
3215255932Salfred		return err;
3216255932Salfred
3217255932Salfred	if (srq->com.from_state != RES_SRQ_HW) {
3218255932Salfred		err = -EBUSY;
3219255932Salfred		goto out;
3220255932Salfred	}
3221255932Salfred
3222255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3223255932Salfredout:
3224255932Salfred	put_res(dev, slave, srqn, RES_SRQ);
3225255932Salfred	return err;
3226255932Salfred}
3227255932Salfred
3228255932Salfredint mlx4_GEN_QP_wrapper(struct mlx4_dev *dev, int slave,
3229255932Salfred			struct mlx4_vhcr *vhcr,
3230255932Salfred			struct mlx4_cmd_mailbox *inbox,
3231255932Salfred			struct mlx4_cmd_mailbox *outbox,
3232255932Salfred			struct mlx4_cmd_info *cmd)
3233255932Salfred{
3234255932Salfred	int err;
3235255932Salfred	int qpn = vhcr->in_modifier & 0x7fffff;
3236255932Salfred	struct res_qp *qp;
3237255932Salfred
3238255932Salfred	err = get_res(dev, slave, qpn, RES_QP, &qp);
3239255932Salfred	if (err)
3240255932Salfred		return err;
3241255932Salfred	if (qp->com.from_state != RES_QP_HW) {
3242255932Salfred		err = -EBUSY;
3243255932Salfred		goto out;
3244255932Salfred	}
3245255932Salfred
3246255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3247255932Salfredout:
3248255932Salfred	put_res(dev, slave, qpn, RES_QP);
3249255932Salfred	return err;
3250255932Salfred}
3251255932Salfred
3252255932Salfredint mlx4_INIT2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
3253255932Salfred			      struct mlx4_vhcr *vhcr,
3254255932Salfred			      struct mlx4_cmd_mailbox *inbox,
3255255932Salfred			      struct mlx4_cmd_mailbox *outbox,
3256255932Salfred			      struct mlx4_cmd_info *cmd)
3257255932Salfred{
3258255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3259255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3260255932Salfred	update_pkey_index(dev, slave, inbox);
3261255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3262255932Salfred}
3263255932Salfred
3264255932Salfredstatic int roce_verify_mac(struct mlx4_dev *dev, int slave,
3265255932Salfred				struct mlx4_qp_context *qpc,
3266255932Salfred				struct mlx4_cmd_mailbox *inbox)
3267255932Salfred{
3268255932Salfred	u64 mac;
3269255932Salfred	int port;
3270255932Salfred	u32 ts = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
3271255932Salfred	u8 sched = *(u8 *)(inbox->buf + 64);
3272255932Salfred	u8 smac_ix;
3273255932Salfred
3274255932Salfred	port = (sched >> 6 & 1) + 1;
3275255932Salfred	if (mlx4_is_eth(dev, port) && (ts != MLX4_QP_ST_MLX)) {
3276255932Salfred		smac_ix = qpc->pri_path.grh_mylmc & 0x7f;
3277255932Salfred		if (mac_find_smac_ix_in_slave(dev, slave, port, smac_ix, &mac))
3278255932Salfred			return -ENOENT;
3279255932Salfred	}
3280255932Salfred	return 0;
3281255932Salfred}
3282255932Salfred
3283255932Salfredint mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
3284255932Salfred			     struct mlx4_vhcr *vhcr,
3285255932Salfred			     struct mlx4_cmd_mailbox *inbox,
3286255932Salfred			     struct mlx4_cmd_mailbox *outbox,
3287255932Salfred			     struct mlx4_cmd_info *cmd)
3288255932Salfred{
3289255932Salfred	int err;
3290255932Salfred	struct mlx4_qp_context *qpc = inbox->buf + 8;
3291255932Salfred
3292255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_INIT2RTR, slave);
3293255932Salfred	if (err)
3294255932Salfred		return err;
3295255932Salfred
3296255932Salfred	if (roce_verify_mac(dev, slave, qpc, inbox))
3297255932Salfred		return -EINVAL;
3298255932Salfred
3299255932Salfred	update_pkey_index(dev, slave, inbox);
3300255932Salfred	update_gid(dev, inbox, (u8)slave);
3301255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, qpc);
3302255932Salfred	err = update_vport_qp_param(dev, inbox, slave);
3303255932Salfred	if (err)
3304255932Salfred		return err;
3305255932Salfred
3306255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3307255932Salfred}
3308255932Salfred
3309255932Salfredint mlx4_RTR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3310255932Salfred			    struct mlx4_vhcr *vhcr,
3311255932Salfred			    struct mlx4_cmd_mailbox *inbox,
3312255932Salfred			    struct mlx4_cmd_mailbox *outbox,
3313255932Salfred			    struct mlx4_cmd_info *cmd)
3314255932Salfred{
3315255932Salfred	int err;
3316255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3317255932Salfred
3318255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_RTR2RTS, slave);
3319255932Salfred	if (err)
3320255932Salfred		return err;
3321255932Salfred
3322255932Salfred	update_pkey_index(dev, slave, inbox);
3323255932Salfred	update_gid(dev, inbox, (u8)slave);
3324255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3325255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3326255932Salfred}
3327255932Salfred
3328255932Salfredint mlx4_RTS2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3329255932Salfred			    struct mlx4_vhcr *vhcr,
3330255932Salfred			    struct mlx4_cmd_mailbox *inbox,
3331255932Salfred			    struct mlx4_cmd_mailbox *outbox,
3332255932Salfred			    struct mlx4_cmd_info *cmd)
3333255932Salfred{
3334255932Salfred	int err;
3335255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3336255932Salfred
3337255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_RTS2RTS, slave);
3338255932Salfred	if (err)
3339255932Salfred		return err;
3340255932Salfred
3341255932Salfred	update_pkey_index(dev, slave, inbox);
3342255932Salfred	update_gid(dev, inbox, (u8)slave);
3343255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3344255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3345255932Salfred}
3346255932Salfred
3347255932Salfred
3348255932Salfredint mlx4_SQERR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3349255932Salfred			      struct mlx4_vhcr *vhcr,
3350255932Salfred			      struct mlx4_cmd_mailbox *inbox,
3351255932Salfred			      struct mlx4_cmd_mailbox *outbox,
3352255932Salfred			      struct mlx4_cmd_info *cmd)
3353255932Salfred{
3354255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3355255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3356255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3357255932Salfred}
3358255932Salfred
3359255932Salfredint mlx4_SQD2SQD_QP_wrapper(struct mlx4_dev *dev, int slave,
3360255932Salfred			    struct mlx4_vhcr *vhcr,
3361255932Salfred			    struct mlx4_cmd_mailbox *inbox,
3362255932Salfred			    struct mlx4_cmd_mailbox *outbox,
3363255932Salfred			    struct mlx4_cmd_info *cmd)
3364255932Salfred{
3365255932Salfred	int err;
3366255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3367255932Salfred
3368255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_SQD2SQD, slave);
3369255932Salfred	if (err)
3370255932Salfred		return err;
3371255932Salfred
3372255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3373255932Salfred	update_gid(dev, inbox, (u8)slave);
3374255932Salfred	update_pkey_index(dev, slave, inbox);
3375255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3376255932Salfred}
3377255932Salfred
3378255932Salfredint mlx4_SQD2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3379255932Salfred			    struct mlx4_vhcr *vhcr,
3380255932Salfred			    struct mlx4_cmd_mailbox *inbox,
3381255932Salfred			    struct mlx4_cmd_mailbox *outbox,
3382255932Salfred			    struct mlx4_cmd_info *cmd)
3383255932Salfred{
3384255932Salfred	int err;
3385255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3386255932Salfred
3387255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_SQD2RTS, slave);
3388255932Salfred	if (err)
3389255932Salfred		return err;
3390255932Salfred
3391255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3392255932Salfred	update_gid(dev, inbox, (u8)slave);
3393255932Salfred	update_pkey_index(dev, slave, inbox);
3394255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3395255932Salfred}
3396255932Salfred
3397255932Salfredint mlx4_2RST_QP_wrapper(struct mlx4_dev *dev, int slave,
3398255932Salfred			 struct mlx4_vhcr *vhcr,
3399255932Salfred			 struct mlx4_cmd_mailbox *inbox,
3400255932Salfred			 struct mlx4_cmd_mailbox *outbox,
3401255932Salfred			 struct mlx4_cmd_info *cmd)
3402255932Salfred{
3403255932Salfred	int err;
3404255932Salfred	int qpn = vhcr->in_modifier & 0x7fffff;
3405255932Salfred	struct res_qp *qp;
3406255932Salfred
3407255932Salfred	err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED, &qp, 0);
3408255932Salfred	if (err)
3409255932Salfred		return err;
3410255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3411255932Salfred	if (err)
3412255932Salfred		goto ex_abort;
3413255932Salfred
3414255932Salfred	atomic_dec(&qp->mtt->ref_count);
3415255932Salfred	atomic_dec(&qp->rcq->ref_count);
3416255932Salfred	atomic_dec(&qp->scq->ref_count);
3417255932Salfred	if (qp->srq)
3418255932Salfred		atomic_dec(&qp->srq->ref_count);
3419255932Salfred	res_end_move(dev, slave, RES_QP, qpn);
3420255932Salfred	return 0;
3421255932Salfred
3422255932Salfredex_abort:
3423255932Salfred	res_abort_move(dev, slave, RES_QP, qpn);
3424255932Salfred
3425255932Salfred	return err;
3426255932Salfred}
3427255932Salfred
3428255932Salfredstatic struct res_gid *find_gid(struct mlx4_dev *dev, int slave,
3429255932Salfred				struct res_qp *rqp, u8 *gid)
3430255932Salfred{
3431255932Salfred	struct res_gid *res;
3432255932Salfred
3433255932Salfred	list_for_each_entry(res, &rqp->mcg_list, list) {
3434255932Salfred		if (!memcmp(res->gid, gid, 16))
3435255932Salfred			return res;
3436255932Salfred	}
3437255932Salfred	return NULL;
3438255932Salfred}
3439255932Salfred
3440255932Salfredstatic int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
3441255932Salfred		       u8 *gid, enum mlx4_protocol prot,
3442255932Salfred		       enum mlx4_steer_type steer)
3443255932Salfred{
3444255932Salfred	struct res_gid *res;
3445255932Salfred	int err;
3446255932Salfred
3447255932Salfred	res = kzalloc(sizeof *res, GFP_KERNEL);
3448255932Salfred	if (!res)
3449255932Salfred		return -ENOMEM;
3450255932Salfred
3451255932Salfred	spin_lock_irq(&rqp->mcg_spl);
3452255932Salfred	if (find_gid(dev, slave, rqp, gid)) {
3453255932Salfred		kfree(res);
3454255932Salfred		err = -EEXIST;
3455255932Salfred	} else {
3456255932Salfred		memcpy(res->gid, gid, 16);
3457255932Salfred		res->prot = prot;
3458255932Salfred		res->steer = steer;
3459255932Salfred		list_add_tail(&res->list, &rqp->mcg_list);
3460255932Salfred		err = 0;
3461255932Salfred	}
3462255932Salfred	spin_unlock_irq(&rqp->mcg_spl);
3463255932Salfred
3464255932Salfred	return err;
3465255932Salfred}
3466255932Salfred
3467255932Salfredstatic int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
3468255932Salfred		       u8 *gid, enum mlx4_protocol prot,
3469255932Salfred		       enum mlx4_steer_type steer)
3470255932Salfred{
3471255932Salfred	struct res_gid *res;
3472255932Salfred	int err;
3473255932Salfred
3474255932Salfred	spin_lock_irq(&rqp->mcg_spl);
3475255932Salfred	res = find_gid(dev, slave, rqp, gid);
3476255932Salfred	if (!res || res->prot != prot || res->steer != steer)
3477255932Salfred		err = -EINVAL;
3478255932Salfred	else {
3479255932Salfred		list_del(&res->list);
3480255932Salfred		kfree(res);
3481255932Salfred		err = 0;
3482255932Salfred	}
3483255932Salfred	spin_unlock_irq(&rqp->mcg_spl);
3484255932Salfred
3485255932Salfred	return err;
3486255932Salfred}
3487255932Salfred
3488255932Salfredint mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
3489255932Salfred			       struct mlx4_vhcr *vhcr,
3490255932Salfred			       struct mlx4_cmd_mailbox *inbox,
3491255932Salfred			       struct mlx4_cmd_mailbox *outbox,
3492255932Salfred			       struct mlx4_cmd_info *cmd)
3493255932Salfred{
3494255932Salfred	struct mlx4_qp qp; /* dummy for calling attach/detach */
3495255932Salfred	u8 *gid = inbox->buf;
3496255932Salfred	enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7;
3497255932Salfred	int err;
3498255932Salfred	int qpn;
3499255932Salfred	struct res_qp *rqp;
3500255932Salfred	int attach = vhcr->op_modifier;
3501255932Salfred	int block_loopback = vhcr->in_modifier >> 31;
3502255932Salfred	u8 steer_type_mask = 2;
3503255932Salfred	enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1;
3504255932Salfred
3505255932Salfred	qpn = vhcr->in_modifier & 0xffffff;
3506255932Salfred	err = get_res(dev, slave, qpn, RES_QP, &rqp);
3507255932Salfred	if (err)
3508255932Salfred		return err;
3509255932Salfred
3510255932Salfred	qp.qpn = qpn;
3511255932Salfred	if (attach) {
3512255932Salfred		err = add_mcg_res(dev, slave, rqp, gid, prot, type);
3513255932Salfred		if (err)
3514255932Salfred			goto ex_put;
3515255932Salfred
3516255932Salfred		err = mlx4_qp_attach_common(dev, &qp, gid,
3517255932Salfred					    block_loopback, prot, type);
3518255932Salfred		if (err)
3519255932Salfred			goto ex_rem;
3520255932Salfred	} else {
3521255932Salfred		err = rem_mcg_res(dev, slave, rqp, gid, prot, type);
3522255932Salfred		if (err)
3523255932Salfred			goto ex_put;
3524255932Salfred		err = mlx4_qp_detach_common(dev, &qp, gid, prot, type);
3525255932Salfred	}
3526255932Salfred
3527255932Salfred	put_res(dev, slave, qpn, RES_QP);
3528255932Salfred	return 0;
3529255932Salfred
3530255932Salfredex_rem:
3531255932Salfred	/* ignore error return below, already in error */
3532255932Salfred	(void) rem_mcg_res(dev, slave, rqp, gid, prot, type);
3533255932Salfredex_put:
3534255932Salfred	put_res(dev, slave, qpn, RES_QP);
3535255932Salfred
3536255932Salfred	return err;
3537255932Salfred}
3538255932Salfred
3539255932Salfred/*
3540255932Salfred * MAC validation for Flow Steering rules.
3541255932Salfred * VF can attach rules only with a mac address which is assigned to it.
3542255932Salfred */
3543255932Salfred
3544255932Salfredstatic int validate_eth_header_mac(int slave, struct _rule_hw *eth_header,
3545255932Salfred				   struct list_head *rlist)
3546255932Salfred{
3547255932Salfred	struct mac_res *res, *tmp;
3548255932Salfred	__be64 be_mac;
3549255932Salfred
3550255932Salfred	/* make sure it isn't multicast or broadcast mac*/
3551255932Salfred	if (!is_multicast_ether_addr(eth_header->eth.dst_mac) &&
3552255932Salfred	    !is_broadcast_ether_addr(eth_header->eth.dst_mac)) {
3553255932Salfred		list_for_each_entry_safe(res, tmp, rlist, list) {
3554255932Salfred			be_mac = cpu_to_be64(res->mac << 16);
3555255932Salfred			if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN))
3556255932Salfred				return 0;
3557255932Salfred		}
3558255932Salfred		pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n",
3559255932Salfred		       eth_header->eth.dst_mac, slave);
3560255932Salfred		return -EINVAL;
3561255932Salfred	}
3562255932Salfred	return 0;
3563255932Salfred}
3564255932Salfred
3565255932Salfred/*
3566255932Salfred * In case of missing eth header, append eth header with a MAC address
3567255932Salfred * assigned to the VF.
3568255932Salfred */
3569255932Salfredstatic int add_eth_header(struct mlx4_dev *dev, int slave,
3570255932Salfred			  struct mlx4_cmd_mailbox *inbox,
3571255932Salfred			  struct list_head *rlist, int header_id)
3572255932Salfred{
3573255932Salfred	struct mac_res *res, *tmp;
3574255932Salfred	u8 port;
3575255932Salfred	struct mlx4_net_trans_rule_hw_ctrl *ctrl;
3576255932Salfred	struct mlx4_net_trans_rule_hw_eth *eth_header;
3577255932Salfred	struct mlx4_net_trans_rule_hw_ipv4 *ip_header;
3578255932Salfred	struct mlx4_net_trans_rule_hw_tcp_udp *l4_header;
3579255932Salfred	__be64 be_mac = 0;
3580255932Salfred	__be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);
3581255932Salfred
3582255932Salfred	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
3583255932Salfred	port = ctrl->port;
3584255932Salfred	eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1);
3585255932Salfred
3586255932Salfred	/* Clear a space in the inbox for eth header */
3587255932Salfred	switch (header_id) {
3588255932Salfred	case MLX4_NET_TRANS_RULE_ID_IPV4:
3589255932Salfred		ip_header =
3590255932Salfred			(struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1);
3591255932Salfred		memmove(ip_header, eth_header,
3592255932Salfred			sizeof(*ip_header) + sizeof(*l4_header));
3593255932Salfred		break;
3594255932Salfred	case MLX4_NET_TRANS_RULE_ID_TCP:
3595255932Salfred	case MLX4_NET_TRANS_RULE_ID_UDP:
3596255932Salfred		l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *)
3597255932Salfred			    (eth_header + 1);
3598255932Salfred		memmove(l4_header, eth_header, sizeof(*l4_header));
3599255932Salfred		break;
3600255932Salfred	default:
3601255932Salfred		return -EINVAL;
3602255932Salfred	}
3603255932Salfred	list_for_each_entry_safe(res, tmp, rlist, list) {
3604255932Salfred		if (port == res->port) {
3605255932Salfred			be_mac = cpu_to_be64(res->mac << 16);
3606255932Salfred			break;
3607255932Salfred		}
3608255932Salfred	}
3609255932Salfred	if (!be_mac) {
3610255932Salfred		pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n",
3611255932Salfred		       port);
3612255932Salfred		return -EINVAL;
3613255932Salfred	}
3614255932Salfred
3615255932Salfred	memset(eth_header, 0, sizeof(*eth_header));
3616255932Salfred	eth_header->size = sizeof(*eth_header) >> 2;
3617255932Salfred	eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]);
3618255932Salfred	memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN);
3619255932Salfred	memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN);
3620255932Salfred
3621255932Salfred	return 0;
3622255932Salfred
3623255932Salfred}
3624255932Salfred
3625255932Salfredint mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
3626255932Salfred					 struct mlx4_vhcr *vhcr,
3627255932Salfred					 struct mlx4_cmd_mailbox *inbox,
3628255932Salfred					 struct mlx4_cmd_mailbox *outbox,
3629255932Salfred					 struct mlx4_cmd_info *cmd)
3630255932Salfred{
3631255932Salfred
3632255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
3633255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
3634255932Salfred	struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
3635255932Salfred	int err;
3636255932Salfred	struct mlx4_net_trans_rule_hw_ctrl *ctrl;
3637255932Salfred	struct _rule_hw  *rule_header;
3638255932Salfred	int header_id;
3639255932Salfred
3640255932Salfred	if (dev->caps.steering_mode !=
3641255932Salfred	    MLX4_STEERING_MODE_DEVICE_MANAGED)
3642255932Salfred		return -EOPNOTSUPP;
3643255932Salfred
3644255932Salfred	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
3645255932Salfred	rule_header = (struct _rule_hw *)(ctrl + 1);
3646255932Salfred	header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));
3647255932Salfred
3648255932Salfred	switch (header_id) {
3649255932Salfred	case MLX4_NET_TRANS_RULE_ID_ETH:
3650255932Salfred		if (validate_eth_header_mac(slave, rule_header, rlist))
3651255932Salfred			return -EINVAL;
3652255932Salfred		break;
3653255932Salfred	case MLX4_NET_TRANS_RULE_ID_IB:
3654255932Salfred		break;
3655255932Salfred	case MLX4_NET_TRANS_RULE_ID_IPV4:
3656255932Salfred	case MLX4_NET_TRANS_RULE_ID_TCP:
3657255932Salfred	case MLX4_NET_TRANS_RULE_ID_UDP:
3658255932Salfred		pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n");
3659255932Salfred		if (add_eth_header(dev, slave, inbox, rlist, header_id))
3660255932Salfred			return -EINVAL;
3661255932Salfred		vhcr->in_modifier +=
3662255932Salfred			sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2;
3663255932Salfred		break;
3664255932Salfred	default:
3665255932Salfred		pr_err("Corrupted mailbox.\n");
3666255932Salfred		return -EINVAL;
3667255932Salfred	}
3668255932Salfred
3669255932Salfred	err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
3670255932Salfred			   vhcr->in_modifier, 0,
3671255932Salfred			   MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
3672255932Salfred			   MLX4_CMD_NATIVE);
3673255932Salfred	if (err)
3674255932Salfred		return err;
3675255932Salfred
3676255932Salfred	err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0);
3677255932Salfred	if (err) {
3678255932Salfred		mlx4_err(dev, "Fail to add flow steering resources.\n ");
3679255932Salfred		/* detach rule*/
3680255932Salfred		mlx4_cmd(dev, vhcr->out_param, 0, 0,
3681255932Salfred			 MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
3682255932Salfred			 MLX4_CMD_NATIVE);
3683255932Salfred	}
3684255932Salfred	return err;
3685255932Salfred}
3686255932Salfred
3687255932Salfredint mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
3688255932Salfred					 struct mlx4_vhcr *vhcr,
3689255932Salfred					 struct mlx4_cmd_mailbox *inbox,
3690255932Salfred					 struct mlx4_cmd_mailbox *outbox,
3691255932Salfred					 struct mlx4_cmd_info *cmd)
3692255932Salfred{
3693255932Salfred	int err;
3694255932Salfred
3695255932Salfred	if (dev->caps.steering_mode !=
3696255932Salfred	    MLX4_STEERING_MODE_DEVICE_MANAGED)
3697255932Salfred		return -EOPNOTSUPP;
3698255932Salfred
3699255932Salfred	err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0);
3700255932Salfred	if (err) {
3701255932Salfred		mlx4_err(dev, "Fail to remove flow steering resources.\n ");
3702255932Salfred		return err;
3703255932Salfred	}
3704255932Salfred
3705255932Salfred	err = mlx4_cmd(dev, vhcr->in_param, 0, 0,
3706255932Salfred		       MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
3707255932Salfred		       MLX4_CMD_NATIVE);
3708255932Salfred	return err;
3709255932Salfred}
3710255932Salfred
3711255932Salfredenum {
3712255932Salfred	BUSY_MAX_RETRIES = 10
3713255932Salfred};
3714255932Salfred
3715255932Salfredint mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave,
3716255932Salfred			       struct mlx4_vhcr *vhcr,
3717255932Salfred			       struct mlx4_cmd_mailbox *inbox,
3718255932Salfred			       struct mlx4_cmd_mailbox *outbox,
3719255932Salfred			       struct mlx4_cmd_info *cmd)
3720255932Salfred{
3721255932Salfred	int err;
3722255932Salfred	int index = vhcr->in_modifier & 0xffff;
3723255932Salfred
3724255932Salfred	err = get_res(dev, slave, index, RES_COUNTER, NULL);
3725255932Salfred	if (err)
3726255932Salfred		return err;
3727255932Salfred
3728255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3729255932Salfred	put_res(dev, slave, index, RES_COUNTER);
3730255932Salfred	return err;
3731255932Salfred}
3732255932Salfred
3733255932Salfredstatic void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp)
3734255932Salfred{
3735255932Salfred	struct res_gid *rgid;
3736255932Salfred	struct res_gid *tmp;
3737255932Salfred	struct mlx4_qp qp; /* dummy for calling attach/detach */
3738255932Salfred
3739255932Salfred	list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) {
3740255932Salfred		qp.qpn = rqp->local_qpn;
3741255932Salfred		(void) mlx4_qp_detach_common(dev, &qp, rgid->gid, rgid->prot,
3742255932Salfred					     rgid->steer);
3743255932Salfred		list_del(&rgid->list);
3744255932Salfred		kfree(rgid);
3745255932Salfred	}
3746255932Salfred}
3747255932Salfred
3748255932Salfredstatic int _move_all_busy(struct mlx4_dev *dev, int slave,
3749255932Salfred			  enum mlx4_resource type, int print)
3750255932Salfred{
3751255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
3752255932Salfred	struct mlx4_resource_tracker *tracker =
3753255932Salfred		&priv->mfunc.master.res_tracker;
3754255932Salfred	struct list_head *rlist = &tracker->slave_list[slave].res_list[type];
3755255932Salfred	struct res_common *r;
3756255932Salfred	struct res_common *tmp;
3757255932Salfred	int busy;
3758255932Salfred
3759255932Salfred	busy = 0;
3760255932Salfred	spin_lock_irq(mlx4_tlock(dev));
3761255932Salfred	list_for_each_entry_safe(r, tmp, rlist, list) {
3762255932Salfred		if (r->owner == slave) {
3763255932Salfred			if (!r->removing) {
3764255932Salfred				if (r->state == RES_ANY_BUSY) {
3765255932Salfred					if (print)
3766255932Salfred						mlx4_dbg(dev,
3767255932Salfred							 "%s id 0x%llx is busy\n",
3768255932Salfred							  ResourceType(type),
3769255932Salfred							  r->res_id);
3770255932Salfred					++busy;
3771255932Salfred				} else {
3772255932Salfred					r->from_state = r->state;
3773255932Salfred					r->state = RES_ANY_BUSY;
3774255932Salfred					r->removing = 1;
3775255932Salfred				}
3776255932Salfred			}
3777255932Salfred		}
3778255932Salfred	}
3779255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
3780255932Salfred
3781255932Salfred	return busy;
3782255932Salfred}
3783255932Salfred
3784255932Salfredstatic int move_all_busy(struct mlx4_dev *dev, int slave,
3785255932Salfred			 enum mlx4_resource type)
3786255932Salfred{
3787255932Salfred	unsigned long begin;
3788255932Salfred	int busy;
3789255932Salfred
3790255932Salfred	begin = jiffies;
3791255932Salfred	do {
3792255932Salfred		busy = _move_all_busy(dev, slave, type, 0);
3793255932Salfred		if (time_after(jiffies, begin + 5 * HZ))
3794255932Salfred			break;
3795255932Salfred		if (busy)
3796255932Salfred			cond_resched();
3797255932Salfred	} while (busy);
3798255932Salfred
3799255932Salfred	if (busy)
3800255932Salfred		busy = _move_all_busy(dev, slave, type, 1);
3801255932Salfred
3802255932Salfred	return busy;
3803255932Salfred}
3804255932Salfredstatic void rem_slave_qps(struct mlx4_dev *dev, int slave)
3805255932Salfred{
3806255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
3807255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
3808255932Salfred	struct list_head *qp_list =
3809255932Salfred		&tracker->slave_list[slave].res_list[RES_QP];
3810255932Salfred	struct res_qp *qp;
3811255932Salfred	struct res_qp *tmp;
3812255932Salfred	int state;
3813255932Salfred	u64 in_param;
3814255932Salfred	int qpn;
3815255932Salfred	int err;
3816255932Salfred
3817255932Salfred	err = move_all_busy(dev, slave, RES_QP);
3818255932Salfred	if (err)
3819255932Salfred		mlx4_warn(dev, "rem_slave_qps: Could not move all qps to busy"
3820255932Salfred			  "for slave %d\n", slave);
3821255932Salfred
3822255932Salfred	spin_lock_irq(mlx4_tlock(dev));
3823255932Salfred	list_for_each_entry_safe(qp, tmp, qp_list, com.list) {
3824255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
3825255932Salfred		if (qp->com.owner == slave) {
3826255932Salfred			qpn = qp->com.res_id;
3827255932Salfred			detach_qp(dev, slave, qp);
3828255932Salfred			state = qp->com.from_state;
3829255932Salfred			while (state != 0) {
3830255932Salfred				switch (state) {
3831255932Salfred				case RES_QP_RESERVED:
3832255932Salfred					spin_lock_irq(mlx4_tlock(dev));
3833255932Salfred					rb_erase(&qp->com.node,
3834255932Salfred						 &tracker->res_tree[RES_QP]);
3835255932Salfred					list_del(&qp->com.list);
3836255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
3837255932Salfred					kfree(qp);
3838255932Salfred					state = 0;
3839255932Salfred					break;
3840255932Salfred				case RES_QP_MAPPED:
3841255932Salfred					if (!valid_reserved(dev, slave, qpn))
3842255932Salfred						__mlx4_qp_free_icm(dev, qpn);
3843255932Salfred					state = RES_QP_RESERVED;
3844255932Salfred					break;
3845255932Salfred				case RES_QP_HW:
3846255932Salfred					in_param = slave;
3847255932Salfred					err = mlx4_cmd(dev, in_param,
3848255932Salfred						       qp->local_qpn, 2,
3849255932Salfred						       MLX4_CMD_2RST_QP,
3850255932Salfred						       MLX4_CMD_TIME_CLASS_A,
3851255932Salfred						       MLX4_CMD_NATIVE);
3852255932Salfred					if (err)
3853255932Salfred						mlx4_dbg(dev, "rem_slave_qps: failed"
3854255932Salfred							 " to move slave %d qpn %d to"
3855255932Salfred							 " reset\n", slave,
3856255932Salfred							 qp->local_qpn);
3857255932Salfred					atomic_dec(&qp->rcq->ref_count);
3858255932Salfred					atomic_dec(&qp->scq->ref_count);
3859255932Salfred					atomic_dec(&qp->mtt->ref_count);
3860255932Salfred					if (qp->srq)
3861255932Salfred						atomic_dec(&qp->srq->ref_count);
3862255932Salfred					state = RES_QP_MAPPED;
3863255932Salfred					break;
3864255932Salfred				default:
3865255932Salfred					state = 0;
3866255932Salfred				}
3867255932Salfred			}
3868255932Salfred		}
3869255932Salfred		spin_lock_irq(mlx4_tlock(dev));
3870255932Salfred	}
3871255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
3872255932Salfred}
3873255932Salfred
3874255932Salfredstatic void rem_slave_srqs(struct mlx4_dev *dev, int slave)
3875255932Salfred{
3876255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
3877255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
3878255932Salfred	struct list_head *srq_list =
3879255932Salfred		&tracker->slave_list[slave].res_list[RES_SRQ];
3880255932Salfred	struct res_srq *srq;
3881255932Salfred	struct res_srq *tmp;
3882255932Salfred	int state;
3883255932Salfred	u64 in_param;
3884255932Salfred	LIST_HEAD(tlist);
3885255932Salfred	int srqn;
3886255932Salfred	int err;
3887255932Salfred
3888255932Salfred	err = move_all_busy(dev, slave, RES_SRQ);
3889255932Salfred	if (err)
3890255932Salfred		mlx4_warn(dev, "rem_slave_srqs: Could not move all srqs to "
3891255932Salfred			  "busy for slave %d\n", slave);
3892255932Salfred
3893255932Salfred	spin_lock_irq(mlx4_tlock(dev));
3894255932Salfred	list_for_each_entry_safe(srq, tmp, srq_list, com.list) {
3895255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
3896255932Salfred		if (srq->com.owner == slave) {
3897255932Salfred			srqn = srq->com.res_id;
3898255932Salfred			state = srq->com.from_state;
3899255932Salfred			while (state != 0) {
3900255932Salfred				switch (state) {
3901255932Salfred				case RES_SRQ_ALLOCATED:
3902255932Salfred					__mlx4_srq_free_icm(dev, srqn);
3903255932Salfred					spin_lock_irq(mlx4_tlock(dev));
3904255932Salfred					rb_erase(&srq->com.node,
3905255932Salfred						 &tracker->res_tree[RES_SRQ]);
3906255932Salfred					list_del(&srq->com.list);
3907255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
3908255932Salfred					kfree(srq);
3909255932Salfred					state = 0;
3910255932Salfred					break;
3911255932Salfred
3912255932Salfred				case RES_SRQ_HW:
3913255932Salfred					in_param = slave;
3914255932Salfred					err = mlx4_cmd(dev, in_param, srqn, 1,
3915255932Salfred						       MLX4_CMD_HW2SW_SRQ,
3916255932Salfred						       MLX4_CMD_TIME_CLASS_A,
3917255932Salfred						       MLX4_CMD_NATIVE);
3918255932Salfred					if (err)
3919255932Salfred						mlx4_dbg(dev, "rem_slave_srqs: failed"
3920255932Salfred							 " to move slave %d srq %d to"
3921255932Salfred							 " SW ownership\n",
3922255932Salfred							 slave, srqn);
3923255932Salfred
3924255932Salfred					atomic_dec(&srq->mtt->ref_count);
3925255932Salfred					if (srq->cq)
3926255932Salfred						atomic_dec(&srq->cq->ref_count);
3927255932Salfred					state = RES_SRQ_ALLOCATED;
3928255932Salfred					break;
3929255932Salfred
3930255932Salfred				default:
3931255932Salfred					state = 0;
3932255932Salfred				}
3933255932Salfred			}
3934255932Salfred		}
3935255932Salfred		spin_lock_irq(mlx4_tlock(dev));
3936255932Salfred	}
3937255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
3938255932Salfred}
3939255932Salfred
3940255932Salfredstatic void rem_slave_cqs(struct mlx4_dev *dev, int slave)
3941255932Salfred{
3942255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
3943255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
3944255932Salfred	struct list_head *cq_list =
3945255932Salfred		&tracker->slave_list[slave].res_list[RES_CQ];
3946255932Salfred	struct res_cq *cq;
3947255932Salfred	struct res_cq *tmp;
3948255932Salfred	int state;
3949255932Salfred	u64 in_param;
3950255932Salfred	LIST_HEAD(tlist);
3951255932Salfred	int cqn;
3952255932Salfred	int err;
3953255932Salfred
3954255932Salfred	err = move_all_busy(dev, slave, RES_CQ);
3955255932Salfred	if (err)
3956255932Salfred		mlx4_warn(dev, "rem_slave_cqs: Could not move all cqs to "
3957255932Salfred			  "busy for slave %d\n", slave);
3958255932Salfred
3959255932Salfred	spin_lock_irq(mlx4_tlock(dev));
3960255932Salfred	list_for_each_entry_safe(cq, tmp, cq_list, com.list) {
3961255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
3962255932Salfred		if (cq->com.owner == slave && !atomic_read(&cq->ref_count)) {
3963255932Salfred			cqn = cq->com.res_id;
3964255932Salfred			state = cq->com.from_state;
3965255932Salfred			while (state != 0) {
3966255932Salfred				switch (state) {
3967255932Salfred				case RES_CQ_ALLOCATED:
3968255932Salfred					__mlx4_cq_free_icm(dev, cqn);
3969255932Salfred					spin_lock_irq(mlx4_tlock(dev));
3970255932Salfred					rb_erase(&cq->com.node,
3971255932Salfred						 &tracker->res_tree[RES_CQ]);
3972255932Salfred					list_del(&cq->com.list);
3973255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
3974255932Salfred					kfree(cq);
3975255932Salfred					state = 0;
3976255932Salfred					break;
3977255932Salfred
3978255932Salfred				case RES_CQ_HW:
3979255932Salfred					in_param = slave;
3980255932Salfred					err = mlx4_cmd(dev, in_param, cqn, 1,
3981255932Salfred						       MLX4_CMD_HW2SW_CQ,
3982255932Salfred						       MLX4_CMD_TIME_CLASS_A,
3983255932Salfred						       MLX4_CMD_NATIVE);
3984255932Salfred					if (err)
3985255932Salfred						mlx4_dbg(dev, "rem_slave_cqs: failed"
3986255932Salfred							 " to move slave %d cq %d to"
3987255932Salfred							 " SW ownership\n",
3988255932Salfred							 slave, cqn);
3989255932Salfred					atomic_dec(&cq->mtt->ref_count);
3990255932Salfred					state = RES_CQ_ALLOCATED;
3991255932Salfred					break;
3992255932Salfred
3993255932Salfred				default:
3994255932Salfred					state = 0;
3995255932Salfred				}
3996255932Salfred			}
3997255932Salfred		}
3998255932Salfred		spin_lock_irq(mlx4_tlock(dev));
3999255932Salfred	}
4000255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4001255932Salfred}
4002255932Salfred
4003255932Salfredstatic void rem_slave_mrs(struct mlx4_dev *dev, int slave)
4004255932Salfred{
4005255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4006255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4007255932Salfred	struct list_head *mpt_list =
4008255932Salfred		&tracker->slave_list[slave].res_list[RES_MPT];
4009255932Salfred	struct res_mpt *mpt;
4010255932Salfred	struct res_mpt *tmp;
4011255932Salfred	int state;
4012255932Salfred	u64 in_param;
4013255932Salfred	LIST_HEAD(tlist);
4014255932Salfred	int mptn;
4015255932Salfred	int err;
4016255932Salfred
4017255932Salfred	err = move_all_busy(dev, slave, RES_MPT);
4018255932Salfred	if (err)
4019255932Salfred		mlx4_warn(dev, "rem_slave_mrs: Could not move all mpts to "
4020255932Salfred			  "busy for slave %d\n", slave);
4021255932Salfred
4022255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4023255932Salfred	list_for_each_entry_safe(mpt, tmp, mpt_list, com.list) {
4024255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4025255932Salfred		if (mpt->com.owner == slave) {
4026255932Salfred			mptn = mpt->com.res_id;
4027255932Salfred			state = mpt->com.from_state;
4028255932Salfred			while (state != 0) {
4029255932Salfred				switch (state) {
4030255932Salfred				case RES_MPT_RESERVED:
4031255932Salfred					__mlx4_mr_release(dev, mpt->key);
4032255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4033255932Salfred					rb_erase(&mpt->com.node,
4034255932Salfred						 &tracker->res_tree[RES_MPT]);
4035255932Salfred					list_del(&mpt->com.list);
4036255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4037255932Salfred					kfree(mpt);
4038255932Salfred					state = 0;
4039255932Salfred					break;
4040255932Salfred
4041255932Salfred				case RES_MPT_MAPPED:
4042255932Salfred					__mlx4_mr_free_icm(dev, mpt->key);
4043255932Salfred					state = RES_MPT_RESERVED;
4044255932Salfred					break;
4045255932Salfred
4046255932Salfred				case RES_MPT_HW:
4047255932Salfred					in_param = slave;
4048255932Salfred					err = mlx4_cmd(dev, in_param, mptn, 0,
4049255932Salfred						     MLX4_CMD_HW2SW_MPT,
4050255932Salfred						     MLX4_CMD_TIME_CLASS_A,
4051255932Salfred						     MLX4_CMD_NATIVE);
4052255932Salfred					if (err)
4053255932Salfred						mlx4_dbg(dev, "rem_slave_mrs: failed"
4054255932Salfred							 " to move slave %d mpt %d to"
4055255932Salfred							 " SW ownership\n",
4056255932Salfred							 slave, mptn);
4057255932Salfred					if (mpt->mtt)
4058255932Salfred						atomic_dec(&mpt->mtt->ref_count);
4059255932Salfred					state = RES_MPT_MAPPED;
4060255932Salfred					break;
4061255932Salfred				default:
4062255932Salfred					state = 0;
4063255932Salfred				}
4064255932Salfred			}
4065255932Salfred		}
4066255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4067255932Salfred	}
4068255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4069255932Salfred}
4070255932Salfred
4071255932Salfredstatic void rem_slave_mtts(struct mlx4_dev *dev, int slave)
4072255932Salfred{
4073255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4074255932Salfred	struct mlx4_resource_tracker *tracker =
4075255932Salfred		&priv->mfunc.master.res_tracker;
4076255932Salfred	struct list_head *mtt_list =
4077255932Salfred		&tracker->slave_list[slave].res_list[RES_MTT];
4078255932Salfred	struct res_mtt *mtt;
4079255932Salfred	struct res_mtt *tmp;
4080255932Salfred	int state;
4081255932Salfred	LIST_HEAD(tlist);
4082255932Salfred	int base;
4083255932Salfred	int err;
4084255932Salfred
4085255932Salfred	err = move_all_busy(dev, slave, RES_MTT);
4086255932Salfred	if (err)
4087255932Salfred		mlx4_warn(dev, "rem_slave_mtts: Could not move all mtts to "
4088255932Salfred			  "busy for slave %d\n", slave);
4089255932Salfred
4090255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4091255932Salfred	list_for_each_entry_safe(mtt, tmp, mtt_list, com.list) {
4092255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4093255932Salfred		if (mtt->com.owner == slave) {
4094255932Salfred			base = mtt->com.res_id;
4095255932Salfred			state = mtt->com.from_state;
4096255932Salfred			while (state != 0) {
4097255932Salfred				switch (state) {
4098255932Salfred				case RES_MTT_ALLOCATED:
4099255932Salfred					__mlx4_free_mtt_range(dev, base,
4100255932Salfred							      mtt->order);
4101255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4102255932Salfred					rb_erase(&mtt->com.node,
4103255932Salfred						 &tracker->res_tree[RES_MTT]);
4104255932Salfred					list_del(&mtt->com.list);
4105255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4106255932Salfred					kfree(mtt);
4107255932Salfred					state = 0;
4108255932Salfred					break;
4109255932Salfred
4110255932Salfred				default:
4111255932Salfred					state = 0;
4112255932Salfred				}
4113255932Salfred			}
4114255932Salfred		}
4115255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4116255932Salfred	}
4117255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4118255932Salfred}
4119255932Salfred
4120255932Salfredstatic void rem_slave_fs_rule(struct mlx4_dev *dev, int slave)
4121255932Salfred{
4122255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4123255932Salfred	struct mlx4_resource_tracker *tracker =
4124255932Salfred		&priv->mfunc.master.res_tracker;
4125255932Salfred	struct list_head *fs_rule_list =
4126255932Salfred		&tracker->slave_list[slave].res_list[RES_FS_RULE];
4127255932Salfred	struct res_fs_rule *fs_rule;
4128255932Salfred	struct res_fs_rule *tmp;
4129255932Salfred	int state;
4130255932Salfred	u64 base;
4131255932Salfred	int err;
4132255932Salfred
4133255932Salfred	err = move_all_busy(dev, slave, RES_FS_RULE);
4134255932Salfred	if (err)
4135255932Salfred		mlx4_warn(dev, "rem_slave_fs_rule: Could not move all mtts to busy for slave %d\n",
4136255932Salfred			  slave);
4137255932Salfred
4138255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4139255932Salfred	list_for_each_entry_safe(fs_rule, tmp, fs_rule_list, com.list) {
4140255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4141255932Salfred		if (fs_rule->com.owner == slave) {
4142255932Salfred			base = fs_rule->com.res_id;
4143255932Salfred			state = fs_rule->com.from_state;
4144255932Salfred			while (state != 0) {
4145255932Salfred				switch (state) {
4146255932Salfred				case RES_FS_RULE_ALLOCATED:
4147255932Salfred					/* detach rule */
4148255932Salfred					err = mlx4_cmd(dev, base, 0, 0,
4149255932Salfred						       MLX4_QP_FLOW_STEERING_DETACH,
4150255932Salfred						       MLX4_CMD_TIME_CLASS_A,
4151255932Salfred						       MLX4_CMD_NATIVE);
4152255932Salfred
4153255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4154255932Salfred					rb_erase(&fs_rule->com.node,
4155255932Salfred						 &tracker->res_tree[RES_FS_RULE]);
4156255932Salfred					list_del(&fs_rule->com.list);
4157255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4158255932Salfred					kfree(fs_rule);
4159255932Salfred					state = 0;
4160255932Salfred					break;
4161255932Salfred
4162255932Salfred				default:
4163255932Salfred					state = 0;
4164255932Salfred				}
4165255932Salfred			}
4166255932Salfred		}
4167255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4168255932Salfred	}
4169255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4170255932Salfred}
4171255932Salfred
4172255932Salfredstatic void rem_slave_eqs(struct mlx4_dev *dev, int slave)
4173255932Salfred{
4174255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4175255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4176255932Salfred	struct list_head *eq_list =
4177255932Salfred		&tracker->slave_list[slave].res_list[RES_EQ];
4178255932Salfred	struct res_eq *eq;
4179255932Salfred	struct res_eq *tmp;
4180255932Salfred	int err;
4181255932Salfred	int state;
4182255932Salfred	LIST_HEAD(tlist);
4183255932Salfred	int eqn;
4184255932Salfred	struct mlx4_cmd_mailbox *mailbox;
4185255932Salfred
4186255932Salfred	err = move_all_busy(dev, slave, RES_EQ);
4187255932Salfred	if (err)
4188255932Salfred		mlx4_warn(dev, "rem_slave_eqs: Could not move all eqs to "
4189255932Salfred			  "busy for slave %d\n", slave);
4190255932Salfred
4191255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4192255932Salfred	list_for_each_entry_safe(eq, tmp, eq_list, com.list) {
4193255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4194255932Salfred		if (eq->com.owner == slave) {
4195255932Salfred			eqn = eq->com.res_id;
4196255932Salfred			state = eq->com.from_state;
4197255932Salfred			while (state != 0) {
4198255932Salfred				switch (state) {
4199255932Salfred				case RES_EQ_RESERVED:
4200255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4201255932Salfred					rb_erase(&eq->com.node,
4202255932Salfred						 &tracker->res_tree[RES_EQ]);
4203255932Salfred					list_del(&eq->com.list);
4204255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4205255932Salfred					kfree(eq);
4206255932Salfred					state = 0;
4207255932Salfred					break;
4208255932Salfred
4209255932Salfred				case RES_EQ_HW:
4210255932Salfred					mailbox = mlx4_alloc_cmd_mailbox(dev);
4211255932Salfred					if (IS_ERR(mailbox)) {
4212255932Salfred						cond_resched();
4213255932Salfred						continue;
4214255932Salfred					}
4215255932Salfred					err = mlx4_cmd_box(dev, slave, 0,
4216255932Salfred							   eqn & 0xff, 0,
4217255932Salfred							   MLX4_CMD_HW2SW_EQ,
4218255932Salfred							   MLX4_CMD_TIME_CLASS_A,
4219255932Salfred							   MLX4_CMD_NATIVE);
4220255932Salfred					if (err)
4221255932Salfred						mlx4_dbg(dev, "rem_slave_eqs: failed"
4222255932Salfred							 " to move slave %d eqs %d to"
4223255932Salfred							 " SW ownership\n", slave, eqn);
4224255932Salfred					mlx4_free_cmd_mailbox(dev, mailbox);
4225255932Salfred					atomic_dec(&eq->mtt->ref_count);
4226255932Salfred					state = RES_EQ_RESERVED;
4227255932Salfred					break;
4228255932Salfred
4229255932Salfred				default:
4230255932Salfred					state = 0;
4231255932Salfred				}
4232255932Salfred			}
4233255932Salfred		}
4234255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4235255932Salfred	}
4236255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4237255932Salfred}
4238255932Salfred
4239255932Salfredstatic void rem_slave_counters(struct mlx4_dev *dev, int slave)
4240255932Salfred{
4241255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4242255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4243255932Salfred	struct list_head *counter_list =
4244255932Salfred		&tracker->slave_list[slave].res_list[RES_COUNTER];
4245255932Salfred	struct res_counter *counter;
4246255932Salfred	struct res_counter *tmp;
4247255932Salfred	int err;
4248255932Salfred	int index;
4249255932Salfred
4250255932Salfred	err = move_all_busy(dev, slave, RES_COUNTER);
4251255932Salfred	if (err)
4252255932Salfred		mlx4_warn(dev, "rem_slave_counters: Could not move all counters to "
4253255932Salfred			  "busy for slave %d\n", slave);
4254255932Salfred
4255255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4256255932Salfred	list_for_each_entry_safe(counter, tmp, counter_list, com.list) {
4257255932Salfred		if (counter->com.owner == slave) {
4258255932Salfred			index = counter->com.res_id;
4259255932Salfred			rb_erase(&counter->com.node,
4260255932Salfred				 &tracker->res_tree[RES_COUNTER]);
4261255932Salfred			list_del(&counter->com.list);
4262255932Salfred			kfree(counter);
4263255932Salfred			__mlx4_counter_free(dev, index);
4264255932Salfred		}
4265255932Salfred	}
4266255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4267255932Salfred}
4268255932Salfred
4269255932Salfredstatic void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
4270255932Salfred{
4271255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4272255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4273255932Salfred	struct list_head *xrcdn_list =
4274255932Salfred		&tracker->slave_list[slave].res_list[RES_XRCD];
4275255932Salfred	struct res_xrcdn *xrcd;
4276255932Salfred	struct res_xrcdn *tmp;
4277255932Salfred	int err;
4278255932Salfred	int xrcdn;
4279255932Salfred
4280255932Salfred	err = move_all_busy(dev, slave, RES_XRCD);
4281255932Salfred	if (err)
4282255932Salfred		mlx4_warn(dev, "rem_slave_xrcdns: Could not move all xrcdns to "
4283255932Salfred			  "busy for slave %d\n", slave);
4284255932Salfred
4285255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4286255932Salfred	list_for_each_entry_safe(xrcd, tmp, xrcdn_list, com.list) {
4287255932Salfred		if (xrcd->com.owner == slave) {
4288255932Salfred			xrcdn = xrcd->com.res_id;
4289255932Salfred			rb_erase(&xrcd->com.node, &tracker->res_tree[RES_XRCD]);
4290255932Salfred			list_del(&xrcd->com.list);
4291255932Salfred			kfree(xrcd);
4292255932Salfred			__mlx4_xrcd_free(dev, xrcdn);
4293255932Salfred		}
4294255932Salfred	}
4295255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4296255932Salfred}
4297255932Salfred
4298255932Salfredvoid mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
4299255932Salfred{
4300255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4301255932Salfred
4302255932Salfred	mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
4303255932Salfred	rem_slave_macs(dev, slave);
4304255932Salfred	rem_slave_vlans(dev, slave);
4305255932Salfred	rem_slave_qps(dev, slave);
4306255932Salfred	rem_slave_srqs(dev, slave);
4307255932Salfred	rem_slave_cqs(dev, slave);
4308255932Salfred	rem_slave_mrs(dev, slave);
4309255932Salfred	rem_slave_eqs(dev, slave);
4310255932Salfred	rem_slave_mtts(dev, slave);
4311255932Salfred	rem_slave_counters(dev, slave);
4312255932Salfred	rem_slave_xrcdns(dev, slave);
4313255932Salfred	rem_slave_fs_rule(dev, slave);
4314255932Salfred	mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
4315255932Salfred}
4316