mlx4_resource_tracker.c revision 272060
1255932Salfred/*
2255932Salfred * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
3272027Shselasky * Copyright (c) 2005, 2006, 2007, 2008, 2014 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>
45272027Shselasky#include <linux/etherdevice.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;
88272027Shselasky	u64			reg_id;
89255932Salfred};
90255932Salfred
91255932Salfredenum res_qp_states {
92255932Salfred	RES_QP_BUSY = RES_ANY_BUSY,
93255932Salfred
94255932Salfred	/* QP number was allocated */
95255932Salfred	RES_QP_RESERVED,
96255932Salfred
97255932Salfred	/* ICM memory for QP context was mapped */
98255932Salfred	RES_QP_MAPPED,
99255932Salfred
100255932Salfred	/* QP is in hw ownership */
101255932Salfred	RES_QP_HW
102255932Salfred};
103255932Salfred
104255932Salfredstruct res_qp {
105255932Salfred	struct res_common	com;
106255932Salfred	struct res_mtt	       *mtt;
107255932Salfred	struct res_cq	       *rcq;
108255932Salfred	struct res_cq	       *scq;
109255932Salfred	struct res_srq	       *srq;
110255932Salfred	struct list_head	mcg_list;
111255932Salfred	spinlock_t		mcg_spl;
112255932Salfred	int			local_qpn;
113272027Shselasky	atomic_t		ref_count;
114272027Shselasky	u32			qpc_flags;
115272027Shselasky	/* saved qp params before VST enforcement in order to restore on VGT */
116272027Shselasky	u8			sched_queue;
117272027Shselasky	__be32			param3;
118272027Shselasky	u8			vlan_control;
119272027Shselasky	u8			fvl_rx;
120272027Shselasky	u8			pri_path_fl;
121272027Shselasky	u8			vlan_index;
122272027Shselasky	u8			feup;
123255932Salfred};
124255932Salfred
125255932Salfredenum res_mtt_states {
126255932Salfred	RES_MTT_BUSY = RES_ANY_BUSY,
127255932Salfred	RES_MTT_ALLOCATED,
128255932Salfred};
129255932Salfred
130255932Salfredstatic inline const char *mtt_states_str(enum res_mtt_states state)
131255932Salfred{
132255932Salfred	switch (state) {
133255932Salfred	case RES_MTT_BUSY: return "RES_MTT_BUSY";
134255932Salfred	case RES_MTT_ALLOCATED: return "RES_MTT_ALLOCATED";
135255932Salfred	default: return "Unknown";
136255932Salfred	}
137255932Salfred}
138255932Salfred
139255932Salfredstruct res_mtt {
140255932Salfred	struct res_common	com;
141255932Salfred	int			order;
142255932Salfred	atomic_t		ref_count;
143255932Salfred};
144255932Salfred
145255932Salfredenum res_mpt_states {
146255932Salfred	RES_MPT_BUSY = RES_ANY_BUSY,
147255932Salfred	RES_MPT_RESERVED,
148255932Salfred	RES_MPT_MAPPED,
149255932Salfred	RES_MPT_HW,
150255932Salfred};
151255932Salfred
152255932Salfredstruct res_mpt {
153255932Salfred	struct res_common	com;
154255932Salfred	struct res_mtt	       *mtt;
155255932Salfred	int			key;
156255932Salfred};
157255932Salfred
158255932Salfredenum res_eq_states {
159255932Salfred	RES_EQ_BUSY = RES_ANY_BUSY,
160255932Salfred	RES_EQ_RESERVED,
161255932Salfred	RES_EQ_HW,
162255932Salfred};
163255932Salfred
164255932Salfredstruct res_eq {
165255932Salfred	struct res_common	com;
166255932Salfred	struct res_mtt	       *mtt;
167255932Salfred};
168255932Salfred
169255932Salfredenum res_cq_states {
170255932Salfred	RES_CQ_BUSY = RES_ANY_BUSY,
171255932Salfred	RES_CQ_ALLOCATED,
172255932Salfred	RES_CQ_HW,
173255932Salfred};
174255932Salfred
175255932Salfredstruct res_cq {
176255932Salfred	struct res_common	com;
177255932Salfred	struct res_mtt	       *mtt;
178255932Salfred	atomic_t		ref_count;
179255932Salfred};
180255932Salfred
181255932Salfredenum res_srq_states {
182255932Salfred	RES_SRQ_BUSY = RES_ANY_BUSY,
183255932Salfred	RES_SRQ_ALLOCATED,
184255932Salfred	RES_SRQ_HW,
185255932Salfred};
186255932Salfred
187255932Salfredstruct res_srq {
188255932Salfred	struct res_common	com;
189255932Salfred	struct res_mtt	       *mtt;
190255932Salfred	struct res_cq	       *cq;
191255932Salfred	atomic_t		ref_count;
192255932Salfred};
193255932Salfred
194255932Salfredenum res_counter_states {
195255932Salfred	RES_COUNTER_BUSY = RES_ANY_BUSY,
196255932Salfred	RES_COUNTER_ALLOCATED,
197255932Salfred};
198255932Salfred
199255932Salfredstruct res_counter {
200255932Salfred	struct res_common	com;
201255932Salfred	int			port;
202255932Salfred};
203255932Salfred
204255932Salfredenum res_xrcdn_states {
205255932Salfred	RES_XRCD_BUSY = RES_ANY_BUSY,
206255932Salfred	RES_XRCD_ALLOCATED,
207255932Salfred};
208255932Salfred
209255932Salfredstruct res_xrcdn {
210255932Salfred	struct res_common	com;
211255932Salfred	int			port;
212255932Salfred};
213255932Salfred
214255932Salfredenum res_fs_rule_states {
215255932Salfred	RES_FS_RULE_BUSY = RES_ANY_BUSY,
216255932Salfred	RES_FS_RULE_ALLOCATED,
217255932Salfred};
218255932Salfred
219255932Salfredstruct res_fs_rule {
220255932Salfred	struct res_common	com;
221272027Shselasky	int			qpn;
222255932Salfred};
223255932Salfred
224255932Salfredstatic int mlx4_is_eth(struct mlx4_dev *dev, int port)
225255932Salfred{
226255932Salfred	return dev->caps.port_mask[port] == MLX4_PORT_TYPE_IB ? 0 : 1;
227255932Salfred}
228255932Salfred
229255932Salfredstatic void *res_tracker_lookup(struct rb_root *root, u64 res_id)
230255932Salfred{
231255932Salfred	struct rb_node *node = root->rb_node;
232255932Salfred
233255932Salfred	while (node) {
234255932Salfred		struct res_common *res = container_of(node, struct res_common,
235255932Salfred						      node);
236255932Salfred
237255932Salfred		if (res_id < res->res_id)
238255932Salfred			node = node->rb_left;
239255932Salfred		else if (res_id > res->res_id)
240255932Salfred			node = node->rb_right;
241255932Salfred		else
242255932Salfred			return res;
243255932Salfred	}
244255932Salfred	return NULL;
245255932Salfred}
246255932Salfred
247255932Salfredstatic int res_tracker_insert(struct rb_root *root, struct res_common *res)
248255932Salfred{
249255932Salfred	struct rb_node **new = &(root->rb_node), *parent = NULL;
250255932Salfred
251255932Salfred	/* Figure out where to put new node */
252255932Salfred	while (*new) {
253255932Salfred		struct res_common *this = container_of(*new, struct res_common,
254255932Salfred						       node);
255255932Salfred
256255932Salfred		parent = *new;
257255932Salfred		if (res->res_id < this->res_id)
258255932Salfred			new = &((*new)->rb_left);
259255932Salfred		else if (res->res_id > this->res_id)
260255932Salfred			new = &((*new)->rb_right);
261255932Salfred		else
262255932Salfred			return -EEXIST;
263255932Salfred	}
264255932Salfred
265255932Salfred	/* Add new node and rebalance tree. */
266255932Salfred	rb_link_node(&res->node, parent, new);
267255932Salfred	rb_insert_color(&res->node, root);
268255932Salfred
269255932Salfred	return 0;
270255932Salfred}
271255932Salfred
272255932Salfredenum qp_transition {
273255932Salfred	QP_TRANS_INIT2RTR,
274255932Salfred	QP_TRANS_RTR2RTS,
275255932Salfred	QP_TRANS_RTS2RTS,
276255932Salfred	QP_TRANS_SQERR2RTS,
277255932Salfred	QP_TRANS_SQD2SQD,
278255932Salfred	QP_TRANS_SQD2RTS
279255932Salfred};
280255932Salfred
281255932Salfred/* For Debug uses */
282255932Salfredstatic const char *ResourceType(enum mlx4_resource rt)
283255932Salfred{
284255932Salfred	switch (rt) {
285255932Salfred	case RES_QP: return "RES_QP";
286255932Salfred	case RES_CQ: return "RES_CQ";
287255932Salfred	case RES_SRQ: return "RES_SRQ";
288255932Salfred	case RES_MPT: return "RES_MPT";
289255932Salfred	case RES_MTT: return "RES_MTT";
290255932Salfred	case RES_MAC: return  "RES_MAC";
291255932Salfred	case RES_VLAN: return  "RES_VLAN";
292255932Salfred	case RES_EQ: return "RES_EQ";
293255932Salfred	case RES_COUNTER: return "RES_COUNTER";
294255932Salfred	case RES_FS_RULE: return "RES_FS_RULE";
295255932Salfred	case RES_XRCD: return "RES_XRCD";
296255932Salfred	default: return "Unknown resource type !!!";
297255932Salfred	};
298255932Salfred}
299255932Salfred
300255932Salfredstatic void rem_slave_vlans(struct mlx4_dev *dev, int slave);
301255932Salfredstatic inline int mlx4_grant_resource(struct mlx4_dev *dev, int slave,
302255932Salfred				      enum mlx4_resource res_type, int count,
303255932Salfred				      int port)
304255932Salfred{
305255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
306255932Salfred	struct resource_allocator *res_alloc =
307255932Salfred		&priv->mfunc.master.res_tracker.res_alloc[res_type];
308255932Salfred	int err = -EINVAL;
309255932Salfred	int allocated, free, reserved, guaranteed, from_free;
310255932Salfred
311255932Salfred	spin_lock(&res_alloc->alloc_lock);
312255932Salfred	allocated = (port > 0) ?
313255932Salfred		res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] :
314255932Salfred		res_alloc->allocated[slave];
315255932Salfred	free = (port > 0) ? res_alloc->res_port_free[port - 1] :
316255932Salfred		res_alloc->res_free;
317255932Salfred	reserved = (port > 0) ? res_alloc->res_port_rsvd[port - 1] :
318255932Salfred		res_alloc->res_reserved;
319255932Salfred	guaranteed = res_alloc->guaranteed[slave];
320255932Salfred
321255932Salfred	if (allocated + count > res_alloc->quota[slave])
322255932Salfred		goto out;
323255932Salfred
324255932Salfred	if (allocated + count <= guaranteed) {
325255932Salfred		err = 0;
326255932Salfred	} else {
327255932Salfred		/* portion may need to be obtained from free area */
328255932Salfred		if (guaranteed - allocated > 0)
329255932Salfred			from_free = count - (guaranteed - allocated);
330255932Salfred		else
331255932Salfred			from_free = count;
332255932Salfred
333255932Salfred		if (free - from_free > reserved)
334255932Salfred			err = 0;
335255932Salfred	}
336255932Salfred
337255932Salfred	if (!err) {
338255932Salfred		/* grant the request */
339255932Salfred		if (port > 0) {
340255932Salfred			res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] += count;
341255932Salfred			res_alloc->res_port_free[port - 1] -= count;
342255932Salfred		} else {
343255932Salfred			res_alloc->allocated[slave] += count;
344255932Salfred			res_alloc->res_free -= count;
345255932Salfred		}
346255932Salfred	}
347255932Salfred
348255932Salfredout:
349255932Salfred	spin_unlock(&res_alloc->alloc_lock);
350255932Salfred	return err;
351255932Salfred
352255932Salfred}
353255932Salfred
354255932Salfredstatic inline void mlx4_release_resource(struct mlx4_dev *dev, int slave,
355255932Salfred				    enum mlx4_resource res_type, int count,
356255932Salfred				    int port)
357255932Salfred{
358255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
359255932Salfred	struct resource_allocator *res_alloc =
360255932Salfred		&priv->mfunc.master.res_tracker.res_alloc[res_type];
361255932Salfred
362255932Salfred	spin_lock(&res_alloc->alloc_lock);
363255932Salfred	if (port > 0) {
364255932Salfred		res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] -= count;
365255932Salfred		res_alloc->res_port_free[port - 1] += count;
366255932Salfred	} else {
367255932Salfred		res_alloc->allocated[slave] -= count;
368255932Salfred		res_alloc->res_free += count;
369255932Salfred	}
370255932Salfred
371255932Salfred	spin_unlock(&res_alloc->alloc_lock);
372255932Salfred	return;
373255932Salfred}
374255932Salfred
375255932Salfredstatic inline void initialize_res_quotas(struct mlx4_dev *dev,
376255932Salfred					 struct resource_allocator *res_alloc,
377255932Salfred					 enum mlx4_resource res_type,
378255932Salfred					 int vf, int num_instances)
379255932Salfred{
380255932Salfred	res_alloc->guaranteed[vf] = num_instances / (2 * (dev->num_vfs + 1));
381255932Salfred	res_alloc->quota[vf] = (num_instances / 2) + res_alloc->guaranteed[vf];
382255932Salfred	if (vf == mlx4_master_func_num(dev)) {
383255932Salfred		res_alloc->res_free = num_instances;
384255932Salfred		if (res_type == RES_MTT) {
385255932Salfred			/* reserved mtts will be taken out of the PF allocation */
386255932Salfred			res_alloc->res_free += dev->caps.reserved_mtts;
387255932Salfred			res_alloc->guaranteed[vf] += dev->caps.reserved_mtts;
388255932Salfred			res_alloc->quota[vf] += dev->caps.reserved_mtts;
389255932Salfred		}
390255932Salfred	}
391255932Salfred}
392255932Salfred
393255932Salfredvoid mlx4_init_quotas(struct mlx4_dev *dev)
394255932Salfred{
395255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
396255932Salfred	int pf;
397255932Salfred
398255932Salfred	/* quotas for VFs are initialized in mlx4_slave_cap */
399255932Salfred	if (mlx4_is_slave(dev))
400255932Salfred		return;
401255932Salfred
402255932Salfred	if (!mlx4_is_mfunc(dev)) {
403255932Salfred		dev->quotas.qp = dev->caps.num_qps - dev->caps.reserved_qps -
404255932Salfred			mlx4_num_reserved_sqps(dev);
405255932Salfred		dev->quotas.cq = dev->caps.num_cqs - dev->caps.reserved_cqs;
406255932Salfred		dev->quotas.srq = dev->caps.num_srqs - dev->caps.reserved_srqs;
407255932Salfred		dev->quotas.mtt = dev->caps.num_mtts - dev->caps.reserved_mtts;
408255932Salfred		dev->quotas.mpt = dev->caps.num_mpts - dev->caps.reserved_mrws;
409255932Salfred		return;
410255932Salfred	}
411255932Salfred
412255932Salfred	pf = mlx4_master_func_num(dev);
413255932Salfred	dev->quotas.qp =
414255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[pf];
415255932Salfred	dev->quotas.cq =
416255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[pf];
417255932Salfred	dev->quotas.srq =
418255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[pf];
419255932Salfred	dev->quotas.mtt =
420255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[pf];
421255932Salfred	dev->quotas.mpt =
422255932Salfred		priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[pf];
423255932Salfred}
424255932Salfredint mlx4_init_resource_tracker(struct mlx4_dev *dev)
425255932Salfred{
426255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
427255932Salfred	int i, j;
428255932Salfred	int t;
429255932Salfred
430255932Salfred	priv->mfunc.master.res_tracker.slave_list =
431255932Salfred		kzalloc(dev->num_slaves * sizeof(struct slave_list),
432255932Salfred			GFP_KERNEL);
433255932Salfred	if (!priv->mfunc.master.res_tracker.slave_list)
434255932Salfred		return -ENOMEM;
435255932Salfred
436255932Salfred	for (i = 0 ; i < dev->num_slaves; i++) {
437255932Salfred		for (t = 0; t < MLX4_NUM_OF_RESOURCE_TYPE; ++t)
438255932Salfred			INIT_LIST_HEAD(&priv->mfunc.master.res_tracker.
439255932Salfred				       slave_list[i].res_list[t]);
440255932Salfred		mutex_init(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
441255932Salfred	}
442255932Salfred
443255932Salfred	mlx4_dbg(dev, "Started init_resource_tracker: %ld slaves\n",
444255932Salfred		 dev->num_slaves);
445255932Salfred	for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++)
446255932Salfred		priv->mfunc.master.res_tracker.res_tree[i] = RB_ROOT;
447255932Salfred
448255932Salfred	for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
449255932Salfred		struct resource_allocator *res_alloc =
450255932Salfred			&priv->mfunc.master.res_tracker.res_alloc[i];
451255932Salfred		res_alloc->quota = kmalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL);
452255932Salfred		res_alloc->guaranteed = kmalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL);
453255932Salfred		if (i == RES_MAC || i == RES_VLAN)
454255932Salfred			res_alloc->allocated = kzalloc(MLX4_MAX_PORTS *
455255932Salfred						       (dev->num_vfs + 1) * sizeof(int),
456255932Salfred							GFP_KERNEL);
457255932Salfred		else
458255932Salfred			res_alloc->allocated = kzalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL);
459255932Salfred
460255932Salfred		if (!res_alloc->quota || !res_alloc->guaranteed ||
461255932Salfred		    !res_alloc->allocated)
462255932Salfred			goto no_mem_err;
463255932Salfred
464255932Salfred		spin_lock_init(&res_alloc->alloc_lock);
465255932Salfred		for (t = 0; t < dev->num_vfs + 1; t++) {
466255932Salfred			switch (i) {
467255932Salfred			case RES_QP:
468255932Salfred				initialize_res_quotas(dev, res_alloc, RES_QP,
469255932Salfred						      t, dev->caps.num_qps -
470255932Salfred						      dev->caps.reserved_qps -
471255932Salfred						      mlx4_num_reserved_sqps(dev));
472255932Salfred				break;
473255932Salfred			case RES_CQ:
474255932Salfred				initialize_res_quotas(dev, res_alloc, RES_CQ,
475255932Salfred						      t, dev->caps.num_cqs -
476255932Salfred						      dev->caps.reserved_cqs);
477255932Salfred				break;
478255932Salfred			case RES_SRQ:
479255932Salfred				initialize_res_quotas(dev, res_alloc, RES_SRQ,
480255932Salfred						      t, dev->caps.num_srqs -
481255932Salfred						      dev->caps.reserved_srqs);
482255932Salfred				break;
483255932Salfred			case RES_MPT:
484255932Salfred				initialize_res_quotas(dev, res_alloc, RES_MPT,
485255932Salfred						      t, dev->caps.num_mpts -
486255932Salfred						      dev->caps.reserved_mrws);
487255932Salfred				break;
488255932Salfred			case RES_MTT:
489255932Salfred				initialize_res_quotas(dev, res_alloc, RES_MTT,
490255932Salfred						      t, dev->caps.num_mtts -
491255932Salfred						      dev->caps.reserved_mtts);
492255932Salfred				break;
493255932Salfred			case RES_MAC:
494255932Salfred				if (t == mlx4_master_func_num(dev)) {
495255932Salfred					res_alloc->quota[t] =
496255932Salfred						MLX4_MAX_MAC_NUM - 2 * dev->num_vfs;
497255932Salfred					res_alloc->guaranteed[t] = res_alloc->quota[t];
498255932Salfred					for (j = 0; j < MLX4_MAX_PORTS; j++)
499255932Salfred						res_alloc->res_port_free[j] = MLX4_MAX_MAC_NUM;
500255932Salfred				} else {
501255932Salfred					res_alloc->quota[t] = 2;
502255932Salfred					res_alloc->guaranteed[t] = 2;
503255932Salfred				}
504255932Salfred				break;
505255932Salfred			case RES_VLAN:
506255932Salfred				if (t == mlx4_master_func_num(dev)) {
507255932Salfred					res_alloc->quota[t] = MLX4_MAX_VLAN_NUM;
508255932Salfred					res_alloc->guaranteed[t] = MLX4_MAX_VLAN_NUM / 2;
509255932Salfred					for (j = 0; j < MLX4_MAX_PORTS; j++)
510255932Salfred						res_alloc->res_port_free[j] =
511255932Salfred							res_alloc->quota[t];
512255932Salfred				} else {
513255932Salfred					res_alloc->quota[t] = MLX4_MAX_VLAN_NUM / 2;
514255932Salfred					res_alloc->guaranteed[t] = 0;
515255932Salfred				}
516255932Salfred				break;
517255932Salfred			case RES_COUNTER:
518255932Salfred				res_alloc->quota[t] = dev->caps.max_counters;
519255932Salfred				res_alloc->guaranteed[t] = 0;
520255932Salfred				if (t == mlx4_master_func_num(dev))
521255932Salfred					res_alloc->res_free = res_alloc->quota[t];
522255932Salfred				break;
523255932Salfred			default:
524255932Salfred				break;
525255932Salfred			}
526255932Salfred			if (i == RES_MAC || i == RES_VLAN) {
527255932Salfred				for (j = 0; j < MLX4_MAX_PORTS; j++)
528255932Salfred					res_alloc->res_port_rsvd[j] +=
529255932Salfred						res_alloc->guaranteed[t];
530255932Salfred			} else {
531255932Salfred				res_alloc->res_reserved += res_alloc->guaranteed[t];
532255932Salfred			}
533255932Salfred		}
534255932Salfred	}
535255932Salfred	spin_lock_init(&priv->mfunc.master.res_tracker.lock);
536255932Salfred	return 0;
537255932Salfred
538255932Salfredno_mem_err:
539255932Salfred	for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
540255932Salfred		kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated);
541255932Salfred		priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL;
542255932Salfred		kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed);
543255932Salfred		priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL;
544255932Salfred		kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota);
545255932Salfred		priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL;
546255932Salfred	}
547255932Salfred	return -ENOMEM;
548255932Salfred}
549255932Salfred
550255932Salfredvoid mlx4_free_resource_tracker(struct mlx4_dev *dev,
551255932Salfred				enum mlx4_res_tracker_free_type type)
552255932Salfred{
553255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
554255932Salfred	int i;
555255932Salfred
556255932Salfred	if (priv->mfunc.master.res_tracker.slave_list) {
557255932Salfred		if (type != RES_TR_FREE_STRUCTS_ONLY) {
558255932Salfred			for (i = 0; i < dev->num_slaves; i++) {
559255932Salfred				if (type == RES_TR_FREE_ALL ||
560255932Salfred				    dev->caps.function != i)
561255932Salfred					mlx4_delete_all_resources_for_slave(dev, i);
562255932Salfred			}
563255932Salfred			/* free master's vlans */
564255932Salfred			i = dev->caps.function;
565255932Salfred			mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
566255932Salfred			rem_slave_vlans(dev, i);
567255932Salfred			mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
568255932Salfred		}
569255932Salfred
570255932Salfred		if (type != RES_TR_FREE_SLAVES_ONLY) {
571255932Salfred			for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
572255932Salfred				kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated);
573255932Salfred				priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL;
574255932Salfred				kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed);
575255932Salfred				priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL;
576255932Salfred				kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota);
577255932Salfred				priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL;
578255932Salfred			}
579255932Salfred			kfree(priv->mfunc.master.res_tracker.slave_list);
580255932Salfred			priv->mfunc.master.res_tracker.slave_list = NULL;
581255932Salfred		}
582255932Salfred	}
583255932Salfred}
584255932Salfred
585255932Salfredstatic void update_pkey_index(struct mlx4_dev *dev, int slave,
586255932Salfred			      struct mlx4_cmd_mailbox *inbox)
587255932Salfred{
588255932Salfred	u8 sched = *(u8 *)(inbox->buf + 64);
589255932Salfred	u8 orig_index = *(u8 *)(inbox->buf + 35);
590255932Salfred	u8 new_index;
591255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
592255932Salfred	int port;
593255932Salfred
594255932Salfred	port = (sched >> 6 & 1) + 1;
595255932Salfred
596255932Salfred	new_index = priv->virt2phys_pkey[slave][port - 1][orig_index];
597255932Salfred	*(u8 *)(inbox->buf + 35) = new_index;
598255932Salfred}
599255932Salfred
600255932Salfredstatic void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
601255932Salfred		       u8 slave)
602255932Salfred{
603255932Salfred	struct mlx4_qp_context	*qp_ctx = inbox->buf + 8;
604255932Salfred	enum mlx4_qp_optpar	optpar = be32_to_cpu(*(__be32 *) inbox->buf);
605255932Salfred	u32			ts = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff;
606255932Salfred	int port;
607255932Salfred
608255932Salfred	if (MLX4_QP_ST_UD == ts) {
609255932Salfred		port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
610255932Salfred		if (mlx4_is_eth(dev, port))
611255932Salfred			qp_ctx->pri_path.mgid_index = mlx4_get_base_gid_ix(dev, slave) | 0x80;
612255932Salfred		else
613255932Salfred			qp_ctx->pri_path.mgid_index = 0x80 | slave;
614255932Salfred
615255932Salfred	} else if (MLX4_QP_ST_RC == ts || MLX4_QP_ST_UC == ts) {
616255932Salfred		if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH) {
617255932Salfred			port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
618255932Salfred			if (mlx4_is_eth(dev, port)) {
619255932Salfred				qp_ctx->pri_path.mgid_index += mlx4_get_base_gid_ix(dev, slave);
620255932Salfred				qp_ctx->pri_path.mgid_index &= 0x7f;
621255932Salfred			} else {
622255932Salfred				qp_ctx->pri_path.mgid_index = slave & 0x7F;
623255932Salfred			}
624255932Salfred		}
625255932Salfred		if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) {
626255932Salfred			port = (qp_ctx->alt_path.sched_queue >> 6 & 1) + 1;
627255932Salfred			if (mlx4_is_eth(dev, port)) {
628255932Salfred				qp_ctx->alt_path.mgid_index += mlx4_get_base_gid_ix(dev, slave);
629255932Salfred				qp_ctx->alt_path.mgid_index &= 0x7f;
630255932Salfred			} else {
631255932Salfred				qp_ctx->alt_path.mgid_index = slave & 0x7F;
632255932Salfred			}
633255932Salfred		}
634255932Salfred	}
635255932Salfred}
636255932Salfred
637272027Shselaskystatic int check_counter_index_validity(struct mlx4_dev *dev, int slave, int port, int idx)
638272027Shselasky{
639272027Shselasky	struct mlx4_priv *priv = mlx4_priv(dev);
640272027Shselasky	struct counter_index *counter, *tmp_counter;
641272027Shselasky
642272027Shselasky	if (slave == 0) {
643272027Shselasky		list_for_each_entry_safe(counter, tmp_counter,
644272027Shselasky					 &priv->counters_table.global_port_list[port - 1],
645272027Shselasky					 list) {
646272027Shselasky			if (counter->index == idx)
647272027Shselasky				return 0;
648272027Shselasky		}
649272027Shselasky		return -EINVAL;
650272027Shselasky	} else {
651272027Shselasky		list_for_each_entry_safe(counter, tmp_counter,
652272027Shselasky					 &priv->counters_table.vf_list[slave - 1][port - 1],
653272027Shselasky					 list) {
654272027Shselasky			if (counter->index == idx)
655272027Shselasky				return 0;
656272027Shselasky		}
657272027Shselasky		return -EINVAL;
658272027Shselasky	}
659272027Shselasky}
660272027Shselasky
661255932Salfredstatic int update_vport_qp_param(struct mlx4_dev *dev,
662255932Salfred				 struct mlx4_cmd_mailbox *inbox,
663272027Shselasky				 u8 slave, u32 qpn)
664255932Salfred{
665255932Salfred	struct mlx4_qp_context	*qpc = inbox->buf + 8;
666255932Salfred	struct mlx4_vport_oper_state *vp_oper;
667255932Salfred	struct mlx4_priv *priv;
668255932Salfred	u32 qp_type;
669255932Salfred	int port;
670255932Salfred
671255932Salfred	port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1;
672255932Salfred	priv = mlx4_priv(dev);
673255932Salfred	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
674272027Shselasky	qp_type	= (be32_to_cpu(qpc->flags) >> 16) & 0xff;
675255932Salfred
676272027Shselasky	if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH &&
677272027Shselasky	    qpc->pri_path.counter_index != MLX4_SINK_COUNTER_INDEX) {
678272027Shselasky		if (check_counter_index_validity(dev, slave, port,
679272027Shselasky						 qpc->pri_path.counter_index))
680255932Salfred			return -EINVAL;
681272027Shselasky	}
682255932Salfred
683272027Shselasky	mlx4_dbg(dev, "%s: QP counter_index %d for slave %d port %d\n",
684272027Shselasky		 __func__, qpc->pri_path.counter_index, slave, port);
685272027Shselasky
686272027Shselasky	if ((dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) &&
687272027Shselasky	    dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH &&
688272027Shselasky	    !mlx4_is_qp_reserved(dev, qpn) &&
689272027Shselasky	    qp_type == MLX4_QP_ST_MLX &&
690272027Shselasky	    qpc->pri_path.counter_index != 0xFF) {
691272027Shselasky		/* disable multicast loopback to qp with same counter */
692272027Shselasky		qpc->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
693272027Shselasky		qpc->pri_path.vlan_control |=
694272027Shselasky			MLX4_VLAN_CTRL_ETH_SRC_CHECK_IF_COUNTER;
695272027Shselasky	}
696272027Shselasky
697272027Shselasky	if (MLX4_VGT != vp_oper->state.default_vlan) {
698272027Shselasky		/* the reserved QPs (special, proxy, tunnel)
699272027Shselasky		 * do not operate over vlans
700272027Shselasky		 */
701272027Shselasky		if (mlx4_is_qp_reserved(dev, qpn))
702272027Shselasky			return 0;
703272027Shselasky
704272027Shselasky		/* force strip vlan by clear vsd */
705272027Shselasky		qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);
706272027Shselasky		/* preserve IF_COUNTER flag */
707272027Shselasky		qpc->pri_path.vlan_control &=
708272027Shselasky			MLX4_VLAN_CTRL_ETH_SRC_CHECK_IF_COUNTER;
709272027Shselasky		if (MLX4_QP_ST_RC != qp_type) {
710272027Shselasky			if (0 != vp_oper->state.default_vlan) {
711272027Shselasky				qpc->pri_path.vlan_control |=
712272027Shselasky					MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
713272027Shselasky					MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
714272027Shselasky					MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
715272027Shselasky			} else { /* priority tagged */
716272027Shselasky				qpc->pri_path.vlan_control |=
717272027Shselasky					MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
718272027Shselasky					MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
719272027Shselasky			}
720272027Shselasky		}
721272027Shselasky		qpc->pri_path.fvl_rx |= MLX4_FVL_RX_FORCE_ETH_VLAN;
722255932Salfred		qpc->pri_path.vlan_index = vp_oper->vlan_idx;
723272027Shselasky		qpc->pri_path.fl |= MLX4_FL_CV | MLX4_FL_ETH_HIDE_CQE_VLAN;
724272027Shselasky		qpc->pri_path.feup |= MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN;
725255932Salfred		qpc->pri_path.sched_queue &= 0xC7;
726255932Salfred		qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3;
727255932Salfred	}
728255932Salfred	if (vp_oper->state.spoofchk) {
729272027Shselasky		qpc->pri_path.feup |= MLX4_FSM_FORCE_ETH_SRC_MAC;
730255932Salfred		qpc->pri_path.grh_mylmc = (0x80 & qpc->pri_path.grh_mylmc) + vp_oper->mac_idx;
731255932Salfred	}
732255932Salfred	return 0;
733255932Salfred}
734255932Salfred
735255932Salfredstatic int mpt_mask(struct mlx4_dev *dev)
736255932Salfred{
737255932Salfred	return dev->caps.num_mpts - 1;
738255932Salfred}
739255932Salfred
740272027Shselaskystatic void *find_res(struct mlx4_dev *dev, u64 res_id,
741255932Salfred		      enum mlx4_resource type)
742255932Salfred{
743255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
744255932Salfred
745255932Salfred	return res_tracker_lookup(&priv->mfunc.master.res_tracker.res_tree[type],
746255932Salfred				  res_id);
747255932Salfred}
748255932Salfred
749255932Salfredstatic int get_res(struct mlx4_dev *dev, int slave, u64 res_id,
750255932Salfred		   enum mlx4_resource type,
751255932Salfred		   void *res)
752255932Salfred{
753255932Salfred	struct res_common *r;
754255932Salfred	int err = 0;
755255932Salfred
756255932Salfred	spin_lock_irq(mlx4_tlock(dev));
757255932Salfred	r = find_res(dev, res_id, type);
758255932Salfred	if (!r) {
759272027Shselasky		err = -ENONET;
760255932Salfred		goto exit;
761255932Salfred	}
762255932Salfred
763255932Salfred	if (r->state == RES_ANY_BUSY) {
764255932Salfred		err = -EBUSY;
765255932Salfred		goto exit;
766255932Salfred	}
767255932Salfred
768255932Salfred	if (r->owner != slave) {
769255932Salfred		err = -EPERM;
770255932Salfred		goto exit;
771255932Salfred	}
772255932Salfred
773255932Salfred	r->from_state = r->state;
774255932Salfred	r->state = RES_ANY_BUSY;
775255932Salfred
776255932Salfred	if (res)
777255932Salfred		*((struct res_common **)res) = r;
778255932Salfred
779255932Salfredexit:
780255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
781255932Salfred	return err;
782255932Salfred}
783255932Salfred
784255932Salfredint mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,
785255932Salfred				    enum mlx4_resource type,
786255932Salfred				    u64 res_id, int *slave)
787255932Salfred{
788255932Salfred
789255932Salfred	struct res_common *r;
790255932Salfred	int err = -ENOENT;
791255932Salfred	int id = res_id;
792255932Salfred
793255932Salfred	if (type == RES_QP)
794255932Salfred		id &= 0x7fffff;
795255932Salfred	spin_lock(mlx4_tlock(dev));
796255932Salfred
797255932Salfred	r = find_res(dev, id, type);
798255932Salfred	if (r) {
799255932Salfred		*slave = r->owner;
800255932Salfred		err = 0;
801255932Salfred	}
802255932Salfred	spin_unlock(mlx4_tlock(dev));
803255932Salfred
804255932Salfred	return err;
805255932Salfred}
806255932Salfred
807255932Salfredstatic void put_res(struct mlx4_dev *dev, int slave, u64 res_id,
808255932Salfred		    enum mlx4_resource type)
809255932Salfred{
810255932Salfred	struct res_common *r;
811255932Salfred
812255932Salfred	spin_lock_irq(mlx4_tlock(dev));
813255932Salfred	r = find_res(dev, res_id, type);
814255932Salfred	if (r)
815255932Salfred		r->state = r->from_state;
816255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
817255932Salfred}
818255932Salfred
819255932Salfredstatic struct res_common *alloc_qp_tr(int id)
820255932Salfred{
821255932Salfred	struct res_qp *ret;
822255932Salfred
823255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
824255932Salfred	if (!ret)
825255932Salfred		return NULL;
826255932Salfred
827255932Salfred	ret->com.res_id = id;
828255932Salfred	ret->com.state = RES_QP_RESERVED;
829255932Salfred	ret->local_qpn = id;
830255932Salfred	INIT_LIST_HEAD(&ret->mcg_list);
831255932Salfred	spin_lock_init(&ret->mcg_spl);
832272027Shselasky	atomic_set(&ret->ref_count, 0);
833255932Salfred
834255932Salfred	return &ret->com;
835255932Salfred}
836255932Salfred
837255932Salfredstatic struct res_common *alloc_mtt_tr(int id, int order)
838255932Salfred{
839255932Salfred	struct res_mtt *ret;
840255932Salfred
841255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
842255932Salfred	if (!ret)
843255932Salfred		return NULL;
844255932Salfred
845255932Salfred	ret->com.res_id = id;
846255932Salfred	ret->order = order;
847255932Salfred	ret->com.state = RES_MTT_ALLOCATED;
848255932Salfred	atomic_set(&ret->ref_count, 0);
849255932Salfred
850255932Salfred	return &ret->com;
851255932Salfred}
852255932Salfred
853255932Salfredstatic struct res_common *alloc_mpt_tr(int id, int key)
854255932Salfred{
855255932Salfred	struct res_mpt *ret;
856255932Salfred
857255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
858255932Salfred	if (!ret)
859255932Salfred		return NULL;
860255932Salfred
861255932Salfred	ret->com.res_id = id;
862255932Salfred	ret->com.state = RES_MPT_RESERVED;
863255932Salfred	ret->key = key;
864255932Salfred
865255932Salfred	return &ret->com;
866255932Salfred}
867255932Salfred
868255932Salfredstatic struct res_common *alloc_eq_tr(int id)
869255932Salfred{
870255932Salfred	struct res_eq *ret;
871255932Salfred
872255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
873255932Salfred	if (!ret)
874255932Salfred		return NULL;
875255932Salfred
876255932Salfred	ret->com.res_id = id;
877255932Salfred	ret->com.state = RES_EQ_RESERVED;
878255932Salfred
879255932Salfred	return &ret->com;
880255932Salfred}
881255932Salfred
882255932Salfredstatic struct res_common *alloc_cq_tr(int id)
883255932Salfred{
884255932Salfred	struct res_cq *ret;
885255932Salfred
886255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
887255932Salfred	if (!ret)
888255932Salfred		return NULL;
889255932Salfred
890255932Salfred	ret->com.res_id = id;
891255932Salfred	ret->com.state = RES_CQ_ALLOCATED;
892255932Salfred	atomic_set(&ret->ref_count, 0);
893255932Salfred
894255932Salfred	return &ret->com;
895255932Salfred}
896255932Salfred
897255932Salfredstatic struct res_common *alloc_srq_tr(int id)
898255932Salfred{
899255932Salfred	struct res_srq *ret;
900255932Salfred
901255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
902255932Salfred	if (!ret)
903255932Salfred		return NULL;
904255932Salfred
905255932Salfred	ret->com.res_id = id;
906255932Salfred	ret->com.state = RES_SRQ_ALLOCATED;
907255932Salfred	atomic_set(&ret->ref_count, 0);
908255932Salfred
909255932Salfred	return &ret->com;
910255932Salfred}
911255932Salfred
912255932Salfredstatic struct res_common *alloc_counter_tr(int id)
913255932Salfred{
914255932Salfred	struct res_counter *ret;
915255932Salfred
916255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
917255932Salfred	if (!ret)
918255932Salfred		return NULL;
919255932Salfred
920255932Salfred	ret->com.res_id = id;
921255932Salfred	ret->com.state = RES_COUNTER_ALLOCATED;
922255932Salfred
923255932Salfred	return &ret->com;
924255932Salfred}
925255932Salfred
926255932Salfredstatic struct res_common *alloc_xrcdn_tr(int id)
927255932Salfred{
928255932Salfred	struct res_xrcdn *ret;
929255932Salfred
930255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
931255932Salfred	if (!ret)
932255932Salfred		return NULL;
933255932Salfred
934255932Salfred	ret->com.res_id = id;
935255932Salfred	ret->com.state = RES_XRCD_ALLOCATED;
936255932Salfred
937255932Salfred	return &ret->com;
938255932Salfred}
939255932Salfred
940272027Shselaskystatic struct res_common *alloc_fs_rule_tr(u64 id, int qpn)
941255932Salfred{
942255932Salfred	struct res_fs_rule *ret;
943255932Salfred
944255932Salfred	ret = kzalloc(sizeof *ret, GFP_KERNEL);
945255932Salfred	if (!ret)
946255932Salfred		return NULL;
947255932Salfred
948255932Salfred	ret->com.res_id = id;
949255932Salfred	ret->com.state = RES_FS_RULE_ALLOCATED;
950272027Shselasky	ret->qpn = qpn;
951255932Salfred	return &ret->com;
952255932Salfred}
953255932Salfred
954255932Salfredstatic struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave,
955255932Salfred				   int extra)
956255932Salfred{
957255932Salfred	struct res_common *ret;
958255932Salfred
959255932Salfred	switch (type) {
960255932Salfred	case RES_QP:
961255932Salfred		ret = alloc_qp_tr(id);
962255932Salfred		break;
963255932Salfred	case RES_MPT:
964255932Salfred		ret = alloc_mpt_tr(id, extra);
965255932Salfred		break;
966255932Salfred	case RES_MTT:
967255932Salfred		ret = alloc_mtt_tr(id, extra);
968255932Salfred		break;
969255932Salfred	case RES_EQ:
970255932Salfred		ret = alloc_eq_tr(id);
971255932Salfred		break;
972255932Salfred	case RES_CQ:
973255932Salfred		ret = alloc_cq_tr(id);
974255932Salfred		break;
975255932Salfred	case RES_SRQ:
976255932Salfred		ret = alloc_srq_tr(id);
977255932Salfred		break;
978255932Salfred	case RES_MAC:
979255932Salfred		printk(KERN_ERR "implementation missing\n");
980255932Salfred		return NULL;
981255932Salfred	case RES_COUNTER:
982255932Salfred		ret = alloc_counter_tr(id);
983255932Salfred		break;
984255932Salfred	case RES_XRCD:
985255932Salfred		ret = alloc_xrcdn_tr(id);
986255932Salfred		break;
987255932Salfred	case RES_FS_RULE:
988272027Shselasky		ret = alloc_fs_rule_tr(id, extra);
989255932Salfred		break;
990255932Salfred	default:
991255932Salfred		return NULL;
992255932Salfred	}
993255932Salfred	if (ret)
994255932Salfred		ret->owner = slave;
995255932Salfred
996255932Salfred	return ret;
997255932Salfred}
998255932Salfred
999255932Salfredstatic int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
1000255932Salfred			 enum mlx4_resource type, int extra)
1001255932Salfred{
1002255932Salfred	int i;
1003255932Salfred	int err;
1004255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1005255932Salfred	struct res_common **res_arr;
1006255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1007255932Salfred	struct rb_root *root = &tracker->res_tree[type];
1008255932Salfred
1009255932Salfred	res_arr = kzalloc(count * sizeof *res_arr, GFP_KERNEL);
1010255932Salfred	if (!res_arr)
1011255932Salfred		return -ENOMEM;
1012255932Salfred
1013255932Salfred	for (i = 0; i < count; ++i) {
1014255932Salfred		res_arr[i] = alloc_tr(base + i, type, slave, extra);
1015255932Salfred		if (!res_arr[i]) {
1016255932Salfred			for (--i; i >= 0; --i)
1017255932Salfred				kfree(res_arr[i]);
1018255932Salfred
1019255932Salfred			kfree(res_arr);
1020255932Salfred			return -ENOMEM;
1021255932Salfred		}
1022255932Salfred	}
1023255932Salfred
1024255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1025255932Salfred	for (i = 0; i < count; ++i) {
1026255932Salfred		if (find_res(dev, base + i, type)) {
1027255932Salfred			err = -EEXIST;
1028255932Salfred			goto undo;
1029255932Salfred		}
1030255932Salfred		err = res_tracker_insert(root, res_arr[i]);
1031255932Salfred		if (err)
1032255932Salfred			goto undo;
1033255932Salfred		list_add_tail(&res_arr[i]->list,
1034255932Salfred			      &tracker->slave_list[slave].res_list[type]);
1035255932Salfred	}
1036255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1037255932Salfred	kfree(res_arr);
1038255932Salfred
1039255932Salfred	return 0;
1040255932Salfred
1041255932Salfredundo:
1042272027Shselasky	for (--i; i >= 0; --i) {
1043255932Salfred		rb_erase(&res_arr[i]->node, root);
1044272027Shselasky		list_del_init(&res_arr[i]->list);
1045272027Shselasky	}
1046255932Salfred
1047255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1048255932Salfred
1049255932Salfred	for (i = 0; i < count; ++i)
1050255932Salfred		kfree(res_arr[i]);
1051255932Salfred
1052255932Salfred	kfree(res_arr);
1053255932Salfred
1054255932Salfred	return err;
1055255932Salfred}
1056255932Salfred
1057255932Salfredstatic int remove_qp_ok(struct res_qp *res)
1058255932Salfred{
1059272027Shselasky	if (res->com.state == RES_QP_BUSY || atomic_read(&res->ref_count) ||
1060272027Shselasky	    !list_empty(&res->mcg_list)) {
1061272027Shselasky		pr_err("resource tracker: fail to remove qp, state %d, ref_count %d\n",
1062272027Shselasky		       res->com.state, atomic_read(&res->ref_count));
1063255932Salfred		return -EBUSY;
1064272027Shselasky	} else if (res->com.state != RES_QP_RESERVED) {
1065255932Salfred		return -EPERM;
1066272027Shselasky	}
1067255932Salfred
1068255932Salfred	return 0;
1069255932Salfred}
1070255932Salfred
1071255932Salfredstatic int remove_mtt_ok(struct res_mtt *res, int order)
1072255932Salfred{
1073255932Salfred	if (res->com.state == RES_MTT_BUSY ||
1074255932Salfred	    atomic_read(&res->ref_count)) {
1075255932Salfred		printk(KERN_DEBUG "%s-%d: state %s, ref_count %d\n",
1076255932Salfred		       __func__, __LINE__,
1077255932Salfred		       mtt_states_str(res->com.state),
1078255932Salfred		       atomic_read(&res->ref_count));
1079255932Salfred		return -EBUSY;
1080255932Salfred	} else if (res->com.state != RES_MTT_ALLOCATED)
1081255932Salfred		return -EPERM;
1082255932Salfred	else if (res->order != order)
1083255932Salfred		return -EINVAL;
1084255932Salfred
1085255932Salfred	return 0;
1086255932Salfred}
1087255932Salfred
1088255932Salfredstatic int remove_mpt_ok(struct res_mpt *res)
1089255932Salfred{
1090255932Salfred	if (res->com.state == RES_MPT_BUSY)
1091255932Salfred		return -EBUSY;
1092255932Salfred	else if (res->com.state != RES_MPT_RESERVED)
1093255932Salfred		return -EPERM;
1094255932Salfred
1095255932Salfred	return 0;
1096255932Salfred}
1097255932Salfred
1098255932Salfredstatic int remove_eq_ok(struct res_eq *res)
1099255932Salfred{
1100255932Salfred	if (res->com.state == RES_MPT_BUSY)
1101255932Salfred		return -EBUSY;
1102255932Salfred	else if (res->com.state != RES_MPT_RESERVED)
1103255932Salfred		return -EPERM;
1104255932Salfred
1105255932Salfred	return 0;
1106255932Salfred}
1107255932Salfred
1108255932Salfredstatic int remove_counter_ok(struct res_counter *res)
1109255932Salfred{
1110255932Salfred	if (res->com.state == RES_COUNTER_BUSY)
1111255932Salfred		return -EBUSY;
1112255932Salfred	else if (res->com.state != RES_COUNTER_ALLOCATED)
1113255932Salfred		return -EPERM;
1114255932Salfred
1115255932Salfred	return 0;
1116255932Salfred}
1117255932Salfred
1118255932Salfredstatic int remove_xrcdn_ok(struct res_xrcdn *res)
1119255932Salfred{
1120255932Salfred	if (res->com.state == RES_XRCD_BUSY)
1121255932Salfred		return -EBUSY;
1122255932Salfred	else if (res->com.state != RES_XRCD_ALLOCATED)
1123255932Salfred		return -EPERM;
1124255932Salfred
1125255932Salfred	return 0;
1126255932Salfred}
1127255932Salfred
1128255932Salfredstatic int remove_fs_rule_ok(struct res_fs_rule *res)
1129255932Salfred{
1130255932Salfred	if (res->com.state == RES_FS_RULE_BUSY)
1131255932Salfred		return -EBUSY;
1132255932Salfred	else if (res->com.state != RES_FS_RULE_ALLOCATED)
1133255932Salfred		return -EPERM;
1134255932Salfred
1135255932Salfred	return 0;
1136255932Salfred}
1137255932Salfred
1138255932Salfredstatic int remove_cq_ok(struct res_cq *res)
1139255932Salfred{
1140255932Salfred	if (res->com.state == RES_CQ_BUSY)
1141255932Salfred		return -EBUSY;
1142255932Salfred	else if (res->com.state != RES_CQ_ALLOCATED)
1143255932Salfred		return -EPERM;
1144255932Salfred
1145255932Salfred	return 0;
1146255932Salfred}
1147255932Salfred
1148255932Salfredstatic int remove_srq_ok(struct res_srq *res)
1149255932Salfred{
1150255932Salfred	if (res->com.state == RES_SRQ_BUSY)
1151255932Salfred		return -EBUSY;
1152255932Salfred	else if (res->com.state != RES_SRQ_ALLOCATED)
1153255932Salfred		return -EPERM;
1154255932Salfred
1155255932Salfred	return 0;
1156255932Salfred}
1157255932Salfred
1158255932Salfredstatic int remove_ok(struct res_common *res, enum mlx4_resource type, int extra)
1159255932Salfred{
1160255932Salfred	switch (type) {
1161255932Salfred	case RES_QP:
1162255932Salfred		return remove_qp_ok((struct res_qp *)res);
1163255932Salfred	case RES_CQ:
1164255932Salfred		return remove_cq_ok((struct res_cq *)res);
1165255932Salfred	case RES_SRQ:
1166255932Salfred		return remove_srq_ok((struct res_srq *)res);
1167255932Salfred	case RES_MPT:
1168255932Salfred		return remove_mpt_ok((struct res_mpt *)res);
1169255932Salfred	case RES_MTT:
1170255932Salfred		return remove_mtt_ok((struct res_mtt *)res, extra);
1171255932Salfred	case RES_MAC:
1172255932Salfred		return -ENOSYS;
1173255932Salfred	case RES_EQ:
1174255932Salfred		return remove_eq_ok((struct res_eq *)res);
1175255932Salfred	case RES_COUNTER:
1176255932Salfred		return remove_counter_ok((struct res_counter *)res);
1177255932Salfred	case RES_XRCD:
1178255932Salfred		return remove_xrcdn_ok((struct res_xrcdn *)res);
1179255932Salfred	case RES_FS_RULE:
1180255932Salfred		return remove_fs_rule_ok((struct res_fs_rule *)res);
1181255932Salfred	default:
1182255932Salfred		return -EINVAL;
1183255932Salfred	}
1184255932Salfred}
1185255932Salfred
1186255932Salfredstatic int rem_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
1187255932Salfred			 enum mlx4_resource type, int extra)
1188255932Salfred{
1189255932Salfred	u64 i;
1190255932Salfred	int err;
1191255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1192255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1193255932Salfred	struct res_common *r;
1194255932Salfred
1195255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1196255932Salfred	for (i = base; i < base + count; ++i) {
1197255932Salfred		r = res_tracker_lookup(&tracker->res_tree[type], i);
1198255932Salfred		if (!r) {
1199255932Salfred			err = -ENOENT;
1200255932Salfred			goto out;
1201255932Salfred		}
1202255932Salfred		if (r->owner != slave) {
1203255932Salfred			err = -EPERM;
1204255932Salfred			goto out;
1205255932Salfred		}
1206255932Salfred		err = remove_ok(r, type, extra);
1207255932Salfred		if (err)
1208255932Salfred			goto out;
1209255932Salfred	}
1210255932Salfred
1211255932Salfred	for (i = base; i < base + count; ++i) {
1212255932Salfred		r = res_tracker_lookup(&tracker->res_tree[type], i);
1213255932Salfred		rb_erase(&r->node, &tracker->res_tree[type]);
1214255932Salfred		list_del(&r->list);
1215255932Salfred		kfree(r);
1216255932Salfred	}
1217255932Salfred	err = 0;
1218255932Salfred
1219255932Salfredout:
1220255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1221255932Salfred
1222255932Salfred	return err;
1223255932Salfred}
1224255932Salfred
1225255932Salfredstatic int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn,
1226255932Salfred				enum res_qp_states state, struct res_qp **qp,
1227255932Salfred				int alloc)
1228255932Salfred{
1229255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1230255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1231255932Salfred	struct res_qp *r;
1232255932Salfred	int err = 0;
1233255932Salfred
1234255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1235255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_QP], qpn);
1236255932Salfred	if (!r)
1237255932Salfred		err = -ENOENT;
1238255932Salfred	else if (r->com.owner != slave)
1239255932Salfred		err = -EPERM;
1240255932Salfred	else {
1241255932Salfred		switch (state) {
1242255932Salfred		case RES_QP_BUSY:
1243255932Salfred			mlx4_dbg(dev, "%s: failed RES_QP, 0x%llx\n",
1244272027Shselasky				 __func__, (unsigned long long)r->com.res_id);
1245255932Salfred			err = -EBUSY;
1246255932Salfred			break;
1247255932Salfred
1248255932Salfred		case RES_QP_RESERVED:
1249255932Salfred			if (r->com.state == RES_QP_MAPPED && !alloc)
1250255932Salfred				break;
1251255932Salfred
1252272027Shselasky			mlx4_dbg(dev, "failed RES_QP, 0x%llx\n", (unsigned long long)r->com.res_id);
1253255932Salfred			err = -EINVAL;
1254255932Salfred			break;
1255255932Salfred
1256255932Salfred		case RES_QP_MAPPED:
1257255932Salfred			if ((r->com.state == RES_QP_RESERVED && alloc) ||
1258255932Salfred			    r->com.state == RES_QP_HW)
1259255932Salfred				break;
1260255932Salfred			else {
1261255932Salfred				mlx4_dbg(dev, "failed RES_QP, 0x%llx\n",
1262272027Shselasky					  (unsigned long long)r->com.res_id);
1263255932Salfred				err = -EINVAL;
1264255932Salfred			}
1265255932Salfred
1266255932Salfred			break;
1267255932Salfred
1268255932Salfred		case RES_QP_HW:
1269255932Salfred			if (r->com.state != RES_QP_MAPPED)
1270255932Salfred				err = -EINVAL;
1271255932Salfred			break;
1272255932Salfred		default:
1273255932Salfred			err = -EINVAL;
1274255932Salfred		}
1275255932Salfred
1276255932Salfred		if (!err) {
1277255932Salfred			r->com.from_state = r->com.state;
1278255932Salfred			r->com.to_state = state;
1279255932Salfred			r->com.state = RES_QP_BUSY;
1280255932Salfred			if (qp)
1281255932Salfred				*qp = r;
1282255932Salfred		}
1283255932Salfred	}
1284255932Salfred
1285255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1286255932Salfred
1287255932Salfred	return err;
1288255932Salfred}
1289255932Salfred
1290255932Salfredstatic int mr_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
1291255932Salfred				enum res_mpt_states state, struct res_mpt **mpt)
1292255932Salfred{
1293255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1294255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1295255932Salfred	struct res_mpt *r;
1296255932Salfred	int err = 0;
1297255932Salfred
1298255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1299255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_MPT], index);
1300255932Salfred	if (!r)
1301255932Salfred		err = -ENOENT;
1302255932Salfred	else if (r->com.owner != slave)
1303255932Salfred		err = -EPERM;
1304255932Salfred	else {
1305255932Salfred		switch (state) {
1306255932Salfred		case RES_MPT_BUSY:
1307255932Salfred			err = -EINVAL;
1308255932Salfred			break;
1309255932Salfred
1310255932Salfred		case RES_MPT_RESERVED:
1311255932Salfred			if (r->com.state != RES_MPT_MAPPED)
1312255932Salfred				err = -EINVAL;
1313255932Salfred			break;
1314255932Salfred
1315255932Salfred		case RES_MPT_MAPPED:
1316255932Salfred			if (r->com.state != RES_MPT_RESERVED &&
1317255932Salfred			    r->com.state != RES_MPT_HW)
1318255932Salfred				err = -EINVAL;
1319255932Salfred			break;
1320255932Salfred
1321255932Salfred		case RES_MPT_HW:
1322255932Salfred			if (r->com.state != RES_MPT_MAPPED)
1323255932Salfred				err = -EINVAL;
1324255932Salfred			break;
1325255932Salfred		default:
1326255932Salfred			err = -EINVAL;
1327255932Salfred		}
1328255932Salfred
1329255932Salfred		if (!err) {
1330255932Salfred			r->com.from_state = r->com.state;
1331255932Salfred			r->com.to_state = state;
1332255932Salfred			r->com.state = RES_MPT_BUSY;
1333255932Salfred			if (mpt)
1334255932Salfred				*mpt = r;
1335255932Salfred		}
1336255932Salfred	}
1337255932Salfred
1338255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1339255932Salfred
1340255932Salfred	return err;
1341255932Salfred}
1342255932Salfred
1343255932Salfredstatic int eq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
1344255932Salfred				enum res_eq_states state, struct res_eq **eq)
1345255932Salfred{
1346255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1347255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1348255932Salfred	struct res_eq *r;
1349255932Salfred	int err = 0;
1350255932Salfred
1351255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1352255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_EQ], index);
1353255932Salfred	if (!r)
1354255932Salfred		err = -ENOENT;
1355255932Salfred	else if (r->com.owner != slave)
1356255932Salfred		err = -EPERM;
1357255932Salfred	else {
1358255932Salfred		switch (state) {
1359255932Salfred		case RES_EQ_BUSY:
1360255932Salfred			err = -EINVAL;
1361255932Salfred			break;
1362255932Salfred
1363255932Salfred		case RES_EQ_RESERVED:
1364255932Salfred			if (r->com.state != RES_EQ_HW)
1365255932Salfred				err = -EINVAL;
1366255932Salfred			break;
1367255932Salfred
1368255932Salfred		case RES_EQ_HW:
1369255932Salfred			if (r->com.state != RES_EQ_RESERVED)
1370255932Salfred				err = -EINVAL;
1371255932Salfred			break;
1372255932Salfred
1373255932Salfred		default:
1374255932Salfred			err = -EINVAL;
1375255932Salfred		}
1376255932Salfred
1377255932Salfred		if (!err) {
1378255932Salfred			r->com.from_state = r->com.state;
1379255932Salfred			r->com.to_state = state;
1380255932Salfred			r->com.state = RES_EQ_BUSY;
1381255932Salfred			if (eq)
1382255932Salfred				*eq = r;
1383255932Salfred		}
1384255932Salfred	}
1385255932Salfred
1386255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1387255932Salfred
1388255932Salfred	return err;
1389255932Salfred}
1390255932Salfred
1391255932Salfredstatic int cq_res_start_move_to(struct mlx4_dev *dev, int slave, int cqn,
1392255932Salfred				enum res_cq_states state, struct res_cq **cq)
1393255932Salfred{
1394255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1395255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1396255932Salfred	struct res_cq *r;
1397255932Salfred	int err;
1398255932Salfred
1399255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1400255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_CQ], cqn);
1401255932Salfred	if (!r)
1402255932Salfred		err = -ENOENT;
1403255932Salfred	else if (r->com.owner != slave)
1404255932Salfred		err = -EPERM;
1405255932Salfred	else {
1406255932Salfred		switch (state) {
1407255932Salfred		case RES_CQ_BUSY:
1408255932Salfred			err = -EBUSY;
1409255932Salfred			break;
1410255932Salfred
1411255932Salfred		case RES_CQ_ALLOCATED:
1412255932Salfred			if (r->com.state != RES_CQ_HW)
1413255932Salfred				err = -EINVAL;
1414255932Salfred			else if (atomic_read(&r->ref_count))
1415255932Salfred				err = -EBUSY;
1416255932Salfred			else
1417255932Salfred				err = 0;
1418255932Salfred			break;
1419255932Salfred
1420255932Salfred		case RES_CQ_HW:
1421255932Salfred			if (r->com.state != RES_CQ_ALLOCATED)
1422255932Salfred				err = -EINVAL;
1423255932Salfred			else
1424255932Salfred				err = 0;
1425255932Salfred			break;
1426255932Salfred
1427255932Salfred		default:
1428255932Salfred			err = -EINVAL;
1429255932Salfred		}
1430255932Salfred
1431255932Salfred		if (!err) {
1432255932Salfred			r->com.from_state = r->com.state;
1433255932Salfred			r->com.to_state = state;
1434255932Salfred			r->com.state = RES_CQ_BUSY;
1435255932Salfred			if (cq)
1436255932Salfred				*cq = r;
1437255932Salfred		}
1438255932Salfred	}
1439255932Salfred
1440255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1441255932Salfred
1442255932Salfred	return err;
1443255932Salfred}
1444255932Salfred
1445255932Salfredstatic int srq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
1446255932Salfred				 enum res_srq_states state, struct res_srq **srq)
1447255932Salfred{
1448255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1449255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1450255932Salfred	struct res_srq *r;
1451255932Salfred	int err = 0;
1452255932Salfred
1453255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1454255932Salfred	r = res_tracker_lookup(&tracker->res_tree[RES_SRQ], index);
1455255932Salfred	if (!r)
1456255932Salfred		err = -ENOENT;
1457255932Salfred	else if (r->com.owner != slave)
1458255932Salfred		err = -EPERM;
1459255932Salfred	else {
1460255932Salfred		switch (state) {
1461255932Salfred		case RES_SRQ_BUSY:
1462255932Salfred			err = -EINVAL;
1463255932Salfred			break;
1464255932Salfred
1465255932Salfred		case RES_SRQ_ALLOCATED:
1466255932Salfred			if (r->com.state != RES_SRQ_HW)
1467255932Salfred				err = -EINVAL;
1468255932Salfred			else if (atomic_read(&r->ref_count))
1469255932Salfred				err = -EBUSY;
1470255932Salfred			break;
1471255932Salfred
1472255932Salfred		case RES_SRQ_HW:
1473255932Salfred			if (r->com.state != RES_SRQ_ALLOCATED)
1474255932Salfred				err = -EINVAL;
1475255932Salfred			break;
1476255932Salfred
1477255932Salfred		default:
1478255932Salfred			err = -EINVAL;
1479255932Salfred		}
1480255932Salfred
1481255932Salfred		if (!err) {
1482255932Salfred			r->com.from_state = r->com.state;
1483255932Salfred			r->com.to_state = state;
1484255932Salfred			r->com.state = RES_SRQ_BUSY;
1485255932Salfred			if (srq)
1486255932Salfred				*srq = r;
1487255932Salfred		}
1488255932Salfred	}
1489255932Salfred
1490255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1491255932Salfred
1492255932Salfred	return err;
1493255932Salfred}
1494255932Salfred
1495255932Salfredstatic void res_abort_move(struct mlx4_dev *dev, int slave,
1496255932Salfred			   enum mlx4_resource type, int id)
1497255932Salfred{
1498255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1499255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1500255932Salfred	struct res_common *r;
1501255932Salfred
1502255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1503255932Salfred	r = res_tracker_lookup(&tracker->res_tree[type], id);
1504255932Salfred	if (r && (r->owner == slave))
1505255932Salfred		r->state = r->from_state;
1506255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1507255932Salfred}
1508255932Salfred
1509255932Salfredstatic void res_end_move(struct mlx4_dev *dev, int slave,
1510255932Salfred			 enum mlx4_resource type, int id)
1511255932Salfred{
1512255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1513255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1514255932Salfred	struct res_common *r;
1515255932Salfred
1516255932Salfred	spin_lock_irq(mlx4_tlock(dev));
1517255932Salfred	r = res_tracker_lookup(&tracker->res_tree[type], id);
1518255932Salfred	if (r && (r->owner == slave))
1519255932Salfred		r->state = r->to_state;
1520255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
1521255932Salfred}
1522255932Salfred
1523255932Salfredstatic int valid_reserved(struct mlx4_dev *dev, int slave, int qpn)
1524255932Salfred{
1525255932Salfred	return mlx4_is_qp_reserved(dev, qpn) &&
1526255932Salfred		(mlx4_is_master(dev) || mlx4_is_guest_proxy(dev, slave, qpn));
1527255932Salfred}
1528255932Salfred
1529255932Salfredstatic int fw_reserved(struct mlx4_dev *dev, int qpn)
1530255932Salfred{
1531255932Salfred	return qpn < dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW];
1532255932Salfred}
1533255932Salfred
1534255932Salfredstatic int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1535255932Salfred			u64 in_param, u64 *out_param)
1536255932Salfred{
1537255932Salfred	int err;
1538255932Salfred	int count;
1539255932Salfred	int align;
1540255932Salfred	int base;
1541255932Salfred	int qpn;
1542272027Shselasky	u8 flags;
1543255932Salfred
1544255932Salfred	switch (op) {
1545255932Salfred	case RES_OP_RESERVE:
1546255932Salfred		count = get_param_l(&in_param) & 0xffffff;
1547272027Shselasky		flags = get_param_l(&in_param) >> 24;
1548255932Salfred		align = get_param_h(&in_param);
1549255932Salfred		err = mlx4_grant_resource(dev, slave, RES_QP, count, 0);
1550255932Salfred		if (err)
1551255932Salfred			return err;
1552255932Salfred
1553272027Shselasky		err = __mlx4_qp_reserve_range(dev, count, align, &base, flags);
1554255932Salfred		if (err) {
1555255932Salfred			mlx4_release_resource(dev, slave, RES_QP, count, 0);
1556255932Salfred			return err;
1557255932Salfred		}
1558255932Salfred
1559255932Salfred		err = add_res_range(dev, slave, base, count, RES_QP, 0);
1560255932Salfred		if (err) {
1561255932Salfred			mlx4_release_resource(dev, slave, RES_QP, count, 0);
1562255932Salfred			__mlx4_qp_release_range(dev, base, count);
1563255932Salfred			return err;
1564255932Salfred		}
1565255932Salfred		set_param_l(out_param, base);
1566255932Salfred		break;
1567255932Salfred	case RES_OP_MAP_ICM:
1568255932Salfred		qpn = get_param_l(&in_param) & 0x7fffff;
1569255932Salfred		if (valid_reserved(dev, slave, qpn)) {
1570255932Salfred			err = add_res_range(dev, slave, qpn, 1, RES_QP, 0);
1571255932Salfred			if (err)
1572255932Salfred				return err;
1573255932Salfred		}
1574255932Salfred
1575255932Salfred		err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED,
1576255932Salfred					   NULL, 1);
1577255932Salfred		if (err)
1578255932Salfred			return err;
1579255932Salfred
1580255932Salfred		if (!fw_reserved(dev, qpn)) {
1581255932Salfred			err = __mlx4_qp_alloc_icm(dev, qpn);
1582255932Salfred			if (err) {
1583255932Salfred				res_abort_move(dev, slave, RES_QP, qpn);
1584255932Salfred				return err;
1585255932Salfred			}
1586255932Salfred		}
1587255932Salfred
1588255932Salfred		res_end_move(dev, slave, RES_QP, qpn);
1589255932Salfred		break;
1590255932Salfred
1591255932Salfred	default:
1592255932Salfred		err = -EINVAL;
1593255932Salfred		break;
1594255932Salfred	}
1595255932Salfred	return err;
1596255932Salfred}
1597255932Salfred
1598255932Salfredstatic int mtt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1599255932Salfred			 u64 in_param, u64 *out_param)
1600255932Salfred{
1601255932Salfred	int err = -EINVAL;
1602255932Salfred	int base;
1603255932Salfred	int order;
1604255932Salfred
1605255932Salfred	if (op != RES_OP_RESERVE_AND_MAP)
1606255932Salfred		return err;
1607255932Salfred
1608255932Salfred	order = get_param_l(&in_param);
1609255932Salfred
1610255932Salfred	err = mlx4_grant_resource(dev, slave, RES_MTT, 1 << order, 0);
1611255932Salfred	if (err)
1612255932Salfred		return err;
1613255932Salfred
1614255932Salfred	base = __mlx4_alloc_mtt_range(dev, order);
1615255932Salfred	if (base == -1) {
1616255932Salfred		mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);
1617255932Salfred		return -ENOMEM;
1618255932Salfred	}
1619255932Salfred
1620255932Salfred	err = add_res_range(dev, slave, base, 1, RES_MTT, order);
1621255932Salfred	if (err) {
1622255932Salfred		mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);
1623255932Salfred		__mlx4_free_mtt_range(dev, base, order);
1624255932Salfred	} else
1625255932Salfred		set_param_l(out_param, base);
1626255932Salfred
1627255932Salfred	return err;
1628255932Salfred}
1629255932Salfred
1630255932Salfredstatic int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1631255932Salfred			 u64 in_param, u64 *out_param)
1632255932Salfred{
1633255932Salfred	int err = -EINVAL;
1634255932Salfred	int index;
1635255932Salfred	int id;
1636255932Salfred	struct res_mpt *mpt;
1637255932Salfred
1638255932Salfred	switch (op) {
1639255932Salfred	case RES_OP_RESERVE:
1640255932Salfred		err = mlx4_grant_resource(dev, slave, RES_MPT, 1, 0);
1641255932Salfred		if (err)
1642255932Salfred			break;
1643255932Salfred
1644272027Shselasky		index = __mlx4_mpt_reserve(dev);
1645255932Salfred		if (index == -1) {
1646255932Salfred			mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
1647255932Salfred			break;
1648255932Salfred		}
1649255932Salfred		id = index & mpt_mask(dev);
1650255932Salfred
1651255932Salfred		err = add_res_range(dev, slave, id, 1, RES_MPT, index);
1652255932Salfred		if (err) {
1653255932Salfred			mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
1654272027Shselasky			__mlx4_mpt_release(dev, index);
1655255932Salfred			break;
1656255932Salfred		}
1657255932Salfred		set_param_l(out_param, index);
1658255932Salfred		break;
1659255932Salfred	case RES_OP_MAP_ICM:
1660255932Salfred		index = get_param_l(&in_param);
1661255932Salfred		id = index & mpt_mask(dev);
1662255932Salfred		err = mr_res_start_move_to(dev, slave, id,
1663255932Salfred					   RES_MPT_MAPPED, &mpt);
1664255932Salfred		if (err)
1665255932Salfred			return err;
1666255932Salfred
1667272027Shselasky		err = __mlx4_mpt_alloc_icm(dev, mpt->key);
1668255932Salfred		if (err) {
1669255932Salfred			res_abort_move(dev, slave, RES_MPT, id);
1670255932Salfred			return err;
1671255932Salfred		}
1672255932Salfred
1673255932Salfred		res_end_move(dev, slave, RES_MPT, id);
1674255932Salfred		break;
1675255932Salfred	}
1676255932Salfred	return err;
1677255932Salfred}
1678255932Salfred
1679255932Salfredstatic int cq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1680255932Salfred			u64 in_param, u64 *out_param)
1681255932Salfred{
1682255932Salfred	int cqn;
1683255932Salfred	int err;
1684255932Salfred
1685255932Salfred	switch (op) {
1686255932Salfred	case RES_OP_RESERVE_AND_MAP:
1687255932Salfred		err = mlx4_grant_resource(dev, slave, RES_CQ, 1, 0);
1688255932Salfred		if (err)
1689255932Salfred			break;
1690255932Salfred
1691255932Salfred		err = __mlx4_cq_alloc_icm(dev, &cqn);
1692255932Salfred		if (err) {
1693255932Salfred			mlx4_release_resource(dev, slave, RES_CQ, 1, 0);
1694255932Salfred			break;
1695255932Salfred		}
1696255932Salfred
1697255932Salfred		err = add_res_range(dev, slave, cqn, 1, RES_CQ, 0);
1698255932Salfred		if (err) {
1699255932Salfred			mlx4_release_resource(dev, slave, RES_CQ, 1, 0);
1700255932Salfred			__mlx4_cq_free_icm(dev, cqn);
1701255932Salfred			break;
1702255932Salfred		}
1703255932Salfred
1704255932Salfred		set_param_l(out_param, cqn);
1705255932Salfred		break;
1706255932Salfred
1707255932Salfred	default:
1708255932Salfred		err = -EINVAL;
1709255932Salfred	}
1710255932Salfred
1711255932Salfred	return err;
1712255932Salfred}
1713255932Salfred
1714255932Salfredstatic int srq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1715255932Salfred			 u64 in_param, u64 *out_param)
1716255932Salfred{
1717255932Salfred	int srqn;
1718255932Salfred	int err;
1719255932Salfred
1720255932Salfred	switch (op) {
1721255932Salfred	case RES_OP_RESERVE_AND_MAP:
1722255932Salfred		err = mlx4_grant_resource(dev, slave, RES_SRQ, 1, 0);
1723255932Salfred		if (err)
1724255932Salfred			break;
1725255932Salfred
1726255932Salfred		err = __mlx4_srq_alloc_icm(dev, &srqn);
1727255932Salfred		if (err) {
1728255932Salfred			mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);
1729255932Salfred			break;
1730255932Salfred		}
1731255932Salfred
1732255932Salfred		err = add_res_range(dev, slave, srqn, 1, RES_SRQ, 0);
1733255932Salfred		if (err) {
1734255932Salfred			mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);
1735255932Salfred			__mlx4_srq_free_icm(dev, srqn);
1736255932Salfred			break;
1737255932Salfred		}
1738255932Salfred
1739255932Salfred		set_param_l(out_param, srqn);
1740255932Salfred		break;
1741255932Salfred
1742255932Salfred	default:
1743255932Salfred		err = -EINVAL;
1744255932Salfred	}
1745255932Salfred
1746255932Salfred	return err;
1747255932Salfred}
1748255932Salfred
1749255932Salfredstatic int mac_find_smac_ix_in_slave(struct mlx4_dev *dev, int slave, int port,
1750255932Salfred				     u8 smac_index, u64 *mac)
1751255932Salfred{
1752255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1753255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1754255932Salfred	struct list_head *mac_list =
1755255932Salfred		&tracker->slave_list[slave].res_list[RES_MAC];
1756255932Salfred	struct mac_res *res, *tmp;
1757255932Salfred
1758255932Salfred	list_for_each_entry_safe(res, tmp, mac_list, list) {
1759255932Salfred		if (res->smac_index == smac_index && res->port == (u8) port) {
1760255932Salfred			*mac = res->mac;
1761255932Salfred			return 0;
1762255932Salfred		}
1763255932Salfred	}
1764255932Salfred	return -ENOENT;
1765255932Salfred}
1766255932Salfred
1767255932Salfredstatic int mac_add_to_slave(struct mlx4_dev *dev, int slave, u64 mac, int port, u8 smac_index)
1768255932Salfred{
1769255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1770255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1771255932Salfred	struct list_head *mac_list =
1772255932Salfred		&tracker->slave_list[slave].res_list[RES_MAC];
1773255932Salfred	struct mac_res *res, *tmp;
1774255932Salfred
1775255932Salfred	list_for_each_entry_safe(res, tmp, mac_list, list) {
1776255932Salfred		if (res->mac == mac && res->port == (u8) port) {
1777255932Salfred			/* mac found. update ref count */
1778255932Salfred			++res->ref_count;
1779255932Salfred			return 0;
1780255932Salfred		}
1781255932Salfred	}
1782255932Salfred
1783255932Salfred	if (mlx4_grant_resource(dev, slave, RES_MAC, 1, port))
1784255932Salfred		return -EINVAL;
1785255932Salfred	res = kzalloc(sizeof *res, GFP_KERNEL);
1786255932Salfred	if (!res) {
1787255932Salfred		mlx4_release_resource(dev, slave, RES_MAC, 1, port);
1788255932Salfred		return -ENOMEM;
1789255932Salfred	}
1790255932Salfred	res->mac = mac;
1791255932Salfred	res->port = (u8) port;
1792255932Salfred	res->smac_index = smac_index;
1793255932Salfred	res->ref_count = 1;
1794255932Salfred	list_add_tail(&res->list,
1795255932Salfred		      &tracker->slave_list[slave].res_list[RES_MAC]);
1796255932Salfred	return 0;
1797255932Salfred}
1798255932Salfred
1799255932Salfred
1800255932Salfredstatic void mac_del_from_slave(struct mlx4_dev *dev, int slave, u64 mac,
1801255932Salfred			       int port)
1802255932Salfred{
1803255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1804255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1805255932Salfred	struct list_head *mac_list =
1806255932Salfred		&tracker->slave_list[slave].res_list[RES_MAC];
1807255932Salfred	struct mac_res *res, *tmp;
1808255932Salfred
1809255932Salfred	list_for_each_entry_safe(res, tmp, mac_list, list) {
1810255932Salfred		if (res->mac == mac && res->port == (u8) port) {
1811255932Salfred			if (!--res->ref_count) {
1812255932Salfred				list_del(&res->list);
1813255932Salfred				mlx4_release_resource(dev, slave, RES_MAC, 1, port);
1814255932Salfred				kfree(res);
1815255932Salfred			}
1816255932Salfred			break;
1817255932Salfred		}
1818255932Salfred	}
1819255932Salfred}
1820255932Salfred
1821255932Salfredstatic void rem_slave_macs(struct mlx4_dev *dev, int slave)
1822255932Salfred{
1823255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1824255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1825255932Salfred	struct list_head *mac_list =
1826255932Salfred		&tracker->slave_list[slave].res_list[RES_MAC];
1827255932Salfred	struct mac_res *res, *tmp;
1828255932Salfred	int i;
1829255932Salfred
1830255932Salfred	list_for_each_entry_safe(res, tmp, mac_list, list) {
1831255932Salfred		list_del(&res->list);
1832255932Salfred		/* dereference the mac the num times the slave referenced it */
1833255932Salfred		for (i = 0; i < res->ref_count; i++)
1834255932Salfred			__mlx4_unregister_mac(dev, res->port, res->mac);
1835255932Salfred		mlx4_release_resource(dev, slave, RES_MAC, 1, res->port);
1836255932Salfred		kfree(res);
1837255932Salfred	}
1838255932Salfred}
1839255932Salfred
1840255932Salfredstatic int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1841255932Salfred			 u64 in_param, u64 *out_param, int in_port)
1842255932Salfred{
1843255932Salfred	int err = -EINVAL;
1844255932Salfred	int port;
1845255932Salfred	u64 mac;
1846272060Shselasky	u8 smac_index = 0;
1847255932Salfred
1848255932Salfred	if (op != RES_OP_RESERVE_AND_MAP)
1849255932Salfred		return err;
1850255932Salfred
1851255932Salfred	port = !in_port ? get_param_l(out_param) : in_port;
1852255932Salfred	mac = in_param;
1853255932Salfred
1854255932Salfred	err = __mlx4_register_mac(dev, port, mac);
1855255932Salfred	if (err >= 0) {
1856255932Salfred		smac_index = err;
1857255932Salfred		set_param_l(out_param, err);
1858255932Salfred		err = 0;
1859255932Salfred	}
1860255932Salfred
1861255932Salfred	if (!err) {
1862255932Salfred		err = mac_add_to_slave(dev, slave, mac, port, smac_index);
1863255932Salfred		if (err)
1864255932Salfred			__mlx4_unregister_mac(dev, port, mac);
1865255932Salfred	}
1866255932Salfred	return err;
1867255932Salfred}
1868255932Salfred
1869255932Salfredstatic int vlan_add_to_slave(struct mlx4_dev *dev, int slave, u16 vlan,
1870255932Salfred			     int port, int vlan_index)
1871255932Salfred{
1872255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1873255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1874255932Salfred	struct list_head *vlan_list =
1875255932Salfred		&tracker->slave_list[slave].res_list[RES_VLAN];
1876255932Salfred	struct vlan_res *res, *tmp;
1877255932Salfred
1878255932Salfred	list_for_each_entry_safe(res, tmp, vlan_list, list) {
1879255932Salfred		if (res->vlan == vlan && res->port == (u8) port) {
1880255932Salfred			/* vlan found. update ref count */
1881255932Salfred			++res->ref_count;
1882255932Salfred			return 0;
1883255932Salfred		}
1884255932Salfred	}
1885255932Salfred
1886255932Salfred	if (mlx4_grant_resource(dev, slave, RES_VLAN, 1, port))
1887255932Salfred		return -EINVAL;
1888255932Salfred	res = kzalloc(sizeof(*res), GFP_KERNEL);
1889255932Salfred	if (!res) {
1890255932Salfred		mlx4_release_resource(dev, slave, RES_VLAN, 1, port);
1891255932Salfred		return -ENOMEM;
1892255932Salfred	}
1893255932Salfred	res->vlan = vlan;
1894255932Salfred	res->port = (u8) port;
1895255932Salfred	res->vlan_index = vlan_index;
1896255932Salfred	res->ref_count = 1;
1897255932Salfred	list_add_tail(&res->list,
1898255932Salfred		      &tracker->slave_list[slave].res_list[RES_VLAN]);
1899255932Salfred	return 0;
1900255932Salfred}
1901255932Salfred
1902255932Salfred
1903255932Salfredstatic void vlan_del_from_slave(struct mlx4_dev *dev, int slave, u16 vlan,
1904255932Salfred				int port)
1905255932Salfred{
1906255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1907255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1908255932Salfred	struct list_head *vlan_list =
1909255932Salfred		&tracker->slave_list[slave].res_list[RES_VLAN];
1910255932Salfred	struct vlan_res *res, *tmp;
1911255932Salfred
1912255932Salfred	list_for_each_entry_safe(res, tmp, vlan_list, list) {
1913255932Salfred		if (res->vlan == vlan && res->port == (u8) port) {
1914255932Salfred			if (!--res->ref_count) {
1915255932Salfred				list_del(&res->list);
1916255932Salfred				mlx4_release_resource(dev, slave, RES_VLAN,
1917255932Salfred						      1, port);
1918255932Salfred				kfree(res);
1919255932Salfred			}
1920255932Salfred			break;
1921255932Salfred		}
1922255932Salfred	}
1923255932Salfred}
1924255932Salfred
1925255932Salfredstatic void rem_slave_vlans(struct mlx4_dev *dev, int slave)
1926255932Salfred{
1927255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
1928255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
1929255932Salfred	struct list_head *vlan_list =
1930255932Salfred		&tracker->slave_list[slave].res_list[RES_VLAN];
1931255932Salfred	struct vlan_res *res, *tmp;
1932255932Salfred	int i;
1933255932Salfred
1934255932Salfred	list_for_each_entry_safe(res, tmp, vlan_list, list) {
1935255932Salfred		list_del(&res->list);
1936255932Salfred		/* dereference the vlan the num times the slave referenced it */
1937255932Salfred		for (i = 0; i < res->ref_count; i++)
1938255932Salfred			__mlx4_unregister_vlan(dev, res->port, res->vlan);
1939255932Salfred		mlx4_release_resource(dev, slave, RES_VLAN, 1, res->port);
1940255932Salfred		kfree(res);
1941255932Salfred	}
1942255932Salfred}
1943255932Salfred
1944255932Salfredstatic int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1945272027Shselasky			  u64 in_param, u64 *out_param, int in_port)
1946255932Salfred{
1947272027Shselasky	struct mlx4_priv *priv = mlx4_priv(dev);
1948272027Shselasky	struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
1949255932Salfred	int err = -EINVAL;
1950255932Salfred	u16 vlan;
1951255932Salfred	int vlan_index;
1952272027Shselasky	int port;
1953255932Salfred
1954272027Shselasky	port = !in_port ? get_param_l(out_param) : in_port;
1955272027Shselasky
1956255932Salfred	if (!port)
1957255932Salfred		return err;
1958255932Salfred
1959255932Salfred	if (op != RES_OP_RESERVE_AND_MAP)
1960255932Salfred		return err;
1961255932Salfred
1962272027Shselasky	/* upstream kernels had NOP for reg/unreg vlan. Continue this. */
1963272027Shselasky	if (!in_port && port > 0 && port <= dev->caps.num_ports) {
1964272027Shselasky		slave_state[slave].old_vlan_api = true;
1965272027Shselasky		return 0;
1966272027Shselasky	}
1967272027Shselasky
1968255932Salfred	vlan = (u16) in_param;
1969255932Salfred
1970255932Salfred	err = __mlx4_register_vlan(dev, port, vlan, &vlan_index);
1971255932Salfred	if (!err) {
1972255932Salfred		set_param_l(out_param, (u32) vlan_index);
1973255932Salfred		err = vlan_add_to_slave(dev, slave, vlan, port, vlan_index);
1974255932Salfred		if (err)
1975255932Salfred			__mlx4_unregister_vlan(dev, port, vlan);
1976255932Salfred	}
1977255932Salfred	return err;
1978255932Salfred}
1979255932Salfred
1980255932Salfredstatic int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1981272027Shselasky			     u64 in_param, u64 *out_param, int port)
1982255932Salfred{
1983255932Salfred	u32 index;
1984255932Salfred	int err;
1985255932Salfred
1986255932Salfred	if (op != RES_OP_RESERVE)
1987255932Salfred		return -EINVAL;
1988255932Salfred
1989272027Shselasky	err = __mlx4_counter_alloc(dev, slave, port, &index);
1990272027Shselasky	if (!err)
1991255932Salfred		set_param_l(out_param, index);
1992255932Salfred
1993255932Salfred	return err;
1994255932Salfred}
1995255932Salfred
1996255932Salfredstatic int xrcdn_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1997255932Salfred			   u64 in_param, u64 *out_param)
1998255932Salfred{
1999255932Salfred	u32 xrcdn;
2000255932Salfred	int err;
2001255932Salfred
2002255932Salfred	if (op != RES_OP_RESERVE)
2003255932Salfred		return -EINVAL;
2004255932Salfred
2005255932Salfred	err = __mlx4_xrcd_alloc(dev, &xrcdn);
2006255932Salfred	if (err)
2007255932Salfred		return err;
2008255932Salfred
2009255932Salfred	err = add_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
2010255932Salfred	if (err)
2011255932Salfred		__mlx4_xrcd_free(dev, xrcdn);
2012255932Salfred	else
2013255932Salfred		set_param_l(out_param, xrcdn);
2014255932Salfred
2015255932Salfred	return err;
2016255932Salfred}
2017255932Salfred
2018255932Salfredint mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
2019255932Salfred			   struct mlx4_vhcr *vhcr,
2020255932Salfred			   struct mlx4_cmd_mailbox *inbox,
2021255932Salfred			   struct mlx4_cmd_mailbox *outbox,
2022255932Salfred			   struct mlx4_cmd_info *cmd)
2023255932Salfred{
2024255932Salfred	int err;
2025255932Salfred	int alop = vhcr->op_modifier;
2026255932Salfred
2027255932Salfred	switch (vhcr->in_modifier & 0xFF) {
2028255932Salfred	case RES_QP:
2029255932Salfred		err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop,
2030255932Salfred				   vhcr->in_param, &vhcr->out_param);
2031255932Salfred		break;
2032255932Salfred
2033255932Salfred	case RES_MTT:
2034255932Salfred		err = mtt_alloc_res(dev, slave, vhcr->op_modifier, alop,
2035255932Salfred				    vhcr->in_param, &vhcr->out_param);
2036255932Salfred		break;
2037255932Salfred
2038255932Salfred	case RES_MPT:
2039255932Salfred		err = mpt_alloc_res(dev, slave, vhcr->op_modifier, alop,
2040255932Salfred				    vhcr->in_param, &vhcr->out_param);
2041255932Salfred		break;
2042255932Salfred
2043255932Salfred	case RES_CQ:
2044255932Salfred		err = cq_alloc_res(dev, slave, vhcr->op_modifier, alop,
2045255932Salfred				   vhcr->in_param, &vhcr->out_param);
2046255932Salfred		break;
2047255932Salfred
2048255932Salfred	case RES_SRQ:
2049255932Salfred		err = srq_alloc_res(dev, slave, vhcr->op_modifier, alop,
2050255932Salfred				    vhcr->in_param, &vhcr->out_param);
2051255932Salfred		break;
2052255932Salfred
2053255932Salfred	case RES_MAC:
2054255932Salfred		err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop,
2055255932Salfred				    vhcr->in_param, &vhcr->out_param,
2056255932Salfred				    (vhcr->in_modifier >> 8) & 0xFF);
2057255932Salfred		break;
2058255932Salfred
2059255932Salfred	case RES_VLAN:
2060255932Salfred		err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop,
2061255932Salfred				     vhcr->in_param, &vhcr->out_param,
2062255932Salfred				     (vhcr->in_modifier >> 8) & 0xFF);
2063255932Salfred		break;
2064255932Salfred
2065255932Salfred	case RES_COUNTER:
2066255932Salfred		err = counter_alloc_res(dev, slave, vhcr->op_modifier, alop,
2067272027Shselasky					vhcr->in_param, &vhcr->out_param,
2068272027Shselasky					(vhcr->in_modifier >> 8) & 0xFF);
2069255932Salfred		break;
2070255932Salfred
2071255932Salfred	case RES_XRCD:
2072255932Salfred		err = xrcdn_alloc_res(dev, slave, vhcr->op_modifier, alop,
2073255932Salfred				      vhcr->in_param, &vhcr->out_param);
2074255932Salfred		break;
2075255932Salfred
2076255932Salfred	default:
2077255932Salfred		err = -EINVAL;
2078255932Salfred		break;
2079255932Salfred	}
2080255932Salfred
2081255932Salfred	return err;
2082255932Salfred}
2083255932Salfred
2084255932Salfredstatic int qp_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2085255932Salfred		       u64 in_param)
2086255932Salfred{
2087255932Salfred	int err;
2088255932Salfred	int count;
2089255932Salfred	int base;
2090255932Salfred	int qpn;
2091255932Salfred
2092255932Salfred	switch (op) {
2093255932Salfred	case RES_OP_RESERVE:
2094255932Salfred		base = get_param_l(&in_param) & 0x7fffff;
2095255932Salfred		count = get_param_h(&in_param);
2096255932Salfred		err = rem_res_range(dev, slave, base, count, RES_QP, 0);
2097255932Salfred		if (err)
2098255932Salfred			break;
2099255932Salfred		mlx4_release_resource(dev, slave, RES_QP, count, 0);
2100255932Salfred		__mlx4_qp_release_range(dev, base, count);
2101255932Salfred		break;
2102255932Salfred	case RES_OP_MAP_ICM:
2103255932Salfred		qpn = get_param_l(&in_param) & 0x7fffff;
2104255932Salfred		err = qp_res_start_move_to(dev, slave, qpn, RES_QP_RESERVED,
2105255932Salfred					   NULL, 0);
2106255932Salfred		if (err)
2107255932Salfred			return err;
2108255932Salfred
2109255932Salfred		if (!fw_reserved(dev, qpn))
2110255932Salfred			__mlx4_qp_free_icm(dev, qpn);
2111255932Salfred
2112255932Salfred		res_end_move(dev, slave, RES_QP, qpn);
2113255932Salfred
2114255932Salfred		if (valid_reserved(dev, slave, qpn))
2115255932Salfred			err = rem_res_range(dev, slave, qpn, 1, RES_QP, 0);
2116255932Salfred		break;
2117255932Salfred	default:
2118255932Salfred		err = -EINVAL;
2119255932Salfred		break;
2120255932Salfred	}
2121255932Salfred	return err;
2122255932Salfred}
2123255932Salfred
2124255932Salfredstatic int mtt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2125255932Salfred			u64 in_param, u64 *out_param)
2126255932Salfred{
2127255932Salfred	int err = -EINVAL;
2128255932Salfred	int base;
2129255932Salfred	int order;
2130255932Salfred
2131255932Salfred	if (op != RES_OP_RESERVE_AND_MAP)
2132255932Salfred		return err;
2133255932Salfred
2134255932Salfred	base = get_param_l(&in_param);
2135255932Salfred	order = get_param_h(&in_param);
2136255932Salfred	err = rem_res_range(dev, slave, base, 1, RES_MTT, order);
2137255932Salfred	if (!err) {
2138255932Salfred		mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);
2139255932Salfred		__mlx4_free_mtt_range(dev, base, order);
2140255932Salfred	}
2141255932Salfred	return err;
2142255932Salfred}
2143255932Salfred
2144255932Salfredstatic int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2145255932Salfred			u64 in_param)
2146255932Salfred{
2147255932Salfred	int err = -EINVAL;
2148255932Salfred	int index;
2149255932Salfred	int id;
2150255932Salfred	struct res_mpt *mpt;
2151255932Salfred
2152255932Salfred	switch (op) {
2153255932Salfred	case RES_OP_RESERVE:
2154255932Salfred		index = get_param_l(&in_param);
2155255932Salfred		id = index & mpt_mask(dev);
2156255932Salfred		err = get_res(dev, slave, id, RES_MPT, &mpt);
2157255932Salfred		if (err)
2158255932Salfred			break;
2159255932Salfred		index = mpt->key;
2160255932Salfred		put_res(dev, slave, id, RES_MPT);
2161255932Salfred
2162255932Salfred		err = rem_res_range(dev, slave, id, 1, RES_MPT, 0);
2163255932Salfred		if (err)
2164255932Salfred			break;
2165255932Salfred		mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
2166272027Shselasky		__mlx4_mpt_release(dev, index);
2167255932Salfred		break;
2168255932Salfred	case RES_OP_MAP_ICM:
2169255932Salfred			index = get_param_l(&in_param);
2170255932Salfred			id = index & mpt_mask(dev);
2171255932Salfred			err = mr_res_start_move_to(dev, slave, id,
2172255932Salfred						   RES_MPT_RESERVED, &mpt);
2173255932Salfred			if (err)
2174255932Salfred				return err;
2175255932Salfred
2176272027Shselasky			__mlx4_mpt_free_icm(dev, mpt->key);
2177255932Salfred			res_end_move(dev, slave, RES_MPT, id);
2178255932Salfred			return err;
2179255932Salfred		break;
2180255932Salfred	default:
2181255932Salfred		err = -EINVAL;
2182255932Salfred		break;
2183255932Salfred	}
2184255932Salfred	return err;
2185255932Salfred}
2186255932Salfred
2187255932Salfredstatic int cq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2188255932Salfred		       u64 in_param, u64 *out_param)
2189255932Salfred{
2190255932Salfred	int cqn;
2191255932Salfred	int err;
2192255932Salfred
2193255932Salfred	switch (op) {
2194255932Salfred	case RES_OP_RESERVE_AND_MAP:
2195255932Salfred		cqn = get_param_l(&in_param);
2196255932Salfred		err = rem_res_range(dev, slave, cqn, 1, RES_CQ, 0);
2197255932Salfred		if (err)
2198255932Salfred			break;
2199255932Salfred
2200255932Salfred		mlx4_release_resource(dev, slave, RES_CQ, 1, 0);
2201255932Salfred		__mlx4_cq_free_icm(dev, cqn);
2202255932Salfred		break;
2203255932Salfred
2204255932Salfred	default:
2205255932Salfred		err = -EINVAL;
2206255932Salfred		break;
2207255932Salfred	}
2208255932Salfred
2209255932Salfred	return err;
2210255932Salfred}
2211255932Salfred
2212255932Salfredstatic int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2213255932Salfred			u64 in_param, u64 *out_param)
2214255932Salfred{
2215255932Salfred	int srqn;
2216255932Salfred	int err;
2217255932Salfred
2218255932Salfred	switch (op) {
2219255932Salfred	case RES_OP_RESERVE_AND_MAP:
2220255932Salfred		srqn = get_param_l(&in_param);
2221255932Salfred		err = rem_res_range(dev, slave, srqn, 1, RES_SRQ, 0);
2222255932Salfred		if (err)
2223255932Salfred			break;
2224255932Salfred
2225255932Salfred		mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);
2226255932Salfred		__mlx4_srq_free_icm(dev, srqn);
2227255932Salfred		break;
2228255932Salfred
2229255932Salfred	default:
2230255932Salfred		err = -EINVAL;
2231255932Salfred		break;
2232255932Salfred	}
2233255932Salfred
2234255932Salfred	return err;
2235255932Salfred}
2236255932Salfred
2237255932Salfredstatic int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2238255932Salfred			    u64 in_param, u64 *out_param, int in_port)
2239255932Salfred{
2240255932Salfred	int port;
2241255932Salfred	int err = 0;
2242255932Salfred
2243255932Salfred	switch (op) {
2244255932Salfred	case RES_OP_RESERVE_AND_MAP:
2245255932Salfred		port = !in_port ? get_param_l(out_param) : in_port;
2246255932Salfred		mac_del_from_slave(dev, slave, in_param, port);
2247255932Salfred		__mlx4_unregister_mac(dev, port, in_param);
2248255932Salfred		break;
2249255932Salfred	default:
2250255932Salfred		err = -EINVAL;
2251255932Salfred		break;
2252255932Salfred	}
2253255932Salfred
2254255932Salfred	return err;
2255255932Salfred
2256255932Salfred}
2257255932Salfred
2258255932Salfredstatic int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2259255932Salfred			    u64 in_param, u64 *out_param, int port)
2260255932Salfred{
2261272027Shselasky	struct mlx4_priv *priv = mlx4_priv(dev);
2262272027Shselasky	struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
2263255932Salfred	int err = 0;
2264255932Salfred
2265255932Salfred	switch (op) {
2266255932Salfred	case RES_OP_RESERVE_AND_MAP:
2267272027Shselasky		if (slave_state[slave].old_vlan_api == true)
2268272027Shselasky			return 0;
2269255932Salfred		if (!port)
2270255932Salfred			return -EINVAL;
2271255932Salfred		vlan_del_from_slave(dev, slave, in_param, port);
2272255932Salfred		__mlx4_unregister_vlan(dev, port, in_param);
2273255932Salfred		break;
2274255932Salfred	default:
2275255932Salfred		err = -EINVAL;
2276255932Salfred		break;
2277255932Salfred	}
2278255932Salfred
2279255932Salfred	return err;
2280255932Salfred}
2281255932Salfred
2282255932Salfredstatic int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2283272027Shselasky			    u64 in_param, u64 *out_param, int port)
2284255932Salfred{
2285255932Salfred	int index;
2286255932Salfred
2287255932Salfred	if (op != RES_OP_RESERVE)
2288255932Salfred		return -EINVAL;
2289255932Salfred
2290255932Salfred	index = get_param_l(&in_param);
2291255932Salfred
2292272027Shselasky	__mlx4_counter_free(dev, slave, port, index);
2293255932Salfred
2294272027Shselasky	return 0;
2295255932Salfred}
2296255932Salfred
2297255932Salfredstatic int xrcdn_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
2298255932Salfred			  u64 in_param, u64 *out_param)
2299255932Salfred{
2300255932Salfred	int xrcdn;
2301255932Salfred	int err;
2302255932Salfred
2303255932Salfred	if (op != RES_OP_RESERVE)
2304255932Salfred		return -EINVAL;
2305255932Salfred
2306255932Salfred	xrcdn = get_param_l(&in_param);
2307255932Salfred	err = rem_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
2308255932Salfred	if (err)
2309255932Salfred		return err;
2310255932Salfred
2311255932Salfred	__mlx4_xrcd_free(dev, xrcdn);
2312255932Salfred
2313255932Salfred	return err;
2314255932Salfred}
2315255932Salfred
2316255932Salfredint mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
2317255932Salfred			  struct mlx4_vhcr *vhcr,
2318255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2319255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2320255932Salfred			  struct mlx4_cmd_info *cmd)
2321255932Salfred{
2322255932Salfred	int err = -EINVAL;
2323255932Salfred	int alop = vhcr->op_modifier;
2324255932Salfred
2325255932Salfred	switch (vhcr->in_modifier & 0xFF) {
2326255932Salfred	case RES_QP:
2327255932Salfred		err = qp_free_res(dev, slave, vhcr->op_modifier, alop,
2328255932Salfred				  vhcr->in_param);
2329255932Salfred		break;
2330255932Salfred
2331255932Salfred	case RES_MTT:
2332255932Salfred		err = mtt_free_res(dev, slave, vhcr->op_modifier, alop,
2333255932Salfred				   vhcr->in_param, &vhcr->out_param);
2334255932Salfred		break;
2335255932Salfred
2336255932Salfred	case RES_MPT:
2337255932Salfred		err = mpt_free_res(dev, slave, vhcr->op_modifier, alop,
2338255932Salfred				   vhcr->in_param);
2339255932Salfred		break;
2340255932Salfred
2341255932Salfred	case RES_CQ:
2342255932Salfred		err = cq_free_res(dev, slave, vhcr->op_modifier, alop,
2343255932Salfred				  vhcr->in_param, &vhcr->out_param);
2344255932Salfred		break;
2345255932Salfred
2346255932Salfred	case RES_SRQ:
2347255932Salfred		err = srq_free_res(dev, slave, vhcr->op_modifier, alop,
2348255932Salfred				   vhcr->in_param, &vhcr->out_param);
2349255932Salfred		break;
2350255932Salfred
2351255932Salfred	case RES_MAC:
2352255932Salfred		err = mac_free_res(dev, slave, vhcr->op_modifier, alop,
2353255932Salfred				   vhcr->in_param, &vhcr->out_param,
2354255932Salfred				   (vhcr->in_modifier >> 8) & 0xFF);
2355255932Salfred		break;
2356255932Salfred
2357255932Salfred	case RES_VLAN:
2358255932Salfred		err = vlan_free_res(dev, slave, vhcr->op_modifier, alop,
2359255932Salfred				    vhcr->in_param, &vhcr->out_param,
2360255932Salfred				    (vhcr->in_modifier >> 8) & 0xFF);
2361255932Salfred		break;
2362255932Salfred
2363255932Salfred	case RES_COUNTER:
2364255932Salfred		err = counter_free_res(dev, slave, vhcr->op_modifier, alop,
2365272027Shselasky				       vhcr->in_param, &vhcr->out_param,
2366272027Shselasky				       (vhcr->in_modifier >> 8) & 0xFF);
2367255932Salfred		break;
2368255932Salfred
2369255932Salfred	case RES_XRCD:
2370255932Salfred		err = xrcdn_free_res(dev, slave, vhcr->op_modifier, alop,
2371255932Salfred				     vhcr->in_param, &vhcr->out_param);
2372255932Salfred
2373255932Salfred	default:
2374255932Salfred		break;
2375255932Salfred	}
2376255932Salfred	return err;
2377255932Salfred}
2378255932Salfred
2379255932Salfred/* ugly but other choices are uglier */
2380255932Salfredstatic int mr_phys_mpt(struct mlx4_mpt_entry *mpt)
2381255932Salfred{
2382255932Salfred	return (be32_to_cpu(mpt->flags) >> 9) & 1;
2383255932Salfred}
2384255932Salfred
2385255932Salfredstatic int mr_get_mtt_addr(struct mlx4_mpt_entry *mpt)
2386255932Salfred{
2387255932Salfred	return (int)be64_to_cpu(mpt->mtt_addr) & 0xfffffff8;
2388255932Salfred}
2389255932Salfred
2390255932Salfredstatic int mr_get_mtt_size(struct mlx4_mpt_entry *mpt)
2391255932Salfred{
2392255932Salfred	return be32_to_cpu(mpt->mtt_sz);
2393255932Salfred}
2394255932Salfred
2395272027Shselaskystatic u32 mr_get_pd(struct mlx4_mpt_entry *mpt)
2396272027Shselasky{
2397272027Shselasky	return be32_to_cpu(mpt->pd_flags) & 0x00ffffff;
2398272027Shselasky}
2399272027Shselasky
2400272027Shselaskystatic int mr_is_fmr(struct mlx4_mpt_entry *mpt)
2401272027Shselasky{
2402272027Shselasky	return be32_to_cpu(mpt->pd_flags) & MLX4_MPT_PD_FLAG_FAST_REG;
2403272027Shselasky}
2404272027Shselasky
2405272027Shselaskystatic int mr_is_bind_enabled(struct mlx4_mpt_entry *mpt)
2406272027Shselasky{
2407272027Shselasky	return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_BIND_ENABLE;
2408272027Shselasky}
2409272027Shselasky
2410272027Shselaskystatic int mr_is_region(struct mlx4_mpt_entry *mpt)
2411272027Shselasky{
2412272027Shselasky	return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_REGION;
2413272027Shselasky}
2414272027Shselasky
2415255932Salfredstatic int qp_get_mtt_addr(struct mlx4_qp_context *qpc)
2416255932Salfred{
2417255932Salfred	return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;
2418255932Salfred}
2419255932Salfred
2420255932Salfredstatic int srq_get_mtt_addr(struct mlx4_srq_context *srqc)
2421255932Salfred{
2422255932Salfred	return be32_to_cpu(srqc->mtt_base_addr_l) & 0xfffffff8;
2423255932Salfred}
2424255932Salfred
2425255932Salfredstatic int qp_get_mtt_size(struct mlx4_qp_context *qpc)
2426255932Salfred{
2427255932Salfred	int page_shift = (qpc->log_page_size & 0x3f) + 12;
2428255932Salfred	int log_sq_size = (qpc->sq_size_stride >> 3) & 0xf;
2429255932Salfred	int log_sq_sride = qpc->sq_size_stride & 7;
2430255932Salfred	int log_rq_size = (qpc->rq_size_stride >> 3) & 0xf;
2431255932Salfred	int log_rq_stride = qpc->rq_size_stride & 7;
2432255932Salfred	int srq = (be32_to_cpu(qpc->srqn) >> 24) & 1;
2433255932Salfred	int rss = (be32_to_cpu(qpc->flags) >> 13) & 1;
2434272027Shselasky	u32 ts = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
2435272027Shselasky	int xrc = (ts == MLX4_QP_ST_XRC) ? 1 : 0;
2436255932Salfred	int sq_size;
2437255932Salfred	int rq_size;
2438255932Salfred	int total_pages;
2439255932Salfred	int total_mem;
2440255932Salfred	int page_offset = (be32_to_cpu(qpc->params2) >> 6) & 0x3f;
2441255932Salfred
2442255932Salfred	sq_size = 1 << (log_sq_size + log_sq_sride + 4);
2443255932Salfred	rq_size = (srq|rss|xrc) ? 0 : (1 << (log_rq_size + log_rq_stride + 4));
2444255932Salfred	total_mem = sq_size + rq_size;
2445255932Salfred	total_pages =
2446255932Salfred		roundup_pow_of_two((total_mem + (page_offset << 6)) >>
2447255932Salfred				   page_shift);
2448255932Salfred
2449255932Salfred	return total_pages;
2450255932Salfred}
2451255932Salfred
2452255932Salfredstatic int check_mtt_range(struct mlx4_dev *dev, int slave, int start,
2453255932Salfred			   int size, struct res_mtt *mtt)
2454255932Salfred{
2455255932Salfred	int res_start = mtt->com.res_id;
2456255932Salfred	int res_size = (1 << mtt->order);
2457255932Salfred
2458255932Salfred	if (start < res_start || start + size > res_start + res_size)
2459255932Salfred		return -EPERM;
2460255932Salfred	return 0;
2461255932Salfred}
2462255932Salfred
2463255932Salfredint mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,
2464255932Salfred			   struct mlx4_vhcr *vhcr,
2465255932Salfred			   struct mlx4_cmd_mailbox *inbox,
2466255932Salfred			   struct mlx4_cmd_mailbox *outbox,
2467255932Salfred			   struct mlx4_cmd_info *cmd)
2468255932Salfred{
2469255932Salfred	int err;
2470255932Salfred	int index = vhcr->in_modifier;
2471255932Salfred	struct res_mtt *mtt;
2472255932Salfred	struct res_mpt *mpt;
2473255932Salfred	int mtt_base = mr_get_mtt_addr(inbox->buf) / dev->caps.mtt_entry_sz;
2474255932Salfred	int phys;
2475255932Salfred	int id;
2476272027Shselasky	u32 pd;
2477272027Shselasky	int pd_slave;
2478255932Salfred
2479255932Salfred	id = index & mpt_mask(dev);
2480255932Salfred	err = mr_res_start_move_to(dev, slave, id, RES_MPT_HW, &mpt);
2481255932Salfred	if (err)
2482255932Salfred		return err;
2483255932Salfred
2484272027Shselasky	/* Currently disable memory windows since this feature isn't tested yet
2485272027Shselasky	* under virtualization.
2486272027Shselasky	*/
2487272027Shselasky	if (!mr_is_region(inbox->buf)) {
2488272027Shselasky		err = -ENOSYS;
2489272027Shselasky		goto ex_abort;
2490272027Shselasky	}
2491272027Shselasky
2492272027Shselasky	/* Make sure that the PD bits related to the slave id are zeros. */
2493272027Shselasky	pd = mr_get_pd(inbox->buf);
2494272027Shselasky	pd_slave = (pd >> 17) & 0x7f;
2495272027Shselasky	if (pd_slave != 0 && pd_slave != slave) {
2496272027Shselasky		err = -EPERM;
2497272027Shselasky		goto ex_abort;
2498272027Shselasky	}
2499272027Shselasky
2500272027Shselasky	if (mr_is_fmr(inbox->buf)) {
2501272027Shselasky		/* FMR and Bind Enable are forbidden in slave devices. */
2502272027Shselasky		if (mr_is_bind_enabled(inbox->buf)) {
2503272027Shselasky			err = -EPERM;
2504272027Shselasky			goto ex_abort;
2505272027Shselasky		}
2506272027Shselasky		/* FMR and Memory Windows are also forbidden. */
2507272027Shselasky		if (!mr_is_region(inbox->buf)) {
2508272027Shselasky			err = -EPERM;
2509272027Shselasky			goto ex_abort;
2510272027Shselasky		}
2511272027Shselasky	}
2512272027Shselasky
2513255932Salfred	phys = mr_phys_mpt(inbox->buf);
2514255932Salfred	if (!phys) {
2515255932Salfred		err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
2516255932Salfred		if (err)
2517255932Salfred			goto ex_abort;
2518255932Salfred
2519255932Salfred		err = check_mtt_range(dev, slave, mtt_base,
2520255932Salfred				      mr_get_mtt_size(inbox->buf), mtt);
2521255932Salfred		if (err)
2522255932Salfred			goto ex_put;
2523255932Salfred
2524255932Salfred		mpt->mtt = mtt;
2525255932Salfred	}
2526255932Salfred
2527255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2528255932Salfred	if (err)
2529255932Salfred		goto ex_put;
2530255932Salfred
2531255932Salfred	if (!phys) {
2532255932Salfred		atomic_inc(&mtt->ref_count);
2533255932Salfred		put_res(dev, slave, mtt->com.res_id, RES_MTT);
2534255932Salfred	}
2535255932Salfred
2536255932Salfred	res_end_move(dev, slave, RES_MPT, id);
2537255932Salfred	return 0;
2538255932Salfred
2539255932Salfredex_put:
2540255932Salfred	if (!phys)
2541255932Salfred		put_res(dev, slave, mtt->com.res_id, RES_MTT);
2542255932Salfredex_abort:
2543255932Salfred	res_abort_move(dev, slave, RES_MPT, id);
2544255932Salfred
2545255932Salfred	return err;
2546255932Salfred}
2547255932Salfred
2548255932Salfredint mlx4_HW2SW_MPT_wrapper(struct mlx4_dev *dev, int slave,
2549255932Salfred			   struct mlx4_vhcr *vhcr,
2550255932Salfred			   struct mlx4_cmd_mailbox *inbox,
2551255932Salfred			   struct mlx4_cmd_mailbox *outbox,
2552255932Salfred			   struct mlx4_cmd_info *cmd)
2553255932Salfred{
2554255932Salfred	int err;
2555255932Salfred	int index = vhcr->in_modifier;
2556255932Salfred	struct res_mpt *mpt;
2557255932Salfred	int id;
2558255932Salfred
2559255932Salfred	id = index & mpt_mask(dev);
2560255932Salfred	err = mr_res_start_move_to(dev, slave, id, RES_MPT_MAPPED, &mpt);
2561255932Salfred	if (err)
2562255932Salfred		return err;
2563255932Salfred
2564255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2565255932Salfred	if (err)
2566255932Salfred		goto ex_abort;
2567255932Salfred
2568255932Salfred	if (mpt->mtt)
2569255932Salfred		atomic_dec(&mpt->mtt->ref_count);
2570255932Salfred
2571255932Salfred	res_end_move(dev, slave, RES_MPT, id);
2572255932Salfred	return 0;
2573255932Salfred
2574255932Salfredex_abort:
2575255932Salfred	res_abort_move(dev, slave, RES_MPT, id);
2576255932Salfred
2577255932Salfred	return err;
2578255932Salfred}
2579255932Salfred
2580255932Salfredint mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave,
2581255932Salfred			   struct mlx4_vhcr *vhcr,
2582255932Salfred			   struct mlx4_cmd_mailbox *inbox,
2583255932Salfred			   struct mlx4_cmd_mailbox *outbox,
2584255932Salfred			   struct mlx4_cmd_info *cmd)
2585255932Salfred{
2586255932Salfred	int err;
2587255932Salfred	int index = vhcr->in_modifier;
2588255932Salfred	struct res_mpt *mpt;
2589255932Salfred	int id;
2590255932Salfred
2591255932Salfred	id = index & mpt_mask(dev);
2592255932Salfred	err = get_res(dev, slave, id, RES_MPT, &mpt);
2593255932Salfred	if (err)
2594255932Salfred		return err;
2595255932Salfred
2596255932Salfred	if (mpt->com.from_state != RES_MPT_HW) {
2597255932Salfred		err = -EBUSY;
2598255932Salfred		goto out;
2599255932Salfred	}
2600255932Salfred
2601255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2602255932Salfred
2603255932Salfredout:
2604255932Salfred	put_res(dev, slave, id, RES_MPT);
2605255932Salfred	return err;
2606255932Salfred}
2607255932Salfred
2608255932Salfredstatic int qp_get_rcqn(struct mlx4_qp_context *qpc)
2609255932Salfred{
2610255932Salfred	return be32_to_cpu(qpc->cqn_recv) & 0xffffff;
2611255932Salfred}
2612255932Salfred
2613255932Salfredstatic int qp_get_scqn(struct mlx4_qp_context *qpc)
2614255932Salfred{
2615255932Salfred	return be32_to_cpu(qpc->cqn_send) & 0xffffff;
2616255932Salfred}
2617255932Salfred
2618255932Salfredstatic u32 qp_get_srqn(struct mlx4_qp_context *qpc)
2619255932Salfred{
2620255932Salfred	return be32_to_cpu(qpc->srqn) & 0x1ffffff;
2621255932Salfred}
2622255932Salfred
2623255932Salfredstatic void adjust_proxy_tun_qkey(struct mlx4_dev *dev, struct mlx4_vhcr *vhcr,
2624255932Salfred				  struct mlx4_qp_context *context)
2625255932Salfred{
2626255932Salfred	u32 qpn = vhcr->in_modifier & 0xffffff;
2627255932Salfred	u32 qkey = 0;
2628255932Salfred
2629255932Salfred	if (mlx4_get_parav_qkey(dev, qpn, &qkey))
2630255932Salfred		return;
2631255932Salfred
2632255932Salfred	/* adjust qkey in qp context */
2633255932Salfred	context->qkey = cpu_to_be32(qkey);
2634255932Salfred}
2635255932Salfred
2636255932Salfredint mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
2637255932Salfred			     struct mlx4_vhcr *vhcr,
2638255932Salfred			     struct mlx4_cmd_mailbox *inbox,
2639255932Salfred			     struct mlx4_cmd_mailbox *outbox,
2640255932Salfred			     struct mlx4_cmd_info *cmd)
2641255932Salfred{
2642255932Salfred	int err;
2643255932Salfred	int qpn = vhcr->in_modifier & 0x7fffff;
2644255932Salfred	struct res_mtt *mtt;
2645255932Salfred	struct res_qp *qp;
2646255932Salfred	struct mlx4_qp_context *qpc = inbox->buf + 8;
2647255932Salfred	int mtt_base = qp_get_mtt_addr(qpc) / dev->caps.mtt_entry_sz;
2648255932Salfred	int mtt_size = qp_get_mtt_size(qpc);
2649255932Salfred	struct res_cq *rcq;
2650255932Salfred	struct res_cq *scq;
2651255932Salfred	int rcqn = qp_get_rcqn(qpc);
2652255932Salfred	int scqn = qp_get_scqn(qpc);
2653255932Salfred	u32 srqn = qp_get_srqn(qpc) & 0xffffff;
2654255932Salfred	int use_srq = (qp_get_srqn(qpc) >> 24) & 1;
2655255932Salfred	struct res_srq *srq;
2656255932Salfred	int local_qpn = be32_to_cpu(qpc->local_qpn) & 0xffffff;
2657255932Salfred
2658255932Salfred	err = qp_res_start_move_to(dev, slave, qpn, RES_QP_HW, &qp, 0);
2659255932Salfred	if (err)
2660255932Salfred		return err;
2661255932Salfred	qp->local_qpn = local_qpn;
2662272027Shselasky	qp->sched_queue = 0;
2663272027Shselasky	qp->param3 = 0;
2664272027Shselasky	qp->vlan_control = 0;
2665272027Shselasky	qp->fvl_rx = 0;
2666272027Shselasky	qp->pri_path_fl = 0;
2667272027Shselasky	qp->vlan_index = 0;
2668272027Shselasky	qp->feup = 0;
2669272027Shselasky	qp->qpc_flags = be32_to_cpu(qpc->flags);
2670255932Salfred
2671255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
2672255932Salfred	if (err)
2673255932Salfred		goto ex_abort;
2674255932Salfred
2675255932Salfred	err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt);
2676255932Salfred	if (err)
2677255932Salfred		goto ex_put_mtt;
2678255932Salfred
2679255932Salfred	err = get_res(dev, slave, rcqn, RES_CQ, &rcq);
2680255932Salfred	if (err)
2681255932Salfred		goto ex_put_mtt;
2682255932Salfred
2683255932Salfred	if (scqn != rcqn) {
2684255932Salfred		err = get_res(dev, slave, scqn, RES_CQ, &scq);
2685255932Salfred		if (err)
2686255932Salfred			goto ex_put_rcq;
2687255932Salfred	} else
2688255932Salfred		scq = rcq;
2689255932Salfred
2690255932Salfred	if (use_srq) {
2691255932Salfred		err = get_res(dev, slave, srqn, RES_SRQ, &srq);
2692255932Salfred		if (err)
2693255932Salfred			goto ex_put_scq;
2694255932Salfred	}
2695255932Salfred
2696255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, qpc);
2697255932Salfred	update_pkey_index(dev, slave, inbox);
2698255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2699255932Salfred	if (err)
2700255932Salfred		goto ex_put_srq;
2701255932Salfred	atomic_inc(&mtt->ref_count);
2702255932Salfred	qp->mtt = mtt;
2703255932Salfred	atomic_inc(&rcq->ref_count);
2704255932Salfred	qp->rcq = rcq;
2705255932Salfred	atomic_inc(&scq->ref_count);
2706255932Salfred	qp->scq = scq;
2707255932Salfred
2708255932Salfred	if (scqn != rcqn)
2709255932Salfred		put_res(dev, slave, scqn, RES_CQ);
2710255932Salfred
2711255932Salfred	if (use_srq) {
2712255932Salfred		atomic_inc(&srq->ref_count);
2713255932Salfred		put_res(dev, slave, srqn, RES_SRQ);
2714255932Salfred		qp->srq = srq;
2715255932Salfred	}
2716255932Salfred	put_res(dev, slave, rcqn, RES_CQ);
2717255932Salfred	put_res(dev, slave, mtt_base, RES_MTT);
2718255932Salfred	res_end_move(dev, slave, RES_QP, qpn);
2719255932Salfred
2720255932Salfred	return 0;
2721255932Salfred
2722255932Salfredex_put_srq:
2723255932Salfred	if (use_srq)
2724255932Salfred		put_res(dev, slave, srqn, RES_SRQ);
2725255932Salfredex_put_scq:
2726255932Salfred	if (scqn != rcqn)
2727255932Salfred		put_res(dev, slave, scqn, RES_CQ);
2728255932Salfredex_put_rcq:
2729255932Salfred	put_res(dev, slave, rcqn, RES_CQ);
2730255932Salfredex_put_mtt:
2731255932Salfred	put_res(dev, slave, mtt_base, RES_MTT);
2732255932Salfredex_abort:
2733255932Salfred	res_abort_move(dev, slave, RES_QP, qpn);
2734255932Salfred
2735255932Salfred	return err;
2736255932Salfred}
2737255932Salfred
2738255932Salfredstatic int eq_get_mtt_addr(struct mlx4_eq_context *eqc)
2739255932Salfred{
2740255932Salfred	return be32_to_cpu(eqc->mtt_base_addr_l) & 0xfffffff8;
2741255932Salfred}
2742255932Salfred
2743255932Salfredstatic int eq_get_mtt_size(struct mlx4_eq_context *eqc)
2744255932Salfred{
2745255932Salfred	int log_eq_size = eqc->log_eq_size & 0x1f;
2746255932Salfred	int page_shift = (eqc->log_page_size & 0x3f) + 12;
2747255932Salfred
2748255932Salfred	if (log_eq_size + 5 < page_shift)
2749255932Salfred		return 1;
2750255932Salfred
2751255932Salfred	return 1 << (log_eq_size + 5 - page_shift);
2752255932Salfred}
2753255932Salfred
2754255932Salfredstatic int cq_get_mtt_addr(struct mlx4_cq_context *cqc)
2755255932Salfred{
2756255932Salfred	return be32_to_cpu(cqc->mtt_base_addr_l) & 0xfffffff8;
2757255932Salfred}
2758255932Salfred
2759255932Salfredstatic int cq_get_mtt_size(struct mlx4_cq_context *cqc)
2760255932Salfred{
2761255932Salfred	int log_cq_size = (be32_to_cpu(cqc->logsize_usrpage) >> 24) & 0x1f;
2762255932Salfred	int page_shift = (cqc->log_page_size & 0x3f) + 12;
2763255932Salfred
2764255932Salfred	if (log_cq_size + 5 < page_shift)
2765255932Salfred		return 1;
2766255932Salfred
2767255932Salfred	return 1 << (log_cq_size + 5 - page_shift);
2768255932Salfred}
2769255932Salfred
2770255932Salfredint mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave,
2771255932Salfred			  struct mlx4_vhcr *vhcr,
2772255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2773255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2774255932Salfred			  struct mlx4_cmd_info *cmd)
2775255932Salfred{
2776255932Salfred	int err;
2777255932Salfred	int eqn = vhcr->in_modifier;
2778255932Salfred	int res_id = (slave << 8) | eqn;
2779255932Salfred	struct mlx4_eq_context *eqc = inbox->buf;
2780255932Salfred	int mtt_base = eq_get_mtt_addr(eqc) / dev->caps.mtt_entry_sz;
2781255932Salfred	int mtt_size = eq_get_mtt_size(eqc);
2782255932Salfred	struct res_eq *eq;
2783255932Salfred	struct res_mtt *mtt;
2784255932Salfred
2785255932Salfred	err = add_res_range(dev, slave, res_id, 1, RES_EQ, 0);
2786255932Salfred	if (err)
2787255932Salfred		return err;
2788255932Salfred	err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_HW, &eq);
2789255932Salfred	if (err)
2790255932Salfred		goto out_add;
2791255932Salfred
2792255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
2793255932Salfred	if (err)
2794255932Salfred		goto out_move;
2795255932Salfred
2796255932Salfred	err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt);
2797255932Salfred	if (err)
2798255932Salfred		goto out_put;
2799255932Salfred
2800255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2801255932Salfred	if (err)
2802255932Salfred		goto out_put;
2803255932Salfred
2804255932Salfred	atomic_inc(&mtt->ref_count);
2805255932Salfred	eq->mtt = mtt;
2806255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
2807255932Salfred	res_end_move(dev, slave, RES_EQ, res_id);
2808255932Salfred	return 0;
2809255932Salfred
2810255932Salfredout_put:
2811255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
2812255932Salfredout_move:
2813255932Salfred	res_abort_move(dev, slave, RES_EQ, res_id);
2814255932Salfredout_add:
2815255932Salfred	rem_res_range(dev, slave, res_id, 1, RES_EQ, 0);
2816255932Salfred	return err;
2817255932Salfred}
2818255932Salfred
2819255932Salfredstatic int get_containing_mtt(struct mlx4_dev *dev, int slave, int start,
2820255932Salfred			      int len, struct res_mtt **res)
2821255932Salfred{
2822255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
2823255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
2824255932Salfred	struct res_mtt *mtt;
2825255932Salfred	int err = -EINVAL;
2826255932Salfred
2827255932Salfred	spin_lock_irq(mlx4_tlock(dev));
2828255932Salfred	list_for_each_entry(mtt, &tracker->slave_list[slave].res_list[RES_MTT],
2829255932Salfred			    com.list) {
2830255932Salfred		if (!check_mtt_range(dev, slave, start, len, mtt)) {
2831255932Salfred			*res = mtt;
2832255932Salfred			mtt->com.from_state = mtt->com.state;
2833255932Salfred			mtt->com.state = RES_MTT_BUSY;
2834255932Salfred			err = 0;
2835255932Salfred			break;
2836255932Salfred		}
2837255932Salfred	}
2838255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
2839255932Salfred
2840255932Salfred	return err;
2841255932Salfred}
2842255932Salfred
2843255932Salfredstatic int verify_qp_parameters(struct mlx4_dev *dev,
2844255932Salfred				struct mlx4_cmd_mailbox *inbox,
2845255932Salfred				enum qp_transition transition, u8 slave)
2846255932Salfred{
2847255932Salfred	u32			qp_type;
2848255932Salfred	struct mlx4_qp_context	*qp_ctx;
2849255932Salfred	enum mlx4_qp_optpar	optpar;
2850255932Salfred	int port;
2851255932Salfred	int num_gids;
2852255932Salfred
2853255932Salfred	qp_ctx  = inbox->buf + 8;
2854255932Salfred	qp_type	= (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff;
2855255932Salfred	optpar	= be32_to_cpu(*(__be32 *) inbox->buf);
2856255932Salfred
2857255932Salfred	switch (qp_type) {
2858255932Salfred	case MLX4_QP_ST_RC:
2859255932Salfred	case MLX4_QP_ST_UC:
2860255932Salfred		switch (transition) {
2861255932Salfred		case QP_TRANS_INIT2RTR:
2862255932Salfred		case QP_TRANS_RTR2RTS:
2863255932Salfred		case QP_TRANS_RTS2RTS:
2864255932Salfred		case QP_TRANS_SQD2SQD:
2865255932Salfred		case QP_TRANS_SQD2RTS:
2866255932Salfred			if (slave != mlx4_master_func_num(dev))
2867255932Salfred				if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH) {
2868255932Salfred					port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
2869255932Salfred					if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB)
2870255932Salfred						num_gids = mlx4_get_slave_num_gids(dev, slave);
2871255932Salfred					else
2872255932Salfred						num_gids = 1;
2873255932Salfred					if (qp_ctx->pri_path.mgid_index >= num_gids)
2874255932Salfred						return -EINVAL;
2875255932Salfred				}
2876255932Salfred				if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) {
2877255932Salfred					port = (qp_ctx->alt_path.sched_queue >> 6 & 1) + 1;
2878255932Salfred					if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB)
2879255932Salfred						num_gids = mlx4_get_slave_num_gids(dev, slave);
2880255932Salfred					else
2881255932Salfred						num_gids = 1;
2882255932Salfred					if (qp_ctx->alt_path.mgid_index >= num_gids)
2883255932Salfred						return -EINVAL;
2884255932Salfred				}
2885255932Salfred			break;
2886255932Salfred		default:
2887255932Salfred			break;
2888255932Salfred		}
2889255932Salfred
2890255932Salfred		break;
2891255932Salfred	default:
2892255932Salfred		break;
2893255932Salfred	}
2894255932Salfred
2895255932Salfred	return 0;
2896255932Salfred}
2897255932Salfred
2898255932Salfredint mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave,
2899255932Salfred			   struct mlx4_vhcr *vhcr,
2900255932Salfred			   struct mlx4_cmd_mailbox *inbox,
2901255932Salfred			   struct mlx4_cmd_mailbox *outbox,
2902255932Salfred			   struct mlx4_cmd_info *cmd)
2903255932Salfred{
2904255932Salfred	struct mlx4_mtt mtt;
2905255932Salfred	__be64 *page_list = inbox->buf;
2906255932Salfred	u64 *pg_list = (u64 *)page_list;
2907255932Salfred	int i;
2908255932Salfred	struct res_mtt *rmtt = NULL;
2909255932Salfred	int start = be64_to_cpu(page_list[0]);
2910255932Salfred	int npages = vhcr->in_modifier;
2911255932Salfred	int err;
2912255932Salfred
2913255932Salfred	err = get_containing_mtt(dev, slave, start, npages, &rmtt);
2914255932Salfred	if (err)
2915255932Salfred		return err;
2916255932Salfred
2917255932Salfred	/* Call the SW implementation of write_mtt:
2918255932Salfred	 * - Prepare a dummy mtt struct
2919255932Salfred	 * - Translate inbox contents to simple addresses in host endianess */
2920255932Salfred	mtt.offset = 0;  /* TBD this is broken but I don't handle it since
2921255932Salfred			    we don't really use it */
2922255932Salfred	mtt.order = 0;
2923255932Salfred	mtt.page_shift = 0;
2924255932Salfred	for (i = 0; i < npages; ++i)
2925255932Salfred		pg_list[i + 2] = (be64_to_cpu(page_list[i + 2]) & ~1ULL);
2926255932Salfred
2927255932Salfred	err = __mlx4_write_mtt(dev, &mtt, be64_to_cpu(page_list[0]), npages,
2928255932Salfred			       ((u64 *)page_list + 2));
2929255932Salfred
2930255932Salfred	if (rmtt)
2931255932Salfred		put_res(dev, slave, rmtt->com.res_id, RES_MTT);
2932255932Salfred
2933255932Salfred	return err;
2934255932Salfred}
2935255932Salfred
2936255932Salfredint mlx4_HW2SW_EQ_wrapper(struct mlx4_dev *dev, int slave,
2937255932Salfred			  struct mlx4_vhcr *vhcr,
2938255932Salfred			  struct mlx4_cmd_mailbox *inbox,
2939255932Salfred			  struct mlx4_cmd_mailbox *outbox,
2940255932Salfred			  struct mlx4_cmd_info *cmd)
2941255932Salfred{
2942255932Salfred	int eqn = vhcr->in_modifier;
2943255932Salfred	int res_id = eqn | (slave << 8);
2944255932Salfred	struct res_eq *eq;
2945255932Salfred	int err;
2946255932Salfred
2947255932Salfred	err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_RESERVED, &eq);
2948255932Salfred	if (err)
2949255932Salfred		return err;
2950255932Salfred
2951255932Salfred	err = get_res(dev, slave, eq->mtt->com.res_id, RES_MTT, NULL);
2952255932Salfred	if (err)
2953255932Salfred		goto ex_abort;
2954255932Salfred
2955255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
2956255932Salfred	if (err)
2957255932Salfred		goto ex_put;
2958255932Salfred
2959255932Salfred	atomic_dec(&eq->mtt->ref_count);
2960255932Salfred	put_res(dev, slave, eq->mtt->com.res_id, RES_MTT);
2961255932Salfred	res_end_move(dev, slave, RES_EQ, res_id);
2962255932Salfred	rem_res_range(dev, slave, res_id, 1, RES_EQ, 0);
2963255932Salfred
2964255932Salfred	return 0;
2965255932Salfred
2966255932Salfredex_put:
2967255932Salfred	put_res(dev, slave, eq->mtt->com.res_id, RES_MTT);
2968255932Salfredex_abort:
2969255932Salfred	res_abort_move(dev, slave, RES_EQ, res_id);
2970255932Salfred
2971255932Salfred	return err;
2972255932Salfred}
2973255932Salfred
2974255932Salfredint mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe)
2975255932Salfred{
2976255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
2977255932Salfred	struct mlx4_slave_event_eq_info *event_eq;
2978255932Salfred	struct mlx4_cmd_mailbox *mailbox;
2979255932Salfred	u32 in_modifier = 0;
2980255932Salfred	int err;
2981255932Salfred	int res_id;
2982255932Salfred	struct res_eq *req;
2983255932Salfred
2984255932Salfred	if (!priv->mfunc.master.slave_state)
2985255932Salfred		return -EINVAL;
2986255932Salfred
2987272027Shselasky	/* check for slave valid, slave not PF, and slave active */
2988272027Shselasky	if (slave < 0 || slave >= dev->num_slaves ||
2989272027Shselasky	    slave == dev->caps.function ||
2990272027Shselasky	    !priv->mfunc.master.slave_state[slave].active)
2991272027Shselasky		return 0;
2992272027Shselasky
2993255932Salfred	event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type];
2994255932Salfred
2995255932Salfred	/* Create the event only if the slave is registered */
2996255932Salfred	if (event_eq->eqn < 0)
2997255932Salfred		return 0;
2998255932Salfred
2999255932Salfred	mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]);
3000255932Salfred	res_id = (slave << 8) | event_eq->eqn;
3001255932Salfred	err = get_res(dev, slave, res_id, RES_EQ, &req);
3002255932Salfred	if (err)
3003255932Salfred		goto unlock;
3004255932Salfred
3005255932Salfred	if (req->com.from_state != RES_EQ_HW) {
3006255932Salfred		err = -EINVAL;
3007255932Salfred		goto put;
3008255932Salfred	}
3009255932Salfred
3010255932Salfred	mailbox = mlx4_alloc_cmd_mailbox(dev);
3011255932Salfred	if (IS_ERR(mailbox)) {
3012255932Salfred		err = PTR_ERR(mailbox);
3013255932Salfred		goto put;
3014255932Salfred	}
3015255932Salfred
3016255932Salfred	if (eqe->type == MLX4_EVENT_TYPE_CMD) {
3017255932Salfred		++event_eq->token;
3018255932Salfred		eqe->event.cmd.token = cpu_to_be16(event_eq->token);
3019255932Salfred	}
3020255932Salfred
3021255932Salfred	memcpy(mailbox->buf, (u8 *) eqe, 28);
3022255932Salfred
3023255932Salfred	in_modifier = (slave & 0xff) | ((event_eq->eqn & 0xff) << 16);
3024255932Salfred
3025255932Salfred	err = mlx4_cmd(dev, mailbox->dma, in_modifier, 0,
3026255932Salfred		       MLX4_CMD_GEN_EQE, MLX4_CMD_TIME_CLASS_B,
3027255932Salfred		       MLX4_CMD_NATIVE);
3028255932Salfred
3029255932Salfred	put_res(dev, slave, res_id, RES_EQ);
3030255932Salfred	mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]);
3031255932Salfred	mlx4_free_cmd_mailbox(dev, mailbox);
3032255932Salfred	return err;
3033255932Salfred
3034255932Salfredput:
3035255932Salfred	put_res(dev, slave, res_id, RES_EQ);
3036255932Salfred
3037255932Salfredunlock:
3038255932Salfred	mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]);
3039255932Salfred	return err;
3040255932Salfred}
3041255932Salfred
3042255932Salfredint mlx4_QUERY_EQ_wrapper(struct mlx4_dev *dev, int slave,
3043255932Salfred			  struct mlx4_vhcr *vhcr,
3044255932Salfred			  struct mlx4_cmd_mailbox *inbox,
3045255932Salfred			  struct mlx4_cmd_mailbox *outbox,
3046255932Salfred			  struct mlx4_cmd_info *cmd)
3047255932Salfred{
3048255932Salfred	int eqn = vhcr->in_modifier;
3049255932Salfred	int res_id = eqn | (slave << 8);
3050255932Salfred	struct res_eq *eq;
3051255932Salfred	int err;
3052255932Salfred
3053255932Salfred	err = get_res(dev, slave, res_id, RES_EQ, &eq);
3054255932Salfred	if (err)
3055255932Salfred		return err;
3056255932Salfred
3057255932Salfred	if (eq->com.from_state != RES_EQ_HW) {
3058255932Salfred		err = -EINVAL;
3059255932Salfred		goto ex_put;
3060255932Salfred	}
3061255932Salfred
3062255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3063255932Salfred
3064255932Salfredex_put:
3065255932Salfred	put_res(dev, slave, res_id, RES_EQ);
3066255932Salfred	return err;
3067255932Salfred}
3068255932Salfred
3069255932Salfredint mlx4_SW2HW_CQ_wrapper(struct mlx4_dev *dev, int slave,
3070255932Salfred			  struct mlx4_vhcr *vhcr,
3071255932Salfred			  struct mlx4_cmd_mailbox *inbox,
3072255932Salfred			  struct mlx4_cmd_mailbox *outbox,
3073255932Salfred			  struct mlx4_cmd_info *cmd)
3074255932Salfred{
3075255932Salfred	int err;
3076255932Salfred	int cqn = vhcr->in_modifier;
3077255932Salfred	struct mlx4_cq_context *cqc = inbox->buf;
3078255932Salfred	int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz;
3079255932Salfred	struct res_cq *cq;
3080255932Salfred	struct res_mtt *mtt;
3081255932Salfred
3082255932Salfred	err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_HW, &cq);
3083255932Salfred	if (err)
3084255932Salfred		return err;
3085255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
3086255932Salfred	if (err)
3087255932Salfred		goto out_move;
3088255932Salfred	err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt);
3089255932Salfred	if (err)
3090255932Salfred		goto out_put;
3091255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3092255932Salfred	if (err)
3093255932Salfred		goto out_put;
3094255932Salfred	atomic_inc(&mtt->ref_count);
3095255932Salfred	cq->mtt = mtt;
3096255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3097255932Salfred	res_end_move(dev, slave, RES_CQ, cqn);
3098255932Salfred	return 0;
3099255932Salfred
3100255932Salfredout_put:
3101255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3102255932Salfredout_move:
3103255932Salfred	res_abort_move(dev, slave, RES_CQ, cqn);
3104255932Salfred	return err;
3105255932Salfred}
3106255932Salfred
3107255932Salfredint mlx4_HW2SW_CQ_wrapper(struct mlx4_dev *dev, int slave,
3108255932Salfred			  struct mlx4_vhcr *vhcr,
3109255932Salfred			  struct mlx4_cmd_mailbox *inbox,
3110255932Salfred			  struct mlx4_cmd_mailbox *outbox,
3111255932Salfred			  struct mlx4_cmd_info *cmd)
3112255932Salfred{
3113255932Salfred	int err;
3114255932Salfred	int cqn = vhcr->in_modifier;
3115255932Salfred	struct res_cq *cq;
3116255932Salfred
3117255932Salfred	err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_ALLOCATED, &cq);
3118255932Salfred	if (err)
3119255932Salfred		return err;
3120255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3121255932Salfred	if (err)
3122255932Salfred		goto out_move;
3123255932Salfred	atomic_dec(&cq->mtt->ref_count);
3124255932Salfred	res_end_move(dev, slave, RES_CQ, cqn);
3125255932Salfred	return 0;
3126255932Salfred
3127255932Salfredout_move:
3128255932Salfred	res_abort_move(dev, slave, RES_CQ, cqn);
3129255932Salfred	return err;
3130255932Salfred}
3131255932Salfred
3132255932Salfredint mlx4_QUERY_CQ_wrapper(struct mlx4_dev *dev, int slave,
3133255932Salfred			  struct mlx4_vhcr *vhcr,
3134255932Salfred			  struct mlx4_cmd_mailbox *inbox,
3135255932Salfred			  struct mlx4_cmd_mailbox *outbox,
3136255932Salfred			  struct mlx4_cmd_info *cmd)
3137255932Salfred{
3138255932Salfred	int cqn = vhcr->in_modifier;
3139255932Salfred	struct res_cq *cq;
3140255932Salfred	int err;
3141255932Salfred
3142255932Salfred	err = get_res(dev, slave, cqn, RES_CQ, &cq);
3143255932Salfred	if (err)
3144255932Salfred		return err;
3145255932Salfred
3146255932Salfred	if (cq->com.from_state != RES_CQ_HW)
3147255932Salfred		goto ex_put;
3148255932Salfred
3149255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3150255932Salfredex_put:
3151255932Salfred	put_res(dev, slave, cqn, RES_CQ);
3152255932Salfred
3153255932Salfred	return err;
3154255932Salfred}
3155255932Salfred
3156255932Salfredstatic int handle_resize(struct mlx4_dev *dev, int slave,
3157255932Salfred			 struct mlx4_vhcr *vhcr,
3158255932Salfred			 struct mlx4_cmd_mailbox *inbox,
3159255932Salfred			 struct mlx4_cmd_mailbox *outbox,
3160255932Salfred			 struct mlx4_cmd_info *cmd,
3161255932Salfred			 struct res_cq *cq)
3162255932Salfred{
3163255932Salfred	int err;
3164255932Salfred	struct res_mtt *orig_mtt;
3165255932Salfred	struct res_mtt *mtt;
3166255932Salfred	struct mlx4_cq_context *cqc = inbox->buf;
3167255932Salfred	int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz;
3168255932Salfred
3169255932Salfred	err = get_res(dev, slave, cq->mtt->com.res_id, RES_MTT, &orig_mtt);
3170255932Salfred	if (err)
3171255932Salfred		return err;
3172255932Salfred
3173255932Salfred	if (orig_mtt != cq->mtt) {
3174255932Salfred		err = -EINVAL;
3175255932Salfred		goto ex_put;
3176255932Salfred	}
3177255932Salfred
3178255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
3179255932Salfred	if (err)
3180255932Salfred		goto ex_put;
3181255932Salfred
3182255932Salfred	err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt);
3183255932Salfred	if (err)
3184255932Salfred		goto ex_put1;
3185255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3186255932Salfred	if (err)
3187255932Salfred		goto ex_put1;
3188255932Salfred	atomic_dec(&orig_mtt->ref_count);
3189255932Salfred	put_res(dev, slave, orig_mtt->com.res_id, RES_MTT);
3190255932Salfred	atomic_inc(&mtt->ref_count);
3191255932Salfred	cq->mtt = mtt;
3192255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3193255932Salfred	return 0;
3194255932Salfred
3195255932Salfredex_put1:
3196255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3197255932Salfredex_put:
3198255932Salfred	put_res(dev, slave, orig_mtt->com.res_id, RES_MTT);
3199255932Salfred
3200255932Salfred	return err;
3201255932Salfred
3202255932Salfred}
3203255932Salfred
3204255932Salfredint mlx4_MODIFY_CQ_wrapper(struct mlx4_dev *dev, int slave,
3205255932Salfred			   struct mlx4_vhcr *vhcr,
3206255932Salfred			   struct mlx4_cmd_mailbox *inbox,
3207255932Salfred			   struct mlx4_cmd_mailbox *outbox,
3208255932Salfred			   struct mlx4_cmd_info *cmd)
3209255932Salfred{
3210255932Salfred	int cqn = vhcr->in_modifier;
3211255932Salfred	struct res_cq *cq;
3212255932Salfred	int err;
3213255932Salfred
3214255932Salfred	err = get_res(dev, slave, cqn, RES_CQ, &cq);
3215255932Salfred	if (err)
3216255932Salfred		return err;
3217255932Salfred
3218255932Salfred	if (cq->com.from_state != RES_CQ_HW)
3219255932Salfred		goto ex_put;
3220255932Salfred
3221255932Salfred	if (vhcr->op_modifier == 0) {
3222255932Salfred		err = handle_resize(dev, slave, vhcr, inbox, outbox, cmd, cq);
3223255932Salfred		goto ex_put;
3224255932Salfred	}
3225255932Salfred
3226255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3227255932Salfredex_put:
3228255932Salfred	put_res(dev, slave, cqn, RES_CQ);
3229255932Salfred
3230255932Salfred	return err;
3231255932Salfred}
3232255932Salfred
3233255932Salfredstatic int srq_get_mtt_size(struct mlx4_srq_context *srqc)
3234255932Salfred{
3235255932Salfred	int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf;
3236255932Salfred	int log_rq_stride = srqc->logstride & 7;
3237255932Salfred	int page_shift = (srqc->log_page_size & 0x3f) + 12;
3238255932Salfred
3239255932Salfred	if (log_srq_size + log_rq_stride + 4 < page_shift)
3240255932Salfred		return 1;
3241255932Salfred
3242255932Salfred	return 1 << (log_srq_size + log_rq_stride + 4 - page_shift);
3243255932Salfred}
3244255932Salfred
3245255932Salfredint mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
3246255932Salfred			   struct mlx4_vhcr *vhcr,
3247255932Salfred			   struct mlx4_cmd_mailbox *inbox,
3248255932Salfred			   struct mlx4_cmd_mailbox *outbox,
3249255932Salfred			   struct mlx4_cmd_info *cmd)
3250255932Salfred{
3251255932Salfred	int err;
3252255932Salfred	int srqn = vhcr->in_modifier;
3253255932Salfred	struct res_mtt *mtt;
3254255932Salfred	struct res_srq *srq;
3255255932Salfred	struct mlx4_srq_context *srqc = inbox->buf;
3256255932Salfred	int mtt_base = srq_get_mtt_addr(srqc) / dev->caps.mtt_entry_sz;
3257255932Salfred
3258255932Salfred	if (srqn != (be32_to_cpu(srqc->state_logsize_srqn) & 0xffffff))
3259255932Salfred		return -EINVAL;
3260255932Salfred
3261255932Salfred	err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_HW, &srq);
3262255932Salfred	if (err)
3263255932Salfred		return err;
3264255932Salfred	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
3265255932Salfred	if (err)
3266255932Salfred		goto ex_abort;
3267255932Salfred	err = check_mtt_range(dev, slave, mtt_base, srq_get_mtt_size(srqc),
3268255932Salfred			      mtt);
3269255932Salfred	if (err)
3270255932Salfred		goto ex_put_mtt;
3271255932Salfred
3272255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3273255932Salfred	if (err)
3274255932Salfred		goto ex_put_mtt;
3275255932Salfred
3276255932Salfred	atomic_inc(&mtt->ref_count);
3277255932Salfred	srq->mtt = mtt;
3278255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3279255932Salfred	res_end_move(dev, slave, RES_SRQ, srqn);
3280255932Salfred	return 0;
3281255932Salfred
3282255932Salfredex_put_mtt:
3283255932Salfred	put_res(dev, slave, mtt->com.res_id, RES_MTT);
3284255932Salfredex_abort:
3285255932Salfred	res_abort_move(dev, slave, RES_SRQ, srqn);
3286255932Salfred
3287255932Salfred	return err;
3288255932Salfred}
3289255932Salfred
3290255932Salfredint mlx4_HW2SW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
3291255932Salfred			   struct mlx4_vhcr *vhcr,
3292255932Salfred			   struct mlx4_cmd_mailbox *inbox,
3293255932Salfred			   struct mlx4_cmd_mailbox *outbox,
3294255932Salfred			   struct mlx4_cmd_info *cmd)
3295255932Salfred{
3296255932Salfred	int err;
3297255932Salfred	int srqn = vhcr->in_modifier;
3298255932Salfred	struct res_srq *srq;
3299255932Salfred
3300255932Salfred	err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_ALLOCATED, &srq);
3301255932Salfred	if (err)
3302255932Salfred		return err;
3303255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3304255932Salfred	if (err)
3305255932Salfred		goto ex_abort;
3306255932Salfred	atomic_dec(&srq->mtt->ref_count);
3307255932Salfred	if (srq->cq)
3308255932Salfred		atomic_dec(&srq->cq->ref_count);
3309255932Salfred	res_end_move(dev, slave, RES_SRQ, srqn);
3310255932Salfred
3311255932Salfred	return 0;
3312255932Salfred
3313255932Salfredex_abort:
3314255932Salfred	res_abort_move(dev, slave, RES_SRQ, srqn);
3315255932Salfred
3316255932Salfred	return err;
3317255932Salfred}
3318255932Salfred
3319255932Salfredint mlx4_QUERY_SRQ_wrapper(struct mlx4_dev *dev, int slave,
3320255932Salfred			   struct mlx4_vhcr *vhcr,
3321255932Salfred			   struct mlx4_cmd_mailbox *inbox,
3322255932Salfred			   struct mlx4_cmd_mailbox *outbox,
3323255932Salfred			   struct mlx4_cmd_info *cmd)
3324255932Salfred{
3325255932Salfred	int err;
3326255932Salfred	int srqn = vhcr->in_modifier;
3327255932Salfred	struct res_srq *srq;
3328255932Salfred
3329255932Salfred	err = get_res(dev, slave, srqn, RES_SRQ, &srq);
3330255932Salfred	if (err)
3331255932Salfred		return err;
3332255932Salfred	if (srq->com.from_state != RES_SRQ_HW) {
3333255932Salfred		err = -EBUSY;
3334255932Salfred		goto out;
3335255932Salfred	}
3336255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3337255932Salfredout:
3338255932Salfred	put_res(dev, slave, srqn, RES_SRQ);
3339255932Salfred	return err;
3340255932Salfred}
3341255932Salfred
3342255932Salfredint mlx4_ARM_SRQ_wrapper(struct mlx4_dev *dev, int slave,
3343255932Salfred			 struct mlx4_vhcr *vhcr,
3344255932Salfred			 struct mlx4_cmd_mailbox *inbox,
3345255932Salfred			 struct mlx4_cmd_mailbox *outbox,
3346255932Salfred			 struct mlx4_cmd_info *cmd)
3347255932Salfred{
3348255932Salfred	int err;
3349255932Salfred	int srqn = vhcr->in_modifier;
3350255932Salfred	struct res_srq *srq;
3351255932Salfred
3352255932Salfred	err = get_res(dev, slave, srqn, RES_SRQ, &srq);
3353255932Salfred	if (err)
3354255932Salfred		return err;
3355255932Salfred
3356255932Salfred	if (srq->com.from_state != RES_SRQ_HW) {
3357255932Salfred		err = -EBUSY;
3358255932Salfred		goto out;
3359255932Salfred	}
3360255932Salfred
3361255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3362255932Salfredout:
3363255932Salfred	put_res(dev, slave, srqn, RES_SRQ);
3364255932Salfred	return err;
3365255932Salfred}
3366255932Salfred
3367255932Salfredint mlx4_GEN_QP_wrapper(struct mlx4_dev *dev, int slave,
3368255932Salfred			struct mlx4_vhcr *vhcr,
3369255932Salfred			struct mlx4_cmd_mailbox *inbox,
3370255932Salfred			struct mlx4_cmd_mailbox *outbox,
3371255932Salfred			struct mlx4_cmd_info *cmd)
3372255932Salfred{
3373255932Salfred	int err;
3374255932Salfred	int qpn = vhcr->in_modifier & 0x7fffff;
3375255932Salfred	struct res_qp *qp;
3376255932Salfred
3377255932Salfred	err = get_res(dev, slave, qpn, RES_QP, &qp);
3378255932Salfred	if (err)
3379255932Salfred		return err;
3380255932Salfred	if (qp->com.from_state != RES_QP_HW) {
3381255932Salfred		err = -EBUSY;
3382255932Salfred		goto out;
3383255932Salfred	}
3384255932Salfred
3385255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3386255932Salfredout:
3387255932Salfred	put_res(dev, slave, qpn, RES_QP);
3388255932Salfred	return err;
3389255932Salfred}
3390255932Salfred
3391255932Salfredint mlx4_INIT2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
3392255932Salfred			      struct mlx4_vhcr *vhcr,
3393255932Salfred			      struct mlx4_cmd_mailbox *inbox,
3394255932Salfred			      struct mlx4_cmd_mailbox *outbox,
3395255932Salfred			      struct mlx4_cmd_info *cmd)
3396255932Salfred{
3397255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3398255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3399255932Salfred	update_pkey_index(dev, slave, inbox);
3400255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3401255932Salfred}
3402255932Salfred
3403255932Salfredstatic int roce_verify_mac(struct mlx4_dev *dev, int slave,
3404255932Salfred				struct mlx4_qp_context *qpc,
3405255932Salfred				struct mlx4_cmd_mailbox *inbox)
3406255932Salfred{
3407255932Salfred	u64 mac;
3408255932Salfred	int port;
3409255932Salfred	u32 ts = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
3410255932Salfred	u8 sched = *(u8 *)(inbox->buf + 64);
3411255932Salfred	u8 smac_ix;
3412255932Salfred
3413255932Salfred	port = (sched >> 6 & 1) + 1;
3414255932Salfred	if (mlx4_is_eth(dev, port) && (ts != MLX4_QP_ST_MLX)) {
3415255932Salfred		smac_ix = qpc->pri_path.grh_mylmc & 0x7f;
3416255932Salfred		if (mac_find_smac_ix_in_slave(dev, slave, port, smac_ix, &mac))
3417255932Salfred			return -ENOENT;
3418255932Salfred	}
3419255932Salfred	return 0;
3420255932Salfred}
3421255932Salfred
3422255932Salfredint mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
3423255932Salfred			     struct mlx4_vhcr *vhcr,
3424255932Salfred			     struct mlx4_cmd_mailbox *inbox,
3425255932Salfred			     struct mlx4_cmd_mailbox *outbox,
3426255932Salfred			     struct mlx4_cmd_info *cmd)
3427255932Salfred{
3428255932Salfred	int err;
3429255932Salfred	struct mlx4_qp_context *qpc = inbox->buf + 8;
3430272027Shselasky	int qpn = vhcr->in_modifier & 0x7fffff;
3431272027Shselasky	struct res_qp *qp;
3432272027Shselasky	u8 orig_sched_queue;
3433272027Shselasky	__be32	orig_param3 = qpc->param3;
3434272027Shselasky	u8 orig_vlan_control = qpc->pri_path.vlan_control;
3435272027Shselasky	u8 orig_fvl_rx = qpc->pri_path.fvl_rx;
3436272027Shselasky	u8 orig_pri_path_fl = qpc->pri_path.fl;
3437272027Shselasky	u8 orig_vlan_index = qpc->pri_path.vlan_index;
3438272027Shselasky	u8 orig_feup = qpc->pri_path.feup;
3439255932Salfred
3440255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_INIT2RTR, slave);
3441255932Salfred	if (err)
3442255932Salfred		return err;
3443255932Salfred
3444255932Salfred	if (roce_verify_mac(dev, slave, qpc, inbox))
3445255932Salfred		return -EINVAL;
3446255932Salfred
3447255932Salfred	update_pkey_index(dev, slave, inbox);
3448255932Salfred	update_gid(dev, inbox, (u8)slave);
3449255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, qpc);
3450272027Shselasky	orig_sched_queue = qpc->pri_path.sched_queue;
3451272027Shselasky
3452272027Shselasky	err = get_res(dev, slave, qpn, RES_QP, &qp);
3453255932Salfred	if (err)
3454255932Salfred		return err;
3455272027Shselasky	if (qp->com.from_state != RES_QP_HW) {
3456272027Shselasky		err = -EBUSY;
3457272027Shselasky		goto out;
3458272027Shselasky	}
3459255932Salfred
3460272027Shselasky	/* do not modify vport QP params for RSS QPs */
3461272027Shselasky	if (!(qp->qpc_flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET))) {
3462272027Shselasky		err = update_vport_qp_param(dev, inbox, slave, qpn);
3463272027Shselasky		if (err)
3464272027Shselasky			goto out;
3465272027Shselasky	}
3466272027Shselasky
3467272027Shselasky	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3468272027Shselaskyout:
3469272027Shselasky	/* if no error, save sched queue value passed in by VF. This is
3470272027Shselasky	 * essentially the QOS value provided by the VF. This will be useful
3471272027Shselasky	 * if we allow dynamic changes from VST back to VGT
3472272027Shselasky	 */
3473272027Shselasky	if (!err) {
3474272027Shselasky		qp->sched_queue = orig_sched_queue;
3475272027Shselasky		qp->param3	= orig_param3;
3476272027Shselasky		qp->vlan_control = orig_vlan_control;
3477272027Shselasky		qp->fvl_rx	=  orig_fvl_rx;
3478272027Shselasky		qp->pri_path_fl = orig_pri_path_fl;
3479272027Shselasky		qp->vlan_index  = orig_vlan_index;
3480272027Shselasky		qp->feup	= orig_feup;
3481272027Shselasky	}
3482272027Shselasky	put_res(dev, slave, qpn, RES_QP);
3483272027Shselasky	return err;
3484255932Salfred}
3485255932Salfred
3486255932Salfredint mlx4_RTR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3487255932Salfred			    struct mlx4_vhcr *vhcr,
3488255932Salfred			    struct mlx4_cmd_mailbox *inbox,
3489255932Salfred			    struct mlx4_cmd_mailbox *outbox,
3490255932Salfred			    struct mlx4_cmd_info *cmd)
3491255932Salfred{
3492255932Salfred	int err;
3493255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3494255932Salfred
3495255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_RTR2RTS, slave);
3496255932Salfred	if (err)
3497255932Salfred		return err;
3498255932Salfred
3499255932Salfred	update_pkey_index(dev, slave, inbox);
3500255932Salfred	update_gid(dev, inbox, (u8)slave);
3501255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3502255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3503255932Salfred}
3504255932Salfred
3505255932Salfredint mlx4_RTS2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3506255932Salfred			    struct mlx4_vhcr *vhcr,
3507255932Salfred			    struct mlx4_cmd_mailbox *inbox,
3508255932Salfred			    struct mlx4_cmd_mailbox *outbox,
3509255932Salfred			    struct mlx4_cmd_info *cmd)
3510255932Salfred{
3511255932Salfred	int err;
3512255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3513255932Salfred
3514255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_RTS2RTS, slave);
3515255932Salfred	if (err)
3516255932Salfred		return err;
3517255932Salfred
3518255932Salfred	update_pkey_index(dev, slave, inbox);
3519255932Salfred	update_gid(dev, inbox, (u8)slave);
3520255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3521255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3522255932Salfred}
3523255932Salfred
3524255932Salfred
3525255932Salfredint mlx4_SQERR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3526255932Salfred			      struct mlx4_vhcr *vhcr,
3527255932Salfred			      struct mlx4_cmd_mailbox *inbox,
3528255932Salfred			      struct mlx4_cmd_mailbox *outbox,
3529255932Salfred			      struct mlx4_cmd_info *cmd)
3530255932Salfred{
3531255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3532255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3533255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3534255932Salfred}
3535255932Salfred
3536255932Salfredint mlx4_SQD2SQD_QP_wrapper(struct mlx4_dev *dev, int slave,
3537255932Salfred			    struct mlx4_vhcr *vhcr,
3538255932Salfred			    struct mlx4_cmd_mailbox *inbox,
3539255932Salfred			    struct mlx4_cmd_mailbox *outbox,
3540255932Salfred			    struct mlx4_cmd_info *cmd)
3541255932Salfred{
3542255932Salfred	int err;
3543255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3544255932Salfred
3545255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_SQD2SQD, slave);
3546255932Salfred	if (err)
3547255932Salfred		return err;
3548255932Salfred
3549255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3550255932Salfred	update_gid(dev, inbox, (u8)slave);
3551255932Salfred	update_pkey_index(dev, slave, inbox);
3552255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3553255932Salfred}
3554255932Salfred
3555255932Salfredint mlx4_SQD2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3556255932Salfred			    struct mlx4_vhcr *vhcr,
3557255932Salfred			    struct mlx4_cmd_mailbox *inbox,
3558255932Salfred			    struct mlx4_cmd_mailbox *outbox,
3559255932Salfred			    struct mlx4_cmd_info *cmd)
3560255932Salfred{
3561255932Salfred	int err;
3562255932Salfred	struct mlx4_qp_context *context = inbox->buf + 8;
3563255932Salfred
3564255932Salfred	err = verify_qp_parameters(dev, inbox, QP_TRANS_SQD2RTS, slave);
3565255932Salfred	if (err)
3566255932Salfred		return err;
3567255932Salfred
3568255932Salfred	adjust_proxy_tun_qkey(dev, vhcr, context);
3569255932Salfred	update_gid(dev, inbox, (u8)slave);
3570255932Salfred	update_pkey_index(dev, slave, inbox);
3571255932Salfred	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3572255932Salfred}
3573255932Salfred
3574255932Salfredint mlx4_2RST_QP_wrapper(struct mlx4_dev *dev, int slave,
3575255932Salfred			 struct mlx4_vhcr *vhcr,
3576255932Salfred			 struct mlx4_cmd_mailbox *inbox,
3577255932Salfred			 struct mlx4_cmd_mailbox *outbox,
3578255932Salfred			 struct mlx4_cmd_info *cmd)
3579255932Salfred{
3580255932Salfred	int err;
3581255932Salfred	int qpn = vhcr->in_modifier & 0x7fffff;
3582255932Salfred	struct res_qp *qp;
3583255932Salfred
3584255932Salfred	err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED, &qp, 0);
3585255932Salfred	if (err)
3586255932Salfred		return err;
3587255932Salfred	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3588255932Salfred	if (err)
3589255932Salfred		goto ex_abort;
3590255932Salfred
3591255932Salfred	atomic_dec(&qp->mtt->ref_count);
3592255932Salfred	atomic_dec(&qp->rcq->ref_count);
3593255932Salfred	atomic_dec(&qp->scq->ref_count);
3594255932Salfred	if (qp->srq)
3595255932Salfred		atomic_dec(&qp->srq->ref_count);
3596255932Salfred	res_end_move(dev, slave, RES_QP, qpn);
3597255932Salfred	return 0;
3598255932Salfred
3599255932Salfredex_abort:
3600255932Salfred	res_abort_move(dev, slave, RES_QP, qpn);
3601255932Salfred
3602255932Salfred	return err;
3603255932Salfred}
3604255932Salfred
3605255932Salfredstatic struct res_gid *find_gid(struct mlx4_dev *dev, int slave,
3606255932Salfred				struct res_qp *rqp, u8 *gid)
3607255932Salfred{
3608255932Salfred	struct res_gid *res;
3609255932Salfred
3610255932Salfred	list_for_each_entry(res, &rqp->mcg_list, list) {
3611255932Salfred		if (!memcmp(res->gid, gid, 16))
3612255932Salfred			return res;
3613255932Salfred	}
3614255932Salfred	return NULL;
3615255932Salfred}
3616255932Salfred
3617255932Salfredstatic int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
3618255932Salfred		       u8 *gid, enum mlx4_protocol prot,
3619272027Shselasky		       enum mlx4_steer_type steer, u64 reg_id)
3620255932Salfred{
3621255932Salfred	struct res_gid *res;
3622255932Salfred	int err;
3623255932Salfred
3624255932Salfred	res = kzalloc(sizeof *res, GFP_KERNEL);
3625255932Salfred	if (!res)
3626255932Salfred		return -ENOMEM;
3627255932Salfred
3628255932Salfred	spin_lock_irq(&rqp->mcg_spl);
3629255932Salfred	if (find_gid(dev, slave, rqp, gid)) {
3630255932Salfred		kfree(res);
3631255932Salfred		err = -EEXIST;
3632255932Salfred	} else {
3633255932Salfred		memcpy(res->gid, gid, 16);
3634255932Salfred		res->prot = prot;
3635255932Salfred		res->steer = steer;
3636272027Shselasky		res->reg_id = reg_id;
3637255932Salfred		list_add_tail(&res->list, &rqp->mcg_list);
3638255932Salfred		err = 0;
3639255932Salfred	}
3640255932Salfred	spin_unlock_irq(&rqp->mcg_spl);
3641255932Salfred
3642255932Salfred	return err;
3643255932Salfred}
3644255932Salfred
3645255932Salfredstatic int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
3646255932Salfred		       u8 *gid, enum mlx4_protocol prot,
3647272027Shselasky		       enum mlx4_steer_type steer, u64 *reg_id)
3648255932Salfred{
3649255932Salfred	struct res_gid *res;
3650255932Salfred	int err;
3651255932Salfred
3652255932Salfred	spin_lock_irq(&rqp->mcg_spl);
3653255932Salfred	res = find_gid(dev, slave, rqp, gid);
3654255932Salfred	if (!res || res->prot != prot || res->steer != steer)
3655255932Salfred		err = -EINVAL;
3656255932Salfred	else {
3657272027Shselasky		*reg_id = res->reg_id;
3658255932Salfred		list_del(&res->list);
3659255932Salfred		kfree(res);
3660255932Salfred		err = 0;
3661255932Salfred	}
3662255932Salfred	spin_unlock_irq(&rqp->mcg_spl);
3663255932Salfred
3664255932Salfred	return err;
3665255932Salfred}
3666255932Salfred
3667272027Shselaskystatic int qp_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
3668272027Shselasky		     int block_loopback, enum mlx4_protocol prot,
3669272027Shselasky		     enum mlx4_steer_type type, u64 *reg_id)
3670272027Shselasky{
3671272027Shselasky	switch (dev->caps.steering_mode) {
3672272027Shselasky	case MLX4_STEERING_MODE_DEVICE_MANAGED:
3673272027Shselasky		return mlx4_trans_to_dmfs_attach(dev, qp, gid, gid[5],
3674272027Shselasky						block_loopback, prot,
3675272027Shselasky						reg_id);
3676272027Shselasky	case MLX4_STEERING_MODE_B0:
3677272027Shselasky		return mlx4_qp_attach_common(dev, qp, gid,
3678272027Shselasky					    block_loopback, prot, type);
3679272027Shselasky	default:
3680272027Shselasky		return -EINVAL;
3681272027Shselasky	}
3682272027Shselasky}
3683272027Shselasky
3684272027Shselaskystatic int qp_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
3685272027Shselasky		     enum mlx4_protocol prot, enum mlx4_steer_type type,
3686272027Shselasky		     u64 reg_id)
3687272027Shselasky{
3688272027Shselasky	switch (dev->caps.steering_mode) {
3689272027Shselasky	case MLX4_STEERING_MODE_DEVICE_MANAGED:
3690272027Shselasky		return mlx4_flow_detach(dev, reg_id);
3691272027Shselasky	case MLX4_STEERING_MODE_B0:
3692272027Shselasky		return mlx4_qp_detach_common(dev, qp, gid, prot, type);
3693272027Shselasky	default:
3694272027Shselasky		return -EINVAL;
3695272027Shselasky	}
3696272027Shselasky}
3697272027Shselasky
3698255932Salfredint mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
3699255932Salfred			       struct mlx4_vhcr *vhcr,
3700255932Salfred			       struct mlx4_cmd_mailbox *inbox,
3701255932Salfred			       struct mlx4_cmd_mailbox *outbox,
3702255932Salfred			       struct mlx4_cmd_info *cmd)
3703255932Salfred{
3704255932Salfred	struct mlx4_qp qp; /* dummy for calling attach/detach */
3705255932Salfred	u8 *gid = inbox->buf;
3706255932Salfred	enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7;
3707255932Salfred	int err;
3708255932Salfred	int qpn;
3709255932Salfred	struct res_qp *rqp;
3710272027Shselasky	u64 reg_id = 0;
3711255932Salfred	int attach = vhcr->op_modifier;
3712255932Salfred	int block_loopback = vhcr->in_modifier >> 31;
3713255932Salfred	u8 steer_type_mask = 2;
3714255932Salfred	enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1;
3715255932Salfred
3716255932Salfred	qpn = vhcr->in_modifier & 0xffffff;
3717255932Salfred	err = get_res(dev, slave, qpn, RES_QP, &rqp);
3718255932Salfred	if (err)
3719255932Salfred		return err;
3720255932Salfred
3721255932Salfred	qp.qpn = qpn;
3722255932Salfred	if (attach) {
3723272027Shselasky		err = qp_attach(dev, &qp, gid, block_loopback, prot,
3724272027Shselasky				type, &reg_id);
3725272027Shselasky		if (err) {
3726272027Shselasky			pr_err("Fail to attach rule to qp 0x%x\n", qpn);
3727255932Salfred			goto ex_put;
3728272027Shselasky		}
3729272027Shselasky		err = add_mcg_res(dev, slave, rqp, gid, prot, type, reg_id);
3730255932Salfred		if (err)
3731272027Shselasky			goto ex_detach;
3732255932Salfred	} else {
3733272027Shselasky		err = rem_mcg_res(dev, slave, rqp, gid, prot, type, &reg_id);
3734255932Salfred		if (err)
3735255932Salfred			goto ex_put;
3736272027Shselasky
3737272027Shselasky		err = qp_detach(dev, &qp, gid, prot, type, reg_id);
3738272027Shselasky		if (err)
3739272027Shselasky			pr_err("Fail to detach rule from qp 0x%x reg_id = 0x%llx\n",
3740272027Shselasky			       qpn, (unsigned long long)reg_id);
3741255932Salfred	}
3742255932Salfred	put_res(dev, slave, qpn, RES_QP);
3743272027Shselasky	return err;
3744255932Salfred
3745272027Shselaskyex_detach:
3746272027Shselasky	qp_detach(dev, &qp, gid, prot, type, reg_id);
3747255932Salfredex_put:
3748255932Salfred	put_res(dev, slave, qpn, RES_QP);
3749255932Salfred	return err;
3750255932Salfred}
3751255932Salfred
3752255932Salfred/*
3753255932Salfred * MAC validation for Flow Steering rules.
3754255932Salfred * VF can attach rules only with a mac address which is assigned to it.
3755255932Salfred */
3756255932Salfredstatic int validate_eth_header_mac(int slave, struct _rule_hw *eth_header,
3757255932Salfred				   struct list_head *rlist)
3758255932Salfred{
3759255932Salfred	struct mac_res *res, *tmp;
3760255932Salfred	__be64 be_mac;
3761255932Salfred
3762255932Salfred	/* make sure it isn't multicast or broadcast mac*/
3763255932Salfred	if (!is_multicast_ether_addr(eth_header->eth.dst_mac) &&
3764255932Salfred	    !is_broadcast_ether_addr(eth_header->eth.dst_mac)) {
3765255932Salfred		list_for_each_entry_safe(res, tmp, rlist, list) {
3766255932Salfred			be_mac = cpu_to_be64(res->mac << 16);
3767255932Salfred			if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN))
3768255932Salfred				return 0;
3769255932Salfred		}
3770255932Salfred		pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n",
3771255932Salfred		       eth_header->eth.dst_mac, slave);
3772255932Salfred		return -EINVAL;
3773255932Salfred	}
3774255932Salfred	return 0;
3775255932Salfred}
3776255932Salfred
3777255932Salfred/*
3778255932Salfred * In case of missing eth header, append eth header with a MAC address
3779255932Salfred * assigned to the VF.
3780255932Salfred */
3781255932Salfredstatic int add_eth_header(struct mlx4_dev *dev, int slave,
3782255932Salfred			  struct mlx4_cmd_mailbox *inbox,
3783255932Salfred			  struct list_head *rlist, int header_id)
3784255932Salfred{
3785255932Salfred	struct mac_res *res, *tmp;
3786255932Salfred	u8 port;
3787255932Salfred	struct mlx4_net_trans_rule_hw_ctrl *ctrl;
3788255932Salfred	struct mlx4_net_trans_rule_hw_eth *eth_header;
3789255932Salfred	struct mlx4_net_trans_rule_hw_ipv4 *ip_header;
3790255932Salfred	struct mlx4_net_trans_rule_hw_tcp_udp *l4_header;
3791255932Salfred	__be64 be_mac = 0;
3792255932Salfred	__be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);
3793255932Salfred
3794255932Salfred	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
3795255932Salfred	port = ctrl->port;
3796255932Salfred	eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1);
3797255932Salfred
3798255932Salfred	/* Clear a space in the inbox for eth header */
3799255932Salfred	switch (header_id) {
3800255932Salfred	case MLX4_NET_TRANS_RULE_ID_IPV4:
3801255932Salfred		ip_header =
3802255932Salfred			(struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1);
3803255932Salfred		memmove(ip_header, eth_header,
3804255932Salfred			sizeof(*ip_header) + sizeof(*l4_header));
3805255932Salfred		break;
3806255932Salfred	case MLX4_NET_TRANS_RULE_ID_TCP:
3807255932Salfred	case MLX4_NET_TRANS_RULE_ID_UDP:
3808255932Salfred		l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *)
3809255932Salfred			    (eth_header + 1);
3810255932Salfred		memmove(l4_header, eth_header, sizeof(*l4_header));
3811255932Salfred		break;
3812255932Salfred	default:
3813255932Salfred		return -EINVAL;
3814255932Salfred	}
3815255932Salfred	list_for_each_entry_safe(res, tmp, rlist, list) {
3816255932Salfred		if (port == res->port) {
3817255932Salfred			be_mac = cpu_to_be64(res->mac << 16);
3818255932Salfred			break;
3819255932Salfred		}
3820255932Salfred	}
3821255932Salfred	if (!be_mac) {
3822255932Salfred		pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n",
3823255932Salfred		       port);
3824255932Salfred		return -EINVAL;
3825255932Salfred	}
3826255932Salfred
3827255932Salfred	memset(eth_header, 0, sizeof(*eth_header));
3828255932Salfred	eth_header->size = sizeof(*eth_header) >> 2;
3829255932Salfred	eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]);
3830255932Salfred	memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN);
3831255932Salfred	memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN);
3832255932Salfred
3833255932Salfred	return 0;
3834255932Salfred
3835255932Salfred}
3836255932Salfred
3837255932Salfredint mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
3838255932Salfred					 struct mlx4_vhcr *vhcr,
3839255932Salfred					 struct mlx4_cmd_mailbox *inbox,
3840255932Salfred					 struct mlx4_cmd_mailbox *outbox,
3841255932Salfred					 struct mlx4_cmd_info *cmd)
3842255932Salfred{
3843255932Salfred
3844255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
3845255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
3846255932Salfred	struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
3847255932Salfred	int err;
3848272027Shselasky	int qpn;
3849272027Shselasky	struct res_qp *rqp;
3850255932Salfred	struct mlx4_net_trans_rule_hw_ctrl *ctrl;
3851255932Salfred	struct _rule_hw  *rule_header;
3852255932Salfred	int header_id;
3853255932Salfred
3854255932Salfred	if (dev->caps.steering_mode !=
3855255932Salfred	    MLX4_STEERING_MODE_DEVICE_MANAGED)
3856255932Salfred		return -EOPNOTSUPP;
3857255932Salfred
3858255932Salfred	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
3859272027Shselasky	qpn = be32_to_cpu(ctrl->qpn) & 0xffffff;
3860272027Shselasky	err = get_res(dev, slave, qpn, RES_QP, &rqp);
3861272027Shselasky	if (err) {
3862272027Shselasky		pr_err("Steering rule with qpn 0x%x rejected.\n", qpn);
3863272027Shselasky		return err;
3864272027Shselasky	}
3865255932Salfred	rule_header = (struct _rule_hw *)(ctrl + 1);
3866255932Salfred	header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));
3867255932Salfred
3868255932Salfred	switch (header_id) {
3869255932Salfred	case MLX4_NET_TRANS_RULE_ID_ETH:
3870272027Shselasky		if (validate_eth_header_mac(slave, rule_header, rlist)) {
3871272027Shselasky			err = -EINVAL;
3872272027Shselasky			goto err_put;
3873272027Shselasky		}
3874255932Salfred		break;
3875255932Salfred	case MLX4_NET_TRANS_RULE_ID_IB:
3876255932Salfred		break;
3877255932Salfred	case MLX4_NET_TRANS_RULE_ID_IPV4:
3878255932Salfred	case MLX4_NET_TRANS_RULE_ID_TCP:
3879255932Salfred	case MLX4_NET_TRANS_RULE_ID_UDP:
3880255932Salfred		pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n");
3881272027Shselasky		if (add_eth_header(dev, slave, inbox, rlist, header_id)) {
3882272027Shselasky			err = -EINVAL;
3883272027Shselasky			goto err_put;
3884272027Shselasky		}
3885255932Salfred		vhcr->in_modifier +=
3886255932Salfred			sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2;
3887255932Salfred		break;
3888255932Salfred	default:
3889255932Salfred		pr_err("Corrupted mailbox.\n");
3890272027Shselasky		err = -EINVAL;
3891272027Shselasky		goto err_put;
3892255932Salfred	}
3893255932Salfred
3894255932Salfred	err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
3895255932Salfred			   vhcr->in_modifier, 0,
3896255932Salfred			   MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
3897255932Salfred			   MLX4_CMD_NATIVE);
3898255932Salfred	if (err)
3899272027Shselasky		goto err_put;
3900255932Salfred
3901272027Shselasky	err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, qpn);
3902255932Salfred	if (err) {
3903255932Salfred		mlx4_err(dev, "Fail to add flow steering resources.\n ");
3904255932Salfred		/* detach rule*/
3905255932Salfred		mlx4_cmd(dev, vhcr->out_param, 0, 0,
3906272027Shselasky			 MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
3907255932Salfred			 MLX4_CMD_NATIVE);
3908272027Shselasky		goto err_put;
3909255932Salfred	}
3910272027Shselasky	atomic_inc(&rqp->ref_count);
3911272027Shselaskyerr_put:
3912272027Shselasky	put_res(dev, slave, qpn, RES_QP);
3913255932Salfred	return err;
3914255932Salfred}
3915255932Salfred
3916255932Salfredint mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
3917255932Salfred					 struct mlx4_vhcr *vhcr,
3918255932Salfred					 struct mlx4_cmd_mailbox *inbox,
3919255932Salfred					 struct mlx4_cmd_mailbox *outbox,
3920255932Salfred					 struct mlx4_cmd_info *cmd)
3921255932Salfred{
3922255932Salfred	int err;
3923272027Shselasky	struct res_qp *rqp;
3924272027Shselasky	struct res_fs_rule *rrule;
3925255932Salfred
3926255932Salfred	if (dev->caps.steering_mode !=
3927255932Salfred	    MLX4_STEERING_MODE_DEVICE_MANAGED)
3928255932Salfred		return -EOPNOTSUPP;
3929255932Salfred
3930272027Shselasky	err = get_res(dev, slave, vhcr->in_param, RES_FS_RULE, &rrule);
3931272027Shselasky	if (err)
3932255932Salfred		return err;
3933272027Shselasky	/* Release the rule form busy state before removal */
3934272027Shselasky	put_res(dev, slave, vhcr->in_param, RES_FS_RULE);
3935272027Shselasky	err = get_res(dev, slave, rrule->qpn, RES_QP, &rqp);
3936272027Shselasky	if (err)
3937272027Shselasky		return err;
3938255932Salfred
3939255932Salfred	err = mlx4_cmd(dev, vhcr->in_param, 0, 0,
3940255932Salfred		       MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
3941255932Salfred		       MLX4_CMD_NATIVE);
3942272027Shselasky	if (!err) {
3943272027Shselasky		err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE,
3944272027Shselasky				    0);
3945272027Shselasky		atomic_dec(&rqp->ref_count);
3946272027Shselasky
3947272027Shselasky		if (err) {
3948272027Shselasky			mlx4_err(dev, "Fail to remove flow steering resources.\n ");
3949272027Shselasky			goto out;
3950272027Shselasky		}
3951272027Shselasky	}
3952272027Shselasky
3953272027Shselaskyout:
3954272027Shselasky	put_res(dev, slave, rrule->qpn, RES_QP);
3955255932Salfred	return err;
3956255932Salfred}
3957255932Salfred
3958255932Salfredenum {
3959255932Salfred	BUSY_MAX_RETRIES = 10
3960255932Salfred};
3961255932Salfred
3962255932Salfredint mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave,
3963255932Salfred			       struct mlx4_vhcr *vhcr,
3964255932Salfred			       struct mlx4_cmd_mailbox *inbox,
3965255932Salfred			       struct mlx4_cmd_mailbox *outbox,
3966255932Salfred			       struct mlx4_cmd_info *cmd)
3967255932Salfred{
3968255932Salfred	int err;
3969255932Salfred
3970272027Shselasky	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
3971255932Salfred
3972255932Salfred	return err;
3973255932Salfred}
3974255932Salfred
3975255932Salfredstatic void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp)
3976255932Salfred{
3977255932Salfred	struct res_gid *rgid;
3978255932Salfred	struct res_gid *tmp;
3979255932Salfred	struct mlx4_qp qp; /* dummy for calling attach/detach */
3980255932Salfred
3981255932Salfred	list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) {
3982272027Shselasky		switch (dev->caps.steering_mode) {
3983272027Shselasky		case MLX4_STEERING_MODE_DEVICE_MANAGED:
3984272027Shselasky			mlx4_flow_detach(dev, rgid->reg_id);
3985272027Shselasky			break;
3986272027Shselasky		case MLX4_STEERING_MODE_B0:
3987272027Shselasky			qp.qpn = rqp->local_qpn;
3988272027Shselasky			(void) mlx4_qp_detach_common(dev, &qp, rgid->gid,
3989272027Shselasky						     rgid->prot, rgid->steer);
3990272027Shselasky			break;
3991272027Shselasky		}
3992255932Salfred		list_del(&rgid->list);
3993255932Salfred		kfree(rgid);
3994255932Salfred	}
3995255932Salfred}
3996255932Salfred
3997255932Salfredstatic int _move_all_busy(struct mlx4_dev *dev, int slave,
3998255932Salfred			  enum mlx4_resource type, int print)
3999255932Salfred{
4000255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4001255932Salfred	struct mlx4_resource_tracker *tracker =
4002255932Salfred		&priv->mfunc.master.res_tracker;
4003255932Salfred	struct list_head *rlist = &tracker->slave_list[slave].res_list[type];
4004255932Salfred	struct res_common *r;
4005255932Salfred	struct res_common *tmp;
4006255932Salfred	int busy;
4007255932Salfred
4008255932Salfred	busy = 0;
4009255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4010255932Salfred	list_for_each_entry_safe(r, tmp, rlist, list) {
4011255932Salfred		if (r->owner == slave) {
4012255932Salfred			if (!r->removing) {
4013255932Salfred				if (r->state == RES_ANY_BUSY) {
4014255932Salfred					if (print)
4015255932Salfred						mlx4_dbg(dev,
4016255932Salfred							 "%s id 0x%llx is busy\n",
4017255932Salfred							  ResourceType(type),
4018272027Shselasky							  (unsigned long long)r->res_id);
4019255932Salfred					++busy;
4020255932Salfred				} else {
4021255932Salfred					r->from_state = r->state;
4022255932Salfred					r->state = RES_ANY_BUSY;
4023255932Salfred					r->removing = 1;
4024255932Salfred				}
4025255932Salfred			}
4026255932Salfred		}
4027255932Salfred	}
4028255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4029255932Salfred
4030255932Salfred	return busy;
4031255932Salfred}
4032255932Salfred
4033255932Salfredstatic int move_all_busy(struct mlx4_dev *dev, int slave,
4034255932Salfred			 enum mlx4_resource type)
4035255932Salfred{
4036255932Salfred	unsigned long begin;
4037255932Salfred	int busy;
4038255932Salfred
4039255932Salfred	begin = jiffies;
4040255932Salfred	do {
4041255932Salfred		busy = _move_all_busy(dev, slave, type, 0);
4042255932Salfred		if (time_after(jiffies, begin + 5 * HZ))
4043255932Salfred			break;
4044255932Salfred		if (busy)
4045255932Salfred			cond_resched();
4046255932Salfred	} while (busy);
4047255932Salfred
4048255932Salfred	if (busy)
4049255932Salfred		busy = _move_all_busy(dev, slave, type, 1);
4050255932Salfred
4051255932Salfred	return busy;
4052255932Salfred}
4053255932Salfredstatic void rem_slave_qps(struct mlx4_dev *dev, int slave)
4054255932Salfred{
4055255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4056255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4057255932Salfred	struct list_head *qp_list =
4058255932Salfred		&tracker->slave_list[slave].res_list[RES_QP];
4059255932Salfred	struct res_qp *qp;
4060255932Salfred	struct res_qp *tmp;
4061255932Salfred	int state;
4062255932Salfred	u64 in_param;
4063255932Salfred	int qpn;
4064255932Salfred	int err;
4065255932Salfred
4066255932Salfred	err = move_all_busy(dev, slave, RES_QP);
4067255932Salfred	if (err)
4068255932Salfred		mlx4_warn(dev, "rem_slave_qps: Could not move all qps to busy"
4069255932Salfred			  "for slave %d\n", slave);
4070255932Salfred
4071255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4072255932Salfred	list_for_each_entry_safe(qp, tmp, qp_list, com.list) {
4073255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4074255932Salfred		if (qp->com.owner == slave) {
4075255932Salfred			qpn = qp->com.res_id;
4076255932Salfred			detach_qp(dev, slave, qp);
4077255932Salfred			state = qp->com.from_state;
4078255932Salfred			while (state != 0) {
4079255932Salfred				switch (state) {
4080255932Salfred				case RES_QP_RESERVED:
4081255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4082255932Salfred					rb_erase(&qp->com.node,
4083255932Salfred						 &tracker->res_tree[RES_QP]);
4084255932Salfred					list_del(&qp->com.list);
4085255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4086272027Shselasky					if (!valid_reserved(dev, slave, qpn)) {
4087272027Shselasky						__mlx4_qp_release_range(dev, qpn, 1);
4088272027Shselasky						mlx4_release_resource(dev, slave,
4089272027Shselasky								      RES_QP, 1, 0);
4090272027Shselasky					}
4091255932Salfred					kfree(qp);
4092255932Salfred					state = 0;
4093255932Salfred					break;
4094255932Salfred				case RES_QP_MAPPED:
4095255932Salfred					if (!valid_reserved(dev, slave, qpn))
4096255932Salfred						__mlx4_qp_free_icm(dev, qpn);
4097255932Salfred					state = RES_QP_RESERVED;
4098255932Salfred					break;
4099255932Salfred				case RES_QP_HW:
4100255932Salfred					in_param = slave;
4101255932Salfred					err = mlx4_cmd(dev, in_param,
4102255932Salfred						       qp->local_qpn, 2,
4103255932Salfred						       MLX4_CMD_2RST_QP,
4104255932Salfred						       MLX4_CMD_TIME_CLASS_A,
4105255932Salfred						       MLX4_CMD_NATIVE);
4106255932Salfred					if (err)
4107255932Salfred						mlx4_dbg(dev, "rem_slave_qps: failed"
4108255932Salfred							 " to move slave %d qpn %d to"
4109255932Salfred							 " reset\n", slave,
4110255932Salfred							 qp->local_qpn);
4111255932Salfred					atomic_dec(&qp->rcq->ref_count);
4112255932Salfred					atomic_dec(&qp->scq->ref_count);
4113255932Salfred					atomic_dec(&qp->mtt->ref_count);
4114255932Salfred					if (qp->srq)
4115255932Salfred						atomic_dec(&qp->srq->ref_count);
4116255932Salfred					state = RES_QP_MAPPED;
4117255932Salfred					break;
4118255932Salfred				default:
4119255932Salfred					state = 0;
4120255932Salfred				}
4121255932Salfred			}
4122255932Salfred		}
4123255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4124255932Salfred	}
4125255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4126255932Salfred}
4127255932Salfred
4128255932Salfredstatic void rem_slave_srqs(struct mlx4_dev *dev, int slave)
4129255932Salfred{
4130255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4131255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4132255932Salfred	struct list_head *srq_list =
4133255932Salfred		&tracker->slave_list[slave].res_list[RES_SRQ];
4134255932Salfred	struct res_srq *srq;
4135255932Salfred	struct res_srq *tmp;
4136255932Salfred	int state;
4137255932Salfred	u64 in_param;
4138255932Salfred	LIST_HEAD(tlist);
4139255932Salfred	int srqn;
4140255932Salfred	int err;
4141255932Salfred
4142255932Salfred	err = move_all_busy(dev, slave, RES_SRQ);
4143255932Salfred	if (err)
4144255932Salfred		mlx4_warn(dev, "rem_slave_srqs: Could not move all srqs to "
4145255932Salfred			  "busy for slave %d\n", slave);
4146255932Salfred
4147255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4148255932Salfred	list_for_each_entry_safe(srq, tmp, srq_list, com.list) {
4149255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4150255932Salfred		if (srq->com.owner == slave) {
4151255932Salfred			srqn = srq->com.res_id;
4152255932Salfred			state = srq->com.from_state;
4153255932Salfred			while (state != 0) {
4154255932Salfred				switch (state) {
4155255932Salfred				case RES_SRQ_ALLOCATED:
4156255932Salfred					__mlx4_srq_free_icm(dev, srqn);
4157255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4158255932Salfred					rb_erase(&srq->com.node,
4159255932Salfred						 &tracker->res_tree[RES_SRQ]);
4160255932Salfred					list_del(&srq->com.list);
4161255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4162272027Shselasky					mlx4_release_resource(dev, slave,
4163272027Shselasky							      RES_SRQ, 1, 0);
4164255932Salfred					kfree(srq);
4165255932Salfred					state = 0;
4166255932Salfred					break;
4167255932Salfred
4168255932Salfred				case RES_SRQ_HW:
4169255932Salfred					in_param = slave;
4170255932Salfred					err = mlx4_cmd(dev, in_param, srqn, 1,
4171255932Salfred						       MLX4_CMD_HW2SW_SRQ,
4172255932Salfred						       MLX4_CMD_TIME_CLASS_A,
4173255932Salfred						       MLX4_CMD_NATIVE);
4174255932Salfred					if (err)
4175255932Salfred						mlx4_dbg(dev, "rem_slave_srqs: failed"
4176255932Salfred							 " to move slave %d srq %d to"
4177255932Salfred							 " SW ownership\n",
4178255932Salfred							 slave, srqn);
4179255932Salfred
4180255932Salfred					atomic_dec(&srq->mtt->ref_count);
4181255932Salfred					if (srq->cq)
4182255932Salfred						atomic_dec(&srq->cq->ref_count);
4183255932Salfred					state = RES_SRQ_ALLOCATED;
4184255932Salfred					break;
4185255932Salfred
4186255932Salfred				default:
4187255932Salfred					state = 0;
4188255932Salfred				}
4189255932Salfred			}
4190255932Salfred		}
4191255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4192255932Salfred	}
4193255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4194255932Salfred}
4195255932Salfred
4196255932Salfredstatic void rem_slave_cqs(struct mlx4_dev *dev, int slave)
4197255932Salfred{
4198255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4199255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4200255932Salfred	struct list_head *cq_list =
4201255932Salfred		&tracker->slave_list[slave].res_list[RES_CQ];
4202255932Salfred	struct res_cq *cq;
4203255932Salfred	struct res_cq *tmp;
4204255932Salfred	int state;
4205255932Salfred	u64 in_param;
4206255932Salfred	LIST_HEAD(tlist);
4207255932Salfred	int cqn;
4208255932Salfred	int err;
4209255932Salfred
4210255932Salfred	err = move_all_busy(dev, slave, RES_CQ);
4211255932Salfred	if (err)
4212255932Salfred		mlx4_warn(dev, "rem_slave_cqs: Could not move all cqs to "
4213255932Salfred			  "busy for slave %d\n", slave);
4214255932Salfred
4215255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4216255932Salfred	list_for_each_entry_safe(cq, tmp, cq_list, com.list) {
4217255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4218255932Salfred		if (cq->com.owner == slave && !atomic_read(&cq->ref_count)) {
4219255932Salfred			cqn = cq->com.res_id;
4220255932Salfred			state = cq->com.from_state;
4221255932Salfred			while (state != 0) {
4222255932Salfred				switch (state) {
4223255932Salfred				case RES_CQ_ALLOCATED:
4224255932Salfred					__mlx4_cq_free_icm(dev, cqn);
4225255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4226255932Salfred					rb_erase(&cq->com.node,
4227255932Salfred						 &tracker->res_tree[RES_CQ]);
4228255932Salfred					list_del(&cq->com.list);
4229255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4230272027Shselasky					mlx4_release_resource(dev, slave,
4231272027Shselasky							      RES_CQ, 1, 0);
4232255932Salfred					kfree(cq);
4233255932Salfred					state = 0;
4234255932Salfred					break;
4235255932Salfred
4236255932Salfred				case RES_CQ_HW:
4237255932Salfred					in_param = slave;
4238255932Salfred					err = mlx4_cmd(dev, in_param, cqn, 1,
4239255932Salfred						       MLX4_CMD_HW2SW_CQ,
4240255932Salfred						       MLX4_CMD_TIME_CLASS_A,
4241255932Salfred						       MLX4_CMD_NATIVE);
4242255932Salfred					if (err)
4243255932Salfred						mlx4_dbg(dev, "rem_slave_cqs: failed"
4244255932Salfred							 " to move slave %d cq %d to"
4245255932Salfred							 " SW ownership\n",
4246255932Salfred							 slave, cqn);
4247255932Salfred					atomic_dec(&cq->mtt->ref_count);
4248255932Salfred					state = RES_CQ_ALLOCATED;
4249255932Salfred					break;
4250255932Salfred
4251255932Salfred				default:
4252255932Salfred					state = 0;
4253255932Salfred				}
4254255932Salfred			}
4255255932Salfred		}
4256255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4257255932Salfred	}
4258255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4259255932Salfred}
4260255932Salfred
4261255932Salfredstatic void rem_slave_mrs(struct mlx4_dev *dev, int slave)
4262255932Salfred{
4263255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4264255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4265255932Salfred	struct list_head *mpt_list =
4266255932Salfred		&tracker->slave_list[slave].res_list[RES_MPT];
4267255932Salfred	struct res_mpt *mpt;
4268255932Salfred	struct res_mpt *tmp;
4269255932Salfred	int state;
4270255932Salfred	u64 in_param;
4271255932Salfred	LIST_HEAD(tlist);
4272255932Salfred	int mptn;
4273255932Salfred	int err;
4274255932Salfred
4275255932Salfred	err = move_all_busy(dev, slave, RES_MPT);
4276255932Salfred	if (err)
4277255932Salfred		mlx4_warn(dev, "rem_slave_mrs: Could not move all mpts to "
4278255932Salfred			  "busy for slave %d\n", slave);
4279255932Salfred
4280255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4281255932Salfred	list_for_each_entry_safe(mpt, tmp, mpt_list, com.list) {
4282255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4283255932Salfred		if (mpt->com.owner == slave) {
4284255932Salfred			mptn = mpt->com.res_id;
4285255932Salfred			state = mpt->com.from_state;
4286255932Salfred			while (state != 0) {
4287255932Salfred				switch (state) {
4288255932Salfred				case RES_MPT_RESERVED:
4289272027Shselasky					__mlx4_mpt_release(dev, mpt->key);
4290255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4291255932Salfred					rb_erase(&mpt->com.node,
4292255932Salfred						 &tracker->res_tree[RES_MPT]);
4293255932Salfred					list_del(&mpt->com.list);
4294255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4295272027Shselasky					mlx4_release_resource(dev, slave,
4296272027Shselasky							      RES_MPT, 1, 0);
4297255932Salfred					kfree(mpt);
4298255932Salfred					state = 0;
4299255932Salfred					break;
4300255932Salfred
4301255932Salfred				case RES_MPT_MAPPED:
4302272027Shselasky					__mlx4_mpt_free_icm(dev, mpt->key);
4303255932Salfred					state = RES_MPT_RESERVED;
4304255932Salfred					break;
4305255932Salfred
4306255932Salfred				case RES_MPT_HW:
4307255932Salfred					in_param = slave;
4308255932Salfred					err = mlx4_cmd(dev, in_param, mptn, 0,
4309255932Salfred						     MLX4_CMD_HW2SW_MPT,
4310255932Salfred						     MLX4_CMD_TIME_CLASS_A,
4311255932Salfred						     MLX4_CMD_NATIVE);
4312255932Salfred					if (err)
4313255932Salfred						mlx4_dbg(dev, "rem_slave_mrs: failed"
4314255932Salfred							 " to move slave %d mpt %d to"
4315255932Salfred							 " SW ownership\n",
4316255932Salfred							 slave, mptn);
4317255932Salfred					if (mpt->mtt)
4318255932Salfred						atomic_dec(&mpt->mtt->ref_count);
4319255932Salfred					state = RES_MPT_MAPPED;
4320255932Salfred					break;
4321255932Salfred				default:
4322255932Salfred					state = 0;
4323255932Salfred				}
4324255932Salfred			}
4325255932Salfred		}
4326255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4327255932Salfred	}
4328255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4329255932Salfred}
4330255932Salfred
4331255932Salfredstatic void rem_slave_mtts(struct mlx4_dev *dev, int slave)
4332255932Salfred{
4333255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4334255932Salfred	struct mlx4_resource_tracker *tracker =
4335255932Salfred		&priv->mfunc.master.res_tracker;
4336255932Salfred	struct list_head *mtt_list =
4337255932Salfred		&tracker->slave_list[slave].res_list[RES_MTT];
4338255932Salfred	struct res_mtt *mtt;
4339255932Salfred	struct res_mtt *tmp;
4340255932Salfred	int state;
4341255932Salfred	LIST_HEAD(tlist);
4342255932Salfred	int base;
4343255932Salfred	int err;
4344255932Salfred
4345255932Salfred	err = move_all_busy(dev, slave, RES_MTT);
4346255932Salfred	if (err)
4347255932Salfred		mlx4_warn(dev, "rem_slave_mtts: Could not move all mtts to "
4348255932Salfred			  "busy for slave %d\n", slave);
4349255932Salfred
4350255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4351255932Salfred	list_for_each_entry_safe(mtt, tmp, mtt_list, com.list) {
4352255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4353255932Salfred		if (mtt->com.owner == slave) {
4354255932Salfred			base = mtt->com.res_id;
4355255932Salfred			state = mtt->com.from_state;
4356255932Salfred			while (state != 0) {
4357255932Salfred				switch (state) {
4358255932Salfred				case RES_MTT_ALLOCATED:
4359255932Salfred					__mlx4_free_mtt_range(dev, base,
4360255932Salfred							      mtt->order);
4361255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4362255932Salfred					rb_erase(&mtt->com.node,
4363255932Salfred						 &tracker->res_tree[RES_MTT]);
4364255932Salfred					list_del(&mtt->com.list);
4365255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4366272027Shselasky					mlx4_release_resource(dev, slave, RES_MTT,
4367272027Shselasky							      1 << mtt->order, 0);
4368255932Salfred					kfree(mtt);
4369255932Salfred					state = 0;
4370255932Salfred					break;
4371255932Salfred
4372255932Salfred				default:
4373255932Salfred					state = 0;
4374255932Salfred				}
4375255932Salfred			}
4376255932Salfred		}
4377255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4378255932Salfred	}
4379255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4380255932Salfred}
4381255932Salfred
4382255932Salfredstatic void rem_slave_fs_rule(struct mlx4_dev *dev, int slave)
4383255932Salfred{
4384255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4385255932Salfred	struct mlx4_resource_tracker *tracker =
4386255932Salfred		&priv->mfunc.master.res_tracker;
4387255932Salfred	struct list_head *fs_rule_list =
4388255932Salfred		&tracker->slave_list[slave].res_list[RES_FS_RULE];
4389255932Salfred	struct res_fs_rule *fs_rule;
4390255932Salfred	struct res_fs_rule *tmp;
4391255932Salfred	int state;
4392255932Salfred	u64 base;
4393255932Salfred	int err;
4394255932Salfred
4395255932Salfred	err = move_all_busy(dev, slave, RES_FS_RULE);
4396255932Salfred	if (err)
4397255932Salfred		mlx4_warn(dev, "rem_slave_fs_rule: Could not move all mtts to busy for slave %d\n",
4398255932Salfred			  slave);
4399255932Salfred
4400255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4401255932Salfred	list_for_each_entry_safe(fs_rule, tmp, fs_rule_list, com.list) {
4402255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4403255932Salfred		if (fs_rule->com.owner == slave) {
4404255932Salfred			base = fs_rule->com.res_id;
4405255932Salfred			state = fs_rule->com.from_state;
4406255932Salfred			while (state != 0) {
4407255932Salfred				switch (state) {
4408255932Salfred				case RES_FS_RULE_ALLOCATED:
4409255932Salfred					/* detach rule */
4410255932Salfred					err = mlx4_cmd(dev, base, 0, 0,
4411255932Salfred						       MLX4_QP_FLOW_STEERING_DETACH,
4412255932Salfred						       MLX4_CMD_TIME_CLASS_A,
4413255932Salfred						       MLX4_CMD_NATIVE);
4414255932Salfred
4415255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4416255932Salfred					rb_erase(&fs_rule->com.node,
4417255932Salfred						 &tracker->res_tree[RES_FS_RULE]);
4418255932Salfred					list_del(&fs_rule->com.list);
4419255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4420255932Salfred					kfree(fs_rule);
4421255932Salfred					state = 0;
4422255932Salfred					break;
4423255932Salfred
4424255932Salfred				default:
4425255932Salfred					state = 0;
4426255932Salfred				}
4427255932Salfred			}
4428255932Salfred		}
4429255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4430255932Salfred	}
4431255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4432255932Salfred}
4433255932Salfred
4434255932Salfredstatic void rem_slave_eqs(struct mlx4_dev *dev, int slave)
4435255932Salfred{
4436255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4437255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4438255932Salfred	struct list_head *eq_list =
4439255932Salfred		&tracker->slave_list[slave].res_list[RES_EQ];
4440255932Salfred	struct res_eq *eq;
4441255932Salfred	struct res_eq *tmp;
4442255932Salfred	int err;
4443255932Salfred	int state;
4444255932Salfred	LIST_HEAD(tlist);
4445255932Salfred	int eqn;
4446255932Salfred	struct mlx4_cmd_mailbox *mailbox;
4447255932Salfred
4448255932Salfred	err = move_all_busy(dev, slave, RES_EQ);
4449255932Salfred	if (err)
4450255932Salfred		mlx4_warn(dev, "rem_slave_eqs: Could not move all eqs to "
4451255932Salfred			  "busy for slave %d\n", slave);
4452255932Salfred
4453255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4454255932Salfred	list_for_each_entry_safe(eq, tmp, eq_list, com.list) {
4455255932Salfred		spin_unlock_irq(mlx4_tlock(dev));
4456255932Salfred		if (eq->com.owner == slave) {
4457255932Salfred			eqn = eq->com.res_id;
4458255932Salfred			state = eq->com.from_state;
4459255932Salfred			while (state != 0) {
4460255932Salfred				switch (state) {
4461255932Salfred				case RES_EQ_RESERVED:
4462255932Salfred					spin_lock_irq(mlx4_tlock(dev));
4463255932Salfred					rb_erase(&eq->com.node,
4464255932Salfred						 &tracker->res_tree[RES_EQ]);
4465255932Salfred					list_del(&eq->com.list);
4466255932Salfred					spin_unlock_irq(mlx4_tlock(dev));
4467255932Salfred					kfree(eq);
4468255932Salfred					state = 0;
4469255932Salfred					break;
4470255932Salfred
4471255932Salfred				case RES_EQ_HW:
4472255932Salfred					mailbox = mlx4_alloc_cmd_mailbox(dev);
4473255932Salfred					if (IS_ERR(mailbox)) {
4474255932Salfred						cond_resched();
4475255932Salfred						continue;
4476255932Salfred					}
4477255932Salfred					err = mlx4_cmd_box(dev, slave, 0,
4478255932Salfred							   eqn & 0xff, 0,
4479255932Salfred							   MLX4_CMD_HW2SW_EQ,
4480255932Salfred							   MLX4_CMD_TIME_CLASS_A,
4481255932Salfred							   MLX4_CMD_NATIVE);
4482255932Salfred					if (err)
4483255932Salfred						mlx4_dbg(dev, "rem_slave_eqs: failed"
4484255932Salfred							 " to move slave %d eqs %d to"
4485255932Salfred							 " SW ownership\n", slave, eqn);
4486255932Salfred					mlx4_free_cmd_mailbox(dev, mailbox);
4487255932Salfred					atomic_dec(&eq->mtt->ref_count);
4488255932Salfred					state = RES_EQ_RESERVED;
4489255932Salfred					break;
4490255932Salfred
4491255932Salfred				default:
4492255932Salfred					state = 0;
4493255932Salfred				}
4494255932Salfred			}
4495255932Salfred		}
4496255932Salfred		spin_lock_irq(mlx4_tlock(dev));
4497255932Salfred	}
4498255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4499255932Salfred}
4500255932Salfred
4501255932Salfredstatic void rem_slave_counters(struct mlx4_dev *dev, int slave)
4502255932Salfred{
4503272027Shselasky	__mlx4_slave_counters_free(dev, slave);
4504255932Salfred}
4505255932Salfred
4506255932Salfredstatic void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
4507255932Salfred{
4508255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4509255932Salfred	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
4510255932Salfred	struct list_head *xrcdn_list =
4511255932Salfred		&tracker->slave_list[slave].res_list[RES_XRCD];
4512255932Salfred	struct res_xrcdn *xrcd;
4513255932Salfred	struct res_xrcdn *tmp;
4514255932Salfred	int err;
4515255932Salfred	int xrcdn;
4516255932Salfred
4517255932Salfred	err = move_all_busy(dev, slave, RES_XRCD);
4518255932Salfred	if (err)
4519255932Salfred		mlx4_warn(dev, "rem_slave_xrcdns: Could not move all xrcdns to "
4520255932Salfred			  "busy for slave %d\n", slave);
4521255932Salfred
4522255932Salfred	spin_lock_irq(mlx4_tlock(dev));
4523255932Salfred	list_for_each_entry_safe(xrcd, tmp, xrcdn_list, com.list) {
4524255932Salfred		if (xrcd->com.owner == slave) {
4525255932Salfred			xrcdn = xrcd->com.res_id;
4526255932Salfred			rb_erase(&xrcd->com.node, &tracker->res_tree[RES_XRCD]);
4527255932Salfred			list_del(&xrcd->com.list);
4528255932Salfred			kfree(xrcd);
4529255932Salfred			__mlx4_xrcd_free(dev, xrcdn);
4530255932Salfred		}
4531255932Salfred	}
4532255932Salfred	spin_unlock_irq(mlx4_tlock(dev));
4533255932Salfred}
4534255932Salfred
4535255932Salfredvoid mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
4536255932Salfred{
4537255932Salfred	struct mlx4_priv *priv = mlx4_priv(dev);
4538255932Salfred
4539255932Salfred	mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
4540255932Salfred	rem_slave_macs(dev, slave);
4541255932Salfred	rem_slave_vlans(dev, slave);
4542272027Shselasky	rem_slave_fs_rule(dev, slave);
4543255932Salfred	rem_slave_qps(dev, slave);
4544255932Salfred	rem_slave_srqs(dev, slave);
4545255932Salfred	rem_slave_cqs(dev, slave);
4546255932Salfred	rem_slave_mrs(dev, slave);
4547255932Salfred	rem_slave_eqs(dev, slave);
4548255932Salfred	rem_slave_mtts(dev, slave);
4549255932Salfred	rem_slave_counters(dev, slave);
4550255932Salfred	rem_slave_xrcdns(dev, slave);
4551255932Salfred	mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
4552255932Salfred}
4553272027Shselasky
4554272027Shselaskyvoid mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)
4555272027Shselasky{
4556272027Shselasky	struct mlx4_vf_immed_vlan_work *work =
4557272027Shselasky		container_of(_work, struct mlx4_vf_immed_vlan_work, work);
4558272027Shselasky	struct mlx4_cmd_mailbox *mailbox;
4559272027Shselasky	struct mlx4_update_qp_context *upd_context;
4560272027Shselasky	struct mlx4_dev *dev = &work->priv->dev;
4561272027Shselasky	struct mlx4_resource_tracker *tracker =
4562272027Shselasky		&work->priv->mfunc.master.res_tracker;
4563272027Shselasky	struct list_head *qp_list =
4564272027Shselasky		&tracker->slave_list[work->slave].res_list[RES_QP];
4565272027Shselasky	struct res_qp *qp;
4566272027Shselasky	struct res_qp *tmp;
4567272027Shselasky	u64 qp_path_mask_vlan_ctrl =
4568272027Shselasky		       ((1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_UNTAGGED) |
4569272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_1P) |
4570272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_TAGGED) |
4571272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_UNTAGGED) |
4572272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_1P) |
4573272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_TAGGED));
4574272027Shselasky
4575272027Shselasky	u64 qp_path_mask = ((1ULL << MLX4_UPD_QP_PATH_MASK_VLAN_INDEX) |
4576272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_FVL) |
4577272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_CV) |
4578272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_HIDE_CQE_VLAN) |
4579272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_FEUP) |
4580272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_FVL_RX) |
4581272027Shselasky		       (1ULL << MLX4_UPD_QP_PATH_MASK_SCHED_QUEUE));
4582272027Shselasky
4583272027Shselasky	int err;
4584272027Shselasky	int port, errors = 0;
4585272027Shselasky	u8 vlan_control;
4586272027Shselasky
4587272027Shselasky	if (mlx4_is_slave(dev)) {
4588272027Shselasky		mlx4_warn(dev, "Trying to update-qp in slave %d\n",
4589272027Shselasky			  work->slave);
4590272027Shselasky		goto out;
4591272027Shselasky	}
4592272027Shselasky
4593272027Shselasky	mailbox = mlx4_alloc_cmd_mailbox(dev);
4594272027Shselasky	if (IS_ERR(mailbox))
4595272027Shselasky		goto out;
4596272027Shselasky
4597272027Shselasky	if (!work->vlan_id)
4598272027Shselasky		vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
4599272027Shselasky			MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
4600272027Shselasky	else
4601272027Shselasky		vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
4602272027Shselasky			MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
4603272027Shselasky			MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
4604272027Shselasky
4605272027Shselasky	upd_context = mailbox->buf;
4606272027Shselasky	upd_context->qp_mask = cpu_to_be64(MLX4_UPD_QP_MASK_VSD);
4607272027Shselasky
4608272027Shselasky	spin_lock_irq(mlx4_tlock(dev));
4609272027Shselasky	list_for_each_entry_safe(qp, tmp, qp_list, com.list) {
4610272027Shselasky		spin_unlock_irq(mlx4_tlock(dev));
4611272027Shselasky		if (qp->com.owner == work->slave) {
4612272027Shselasky			if (qp->com.from_state != RES_QP_HW ||
4613272027Shselasky			    !qp->sched_queue ||  /* no INIT2RTR trans yet */
4614272027Shselasky			    mlx4_is_qp_reserved(dev, qp->local_qpn) ||
4615272027Shselasky			    qp->qpc_flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET)) {
4616272027Shselasky				spin_lock_irq(mlx4_tlock(dev));
4617272027Shselasky				continue;
4618272027Shselasky			}
4619272027Shselasky			port = (qp->sched_queue >> 6 & 1) + 1;
4620272027Shselasky			if (port != work->port) {
4621272027Shselasky				spin_lock_irq(mlx4_tlock(dev));
4622272027Shselasky				continue;
4623272027Shselasky			}
4624272027Shselasky			if (MLX4_QP_ST_RC == ((qp->qpc_flags >> 16) & 0xff))
4625272027Shselasky				upd_context->primary_addr_path_mask = cpu_to_be64(qp_path_mask);
4626272027Shselasky			else
4627272027Shselasky				upd_context->primary_addr_path_mask =
4628272027Shselasky					cpu_to_be64(qp_path_mask | qp_path_mask_vlan_ctrl);
4629272027Shselasky			if (work->vlan_id == MLX4_VGT) {
4630272027Shselasky				upd_context->qp_context.param3 = qp->param3;
4631272027Shselasky				upd_context->qp_context.pri_path.vlan_control = qp->vlan_control;
4632272027Shselasky				upd_context->qp_context.pri_path.fvl_rx = qp->fvl_rx;
4633272027Shselasky				upd_context->qp_context.pri_path.vlan_index = qp->vlan_index;
4634272027Shselasky				upd_context->qp_context.pri_path.fl = qp->pri_path_fl;
4635272027Shselasky				upd_context->qp_context.pri_path.feup = qp->feup;
4636272027Shselasky				upd_context->qp_context.pri_path.sched_queue =
4637272027Shselasky					qp->sched_queue;
4638272027Shselasky			} else {
4639272027Shselasky				upd_context->qp_context.param3 = qp->param3 & ~cpu_to_be32(MLX4_STRIP_VLAN);
4640272027Shselasky				upd_context->qp_context.pri_path.vlan_control = vlan_control;
4641272027Shselasky				upd_context->qp_context.pri_path.vlan_index = work->vlan_ix;
4642272027Shselasky				upd_context->qp_context.pri_path.fvl_rx =
4643272027Shselasky					qp->fvl_rx | MLX4_FVL_RX_FORCE_ETH_VLAN;
4644272027Shselasky				upd_context->qp_context.pri_path.fl =
4645272027Shselasky					qp->pri_path_fl | MLX4_FL_CV | MLX4_FL_ETH_HIDE_CQE_VLAN;
4646272027Shselasky				upd_context->qp_context.pri_path.feup =
4647272027Shselasky					qp->feup | MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN;
4648272027Shselasky				upd_context->qp_context.pri_path.sched_queue =
4649272027Shselasky					qp->sched_queue & 0xC7;
4650272027Shselasky				upd_context->qp_context.pri_path.sched_queue |=
4651272027Shselasky					((work->qos & 0x7) << 3);
4652272027Shselasky			}
4653272027Shselasky
4654272027Shselasky			err = mlx4_cmd(dev, mailbox->dma,
4655272027Shselasky				       qp->local_qpn & 0xffffff,
4656272027Shselasky				       0, MLX4_CMD_UPDATE_QP,
4657272027Shselasky				       MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
4658272027Shselasky			if (err) {
4659272027Shselasky				mlx4_info(dev, "UPDATE_QP failed for slave %d, "
4660272027Shselasky					  "port %d, qpn %d (%d)\n",
4661272027Shselasky					  work->slave, port, qp->local_qpn,
4662272027Shselasky					  err);
4663272027Shselasky				errors++;
4664272027Shselasky			}
4665272027Shselasky		}
4666272027Shselasky		spin_lock_irq(mlx4_tlock(dev));
4667272027Shselasky	}
4668272027Shselasky	spin_unlock_irq(mlx4_tlock(dev));
4669272027Shselasky	mlx4_free_cmd_mailbox(dev, mailbox);
4670272027Shselasky
4671272027Shselasky	if (errors)
4672272027Shselasky		mlx4_err(dev, "%d UPDATE_QP failures for slave %d, port %d\n",
4673272027Shselasky			 errors, work->slave, work->port);
4674272027Shselasky
4675272027Shselasky	/* unregister previous vlan_id if needed and we had no errors
4676272027Shselasky	 * while updating the QPs
4677272027Shselasky	 */
4678272027Shselasky	if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN && !errors &&
4679272027Shselasky	    NO_INDX != work->orig_vlan_ix)
4680272027Shselasky		__mlx4_unregister_vlan(&work->priv->dev, work->port,
4681272027Shselasky				       work->orig_vlan_id);
4682272027Shselaskyout:
4683272027Shselasky	kfree(work);
4684272027Shselasky	return;
4685272027Shselasky}
4686272027Shselasky
4687