brintos

brintos / linux-shallow public Read only

0
0
Text · 132.8 KiB · 771b920 Raw
5424 lines · c
1/*2 * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.3 * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies.4 * All rights reserved.5 * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc.  All rights reserved.6 *7 * This software is available to you under a choice of one of two8 * licenses.  You may choose to be licensed under the terms of the GNU9 * General Public License (GPL) Version 2, available from the file10 * COPYING in the main directory of this source tree, or the11 * OpenIB.org BSD license below:12 *13 *     Redistribution and use in source and binary forms, with or14 *     without modification, are permitted provided that the following15 *     conditions are met:16 *17 *      - Redistributions of source code must retain the above18 *        copyright notice, this list of conditions and the following19 *        disclaimer.20 *21 *      - Redistributions in binary form must reproduce the above22 *        copyright notice, this list of conditions and the following23 *        disclaimer in the documentation and/or other materials24 *        provided with the distribution.25 *26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE33 * SOFTWARE.34 */35 36#include <linux/sched.h>37#include <linux/pci.h>38#include <linux/errno.h>39#include <linux/kernel.h>40#include <linux/io.h>41#include <linux/slab.h>42#include <linux/mlx4/cmd.h>43#include <linux/mlx4/qp.h>44#include <linux/if_ether.h>45#include <linux/etherdevice.h>46 47#include "mlx4.h"48#include "fw.h"49#include "mlx4_stats.h"50 51#define MLX4_MAC_VALID		(1ull << 63)52#define MLX4_PF_COUNTERS_PER_PORT	253#define MLX4_VF_COUNTERS_PER_PORT	154 55struct mac_res {56	struct list_head list;57	u64 mac;58	int ref_count;59	u8 smac_index;60	u8 port;61};62 63struct vlan_res {64	struct list_head list;65	u16 vlan;66	int ref_count;67	int vlan_index;68	u8 port;69};70 71struct res_common {72	struct list_head	list;73	struct rb_node		node;74	u64		        res_id;75	int			owner;76	int			state;77	int			from_state;78	int			to_state;79	int			removing;80	const char		*func_name;81};82 83enum {84	RES_ANY_BUSY = 185};86 87struct res_gid {88	struct list_head	list;89	u8			gid[16];90	enum mlx4_protocol	prot;91	enum mlx4_steer_type	steer;92	u64			reg_id;93};94 95enum res_qp_states {96	RES_QP_BUSY = RES_ANY_BUSY,97 98	/* QP number was allocated */99	RES_QP_RESERVED,100 101	/* ICM memory for QP context was mapped */102	RES_QP_MAPPED,103 104	/* QP is in hw ownership */105	RES_QP_HW106};107 108struct res_qp {109	struct res_common	com;110	struct res_mtt	       *mtt;111	struct res_cq	       *rcq;112	struct res_cq	       *scq;113	struct res_srq	       *srq;114	struct list_head	mcg_list;115	spinlock_t		mcg_spl;116	int			local_qpn;117	atomic_t		ref_count;118	u32			qpc_flags;119	/* saved qp params before VST enforcement in order to restore on VGT */120	u8			sched_queue;121	__be32			param3;122	u8			vlan_control;123	u8			fvl_rx;124	u8			pri_path_fl;125	u8			vlan_index;126	u8			feup;127};128 129enum res_mtt_states {130	RES_MTT_BUSY = RES_ANY_BUSY,131	RES_MTT_ALLOCATED,132};133 134static inline const char *mtt_states_str(enum res_mtt_states state)135{136	switch (state) {137	case RES_MTT_BUSY: return "RES_MTT_BUSY";138	case RES_MTT_ALLOCATED: return "RES_MTT_ALLOCATED";139	default: return "Unknown";140	}141}142 143struct res_mtt {144	struct res_common	com;145	int			order;146	atomic_t		ref_count;147};148 149enum res_mpt_states {150	RES_MPT_BUSY = RES_ANY_BUSY,151	RES_MPT_RESERVED,152	RES_MPT_MAPPED,153	RES_MPT_HW,154};155 156struct res_mpt {157	struct res_common	com;158	struct res_mtt	       *mtt;159	int			key;160};161 162enum res_eq_states {163	RES_EQ_BUSY = RES_ANY_BUSY,164	RES_EQ_RESERVED,165	RES_EQ_HW,166};167 168struct res_eq {169	struct res_common	com;170	struct res_mtt	       *mtt;171};172 173enum res_cq_states {174	RES_CQ_BUSY = RES_ANY_BUSY,175	RES_CQ_ALLOCATED,176	RES_CQ_HW,177};178 179struct res_cq {180	struct res_common	com;181	struct res_mtt	       *mtt;182	atomic_t		ref_count;183};184 185enum res_srq_states {186	RES_SRQ_BUSY = RES_ANY_BUSY,187	RES_SRQ_ALLOCATED,188	RES_SRQ_HW,189};190 191struct res_srq {192	struct res_common	com;193	struct res_mtt	       *mtt;194	struct res_cq	       *cq;195	atomic_t		ref_count;196};197 198enum res_counter_states {199	RES_COUNTER_BUSY = RES_ANY_BUSY,200	RES_COUNTER_ALLOCATED,201};202 203struct res_counter {204	struct res_common	com;205	int			port;206};207 208enum res_xrcdn_states {209	RES_XRCD_BUSY = RES_ANY_BUSY,210	RES_XRCD_ALLOCATED,211};212 213struct res_xrcdn {214	struct res_common	com;215	int			port;216};217 218enum res_fs_rule_states {219	RES_FS_RULE_BUSY = RES_ANY_BUSY,220	RES_FS_RULE_ALLOCATED,221};222 223struct res_fs_rule {224	struct res_common	com;225	int			qpn;226	/* VF DMFS mbox with port flipped */227	void			*mirr_mbox;228	/* > 0 --> apply mirror when getting into HA mode      */229	/* = 0 --> un-apply mirror when getting out of HA mode */230	u32			mirr_mbox_size;231	struct list_head	mirr_list;232	u64			mirr_rule_id;233};234 235static void *res_tracker_lookup(struct rb_root *root, u64 res_id)236{237	struct rb_node *node = root->rb_node;238 239	while (node) {240		struct res_common *res = rb_entry(node, struct res_common,241						  node);242 243		if (res_id < res->res_id)244			node = node->rb_left;245		else if (res_id > res->res_id)246			node = node->rb_right;247		else248			return res;249	}250	return NULL;251}252 253static int res_tracker_insert(struct rb_root *root, struct res_common *res)254{255	struct rb_node **new = &(root->rb_node), *parent = NULL;256 257	/* Figure out where to put new node */258	while (*new) {259		struct res_common *this = rb_entry(*new, struct res_common,260						   node);261 262		parent = *new;263		if (res->res_id < this->res_id)264			new = &((*new)->rb_left);265		else if (res->res_id > this->res_id)266			new = &((*new)->rb_right);267		else268			return -EEXIST;269	}270 271	/* Add new node and rebalance tree. */272	rb_link_node(&res->node, parent, new);273	rb_insert_color(&res->node, root);274 275	return 0;276}277 278enum qp_transition {279	QP_TRANS_INIT2RTR,280	QP_TRANS_RTR2RTS,281	QP_TRANS_RTS2RTS,282	QP_TRANS_SQERR2RTS,283	QP_TRANS_SQD2SQD,284	QP_TRANS_SQD2RTS285};286 287/* For Debug uses */288static const char *resource_str(enum mlx4_resource rt)289{290	switch (rt) {291	case RES_QP: return "RES_QP";292	case RES_CQ: return "RES_CQ";293	case RES_SRQ: return "RES_SRQ";294	case RES_MPT: return "RES_MPT";295	case RES_MTT: return "RES_MTT";296	case RES_MAC: return  "RES_MAC";297	case RES_VLAN: return  "RES_VLAN";298	case RES_EQ: return "RES_EQ";299	case RES_COUNTER: return "RES_COUNTER";300	case RES_FS_RULE: return "RES_FS_RULE";301	case RES_XRCD: return "RES_XRCD";302	default: return "Unknown resource type !!!";303	}304}305 306static void rem_slave_vlans(struct mlx4_dev *dev, int slave);307static inline int mlx4_grant_resource(struct mlx4_dev *dev, int slave,308				      enum mlx4_resource res_type, int count,309				      int port)310{311	struct mlx4_priv *priv = mlx4_priv(dev);312	struct resource_allocator *res_alloc =313		&priv->mfunc.master.res_tracker.res_alloc[res_type];314	int err = -EDQUOT;315	int allocated, free, reserved, guaranteed, from_free;316	int from_rsvd;317 318	if (slave > dev->persist->num_vfs)319		return -EINVAL;320 321	spin_lock(&res_alloc->alloc_lock);322	allocated = (port > 0) ?323		res_alloc->allocated[(port - 1) *324		(dev->persist->num_vfs + 1) + slave] :325		res_alloc->allocated[slave];326	free = (port > 0) ? res_alloc->res_port_free[port - 1] :327		res_alloc->res_free;328	reserved = (port > 0) ? res_alloc->res_port_rsvd[port - 1] :329		res_alloc->res_reserved;330	guaranteed = res_alloc->guaranteed[slave];331 332	if (allocated + count > res_alloc->quota[slave]) {333		mlx4_warn(dev, "VF %d port %d res %s: quota exceeded, count %d alloc %d quota %d\n",334			  slave, port, resource_str(res_type), count,335			  allocated, res_alloc->quota[slave]);336		goto out;337	}338 339	if (allocated + count <= guaranteed) {340		err = 0;341		from_rsvd = count;342	} else {343		/* portion may need to be obtained from free area */344		if (guaranteed - allocated > 0)345			from_free = count - (guaranteed - allocated);346		else347			from_free = count;348 349		from_rsvd = count - from_free;350 351		if (free - from_free >= reserved)352			err = 0;353		else354			mlx4_warn(dev, "VF %d port %d res %s: free pool empty, free %d from_free %d rsvd %d\n",355				  slave, port, resource_str(res_type), free,356				  from_free, reserved);357	}358 359	if (!err) {360		/* grant the request */361		if (port > 0) {362			res_alloc->allocated[(port - 1) *363			(dev->persist->num_vfs + 1) + slave] += count;364			res_alloc->res_port_free[port - 1] -= count;365			res_alloc->res_port_rsvd[port - 1] -= from_rsvd;366		} else {367			res_alloc->allocated[slave] += count;368			res_alloc->res_free -= count;369			res_alloc->res_reserved -= from_rsvd;370		}371	}372 373out:374	spin_unlock(&res_alloc->alloc_lock);375	return err;376}377 378static inline void mlx4_release_resource(struct mlx4_dev *dev, int slave,379				    enum mlx4_resource res_type, int count,380				    int port)381{382	struct mlx4_priv *priv = mlx4_priv(dev);383	struct resource_allocator *res_alloc =384		&priv->mfunc.master.res_tracker.res_alloc[res_type];385	int allocated, guaranteed, from_rsvd;386 387	if (slave > dev->persist->num_vfs)388		return;389 390	spin_lock(&res_alloc->alloc_lock);391 392	allocated = (port > 0) ?393		res_alloc->allocated[(port - 1) *394		(dev->persist->num_vfs + 1) + slave] :395		res_alloc->allocated[slave];396	guaranteed = res_alloc->guaranteed[slave];397 398	if (allocated - count >= guaranteed) {399		from_rsvd = 0;400	} else {401		/* portion may need to be returned to reserved area */402		if (allocated - guaranteed > 0)403			from_rsvd = count - (allocated - guaranteed);404		else405			from_rsvd = count;406	}407 408	if (port > 0) {409		res_alloc->allocated[(port - 1) *410		(dev->persist->num_vfs + 1) + slave] -= count;411		res_alloc->res_port_free[port - 1] += count;412		res_alloc->res_port_rsvd[port - 1] += from_rsvd;413	} else {414		res_alloc->allocated[slave] -= count;415		res_alloc->res_free += count;416		res_alloc->res_reserved += from_rsvd;417	}418 419	spin_unlock(&res_alloc->alloc_lock);420	return;421}422 423static inline void initialize_res_quotas(struct mlx4_dev *dev,424					 struct resource_allocator *res_alloc,425					 enum mlx4_resource res_type,426					 int vf, int num_instances)427{428	res_alloc->guaranteed[vf] = num_instances /429				    (2 * (dev->persist->num_vfs + 1));430	res_alloc->quota[vf] = (num_instances / 2) + res_alloc->guaranteed[vf];431	if (vf == mlx4_master_func_num(dev)) {432		res_alloc->res_free = num_instances;433		if (res_type == RES_MTT) {434			/* reserved mtts will be taken out of the PF allocation */435			res_alloc->res_free += dev->caps.reserved_mtts;436			res_alloc->guaranteed[vf] += dev->caps.reserved_mtts;437			res_alloc->quota[vf] += dev->caps.reserved_mtts;438		}439	}440}441 442void mlx4_init_quotas(struct mlx4_dev *dev)443{444	struct mlx4_priv *priv = mlx4_priv(dev);445	int pf;446 447	/* quotas for VFs are initialized in mlx4_slave_cap */448	if (mlx4_is_slave(dev))449		return;450 451	if (!mlx4_is_mfunc(dev)) {452		dev->quotas.qp = dev->caps.num_qps - dev->caps.reserved_qps -453			mlx4_num_reserved_sqps(dev);454		dev->quotas.cq = dev->caps.num_cqs - dev->caps.reserved_cqs;455		dev->quotas.srq = dev->caps.num_srqs - dev->caps.reserved_srqs;456		dev->quotas.mtt = dev->caps.num_mtts - dev->caps.reserved_mtts;457		dev->quotas.mpt = dev->caps.num_mpts - dev->caps.reserved_mrws;458		return;459	}460 461	pf = mlx4_master_func_num(dev);462	dev->quotas.qp =463		priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[pf];464	dev->quotas.cq =465		priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[pf];466	dev->quotas.srq =467		priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[pf];468	dev->quotas.mtt =469		priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[pf];470	dev->quotas.mpt =471		priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[pf];472}473 474static int475mlx4_calc_res_counter_guaranteed(struct mlx4_dev *dev,476				 struct resource_allocator *res_alloc,477				 int vf)478{479	struct mlx4_active_ports actv_ports;480	int ports, counters_guaranteed;481 482	/* For master, only allocate according to the number of phys ports */483	if (vf == mlx4_master_func_num(dev))484		return MLX4_PF_COUNTERS_PER_PORT * dev->caps.num_ports;485 486	/* calculate real number of ports for the VF */487	actv_ports = mlx4_get_active_ports(dev, vf);488	ports = bitmap_weight(actv_ports.ports, dev->caps.num_ports);489	counters_guaranteed = ports * MLX4_VF_COUNTERS_PER_PORT;490 491	/* If we do not have enough counters for this VF, do not492	 * allocate any for it. '-1' to reduce the sink counter.493	 */494	if ((res_alloc->res_reserved + counters_guaranteed) >495	    (dev->caps.max_counters - 1))496		return 0;497 498	return counters_guaranteed;499}500 501int mlx4_init_resource_tracker(struct mlx4_dev *dev)502{503	struct mlx4_priv *priv = mlx4_priv(dev);504	int i, j;505	int t;506 507	priv->mfunc.master.res_tracker.slave_list =508		kcalloc(dev->num_slaves, sizeof(struct slave_list),509			GFP_KERNEL);510	if (!priv->mfunc.master.res_tracker.slave_list)511		return -ENOMEM;512 513	for (i = 0 ; i < dev->num_slaves; i++) {514		for (t = 0; t < MLX4_NUM_OF_RESOURCE_TYPE; ++t)515			INIT_LIST_HEAD(&priv->mfunc.master.res_tracker.516				       slave_list[i].res_list[t]);517		mutex_init(&priv->mfunc.master.res_tracker.slave_list[i].mutex);518	}519 520	mlx4_dbg(dev, "Started init_resource_tracker: %ld slaves\n",521		 dev->num_slaves);522	for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++)523		priv->mfunc.master.res_tracker.res_tree[i] = RB_ROOT;524 525	for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {526		struct resource_allocator *res_alloc =527			&priv->mfunc.master.res_tracker.res_alloc[i];528		res_alloc->quota = kmalloc_array(dev->persist->num_vfs + 1,529						 sizeof(int),530						 GFP_KERNEL);531		res_alloc->guaranteed = kmalloc_array(dev->persist->num_vfs + 1,532						      sizeof(int),533						      GFP_KERNEL);534		if (i == RES_MAC || i == RES_VLAN)535			res_alloc->allocated =536				kcalloc(MLX4_MAX_PORTS *537						(dev->persist->num_vfs + 1),538					sizeof(int), GFP_KERNEL);539		else540			res_alloc->allocated =541				kcalloc(dev->persist->num_vfs + 1,542					sizeof(int), GFP_KERNEL);543		/* Reduce the sink counter */544		if (i == RES_COUNTER)545			res_alloc->res_free = dev->caps.max_counters - 1;546 547		if (!res_alloc->quota || !res_alloc->guaranteed ||548		    !res_alloc->allocated)549			goto no_mem_err;550 551		spin_lock_init(&res_alloc->alloc_lock);552		for (t = 0; t < dev->persist->num_vfs + 1; t++) {553			struct mlx4_active_ports actv_ports =554				mlx4_get_active_ports(dev, t);555			switch (i) {556			case RES_QP:557				initialize_res_quotas(dev, res_alloc, RES_QP,558						      t, dev->caps.num_qps -559						      dev->caps.reserved_qps -560						      mlx4_num_reserved_sqps(dev));561				break;562			case RES_CQ:563				initialize_res_quotas(dev, res_alloc, RES_CQ,564						      t, dev->caps.num_cqs -565						      dev->caps.reserved_cqs);566				break;567			case RES_SRQ:568				initialize_res_quotas(dev, res_alloc, RES_SRQ,569						      t, dev->caps.num_srqs -570						      dev->caps.reserved_srqs);571				break;572			case RES_MPT:573				initialize_res_quotas(dev, res_alloc, RES_MPT,574						      t, dev->caps.num_mpts -575						      dev->caps.reserved_mrws);576				break;577			case RES_MTT:578				initialize_res_quotas(dev, res_alloc, RES_MTT,579						      t, dev->caps.num_mtts -580						      dev->caps.reserved_mtts);581				break;582			case RES_MAC:583				if (t == mlx4_master_func_num(dev)) {584					int max_vfs_pport = 0;585					/* Calculate the max vfs per port for */586					/* both ports.			      */587					for (j = 0; j < dev->caps.num_ports;588					     j++) {589						struct mlx4_slaves_pport slaves_pport =590							mlx4_phys_to_slaves_pport(dev, j + 1);591						unsigned current_slaves =592							bitmap_weight(slaves_pport.slaves,593								      dev->caps.num_ports) - 1;594						if (max_vfs_pport < current_slaves)595							max_vfs_pport =596								current_slaves;597					}598					res_alloc->quota[t] =599						MLX4_MAX_MAC_NUM -600						2 * max_vfs_pport;601					res_alloc->guaranteed[t] = 2;602					for (j = 0; j < MLX4_MAX_PORTS; j++)603						res_alloc->res_port_free[j] =604							MLX4_MAX_MAC_NUM;605				} else {606					res_alloc->quota[t] = MLX4_MAX_MAC_NUM;607					res_alloc->guaranteed[t] = 2;608				}609				break;610			case RES_VLAN:611				if (t == mlx4_master_func_num(dev)) {612					res_alloc->quota[t] = MLX4_MAX_VLAN_NUM;613					res_alloc->guaranteed[t] = MLX4_MAX_VLAN_NUM / 2;614					for (j = 0; j < MLX4_MAX_PORTS; j++)615						res_alloc->res_port_free[j] =616							res_alloc->quota[t];617				} else {618					res_alloc->quota[t] = MLX4_MAX_VLAN_NUM / 2;619					res_alloc->guaranteed[t] = 0;620				}621				break;622			case RES_COUNTER:623				res_alloc->quota[t] = dev->caps.max_counters;624				res_alloc->guaranteed[t] =625					mlx4_calc_res_counter_guaranteed(dev, res_alloc, t);626				break;627			default:628				break;629			}630			if (i == RES_MAC || i == RES_VLAN) {631				for (j = 0; j < dev->caps.num_ports; j++)632					if (test_bit(j, actv_ports.ports))633						res_alloc->res_port_rsvd[j] +=634							res_alloc->guaranteed[t];635			} else {636				res_alloc->res_reserved += res_alloc->guaranteed[t];637			}638		}639	}640	spin_lock_init(&priv->mfunc.master.res_tracker.lock);641	return 0;642 643no_mem_err:644	for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {645		kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated);646		priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL;647		kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed);648		priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL;649		kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota);650		priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL;651	}652	return -ENOMEM;653}654 655void mlx4_free_resource_tracker(struct mlx4_dev *dev,656				enum mlx4_res_tracker_free_type type)657{658	struct mlx4_priv *priv = mlx4_priv(dev);659	int i;660 661	if (priv->mfunc.master.res_tracker.slave_list) {662		if (type != RES_TR_FREE_STRUCTS_ONLY) {663			for (i = 0; i < dev->num_slaves; i++) {664				if (type == RES_TR_FREE_ALL ||665				    dev->caps.function != i)666					mlx4_delete_all_resources_for_slave(dev, i);667			}668			/* free master's vlans */669			i = dev->caps.function;670			mlx4_reset_roce_gids(dev, i);671			mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);672			rem_slave_vlans(dev, i);673			mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);674		}675 676		if (type != RES_TR_FREE_SLAVES_ONLY) {677			for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {678				kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated);679				priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL;680				kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed);681				priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL;682				kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota);683				priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL;684			}685			kfree(priv->mfunc.master.res_tracker.slave_list);686			priv->mfunc.master.res_tracker.slave_list = NULL;687		}688	}689}690 691static void update_pkey_index(struct mlx4_dev *dev, int slave,692			      struct mlx4_cmd_mailbox *inbox)693{694	u8 sched = *(u8 *)(inbox->buf + 64);695	u8 orig_index = *(u8 *)(inbox->buf + 35);696	u8 new_index;697	struct mlx4_priv *priv = mlx4_priv(dev);698	int port;699 700	port = (sched >> 6 & 1) + 1;701 702	new_index = priv->virt2phys_pkey[slave][port - 1][orig_index];703	*(u8 *)(inbox->buf + 35) = new_index;704}705 706static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,707		       u8 slave)708{709	struct mlx4_qp_context	*qp_ctx = inbox->buf + 8;710	enum mlx4_qp_optpar	optpar = be32_to_cpu(*(__be32 *) inbox->buf);711	u32			ts = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff;712	int port;713 714	if (MLX4_QP_ST_UD == ts) {715		port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;716		if (mlx4_is_eth(dev, port))717			qp_ctx->pri_path.mgid_index =718				mlx4_get_base_gid_ix(dev, slave, port) | 0x80;719		else720			qp_ctx->pri_path.mgid_index = slave | 0x80;721 722	} else if (MLX4_QP_ST_RC == ts || MLX4_QP_ST_XRC == ts || MLX4_QP_ST_UC == ts) {723		if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH) {724			port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;725			if (mlx4_is_eth(dev, port)) {726				qp_ctx->pri_path.mgid_index +=727					mlx4_get_base_gid_ix(dev, slave, port);728				qp_ctx->pri_path.mgid_index &= 0x7f;729			} else {730				qp_ctx->pri_path.mgid_index = slave & 0x7F;731			}732		}733		if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) {734			port = (qp_ctx->alt_path.sched_queue >> 6 & 1) + 1;735			if (mlx4_is_eth(dev, port)) {736				qp_ctx->alt_path.mgid_index +=737					mlx4_get_base_gid_ix(dev, slave, port);738				qp_ctx->alt_path.mgid_index &= 0x7f;739			} else {740				qp_ctx->alt_path.mgid_index = slave & 0x7F;741			}742		}743	}744}745 746static int handle_counter(struct mlx4_dev *dev, struct mlx4_qp_context *qpc,747			  u8 slave, int port);748 749static int update_vport_qp_param(struct mlx4_dev *dev,750				 struct mlx4_cmd_mailbox *inbox,751				 u8 slave, u32 qpn)752{753	struct mlx4_qp_context	*qpc = inbox->buf + 8;754	struct mlx4_vport_oper_state *vp_oper;755	struct mlx4_priv *priv;756	u32 qp_type;757	int port, err = 0;758 759	port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1;760	priv = mlx4_priv(dev);761	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];762	qp_type	= (be32_to_cpu(qpc->flags) >> 16) & 0xff;763 764	err = handle_counter(dev, qpc, slave, port);765	if (err)766		goto out;767 768	if (MLX4_VGT != vp_oper->state.default_vlan) {769		/* the reserved QPs (special, proxy, tunnel)770		 * do not operate over vlans771		 */772		if (mlx4_is_qp_reserved(dev, qpn))773			return 0;774 775		/* force strip vlan by clear vsd, MLX QP refers to Raw Ethernet */776		if (qp_type == MLX4_QP_ST_UD ||777		    (qp_type == MLX4_QP_ST_MLX && mlx4_is_eth(dev, port))) {778			if (dev->caps.bmme_flags & MLX4_BMME_FLAG_VSD_INIT2RTR) {779				*(__be32 *)inbox->buf =780					cpu_to_be32(be32_to_cpu(*(__be32 *)inbox->buf) |781					MLX4_QP_OPTPAR_VLAN_STRIPPING);782				qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);783			} else {784				struct mlx4_update_qp_params params = {.flags = 0};785 786				err = mlx4_update_qp(dev, qpn, MLX4_UPDATE_QP_VSD, &params);787				if (err)788					goto out;789			}790		}791 792		/* preserve IF_COUNTER flag */793		qpc->pri_path.vlan_control &=794			MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER;795		if (vp_oper->state.link_state == IFLA_VF_LINK_STATE_DISABLE &&796		    dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) {797			qpc->pri_path.vlan_control |=798				MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |799				MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED |800				MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED |801				MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |802				MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED |803				MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;804		} else if (0 != vp_oper->state.default_vlan) {805			if (vp_oper->state.vlan_proto == htons(ETH_P_8021AD)) {806				/* vst QinQ should block untagged on TX,807				 * but cvlan is in payload and phv is set so808				 * hw see it as untagged. Block tagged instead.809				 */810				qpc->pri_path.vlan_control |=811					MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED |812					MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |813					MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |814					MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;815			} else { /* vst 802.1Q */816				qpc->pri_path.vlan_control |=817					MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |818					MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |819					MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;820			}821		} else { /* priority tagged */822			qpc->pri_path.vlan_control |=823				MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |824				MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;825		}826 827		qpc->pri_path.fvl_rx |= MLX4_FVL_RX_FORCE_ETH_VLAN;828		qpc->pri_path.vlan_index = vp_oper->vlan_idx;829		qpc->pri_path.fl |= MLX4_FL_ETH_HIDE_CQE_VLAN;830		if (vp_oper->state.vlan_proto == htons(ETH_P_8021AD))831			qpc->pri_path.fl |= MLX4_FL_SV;832		else833			qpc->pri_path.fl |= MLX4_FL_CV;834		qpc->pri_path.feup |= MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN;835		qpc->pri_path.sched_queue &= 0xC7;836		qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3;837		qpc->qos_vport = vp_oper->state.qos_vport;838	}839	if (vp_oper->state.spoofchk) {840		qpc->pri_path.feup |= MLX4_FSM_FORCE_ETH_SRC_MAC;841		qpc->pri_path.grh_mylmc = (0x80 & qpc->pri_path.grh_mylmc) + vp_oper->mac_idx;842	}843out:844	return err;845}846 847static int mpt_mask(struct mlx4_dev *dev)848{849	return dev->caps.num_mpts - 1;850}851 852static const char *mlx4_resource_type_to_str(enum mlx4_resource t)853{854	switch (t) {855	case RES_QP:856		return "QP";857	case RES_CQ:858		return "CQ";859	case RES_SRQ:860		return "SRQ";861	case RES_XRCD:862		return "XRCD";863	case RES_MPT:864		return "MPT";865	case RES_MTT:866		return "MTT";867	case RES_MAC:868		return "MAC";869	case RES_VLAN:870		return "VLAN";871	case RES_COUNTER:872		return "COUNTER";873	case RES_FS_RULE:874		return "FS_RULE";875	case RES_EQ:876		return "EQ";877	default:878		return "INVALID RESOURCE";879	}880}881 882static void *find_res(struct mlx4_dev *dev, u64 res_id,883		      enum mlx4_resource type)884{885	struct mlx4_priv *priv = mlx4_priv(dev);886 887	return res_tracker_lookup(&priv->mfunc.master.res_tracker.res_tree[type],888				  res_id);889}890 891static int _get_res(struct mlx4_dev *dev, int slave, u64 res_id,892		    enum mlx4_resource type,893		    void *res, const char *func_name)894{895	struct res_common *r;896	int err = 0;897 898	spin_lock_irq(mlx4_tlock(dev));899	r = find_res(dev, res_id, type);900	if (!r) {901		err = -ENONET;902		goto exit;903	}904 905	if (r->state == RES_ANY_BUSY) {906		mlx4_warn(dev,907			  "%s(%d) trying to get resource %llx of type %s, but it's already taken by %s\n",908			  func_name, slave, res_id, mlx4_resource_type_to_str(type),909			  r->func_name);910		err = -EBUSY;911		goto exit;912	}913 914	if (r->owner != slave) {915		err = -EPERM;916		goto exit;917	}918 919	r->from_state = r->state;920	r->state = RES_ANY_BUSY;921	r->func_name = func_name;922 923	if (res)924		*((struct res_common **)res) = r;925 926exit:927	spin_unlock_irq(mlx4_tlock(dev));928	return err;929}930 931#define get_res(dev, slave, res_id, type, res) \932	_get_res((dev), (slave), (res_id), (type), (res), __func__)933 934int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,935				    enum mlx4_resource type,936				    u64 res_id, int *slave)937{938 939	struct res_common *r;940	int err = -ENOENT;941	int id = res_id;942 943	if (type == RES_QP)944		id &= 0x7fffff;945	spin_lock(mlx4_tlock(dev));946 947	r = find_res(dev, id, type);948	if (r) {949		*slave = r->owner;950		err = 0;951	}952	spin_unlock(mlx4_tlock(dev));953 954	return err;955}956 957static void put_res(struct mlx4_dev *dev, int slave, u64 res_id,958		    enum mlx4_resource type)959{960	struct res_common *r;961 962	spin_lock_irq(mlx4_tlock(dev));963	r = find_res(dev, res_id, type);964	if (r) {965		r->state = r->from_state;966		r->func_name = "";967	}968	spin_unlock_irq(mlx4_tlock(dev));969}970 971static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,972			     u64 in_param, u64 *out_param, int port);973 974static int handle_existing_counter(struct mlx4_dev *dev, u8 slave, int port,975				   int counter_index)976{977	struct res_common *r;978	struct res_counter *counter;979	int ret = 0;980 981	if (counter_index == MLX4_SINK_COUNTER_INDEX(dev))982		return ret;983 984	spin_lock_irq(mlx4_tlock(dev));985	r = find_res(dev, counter_index, RES_COUNTER);986	if (!r || r->owner != slave) {987		ret = -EINVAL;988	} else {989		counter = container_of(r, struct res_counter, com);990		if (!counter->port)991			counter->port = port;992	}993 994	spin_unlock_irq(mlx4_tlock(dev));995	return ret;996}997 998static int handle_unexisting_counter(struct mlx4_dev *dev,999				     struct mlx4_qp_context *qpc, u8 slave,1000				     int port)1001{1002	struct mlx4_priv *priv = mlx4_priv(dev);1003	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1004	struct res_common *tmp;1005	struct res_counter *counter;1006	u64 counter_idx = MLX4_SINK_COUNTER_INDEX(dev);1007	int err = 0;1008 1009	spin_lock_irq(mlx4_tlock(dev));1010	list_for_each_entry(tmp,1011			    &tracker->slave_list[slave].res_list[RES_COUNTER],1012			    list) {1013		counter = container_of(tmp, struct res_counter, com);1014		if (port == counter->port) {1015			qpc->pri_path.counter_index  = counter->com.res_id;1016			spin_unlock_irq(mlx4_tlock(dev));1017			return 0;1018		}1019	}1020	spin_unlock_irq(mlx4_tlock(dev));1021 1022	/* No existing counter, need to allocate a new counter */1023	err = counter_alloc_res(dev, slave, RES_OP_RESERVE, 0, 0, &counter_idx,1024				port);1025	if (err == -ENOENT) {1026		err = 0;1027	} else if (err && err != -ENOSPC) {1028		mlx4_err(dev, "%s: failed to create new counter for slave %d err %d\n",1029			 __func__, slave, err);1030	} else {1031		qpc->pri_path.counter_index = counter_idx;1032		mlx4_dbg(dev, "%s: alloc new counter for slave %d index %d\n",1033			 __func__, slave, qpc->pri_path.counter_index);1034		err = 0;1035	}1036 1037	return err;1038}1039 1040static int handle_counter(struct mlx4_dev *dev, struct mlx4_qp_context *qpc,1041			  u8 slave, int port)1042{1043	if (qpc->pri_path.counter_index != MLX4_SINK_COUNTER_INDEX(dev))1044		return handle_existing_counter(dev, slave, port,1045					       qpc->pri_path.counter_index);1046 1047	return handle_unexisting_counter(dev, qpc, slave, port);1048}1049 1050static struct res_common *alloc_qp_tr(int id)1051{1052	struct res_qp *ret;1053 1054	ret = kzalloc(sizeof(*ret), GFP_KERNEL);1055	if (!ret)1056		return NULL;1057 1058	ret->com.res_id = id;1059	ret->com.state = RES_QP_RESERVED;1060	ret->local_qpn = id;1061	INIT_LIST_HEAD(&ret->mcg_list);1062	spin_lock_init(&ret->mcg_spl);1063	atomic_set(&ret->ref_count, 0);1064 1065	return &ret->com;1066}1067 1068static struct res_common *alloc_mtt_tr(int id, int order)1069{1070	struct res_mtt *ret;1071 1072	ret = kzalloc(sizeof(*ret), GFP_KERNEL);1073	if (!ret)1074		return NULL;1075 1076	ret->com.res_id = id;1077	ret->order = order;1078	ret->com.state = RES_MTT_ALLOCATED;1079	atomic_set(&ret->ref_count, 0);1080 1081	return &ret->com;1082}1083 1084static struct res_common *alloc_mpt_tr(int id, int key)1085{1086	struct res_mpt *ret;1087 1088	ret = kzalloc(sizeof(*ret), GFP_KERNEL);1089	if (!ret)1090		return NULL;1091 1092	ret->com.res_id = id;1093	ret->com.state = RES_MPT_RESERVED;1094	ret->key = key;1095 1096	return &ret->com;1097}1098 1099static struct res_common *alloc_eq_tr(int id)1100{1101	struct res_eq *ret;1102 1103	ret = kzalloc(sizeof(*ret), GFP_KERNEL);1104	if (!ret)1105		return NULL;1106 1107	ret->com.res_id = id;1108	ret->com.state = RES_EQ_RESERVED;1109 1110	return &ret->com;1111}1112 1113static struct res_common *alloc_cq_tr(int id)1114{1115	struct res_cq *ret;1116 1117	ret = kzalloc(sizeof(*ret), GFP_KERNEL);1118	if (!ret)1119		return NULL;1120 1121	ret->com.res_id = id;1122	ret->com.state = RES_CQ_ALLOCATED;1123	atomic_set(&ret->ref_count, 0);1124 1125	return &ret->com;1126}1127 1128static struct res_common *alloc_srq_tr(int id)1129{1130	struct res_srq *ret;1131 1132	ret = kzalloc(sizeof(*ret), GFP_KERNEL);1133	if (!ret)1134		return NULL;1135 1136	ret->com.res_id = id;1137	ret->com.state = RES_SRQ_ALLOCATED;1138	atomic_set(&ret->ref_count, 0);1139 1140	return &ret->com;1141}1142 1143static struct res_common *alloc_counter_tr(int id, int port)1144{1145	struct res_counter *ret;1146 1147	ret = kzalloc(sizeof(*ret), GFP_KERNEL);1148	if (!ret)1149		return NULL;1150 1151	ret->com.res_id = id;1152	ret->com.state = RES_COUNTER_ALLOCATED;1153	ret->port = port;1154 1155	return &ret->com;1156}1157 1158static struct res_common *alloc_xrcdn_tr(int id)1159{1160	struct res_xrcdn *ret;1161 1162	ret = kzalloc(sizeof(*ret), GFP_KERNEL);1163	if (!ret)1164		return NULL;1165 1166	ret->com.res_id = id;1167	ret->com.state = RES_XRCD_ALLOCATED;1168 1169	return &ret->com;1170}1171 1172static struct res_common *alloc_fs_rule_tr(u64 id, int qpn)1173{1174	struct res_fs_rule *ret;1175 1176	ret = kzalloc(sizeof(*ret), GFP_KERNEL);1177	if (!ret)1178		return NULL;1179 1180	ret->com.res_id = id;1181	ret->com.state = RES_FS_RULE_ALLOCATED;1182	ret->qpn = qpn;1183	return &ret->com;1184}1185 1186static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave,1187				   int extra)1188{1189	struct res_common *ret;1190 1191	switch (type) {1192	case RES_QP:1193		ret = alloc_qp_tr(id);1194		break;1195	case RES_MPT:1196		ret = alloc_mpt_tr(id, extra);1197		break;1198	case RES_MTT:1199		ret = alloc_mtt_tr(id, extra);1200		break;1201	case RES_EQ:1202		ret = alloc_eq_tr(id);1203		break;1204	case RES_CQ:1205		ret = alloc_cq_tr(id);1206		break;1207	case RES_SRQ:1208		ret = alloc_srq_tr(id);1209		break;1210	case RES_MAC:1211		pr_err("implementation missing\n");1212		return NULL;1213	case RES_COUNTER:1214		ret = alloc_counter_tr(id, extra);1215		break;1216	case RES_XRCD:1217		ret = alloc_xrcdn_tr(id);1218		break;1219	case RES_FS_RULE:1220		ret = alloc_fs_rule_tr(id, extra);1221		break;1222	default:1223		return NULL;1224	}1225	if (ret)1226		ret->owner = slave;1227 1228	return ret;1229}1230 1231int mlx4_calc_vf_counters(struct mlx4_dev *dev, int slave, int port,1232			  struct mlx4_counter *data)1233{1234	struct mlx4_priv *priv = mlx4_priv(dev);1235	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1236	struct res_common *tmp;1237	struct res_counter *counter;1238	int *counters_arr;1239	int i = 0, err = 0;1240 1241	memset(data, 0, sizeof(*data));1242 1243	counters_arr = kmalloc_array(dev->caps.max_counters,1244				     sizeof(*counters_arr), GFP_KERNEL);1245	if (!counters_arr)1246		return -ENOMEM;1247 1248	spin_lock_irq(mlx4_tlock(dev));1249	list_for_each_entry(tmp,1250			    &tracker->slave_list[slave].res_list[RES_COUNTER],1251			    list) {1252		counter = container_of(tmp, struct res_counter, com);1253		if (counter->port == port) {1254			counters_arr[i] = (int)tmp->res_id;1255			i++;1256		}1257	}1258	spin_unlock_irq(mlx4_tlock(dev));1259	counters_arr[i] = -1;1260 1261	i = 0;1262 1263	while (counters_arr[i] != -1) {1264		err = mlx4_get_counter_stats(dev, counters_arr[i], data,1265					     0);1266		if (err) {1267			memset(data, 0, sizeof(*data));1268			goto table_changed;1269		}1270		i++;1271	}1272 1273table_changed:1274	kfree(counters_arr);1275	return 0;1276}1277 1278static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,1279			 enum mlx4_resource type, int extra)1280{1281	int i;1282	int err;1283	struct mlx4_priv *priv = mlx4_priv(dev);1284	struct res_common **res_arr;1285	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1286	struct rb_root *root = &tracker->res_tree[type];1287 1288	res_arr = kcalloc(count, sizeof(*res_arr), GFP_KERNEL);1289	if (!res_arr)1290		return -ENOMEM;1291 1292	for (i = 0; i < count; ++i) {1293		res_arr[i] = alloc_tr(base + i, type, slave, extra);1294		if (!res_arr[i]) {1295			for (--i; i >= 0; --i)1296				kfree(res_arr[i]);1297 1298			kfree(res_arr);1299			return -ENOMEM;1300		}1301	}1302 1303	spin_lock_irq(mlx4_tlock(dev));1304	for (i = 0; i < count; ++i) {1305		if (find_res(dev, base + i, type)) {1306			err = -EEXIST;1307			goto undo;1308		}1309		err = res_tracker_insert(root, res_arr[i]);1310		if (err)1311			goto undo;1312		list_add_tail(&res_arr[i]->list,1313			      &tracker->slave_list[slave].res_list[type]);1314	}1315	spin_unlock_irq(mlx4_tlock(dev));1316	kfree(res_arr);1317 1318	return 0;1319 1320undo:1321	for (--i; i >= 0; --i) {1322		rb_erase(&res_arr[i]->node, root);1323		list_del_init(&res_arr[i]->list);1324	}1325 1326	spin_unlock_irq(mlx4_tlock(dev));1327 1328	for (i = 0; i < count; ++i)1329		kfree(res_arr[i]);1330 1331	kfree(res_arr);1332 1333	return err;1334}1335 1336static int remove_qp_ok(struct res_qp *res)1337{1338	if (res->com.state == RES_QP_BUSY || atomic_read(&res->ref_count) ||1339	    !list_empty(&res->mcg_list)) {1340		pr_err("resource tracker: fail to remove qp, state %d, ref_count %d\n",1341		       res->com.state, atomic_read(&res->ref_count));1342		return -EBUSY;1343	} else if (res->com.state != RES_QP_RESERVED) {1344		return -EPERM;1345	}1346 1347	return 0;1348}1349 1350static int remove_mtt_ok(struct res_mtt *res, int order)1351{1352	if (res->com.state == RES_MTT_BUSY ||1353	    atomic_read(&res->ref_count)) {1354		pr_devel("%s-%d: state %s, ref_count %d\n",1355			 __func__, __LINE__,1356			 mtt_states_str(res->com.state),1357			 atomic_read(&res->ref_count));1358		return -EBUSY;1359	} else if (res->com.state != RES_MTT_ALLOCATED)1360		return -EPERM;1361	else if (res->order != order)1362		return -EINVAL;1363 1364	return 0;1365}1366 1367static int remove_mpt_ok(struct res_mpt *res)1368{1369	if (res->com.state == RES_MPT_BUSY)1370		return -EBUSY;1371	else if (res->com.state != RES_MPT_RESERVED)1372		return -EPERM;1373 1374	return 0;1375}1376 1377static int remove_eq_ok(struct res_eq *res)1378{1379	if (res->com.state == RES_MPT_BUSY)1380		return -EBUSY;1381	else if (res->com.state != RES_MPT_RESERVED)1382		return -EPERM;1383 1384	return 0;1385}1386 1387static int remove_counter_ok(struct res_counter *res)1388{1389	if (res->com.state == RES_COUNTER_BUSY)1390		return -EBUSY;1391	else if (res->com.state != RES_COUNTER_ALLOCATED)1392		return -EPERM;1393 1394	return 0;1395}1396 1397static int remove_xrcdn_ok(struct res_xrcdn *res)1398{1399	if (res->com.state == RES_XRCD_BUSY)1400		return -EBUSY;1401	else if (res->com.state != RES_XRCD_ALLOCATED)1402		return -EPERM;1403 1404	return 0;1405}1406 1407static int remove_fs_rule_ok(struct res_fs_rule *res)1408{1409	if (res->com.state == RES_FS_RULE_BUSY)1410		return -EBUSY;1411	else if (res->com.state != RES_FS_RULE_ALLOCATED)1412		return -EPERM;1413 1414	return 0;1415}1416 1417static int remove_cq_ok(struct res_cq *res)1418{1419	if (res->com.state == RES_CQ_BUSY)1420		return -EBUSY;1421	else if (res->com.state != RES_CQ_ALLOCATED)1422		return -EPERM;1423 1424	return 0;1425}1426 1427static int remove_srq_ok(struct res_srq *res)1428{1429	if (res->com.state == RES_SRQ_BUSY)1430		return -EBUSY;1431	else if (res->com.state != RES_SRQ_ALLOCATED)1432		return -EPERM;1433 1434	return 0;1435}1436 1437static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra)1438{1439	switch (type) {1440	case RES_QP:1441		return remove_qp_ok((struct res_qp *)res);1442	case RES_CQ:1443		return remove_cq_ok((struct res_cq *)res);1444	case RES_SRQ:1445		return remove_srq_ok((struct res_srq *)res);1446	case RES_MPT:1447		return remove_mpt_ok((struct res_mpt *)res);1448	case RES_MTT:1449		return remove_mtt_ok((struct res_mtt *)res, extra);1450	case RES_MAC:1451		return -EOPNOTSUPP;1452	case RES_EQ:1453		return remove_eq_ok((struct res_eq *)res);1454	case RES_COUNTER:1455		return remove_counter_ok((struct res_counter *)res);1456	case RES_XRCD:1457		return remove_xrcdn_ok((struct res_xrcdn *)res);1458	case RES_FS_RULE:1459		return remove_fs_rule_ok((struct res_fs_rule *)res);1460	default:1461		return -EINVAL;1462	}1463}1464 1465static int rem_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,1466			 enum mlx4_resource type, int extra)1467{1468	u64 i;1469	int err;1470	struct mlx4_priv *priv = mlx4_priv(dev);1471	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1472	struct res_common *r;1473 1474	spin_lock_irq(mlx4_tlock(dev));1475	for (i = base; i < base + count; ++i) {1476		r = res_tracker_lookup(&tracker->res_tree[type], i);1477		if (!r) {1478			err = -ENOENT;1479			goto out;1480		}1481		if (r->owner != slave) {1482			err = -EPERM;1483			goto out;1484		}1485		err = remove_ok(r, type, extra);1486		if (err)1487			goto out;1488	}1489 1490	for (i = base; i < base + count; ++i) {1491		r = res_tracker_lookup(&tracker->res_tree[type], i);1492		rb_erase(&r->node, &tracker->res_tree[type]);1493		list_del(&r->list);1494		kfree(r);1495	}1496	err = 0;1497 1498out:1499	spin_unlock_irq(mlx4_tlock(dev));1500 1501	return err;1502}1503 1504static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn,1505				enum res_qp_states state, struct res_qp **qp,1506				int alloc)1507{1508	struct mlx4_priv *priv = mlx4_priv(dev);1509	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1510	struct res_qp *r;1511	int err = 0;1512 1513	spin_lock_irq(mlx4_tlock(dev));1514	r = res_tracker_lookup(&tracker->res_tree[RES_QP], qpn);1515	if (!r)1516		err = -ENOENT;1517	else if (r->com.owner != slave)1518		err = -EPERM;1519	else {1520		switch (state) {1521		case RES_QP_BUSY:1522			mlx4_dbg(dev, "%s: failed RES_QP, 0x%llx\n",1523				 __func__, r->com.res_id);1524			err = -EBUSY;1525			break;1526 1527		case RES_QP_RESERVED:1528			if (r->com.state == RES_QP_MAPPED && !alloc)1529				break;1530 1531			mlx4_dbg(dev, "failed RES_QP, 0x%llx\n", r->com.res_id);1532			err = -EINVAL;1533			break;1534 1535		case RES_QP_MAPPED:1536			if ((r->com.state == RES_QP_RESERVED && alloc) ||1537			    r->com.state == RES_QP_HW)1538				break;1539			else {1540				mlx4_dbg(dev, "failed RES_QP, 0x%llx\n",1541					  r->com.res_id);1542				err = -EINVAL;1543			}1544 1545			break;1546 1547		case RES_QP_HW:1548			if (r->com.state != RES_QP_MAPPED)1549				err = -EINVAL;1550			break;1551		default:1552			err = -EINVAL;1553		}1554 1555		if (!err) {1556			r->com.from_state = r->com.state;1557			r->com.to_state = state;1558			r->com.state = RES_QP_BUSY;1559			if (qp)1560				*qp = r;1561		}1562	}1563 1564	spin_unlock_irq(mlx4_tlock(dev));1565 1566	return err;1567}1568 1569static int mr_res_start_move_to(struct mlx4_dev *dev, int slave, int index,1570				enum res_mpt_states state, struct res_mpt **mpt)1571{1572	struct mlx4_priv *priv = mlx4_priv(dev);1573	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1574	struct res_mpt *r;1575	int err = 0;1576 1577	spin_lock_irq(mlx4_tlock(dev));1578	r = res_tracker_lookup(&tracker->res_tree[RES_MPT], index);1579	if (!r)1580		err = -ENOENT;1581	else if (r->com.owner != slave)1582		err = -EPERM;1583	else {1584		switch (state) {1585		case RES_MPT_BUSY:1586			err = -EINVAL;1587			break;1588 1589		case RES_MPT_RESERVED:1590			if (r->com.state != RES_MPT_MAPPED)1591				err = -EINVAL;1592			break;1593 1594		case RES_MPT_MAPPED:1595			if (r->com.state != RES_MPT_RESERVED &&1596			    r->com.state != RES_MPT_HW)1597				err = -EINVAL;1598			break;1599 1600		case RES_MPT_HW:1601			if (r->com.state != RES_MPT_MAPPED)1602				err = -EINVAL;1603			break;1604		default:1605			err = -EINVAL;1606		}1607 1608		if (!err) {1609			r->com.from_state = r->com.state;1610			r->com.to_state = state;1611			r->com.state = RES_MPT_BUSY;1612			if (mpt)1613				*mpt = r;1614		}1615	}1616 1617	spin_unlock_irq(mlx4_tlock(dev));1618 1619	return err;1620}1621 1622static int eq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,1623				enum res_eq_states state, struct res_eq **eq)1624{1625	struct mlx4_priv *priv = mlx4_priv(dev);1626	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1627	struct res_eq *r;1628	int err = 0;1629 1630	spin_lock_irq(mlx4_tlock(dev));1631	r = res_tracker_lookup(&tracker->res_tree[RES_EQ], index);1632	if (!r)1633		err = -ENOENT;1634	else if (r->com.owner != slave)1635		err = -EPERM;1636	else {1637		switch (state) {1638		case RES_EQ_BUSY:1639			err = -EINVAL;1640			break;1641 1642		case RES_EQ_RESERVED:1643			if (r->com.state != RES_EQ_HW)1644				err = -EINVAL;1645			break;1646 1647		case RES_EQ_HW:1648			if (r->com.state != RES_EQ_RESERVED)1649				err = -EINVAL;1650			break;1651 1652		default:1653			err = -EINVAL;1654		}1655 1656		if (!err) {1657			r->com.from_state = r->com.state;1658			r->com.to_state = state;1659			r->com.state = RES_EQ_BUSY;1660		}1661	}1662 1663	spin_unlock_irq(mlx4_tlock(dev));1664 1665	if (!err && eq)1666		*eq = r;1667 1668	return err;1669}1670 1671static int cq_res_start_move_to(struct mlx4_dev *dev, int slave, int cqn,1672				enum res_cq_states state, struct res_cq **cq)1673{1674	struct mlx4_priv *priv = mlx4_priv(dev);1675	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1676	struct res_cq *r;1677	int err;1678 1679	spin_lock_irq(mlx4_tlock(dev));1680	r = res_tracker_lookup(&tracker->res_tree[RES_CQ], cqn);1681	if (!r) {1682		err = -ENOENT;1683	} else if (r->com.owner != slave) {1684		err = -EPERM;1685	} else if (state == RES_CQ_ALLOCATED) {1686		if (r->com.state != RES_CQ_HW)1687			err = -EINVAL;1688		else if (atomic_read(&r->ref_count))1689			err = -EBUSY;1690		else1691			err = 0;1692	} else if (state != RES_CQ_HW || r->com.state != RES_CQ_ALLOCATED) {1693		err = -EINVAL;1694	} else {1695		err = 0;1696	}1697 1698	if (!err) {1699		r->com.from_state = r->com.state;1700		r->com.to_state = state;1701		r->com.state = RES_CQ_BUSY;1702		if (cq)1703			*cq = r;1704	}1705 1706	spin_unlock_irq(mlx4_tlock(dev));1707 1708	return err;1709}1710 1711static int srq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,1712				 enum res_srq_states state, struct res_srq **srq)1713{1714	struct mlx4_priv *priv = mlx4_priv(dev);1715	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1716	struct res_srq *r;1717	int err = 0;1718 1719	spin_lock_irq(mlx4_tlock(dev));1720	r = res_tracker_lookup(&tracker->res_tree[RES_SRQ], index);1721	if (!r) {1722		err = -ENOENT;1723	} else if (r->com.owner != slave) {1724		err = -EPERM;1725	} else if (state == RES_SRQ_ALLOCATED) {1726		if (r->com.state != RES_SRQ_HW)1727			err = -EINVAL;1728		else if (atomic_read(&r->ref_count))1729			err = -EBUSY;1730	} else if (state != RES_SRQ_HW || r->com.state != RES_SRQ_ALLOCATED) {1731		err = -EINVAL;1732	}1733 1734	if (!err) {1735		r->com.from_state = r->com.state;1736		r->com.to_state = state;1737		r->com.state = RES_SRQ_BUSY;1738		if (srq)1739			*srq = r;1740	}1741 1742	spin_unlock_irq(mlx4_tlock(dev));1743 1744	return err;1745}1746 1747static void res_abort_move(struct mlx4_dev *dev, int slave,1748			   enum mlx4_resource type, int id)1749{1750	struct mlx4_priv *priv = mlx4_priv(dev);1751	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1752	struct res_common *r;1753 1754	spin_lock_irq(mlx4_tlock(dev));1755	r = res_tracker_lookup(&tracker->res_tree[type], id);1756	if (r && (r->owner == slave))1757		r->state = r->from_state;1758	spin_unlock_irq(mlx4_tlock(dev));1759}1760 1761static void res_end_move(struct mlx4_dev *dev, int slave,1762			 enum mlx4_resource type, int id)1763{1764	struct mlx4_priv *priv = mlx4_priv(dev);1765	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;1766	struct res_common *r;1767 1768	spin_lock_irq(mlx4_tlock(dev));1769	r = res_tracker_lookup(&tracker->res_tree[type], id);1770	if (r && (r->owner == slave))1771		r->state = r->to_state;1772	spin_unlock_irq(mlx4_tlock(dev));1773}1774 1775static int valid_reserved(struct mlx4_dev *dev, int slave, int qpn)1776{1777	return mlx4_is_qp_reserved(dev, qpn) &&1778		(mlx4_is_master(dev) || mlx4_is_guest_proxy(dev, slave, qpn));1779}1780 1781static int fw_reserved(struct mlx4_dev *dev, int qpn)1782{1783	return qpn < dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW];1784}1785 1786static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,1787			u64 in_param, u64 *out_param)1788{1789	int err;1790	int count;1791	int align;1792	int base;1793	int qpn;1794	u8 flags;1795 1796	switch (op) {1797	case RES_OP_RESERVE:1798		count = get_param_l(&in_param) & 0xffffff;1799		/* Turn off all unsupported QP allocation flags that the1800		 * slave tries to set.1801		 */1802		flags = (get_param_l(&in_param) >> 24) & dev->caps.alloc_res_qp_mask;1803		align = get_param_h(&in_param);1804		err = mlx4_grant_resource(dev, slave, RES_QP, count, 0);1805		if (err)1806			return err;1807 1808		err = __mlx4_qp_reserve_range(dev, count, align, &base, flags);1809		if (err) {1810			mlx4_release_resource(dev, slave, RES_QP, count, 0);1811			return err;1812		}1813 1814		err = add_res_range(dev, slave, base, count, RES_QP, 0);1815		if (err) {1816			mlx4_release_resource(dev, slave, RES_QP, count, 0);1817			__mlx4_qp_release_range(dev, base, count);1818			return err;1819		}1820		set_param_l(out_param, base);1821		break;1822	case RES_OP_MAP_ICM:1823		qpn = get_param_l(&in_param) & 0x7fffff;1824		if (valid_reserved(dev, slave, qpn)) {1825			err = add_res_range(dev, slave, qpn, 1, RES_QP, 0);1826			if (err)1827				return err;1828		}1829 1830		err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED,1831					   NULL, 1);1832		if (err)1833			return err;1834 1835		if (!fw_reserved(dev, qpn)) {1836			err = __mlx4_qp_alloc_icm(dev, qpn);1837			if (err) {1838				res_abort_move(dev, slave, RES_QP, qpn);1839				return err;1840			}1841		}1842 1843		res_end_move(dev, slave, RES_QP, qpn);1844		break;1845 1846	default:1847		err = -EINVAL;1848		break;1849	}1850	return err;1851}1852 1853static int mtt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,1854			 u64 in_param, u64 *out_param)1855{1856	int err = -EINVAL;1857	int base;1858	int order;1859 1860	if (op != RES_OP_RESERVE_AND_MAP)1861		return err;1862 1863	order = get_param_l(&in_param);1864 1865	err = mlx4_grant_resource(dev, slave, RES_MTT, 1 << order, 0);1866	if (err)1867		return err;1868 1869	base = __mlx4_alloc_mtt_range(dev, order);1870	if (base == -1) {1871		mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);1872		return -ENOMEM;1873	}1874 1875	err = add_res_range(dev, slave, base, 1, RES_MTT, order);1876	if (err) {1877		mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);1878		__mlx4_free_mtt_range(dev, base, order);1879	} else {1880		set_param_l(out_param, base);1881	}1882 1883	return err;1884}1885 1886static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,1887			 u64 in_param, u64 *out_param)1888{1889	int err = -EINVAL;1890	int index;1891	int id;1892	struct res_mpt *mpt;1893 1894	switch (op) {1895	case RES_OP_RESERVE:1896		err = mlx4_grant_resource(dev, slave, RES_MPT, 1, 0);1897		if (err)1898			break;1899 1900		index = __mlx4_mpt_reserve(dev);1901		if (index == -1) {1902			mlx4_release_resource(dev, slave, RES_MPT, 1, 0);1903			break;1904		}1905		id = index & mpt_mask(dev);1906 1907		err = add_res_range(dev, slave, id, 1, RES_MPT, index);1908		if (err) {1909			mlx4_release_resource(dev, slave, RES_MPT, 1, 0);1910			__mlx4_mpt_release(dev, index);1911			break;1912		}1913		set_param_l(out_param, index);1914		break;1915	case RES_OP_MAP_ICM:1916		index = get_param_l(&in_param);1917		id = index & mpt_mask(dev);1918		err = mr_res_start_move_to(dev, slave, id,1919					   RES_MPT_MAPPED, &mpt);1920		if (err)1921			return err;1922 1923		err = __mlx4_mpt_alloc_icm(dev, mpt->key);1924		if (err) {1925			res_abort_move(dev, slave, RES_MPT, id);1926			return err;1927		}1928 1929		res_end_move(dev, slave, RES_MPT, id);1930		break;1931	}1932	return err;1933}1934 1935static int cq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,1936			u64 in_param, u64 *out_param)1937{1938	int cqn;1939	int err;1940 1941	switch (op) {1942	case RES_OP_RESERVE_AND_MAP:1943		err = mlx4_grant_resource(dev, slave, RES_CQ, 1, 0);1944		if (err)1945			break;1946 1947		err = __mlx4_cq_alloc_icm(dev, &cqn);1948		if (err) {1949			mlx4_release_resource(dev, slave, RES_CQ, 1, 0);1950			break;1951		}1952 1953		err = add_res_range(dev, slave, cqn, 1, RES_CQ, 0);1954		if (err) {1955			mlx4_release_resource(dev, slave, RES_CQ, 1, 0);1956			__mlx4_cq_free_icm(dev, cqn);1957			break;1958		}1959 1960		set_param_l(out_param, cqn);1961		break;1962 1963	default:1964		err = -EINVAL;1965	}1966 1967	return err;1968}1969 1970static int srq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,1971			 u64 in_param, u64 *out_param)1972{1973	int srqn;1974	int err;1975 1976	switch (op) {1977	case RES_OP_RESERVE_AND_MAP:1978		err = mlx4_grant_resource(dev, slave, RES_SRQ, 1, 0);1979		if (err)1980			break;1981 1982		err = __mlx4_srq_alloc_icm(dev, &srqn);1983		if (err) {1984			mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);1985			break;1986		}1987 1988		err = add_res_range(dev, slave, srqn, 1, RES_SRQ, 0);1989		if (err) {1990			mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);1991			__mlx4_srq_free_icm(dev, srqn);1992			break;1993		}1994 1995		set_param_l(out_param, srqn);1996		break;1997 1998	default:1999		err = -EINVAL;2000	}2001 2002	return err;2003}2004 2005static int mac_find_smac_ix_in_slave(struct mlx4_dev *dev, int slave, int port,2006				     u8 smac_index, u64 *mac)2007{2008	struct mlx4_priv *priv = mlx4_priv(dev);2009	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;2010	struct list_head *mac_list =2011		&tracker->slave_list[slave].res_list[RES_MAC];2012	struct mac_res *res, *tmp;2013 2014	list_for_each_entry_safe(res, tmp, mac_list, list) {2015		if (res->smac_index == smac_index && res->port == (u8) port) {2016			*mac = res->mac;2017			return 0;2018		}2019	}2020	return -ENOENT;2021}2022 2023static int mac_add_to_slave(struct mlx4_dev *dev, int slave, u64 mac, int port, u8 smac_index)2024{2025	struct mlx4_priv *priv = mlx4_priv(dev);2026	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;2027	struct list_head *mac_list =2028		&tracker->slave_list[slave].res_list[RES_MAC];2029	struct mac_res *res, *tmp;2030 2031	list_for_each_entry_safe(res, tmp, mac_list, list) {2032		if (res->mac == mac && res->port == (u8) port) {2033			/* mac found. update ref count */2034			++res->ref_count;2035			return 0;2036		}2037	}2038 2039	if (mlx4_grant_resource(dev, slave, RES_MAC, 1, port))2040		return -EINVAL;2041	res = kzalloc(sizeof(*res), GFP_KERNEL);2042	if (!res) {2043		mlx4_release_resource(dev, slave, RES_MAC, 1, port);2044		return -ENOMEM;2045	}2046	res->mac = mac;2047	res->port = (u8) port;2048	res->smac_index = smac_index;2049	res->ref_count = 1;2050	list_add_tail(&res->list,2051		      &tracker->slave_list[slave].res_list[RES_MAC]);2052	return 0;2053}2054 2055static void mac_del_from_slave(struct mlx4_dev *dev, int slave, u64 mac,2056			       int port)2057{2058	struct mlx4_priv *priv = mlx4_priv(dev);2059	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;2060	struct list_head *mac_list =2061		&tracker->slave_list[slave].res_list[RES_MAC];2062	struct mac_res *res, *tmp;2063 2064	list_for_each_entry_safe(res, tmp, mac_list, list) {2065		if (res->mac == mac && res->port == (u8) port) {2066			if (!--res->ref_count) {2067				list_del(&res->list);2068				mlx4_release_resource(dev, slave, RES_MAC, 1, port);2069				kfree(res);2070			}2071			break;2072		}2073	}2074}2075 2076static void rem_slave_macs(struct mlx4_dev *dev, int slave)2077{2078	struct mlx4_priv *priv = mlx4_priv(dev);2079	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;2080	struct list_head *mac_list =2081		&tracker->slave_list[slave].res_list[RES_MAC];2082	struct mac_res *res, *tmp;2083	int i;2084 2085	list_for_each_entry_safe(res, tmp, mac_list, list) {2086		list_del(&res->list);2087		/* dereference the mac the num times the slave referenced it */2088		for (i = 0; i < res->ref_count; i++)2089			__mlx4_unregister_mac(dev, res->port, res->mac);2090		mlx4_release_resource(dev, slave, RES_MAC, 1, res->port);2091		kfree(res);2092	}2093}2094 2095static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,2096			 u64 in_param, u64 *out_param, int in_port)2097{2098	int err = -EINVAL;2099	int port;2100	u64 mac;2101	u8 smac_index;2102 2103	if (op != RES_OP_RESERVE_AND_MAP)2104		return err;2105 2106	port = !in_port ? get_param_l(out_param) : in_port;2107	port = mlx4_slave_convert_port(2108			dev, slave, port);2109 2110	if (port < 0)2111		return -EINVAL;2112	mac = in_param;2113 2114	err = __mlx4_register_mac(dev, port, mac);2115	if (err >= 0) {2116		smac_index = err;2117		set_param_l(out_param, err);2118		err = 0;2119	}2120 2121	if (!err) {2122		err = mac_add_to_slave(dev, slave, mac, port, smac_index);2123		if (err)2124			__mlx4_unregister_mac(dev, port, mac);2125	}2126	return err;2127}2128 2129static int vlan_add_to_slave(struct mlx4_dev *dev, int slave, u16 vlan,2130			     int port, int vlan_index)2131{2132	struct mlx4_priv *priv = mlx4_priv(dev);2133	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;2134	struct list_head *vlan_list =2135		&tracker->slave_list[slave].res_list[RES_VLAN];2136	struct vlan_res *res, *tmp;2137 2138	list_for_each_entry_safe(res, tmp, vlan_list, list) {2139		if (res->vlan == vlan && res->port == (u8) port) {2140			/* vlan found. update ref count */2141			++res->ref_count;2142			return 0;2143		}2144	}2145 2146	if (mlx4_grant_resource(dev, slave, RES_VLAN, 1, port))2147		return -EINVAL;2148	res = kzalloc(sizeof(*res), GFP_KERNEL);2149	if (!res) {2150		mlx4_release_resource(dev, slave, RES_VLAN, 1, port);2151		return -ENOMEM;2152	}2153	res->vlan = vlan;2154	res->port = (u8) port;2155	res->vlan_index = vlan_index;2156	res->ref_count = 1;2157	list_add_tail(&res->list,2158		      &tracker->slave_list[slave].res_list[RES_VLAN]);2159	return 0;2160}2161 2162 2163static void vlan_del_from_slave(struct mlx4_dev *dev, int slave, u16 vlan,2164				int port)2165{2166	struct mlx4_priv *priv = mlx4_priv(dev);2167	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;2168	struct list_head *vlan_list =2169		&tracker->slave_list[slave].res_list[RES_VLAN];2170	struct vlan_res *res, *tmp;2171 2172	list_for_each_entry_safe(res, tmp, vlan_list, list) {2173		if (res->vlan == vlan && res->port == (u8) port) {2174			if (!--res->ref_count) {2175				list_del(&res->list);2176				mlx4_release_resource(dev, slave, RES_VLAN,2177						      1, port);2178				kfree(res);2179			}2180			break;2181		}2182	}2183}2184 2185static void rem_slave_vlans(struct mlx4_dev *dev, int slave)2186{2187	struct mlx4_priv *priv = mlx4_priv(dev);2188	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;2189	struct list_head *vlan_list =2190		&tracker->slave_list[slave].res_list[RES_VLAN];2191	struct vlan_res *res, *tmp;2192	int i;2193 2194	list_for_each_entry_safe(res, tmp, vlan_list, list) {2195		list_del(&res->list);2196		/* dereference the vlan the num times the slave referenced it */2197		for (i = 0; i < res->ref_count; i++)2198			__mlx4_unregister_vlan(dev, res->port, res->vlan);2199		mlx4_release_resource(dev, slave, RES_VLAN, 1, res->port);2200		kfree(res);2201	}2202}2203 2204static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,2205			  u64 in_param, u64 *out_param, int in_port)2206{2207	struct mlx4_priv *priv = mlx4_priv(dev);2208	struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;2209	int err;2210	u16 vlan;2211	int vlan_index;2212	int port;2213 2214	port = !in_port ? get_param_l(out_param) : in_port;2215 2216	if (!port || op != RES_OP_RESERVE_AND_MAP)2217		return -EINVAL;2218 2219	port = mlx4_slave_convert_port(2220			dev, slave, port);2221 2222	if (port < 0)2223		return -EINVAL;2224	/* upstream kernels had NOP for reg/unreg vlan. Continue this. */2225	if (!in_port && port > 0 && port <= dev->caps.num_ports) {2226		slave_state[slave].old_vlan_api = true;2227		return 0;2228	}2229 2230	vlan = (u16) in_param;2231 2232	err = __mlx4_register_vlan(dev, port, vlan, &vlan_index);2233	if (!err) {2234		set_param_l(out_param, (u32) vlan_index);2235		err = vlan_add_to_slave(dev, slave, vlan, port, vlan_index);2236		if (err)2237			__mlx4_unregister_vlan(dev, port, vlan);2238	}2239	return err;2240}2241 2242static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,2243			     u64 in_param, u64 *out_param, int port)2244{2245	u32 index;2246	int err;2247 2248	if (op != RES_OP_RESERVE)2249		return -EINVAL;2250 2251	err = mlx4_grant_resource(dev, slave, RES_COUNTER, 1, 0);2252	if (err)2253		return err;2254 2255	err = __mlx4_counter_alloc(dev, &index);2256	if (err) {2257		mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);2258		return err;2259	}2260 2261	err = add_res_range(dev, slave, index, 1, RES_COUNTER, port);2262	if (err) {2263		__mlx4_counter_free(dev, index);2264		mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);2265	} else {2266		set_param_l(out_param, index);2267	}2268 2269	return err;2270}2271 2272static int xrcdn_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,2273			   u64 in_param, u64 *out_param)2274{2275	u32 xrcdn;2276	int err;2277 2278	if (op != RES_OP_RESERVE)2279		return -EINVAL;2280 2281	err = __mlx4_xrcd_alloc(dev, &xrcdn);2282	if (err)2283		return err;2284 2285	err = add_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);2286	if (err)2287		__mlx4_xrcd_free(dev, xrcdn);2288	else2289		set_param_l(out_param, xrcdn);2290 2291	return err;2292}2293 2294int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,2295			   struct mlx4_vhcr *vhcr,2296			   struct mlx4_cmd_mailbox *inbox,2297			   struct mlx4_cmd_mailbox *outbox,2298			   struct mlx4_cmd_info *cmd)2299{2300	int err;2301	int alop = vhcr->op_modifier;2302 2303	switch (vhcr->in_modifier & 0xFF) {2304	case RES_QP:2305		err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop,2306				   vhcr->in_param, &vhcr->out_param);2307		break;2308 2309	case RES_MTT:2310		err = mtt_alloc_res(dev, slave, vhcr->op_modifier, alop,2311				    vhcr->in_param, &vhcr->out_param);2312		break;2313 2314	case RES_MPT:2315		err = mpt_alloc_res(dev, slave, vhcr->op_modifier, alop,2316				    vhcr->in_param, &vhcr->out_param);2317		break;2318 2319	case RES_CQ:2320		err = cq_alloc_res(dev, slave, vhcr->op_modifier, alop,2321				   vhcr->in_param, &vhcr->out_param);2322		break;2323 2324	case RES_SRQ:2325		err = srq_alloc_res(dev, slave, vhcr->op_modifier, alop,2326				    vhcr->in_param, &vhcr->out_param);2327		break;2328 2329	case RES_MAC:2330		err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop,2331				    vhcr->in_param, &vhcr->out_param,2332				    (vhcr->in_modifier >> 8) & 0xFF);2333		break;2334 2335	case RES_VLAN:2336		err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop,2337				     vhcr->in_param, &vhcr->out_param,2338				     (vhcr->in_modifier >> 8) & 0xFF);2339		break;2340 2341	case RES_COUNTER:2342		err = counter_alloc_res(dev, slave, vhcr->op_modifier, alop,2343					vhcr->in_param, &vhcr->out_param, 0);2344		break;2345 2346	case RES_XRCD:2347		err = xrcdn_alloc_res(dev, slave, vhcr->op_modifier, alop,2348				      vhcr->in_param, &vhcr->out_param);2349		break;2350 2351	default:2352		err = -EINVAL;2353		break;2354	}2355 2356	return err;2357}2358 2359static int qp_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,2360		       u64 in_param)2361{2362	int err;2363	int count;2364	int base;2365	int qpn;2366 2367	switch (op) {2368	case RES_OP_RESERVE:2369		base = get_param_l(&in_param) & 0x7fffff;2370		count = get_param_h(&in_param);2371		err = rem_res_range(dev, slave, base, count, RES_QP, 0);2372		if (err)2373			break;2374		mlx4_release_resource(dev, slave, RES_QP, count, 0);2375		__mlx4_qp_release_range(dev, base, count);2376		break;2377	case RES_OP_MAP_ICM:2378		qpn = get_param_l(&in_param) & 0x7fffff;2379		err = qp_res_start_move_to(dev, slave, qpn, RES_QP_RESERVED,2380					   NULL, 0);2381		if (err)2382			return err;2383 2384		if (!fw_reserved(dev, qpn))2385			__mlx4_qp_free_icm(dev, qpn);2386 2387		res_end_move(dev, slave, RES_QP, qpn);2388 2389		if (valid_reserved(dev, slave, qpn))2390			err = rem_res_range(dev, slave, qpn, 1, RES_QP, 0);2391		break;2392	default:2393		err = -EINVAL;2394		break;2395	}2396	return err;2397}2398 2399static int mtt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,2400			u64 in_param, u64 *out_param)2401{2402	int err = -EINVAL;2403	int base;2404	int order;2405 2406	if (op != RES_OP_RESERVE_AND_MAP)2407		return err;2408 2409	base = get_param_l(&in_param);2410	order = get_param_h(&in_param);2411	err = rem_res_range(dev, slave, base, 1, RES_MTT, order);2412	if (!err) {2413		mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);2414		__mlx4_free_mtt_range(dev, base, order);2415	}2416	return err;2417}2418 2419static int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,2420			u64 in_param)2421{2422	int err = -EINVAL;2423	int index;2424	int id;2425	struct res_mpt *mpt;2426 2427	switch (op) {2428	case RES_OP_RESERVE:2429		index = get_param_l(&in_param);2430		id = index & mpt_mask(dev);2431		err = get_res(dev, slave, id, RES_MPT, &mpt);2432		if (err)2433			break;2434		index = mpt->key;2435		put_res(dev, slave, id, RES_MPT);2436 2437		err = rem_res_range(dev, slave, id, 1, RES_MPT, 0);2438		if (err)2439			break;2440		mlx4_release_resource(dev, slave, RES_MPT, 1, 0);2441		__mlx4_mpt_release(dev, index);2442		break;2443	case RES_OP_MAP_ICM:2444		index = get_param_l(&in_param);2445		id = index & mpt_mask(dev);2446		err = mr_res_start_move_to(dev, slave, id,2447					   RES_MPT_RESERVED, &mpt);2448		if (err)2449			return err;2450 2451		__mlx4_mpt_free_icm(dev, mpt->key);2452		res_end_move(dev, slave, RES_MPT, id);2453		break;2454	default:2455		err = -EINVAL;2456		break;2457	}2458	return err;2459}2460 2461static int cq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,2462		       u64 in_param, u64 *out_param)2463{2464	int cqn;2465	int err;2466 2467	switch (op) {2468	case RES_OP_RESERVE_AND_MAP:2469		cqn = get_param_l(&in_param);2470		err = rem_res_range(dev, slave, cqn, 1, RES_CQ, 0);2471		if (err)2472			break;2473 2474		mlx4_release_resource(dev, slave, RES_CQ, 1, 0);2475		__mlx4_cq_free_icm(dev, cqn);2476		break;2477 2478	default:2479		err = -EINVAL;2480		break;2481	}2482 2483	return err;2484}2485 2486static int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,2487			u64 in_param, u64 *out_param)2488{2489	int srqn;2490	int err;2491 2492	switch (op) {2493	case RES_OP_RESERVE_AND_MAP:2494		srqn = get_param_l(&in_param);2495		err = rem_res_range(dev, slave, srqn, 1, RES_SRQ, 0);2496		if (err)2497			break;2498 2499		mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);2500		__mlx4_srq_free_icm(dev, srqn);2501		break;2502 2503	default:2504		err = -EINVAL;2505		break;2506	}2507 2508	return err;2509}2510 2511static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,2512			    u64 in_param, u64 *out_param, int in_port)2513{2514	int port;2515	int err = 0;2516 2517	switch (op) {2518	case RES_OP_RESERVE_AND_MAP:2519		port = !in_port ? get_param_l(out_param) : in_port;2520		port = mlx4_slave_convert_port(2521				dev, slave, port);2522 2523		if (port < 0)2524			return -EINVAL;2525		mac_del_from_slave(dev, slave, in_param, port);2526		__mlx4_unregister_mac(dev, port, in_param);2527		break;2528	default:2529		err = -EINVAL;2530		break;2531	}2532 2533	return err;2534 2535}2536 2537static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,2538			    u64 in_param, u64 *out_param, int port)2539{2540	struct mlx4_priv *priv = mlx4_priv(dev);2541	struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;2542	int err = 0;2543 2544	port = mlx4_slave_convert_port(2545			dev, slave, port);2546 2547	if (port < 0)2548		return -EINVAL;2549	switch (op) {2550	case RES_OP_RESERVE_AND_MAP:2551		if (slave_state[slave].old_vlan_api)2552			return 0;2553		if (!port)2554			return -EINVAL;2555		vlan_del_from_slave(dev, slave, in_param, port);2556		__mlx4_unregister_vlan(dev, port, in_param);2557		break;2558	default:2559		err = -EINVAL;2560		break;2561	}2562 2563	return err;2564}2565 2566static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,2567			    u64 in_param, u64 *out_param)2568{2569	int index;2570	int err;2571 2572	if (op != RES_OP_RESERVE)2573		return -EINVAL;2574 2575	index = get_param_l(&in_param);2576	if (index == MLX4_SINK_COUNTER_INDEX(dev))2577		return 0;2578 2579	err = rem_res_range(dev, slave, index, 1, RES_COUNTER, 0);2580	if (err)2581		return err;2582 2583	__mlx4_counter_free(dev, index);2584	mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);2585 2586	return err;2587}2588 2589static int xrcdn_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,2590			  u64 in_param, u64 *out_param)2591{2592	int xrcdn;2593	int err;2594 2595	if (op != RES_OP_RESERVE)2596		return -EINVAL;2597 2598	xrcdn = get_param_l(&in_param);2599	err = rem_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);2600	if (err)2601		return err;2602 2603	__mlx4_xrcd_free(dev, xrcdn);2604 2605	return err;2606}2607 2608int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,2609			  struct mlx4_vhcr *vhcr,2610			  struct mlx4_cmd_mailbox *inbox,2611			  struct mlx4_cmd_mailbox *outbox,2612			  struct mlx4_cmd_info *cmd)2613{2614	int err = -EINVAL;2615	int alop = vhcr->op_modifier;2616 2617	switch (vhcr->in_modifier & 0xFF) {2618	case RES_QP:2619		err = qp_free_res(dev, slave, vhcr->op_modifier, alop,2620				  vhcr->in_param);2621		break;2622 2623	case RES_MTT:2624		err = mtt_free_res(dev, slave, vhcr->op_modifier, alop,2625				   vhcr->in_param, &vhcr->out_param);2626		break;2627 2628	case RES_MPT:2629		err = mpt_free_res(dev, slave, vhcr->op_modifier, alop,2630				   vhcr->in_param);2631		break;2632 2633	case RES_CQ:2634		err = cq_free_res(dev, slave, vhcr->op_modifier, alop,2635				  vhcr->in_param, &vhcr->out_param);2636		break;2637 2638	case RES_SRQ:2639		err = srq_free_res(dev, slave, vhcr->op_modifier, alop,2640				   vhcr->in_param, &vhcr->out_param);2641		break;2642 2643	case RES_MAC:2644		err = mac_free_res(dev, slave, vhcr->op_modifier, alop,2645				   vhcr->in_param, &vhcr->out_param,2646				   (vhcr->in_modifier >> 8) & 0xFF);2647		break;2648 2649	case RES_VLAN:2650		err = vlan_free_res(dev, slave, vhcr->op_modifier, alop,2651				    vhcr->in_param, &vhcr->out_param,2652				    (vhcr->in_modifier >> 8) & 0xFF);2653		break;2654 2655	case RES_COUNTER:2656		err = counter_free_res(dev, slave, vhcr->op_modifier, alop,2657				       vhcr->in_param, &vhcr->out_param);2658		break;2659 2660	case RES_XRCD:2661		err = xrcdn_free_res(dev, slave, vhcr->op_modifier, alop,2662				     vhcr->in_param, &vhcr->out_param);2663		break;2664 2665	default:2666		break;2667	}2668	return err;2669}2670 2671/* ugly but other choices are uglier */2672static int mr_phys_mpt(struct mlx4_mpt_entry *mpt)2673{2674	return (be32_to_cpu(mpt->flags) >> 9) & 1;2675}2676 2677static int mr_get_mtt_addr(struct mlx4_mpt_entry *mpt)2678{2679	return (int)be64_to_cpu(mpt->mtt_addr) & 0xfffffff8;2680}2681 2682static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt)2683{2684	return be32_to_cpu(mpt->mtt_sz);2685}2686 2687static u32 mr_get_pd(struct mlx4_mpt_entry *mpt)2688{2689	return be32_to_cpu(mpt->pd_flags) & 0x00ffffff;2690}2691 2692static int mr_is_fmr(struct mlx4_mpt_entry *mpt)2693{2694	return be32_to_cpu(mpt->pd_flags) & MLX4_MPT_PD_FLAG_FAST_REG;2695}2696 2697static int mr_is_bind_enabled(struct mlx4_mpt_entry *mpt)2698{2699	return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_BIND_ENABLE;2700}2701 2702static int mr_is_region(struct mlx4_mpt_entry *mpt)2703{2704	return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_REGION;2705}2706 2707static int qp_get_mtt_addr(struct mlx4_qp_context *qpc)2708{2709	return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;2710}2711 2712static int srq_get_mtt_addr(struct mlx4_srq_context *srqc)2713{2714	return be32_to_cpu(srqc->mtt_base_addr_l) & 0xfffffff8;2715}2716 2717static int qp_get_mtt_size(struct mlx4_qp_context *qpc)2718{2719	int page_shift = (qpc->log_page_size & 0x3f) + 12;2720	int log_sq_size = (qpc->sq_size_stride >> 3) & 0xf;2721	int log_sq_sride = qpc->sq_size_stride & 7;2722	int log_rq_size = (qpc->rq_size_stride >> 3) & 0xf;2723	int log_rq_stride = qpc->rq_size_stride & 7;2724	int srq = (be32_to_cpu(qpc->srqn) >> 24) & 1;2725	int rss = (be32_to_cpu(qpc->flags) >> 13) & 1;2726	u32 ts = (be32_to_cpu(qpc->flags) >> 16) & 0xff;2727	int xrc = (ts == MLX4_QP_ST_XRC) ? 1 : 0;2728	int sq_size;2729	int rq_size;2730	int total_pages;2731	int total_mem;2732	int page_offset = (be32_to_cpu(qpc->params2) >> 6) & 0x3f;2733	int tot;2734 2735	sq_size = 1 << (log_sq_size + log_sq_sride + 4);2736	rq_size = (srq|rss|xrc) ? 0 : (1 << (log_rq_size + log_rq_stride + 4));2737	total_mem = sq_size + rq_size;2738	tot = (total_mem + (page_offset << 6)) >> page_shift;2739	total_pages = !tot ? 1 : roundup_pow_of_two(tot);2740 2741	return total_pages;2742}2743 2744static int check_mtt_range(struct mlx4_dev *dev, int slave, int start,2745			   int size, struct res_mtt *mtt)2746{2747	int res_start = mtt->com.res_id;2748	int res_size = (1 << mtt->order);2749 2750	if (start < res_start || start + size > res_start + res_size)2751		return -EPERM;2752	return 0;2753}2754 2755int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,2756			   struct mlx4_vhcr *vhcr,2757			   struct mlx4_cmd_mailbox *inbox,2758			   struct mlx4_cmd_mailbox *outbox,2759			   struct mlx4_cmd_info *cmd)2760{2761	int err;2762	int index = vhcr->in_modifier;2763	struct res_mtt *mtt;2764	struct res_mpt *mpt = NULL;2765	int mtt_base = mr_get_mtt_addr(inbox->buf) / dev->caps.mtt_entry_sz;2766	int phys;2767	int id;2768	u32 pd;2769	int pd_slave;2770 2771	id = index & mpt_mask(dev);2772	err = mr_res_start_move_to(dev, slave, id, RES_MPT_HW, &mpt);2773	if (err)2774		return err;2775 2776	/* Disable memory windows for VFs. */2777	if (!mr_is_region(inbox->buf)) {2778		err = -EPERM;2779		goto ex_abort;2780	}2781 2782	/* Make sure that the PD bits related to the slave id are zeros. */2783	pd = mr_get_pd(inbox->buf);2784	pd_slave = (pd >> 17) & 0x7f;2785	if (pd_slave != 0 && --pd_slave != slave) {2786		err = -EPERM;2787		goto ex_abort;2788	}2789 2790	if (mr_is_fmr(inbox->buf)) {2791		/* FMR and Bind Enable are forbidden in slave devices. */2792		if (mr_is_bind_enabled(inbox->buf)) {2793			err = -EPERM;2794			goto ex_abort;2795		}2796		/* FMR and Memory Windows are also forbidden. */2797		if (!mr_is_region(inbox->buf)) {2798			err = -EPERM;2799			goto ex_abort;2800		}2801	}2802 2803	phys = mr_phys_mpt(inbox->buf);2804	if (!phys) {2805		err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);2806		if (err)2807			goto ex_abort;2808 2809		err = check_mtt_range(dev, slave, mtt_base,2810				      mr_get_mtt_size(inbox->buf), mtt);2811		if (err)2812			goto ex_put;2813 2814		mpt->mtt = mtt;2815	}2816 2817	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);2818	if (err)2819		goto ex_put;2820 2821	if (!phys) {2822		atomic_inc(&mtt->ref_count);2823		put_res(dev, slave, mtt->com.res_id, RES_MTT);2824	}2825 2826	res_end_move(dev, slave, RES_MPT, id);2827	return 0;2828 2829ex_put:2830	if (!phys)2831		put_res(dev, slave, mtt->com.res_id, RES_MTT);2832ex_abort:2833	res_abort_move(dev, slave, RES_MPT, id);2834 2835	return err;2836}2837 2838int mlx4_HW2SW_MPT_wrapper(struct mlx4_dev *dev, int slave,2839			   struct mlx4_vhcr *vhcr,2840			   struct mlx4_cmd_mailbox *inbox,2841			   struct mlx4_cmd_mailbox *outbox,2842			   struct mlx4_cmd_info *cmd)2843{2844	int err;2845	int index = vhcr->in_modifier;2846	struct res_mpt *mpt;2847	int id;2848 2849	id = index & mpt_mask(dev);2850	err = mr_res_start_move_to(dev, slave, id, RES_MPT_MAPPED, &mpt);2851	if (err)2852		return err;2853 2854	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);2855	if (err)2856		goto ex_abort;2857 2858	if (mpt->mtt)2859		atomic_dec(&mpt->mtt->ref_count);2860 2861	res_end_move(dev, slave, RES_MPT, id);2862	return 0;2863 2864ex_abort:2865	res_abort_move(dev, slave, RES_MPT, id);2866 2867	return err;2868}2869 2870int mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave,2871			   struct mlx4_vhcr *vhcr,2872			   struct mlx4_cmd_mailbox *inbox,2873			   struct mlx4_cmd_mailbox *outbox,2874			   struct mlx4_cmd_info *cmd)2875{2876	int err;2877	int index = vhcr->in_modifier;2878	struct res_mpt *mpt;2879	int id;2880 2881	id = index & mpt_mask(dev);2882	err = get_res(dev, slave, id, RES_MPT, &mpt);2883	if (err)2884		return err;2885 2886	if (mpt->com.from_state == RES_MPT_MAPPED) {2887		/* In order to allow rereg in SRIOV, we need to alter the MPT entry. To do2888		 * that, the VF must read the MPT. But since the MPT entry memory is not2889		 * in the VF's virtual memory space, it must use QUERY_MPT to obtain the2890		 * entry contents. To guarantee that the MPT cannot be changed, the driver2891		 * must perform HW2SW_MPT before this query and return the MPT entry to HW2892		 * ownership fofollowing the change. The change here allows the VF to2893		 * perform QUERY_MPT also when the entry is in SW ownership.2894		 */2895		struct mlx4_mpt_entry *mpt_entry = mlx4_table_find(2896					&mlx4_priv(dev)->mr_table.dmpt_table,2897					mpt->key, NULL);2898 2899		if (NULL == mpt_entry || NULL == outbox->buf) {2900			err = -EINVAL;2901			goto out;2902		}2903 2904		memcpy(outbox->buf, mpt_entry, sizeof(*mpt_entry));2905 2906		err = 0;2907	} else if (mpt->com.from_state == RES_MPT_HW) {2908		err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);2909	} else {2910		err = -EBUSY;2911		goto out;2912	}2913 2914 2915out:2916	put_res(dev, slave, id, RES_MPT);2917	return err;2918}2919 2920static int qp_get_rcqn(struct mlx4_qp_context *qpc)2921{2922	return be32_to_cpu(qpc->cqn_recv) & 0xffffff;2923}2924 2925static int qp_get_scqn(struct mlx4_qp_context *qpc)2926{2927	return be32_to_cpu(qpc->cqn_send) & 0xffffff;2928}2929 2930static u32 qp_get_srqn(struct mlx4_qp_context *qpc)2931{2932	return be32_to_cpu(qpc->srqn) & 0x1ffffff;2933}2934 2935static void adjust_proxy_tun_qkey(struct mlx4_dev *dev, struct mlx4_vhcr *vhcr,2936				  struct mlx4_qp_context *context)2937{2938	u32 qpn = vhcr->in_modifier & 0xffffff;2939	u32 qkey = 0;2940 2941	if (mlx4_get_parav_qkey(dev, qpn, &qkey))2942		return;2943 2944	/* adjust qkey in qp context */2945	context->qkey = cpu_to_be32(qkey);2946}2947 2948static int adjust_qp_sched_queue(struct mlx4_dev *dev, int slave,2949				 struct mlx4_qp_context *qpc,2950				 struct mlx4_cmd_mailbox *inbox);2951 2952int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,2953			     struct mlx4_vhcr *vhcr,2954			     struct mlx4_cmd_mailbox *inbox,2955			     struct mlx4_cmd_mailbox *outbox,2956			     struct mlx4_cmd_info *cmd)2957{2958	int err;2959	int qpn = vhcr->in_modifier & 0x7fffff;2960	struct res_mtt *mtt;2961	struct res_qp *qp;2962	struct mlx4_qp_context *qpc = inbox->buf + 8;2963	int mtt_base = qp_get_mtt_addr(qpc) / dev->caps.mtt_entry_sz;2964	int mtt_size = qp_get_mtt_size(qpc);2965	struct res_cq *rcq;2966	struct res_cq *scq;2967	int rcqn = qp_get_rcqn(qpc);2968	int scqn = qp_get_scqn(qpc);2969	u32 srqn = qp_get_srqn(qpc) & 0xffffff;2970	int use_srq = (qp_get_srqn(qpc) >> 24) & 1;2971	struct res_srq *srq;2972	int local_qpn = vhcr->in_modifier & 0xffffff;2973 2974	err = adjust_qp_sched_queue(dev, slave, qpc, inbox);2975	if (err)2976		return err;2977 2978	err = qp_res_start_move_to(dev, slave, qpn, RES_QP_HW, &qp, 0);2979	if (err)2980		return err;2981	qp->local_qpn = local_qpn;2982	qp->sched_queue = 0;2983	qp->param3 = 0;2984	qp->vlan_control = 0;2985	qp->fvl_rx = 0;2986	qp->pri_path_fl = 0;2987	qp->vlan_index = 0;2988	qp->feup = 0;2989	qp->qpc_flags = be32_to_cpu(qpc->flags);2990 2991	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);2992	if (err)2993		goto ex_abort;2994 2995	err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt);2996	if (err)2997		goto ex_put_mtt;2998 2999	err = get_res(dev, slave, rcqn, RES_CQ, &rcq);3000	if (err)3001		goto ex_put_mtt;3002 3003	if (scqn != rcqn) {3004		err = get_res(dev, slave, scqn, RES_CQ, &scq);3005		if (err)3006			goto ex_put_rcq;3007	} else3008		scq = rcq;3009 3010	if (use_srq) {3011		err = get_res(dev, slave, srqn, RES_SRQ, &srq);3012		if (err)3013			goto ex_put_scq;3014	}3015 3016	adjust_proxy_tun_qkey(dev, vhcr, qpc);3017	update_pkey_index(dev, slave, inbox);3018	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3019	if (err)3020		goto ex_put_srq;3021	atomic_inc(&mtt->ref_count);3022	qp->mtt = mtt;3023	atomic_inc(&rcq->ref_count);3024	qp->rcq = rcq;3025	atomic_inc(&scq->ref_count);3026	qp->scq = scq;3027 3028	if (scqn != rcqn)3029		put_res(dev, slave, scqn, RES_CQ);3030 3031	if (use_srq) {3032		atomic_inc(&srq->ref_count);3033		put_res(dev, slave, srqn, RES_SRQ);3034		qp->srq = srq;3035	}3036 3037	/* Save param3 for dynamic changes from VST back to VGT */3038	qp->param3 = qpc->param3;3039	put_res(dev, slave, rcqn, RES_CQ);3040	put_res(dev, slave, mtt_base, RES_MTT);3041	res_end_move(dev, slave, RES_QP, qpn);3042 3043	return 0;3044 3045ex_put_srq:3046	if (use_srq)3047		put_res(dev, slave, srqn, RES_SRQ);3048ex_put_scq:3049	if (scqn != rcqn)3050		put_res(dev, slave, scqn, RES_CQ);3051ex_put_rcq:3052	put_res(dev, slave, rcqn, RES_CQ);3053ex_put_mtt:3054	put_res(dev, slave, mtt_base, RES_MTT);3055ex_abort:3056	res_abort_move(dev, slave, RES_QP, qpn);3057 3058	return err;3059}3060 3061static int eq_get_mtt_addr(struct mlx4_eq_context *eqc)3062{3063	return be32_to_cpu(eqc->mtt_base_addr_l) & 0xfffffff8;3064}3065 3066static int eq_get_mtt_size(struct mlx4_eq_context *eqc)3067{3068	int log_eq_size = eqc->log_eq_size & 0x1f;3069	int page_shift = (eqc->log_page_size & 0x3f) + 12;3070 3071	if (log_eq_size + 5 < page_shift)3072		return 1;3073 3074	return 1 << (log_eq_size + 5 - page_shift);3075}3076 3077static int cq_get_mtt_addr(struct mlx4_cq_context *cqc)3078{3079	return be32_to_cpu(cqc->mtt_base_addr_l) & 0xfffffff8;3080}3081 3082static int cq_get_mtt_size(struct mlx4_cq_context *cqc)3083{3084	int log_cq_size = (be32_to_cpu(cqc->logsize_usrpage) >> 24) & 0x1f;3085	int page_shift = (cqc->log_page_size & 0x3f) + 12;3086 3087	if (log_cq_size + 5 < page_shift)3088		return 1;3089 3090	return 1 << (log_cq_size + 5 - page_shift);3091}3092 3093int mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave,3094			  struct mlx4_vhcr *vhcr,3095			  struct mlx4_cmd_mailbox *inbox,3096			  struct mlx4_cmd_mailbox *outbox,3097			  struct mlx4_cmd_info *cmd)3098{3099	int err;3100	int eqn = vhcr->in_modifier;3101	int res_id = (slave << 10) | eqn;3102	struct mlx4_eq_context *eqc = inbox->buf;3103	int mtt_base = eq_get_mtt_addr(eqc) / dev->caps.mtt_entry_sz;3104	int mtt_size = eq_get_mtt_size(eqc);3105	struct res_eq *eq;3106	struct res_mtt *mtt;3107 3108	err = add_res_range(dev, slave, res_id, 1, RES_EQ, 0);3109	if (err)3110		return err;3111	err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_HW, &eq);3112	if (err)3113		goto out_add;3114 3115	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);3116	if (err)3117		goto out_move;3118 3119	err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt);3120	if (err)3121		goto out_put;3122 3123	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3124	if (err)3125		goto out_put;3126 3127	atomic_inc(&mtt->ref_count);3128	eq->mtt = mtt;3129	put_res(dev, slave, mtt->com.res_id, RES_MTT);3130	res_end_move(dev, slave, RES_EQ, res_id);3131	return 0;3132 3133out_put:3134	put_res(dev, slave, mtt->com.res_id, RES_MTT);3135out_move:3136	res_abort_move(dev, slave, RES_EQ, res_id);3137out_add:3138	rem_res_range(dev, slave, res_id, 1, RES_EQ, 0);3139	return err;3140}3141 3142int mlx4_CONFIG_DEV_wrapper(struct mlx4_dev *dev, int slave,3143			    struct mlx4_vhcr *vhcr,3144			    struct mlx4_cmd_mailbox *inbox,3145			    struct mlx4_cmd_mailbox *outbox,3146			    struct mlx4_cmd_info *cmd)3147{3148	int err;3149	u8 get = vhcr->op_modifier;3150 3151	if (get != 1)3152		return -EPERM;3153 3154	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3155 3156	return err;3157}3158 3159static int get_containing_mtt(struct mlx4_dev *dev, int slave, int start,3160			      int len, struct res_mtt **res)3161{3162	struct mlx4_priv *priv = mlx4_priv(dev);3163	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;3164	struct res_mtt *mtt;3165	int err = -EINVAL;3166 3167	spin_lock_irq(mlx4_tlock(dev));3168	list_for_each_entry(mtt, &tracker->slave_list[slave].res_list[RES_MTT],3169			    com.list) {3170		if (!check_mtt_range(dev, slave, start, len, mtt)) {3171			*res = mtt;3172			mtt->com.from_state = mtt->com.state;3173			mtt->com.state = RES_MTT_BUSY;3174			err = 0;3175			break;3176		}3177	}3178	spin_unlock_irq(mlx4_tlock(dev));3179 3180	return err;3181}3182 3183static int verify_qp_parameters(struct mlx4_dev *dev,3184				struct mlx4_vhcr *vhcr,3185				struct mlx4_cmd_mailbox *inbox,3186				enum qp_transition transition, u8 slave)3187{3188	u32			qp_type;3189	u32			qpn;3190	struct mlx4_qp_context	*qp_ctx;3191	enum mlx4_qp_optpar	optpar;3192	int port;3193	int num_gids;3194 3195	qp_ctx  = inbox->buf + 8;3196	qp_type	= (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff;3197	optpar	= be32_to_cpu(*(__be32 *) inbox->buf);3198 3199	if (slave != mlx4_master_func_num(dev)) {3200		qp_ctx->params2 &= ~cpu_to_be32(MLX4_QP_BIT_FPP);3201		/* setting QP rate-limit is disallowed for VFs */3202		if (qp_ctx->rate_limit_params)3203			return -EPERM;3204	}3205 3206	switch (qp_type) {3207	case MLX4_QP_ST_RC:3208	case MLX4_QP_ST_XRC:3209	case MLX4_QP_ST_UC:3210		switch (transition) {3211		case QP_TRANS_INIT2RTR:3212		case QP_TRANS_RTR2RTS:3213		case QP_TRANS_RTS2RTS:3214		case QP_TRANS_SQD2SQD:3215		case QP_TRANS_SQD2RTS:3216			if (slave != mlx4_master_func_num(dev)) {3217				if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH) {3218					port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;3219					if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB)3220						num_gids = mlx4_get_slave_num_gids(dev, slave, port);3221					else3222						num_gids = 1;3223					if (qp_ctx->pri_path.mgid_index >= num_gids)3224						return -EINVAL;3225				}3226				if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) {3227					port = (qp_ctx->alt_path.sched_queue >> 6 & 1) + 1;3228					if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB)3229						num_gids = mlx4_get_slave_num_gids(dev, slave, port);3230					else3231						num_gids = 1;3232					if (qp_ctx->alt_path.mgid_index >= num_gids)3233						return -EINVAL;3234				}3235			}3236			break;3237		default:3238			break;3239		}3240		break;3241 3242	case MLX4_QP_ST_MLX:3243		qpn = vhcr->in_modifier & 0x7fffff;3244		port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;3245		if (transition == QP_TRANS_INIT2RTR &&3246		    slave != mlx4_master_func_num(dev) &&3247		    mlx4_is_qp_reserved(dev, qpn) &&3248		    !mlx4_vf_smi_enabled(dev, slave, port)) {3249			/* only enabled VFs may create MLX proxy QPs */3250			mlx4_err(dev, "%s: unprivileged slave %d attempting to create an MLX proxy special QP on port %d\n",3251				 __func__, slave, port);3252			return -EPERM;3253		}3254		break;3255 3256	default:3257		break;3258	}3259 3260	return 0;3261}3262 3263int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave,3264			   struct mlx4_vhcr *vhcr,3265			   struct mlx4_cmd_mailbox *inbox,3266			   struct mlx4_cmd_mailbox *outbox,3267			   struct mlx4_cmd_info *cmd)3268{3269	struct mlx4_mtt mtt;3270	__be64 *page_list = inbox->buf;3271	u64 *pg_list = (u64 *)page_list;3272	int i;3273	struct res_mtt *rmtt = NULL;3274	int start = be64_to_cpu(page_list[0]);3275	int npages = vhcr->in_modifier;3276	int err;3277 3278	err = get_containing_mtt(dev, slave, start, npages, &rmtt);3279	if (err)3280		return err;3281 3282	/* Call the SW implementation of write_mtt:3283	 * - Prepare a dummy mtt struct3284	 * - Translate inbox contents to simple addresses in host endianness */3285	mtt.offset = 0;  /* TBD this is broken but I don't handle it since3286			    we don't really use it */3287	mtt.order = 0;3288	mtt.page_shift = 0;3289	for (i = 0; i < npages; ++i)3290		pg_list[i + 2] = (be64_to_cpu(page_list[i + 2]) & ~1ULL);3291 3292	err = __mlx4_write_mtt(dev, &mtt, be64_to_cpu(page_list[0]), npages,3293			       ((u64 *)page_list + 2));3294 3295	if (rmtt)3296		put_res(dev, slave, rmtt->com.res_id, RES_MTT);3297 3298	return err;3299}3300 3301int mlx4_HW2SW_EQ_wrapper(struct mlx4_dev *dev, int slave,3302			  struct mlx4_vhcr *vhcr,3303			  struct mlx4_cmd_mailbox *inbox,3304			  struct mlx4_cmd_mailbox *outbox,3305			  struct mlx4_cmd_info *cmd)3306{3307	int eqn = vhcr->in_modifier;3308	int res_id = eqn | (slave << 10);3309	struct res_eq *eq;3310	int err;3311 3312	err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_RESERVED, &eq);3313	if (err)3314		return err;3315 3316	err = get_res(dev, slave, eq->mtt->com.res_id, RES_MTT, NULL);3317	if (err)3318		goto ex_abort;3319 3320	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3321	if (err)3322		goto ex_put;3323 3324	atomic_dec(&eq->mtt->ref_count);3325	put_res(dev, slave, eq->mtt->com.res_id, RES_MTT);3326	res_end_move(dev, slave, RES_EQ, res_id);3327	rem_res_range(dev, slave, res_id, 1, RES_EQ, 0);3328 3329	return 0;3330 3331ex_put:3332	put_res(dev, slave, eq->mtt->com.res_id, RES_MTT);3333ex_abort:3334	res_abort_move(dev, slave, RES_EQ, res_id);3335 3336	return err;3337}3338 3339int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe)3340{3341	struct mlx4_priv *priv = mlx4_priv(dev);3342	struct mlx4_slave_event_eq_info *event_eq;3343	struct mlx4_cmd_mailbox *mailbox;3344	u32 in_modifier = 0;3345	int err;3346	int res_id;3347	struct res_eq *req;3348 3349	if (!priv->mfunc.master.slave_state)3350		return -EINVAL;3351 3352	/* check for slave valid, slave not PF, and slave active */3353	if (slave < 0 || slave > dev->persist->num_vfs ||3354	    slave == dev->caps.function ||3355	    !priv->mfunc.master.slave_state[slave].active)3356		return 0;3357 3358	event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type];3359 3360	/* Create the event only if the slave is registered */3361	if (event_eq->eqn < 0)3362		return 0;3363 3364	mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]);3365	res_id = (slave << 10) | event_eq->eqn;3366	err = get_res(dev, slave, res_id, RES_EQ, &req);3367	if (err)3368		goto unlock;3369 3370	if (req->com.from_state != RES_EQ_HW) {3371		err = -EINVAL;3372		goto put;3373	}3374 3375	mailbox = mlx4_alloc_cmd_mailbox(dev);3376	if (IS_ERR(mailbox)) {3377		err = PTR_ERR(mailbox);3378		goto put;3379	}3380 3381	if (eqe->type == MLX4_EVENT_TYPE_CMD) {3382		++event_eq->token;3383		eqe->event.cmd.token = cpu_to_be16(event_eq->token);3384	}3385 3386	memcpy(mailbox->buf, (u8 *) eqe, 28);3387 3388	in_modifier = (slave & 0xff) | ((event_eq->eqn & 0x3ff) << 16);3389 3390	err = mlx4_cmd(dev, mailbox->dma, in_modifier, 0,3391		       MLX4_CMD_GEN_EQE, MLX4_CMD_TIME_CLASS_B,3392		       MLX4_CMD_NATIVE);3393 3394	put_res(dev, slave, res_id, RES_EQ);3395	mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]);3396	mlx4_free_cmd_mailbox(dev, mailbox);3397	return err;3398 3399put:3400	put_res(dev, slave, res_id, RES_EQ);3401 3402unlock:3403	mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]);3404	return err;3405}3406 3407int mlx4_QUERY_EQ_wrapper(struct mlx4_dev *dev, int slave,3408			  struct mlx4_vhcr *vhcr,3409			  struct mlx4_cmd_mailbox *inbox,3410			  struct mlx4_cmd_mailbox *outbox,3411			  struct mlx4_cmd_info *cmd)3412{3413	int eqn = vhcr->in_modifier;3414	int res_id = eqn | (slave << 10);3415	struct res_eq *eq;3416	int err;3417 3418	err = get_res(dev, slave, res_id, RES_EQ, &eq);3419	if (err)3420		return err;3421 3422	if (eq->com.from_state != RES_EQ_HW) {3423		err = -EINVAL;3424		goto ex_put;3425	}3426 3427	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3428 3429ex_put:3430	put_res(dev, slave, res_id, RES_EQ);3431	return err;3432}3433 3434int mlx4_SW2HW_CQ_wrapper(struct mlx4_dev *dev, int slave,3435			  struct mlx4_vhcr *vhcr,3436			  struct mlx4_cmd_mailbox *inbox,3437			  struct mlx4_cmd_mailbox *outbox,3438			  struct mlx4_cmd_info *cmd)3439{3440	int err;3441	int cqn = vhcr->in_modifier;3442	struct mlx4_cq_context *cqc = inbox->buf;3443	int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz;3444	struct res_cq *cq = NULL;3445	struct res_mtt *mtt;3446 3447	err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_HW, &cq);3448	if (err)3449		return err;3450	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);3451	if (err)3452		goto out_move;3453	err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt);3454	if (err)3455		goto out_put;3456	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3457	if (err)3458		goto out_put;3459	atomic_inc(&mtt->ref_count);3460	cq->mtt = mtt;3461	put_res(dev, slave, mtt->com.res_id, RES_MTT);3462	res_end_move(dev, slave, RES_CQ, cqn);3463	return 0;3464 3465out_put:3466	put_res(dev, slave, mtt->com.res_id, RES_MTT);3467out_move:3468	res_abort_move(dev, slave, RES_CQ, cqn);3469	return err;3470}3471 3472int mlx4_HW2SW_CQ_wrapper(struct mlx4_dev *dev, int slave,3473			  struct mlx4_vhcr *vhcr,3474			  struct mlx4_cmd_mailbox *inbox,3475			  struct mlx4_cmd_mailbox *outbox,3476			  struct mlx4_cmd_info *cmd)3477{3478	int err;3479	int cqn = vhcr->in_modifier;3480	struct res_cq *cq = NULL;3481 3482	err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_ALLOCATED, &cq);3483	if (err)3484		return err;3485	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3486	if (err)3487		goto out_move;3488	atomic_dec(&cq->mtt->ref_count);3489	res_end_move(dev, slave, RES_CQ, cqn);3490	return 0;3491 3492out_move:3493	res_abort_move(dev, slave, RES_CQ, cqn);3494	return err;3495}3496 3497int mlx4_QUERY_CQ_wrapper(struct mlx4_dev *dev, int slave,3498			  struct mlx4_vhcr *vhcr,3499			  struct mlx4_cmd_mailbox *inbox,3500			  struct mlx4_cmd_mailbox *outbox,3501			  struct mlx4_cmd_info *cmd)3502{3503	int cqn = vhcr->in_modifier;3504	struct res_cq *cq;3505	int err;3506 3507	err = get_res(dev, slave, cqn, RES_CQ, &cq);3508	if (err)3509		return err;3510 3511	if (cq->com.from_state != RES_CQ_HW)3512		goto ex_put;3513 3514	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3515ex_put:3516	put_res(dev, slave, cqn, RES_CQ);3517 3518	return err;3519}3520 3521static int handle_resize(struct mlx4_dev *dev, int slave,3522			 struct mlx4_vhcr *vhcr,3523			 struct mlx4_cmd_mailbox *inbox,3524			 struct mlx4_cmd_mailbox *outbox,3525			 struct mlx4_cmd_info *cmd,3526			 struct res_cq *cq)3527{3528	int err;3529	struct res_mtt *orig_mtt;3530	struct res_mtt *mtt;3531	struct mlx4_cq_context *cqc = inbox->buf;3532	int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz;3533 3534	err = get_res(dev, slave, cq->mtt->com.res_id, RES_MTT, &orig_mtt);3535	if (err)3536		return err;3537 3538	if (orig_mtt != cq->mtt) {3539		err = -EINVAL;3540		goto ex_put;3541	}3542 3543	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);3544	if (err)3545		goto ex_put;3546 3547	err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt);3548	if (err)3549		goto ex_put1;3550	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3551	if (err)3552		goto ex_put1;3553	atomic_dec(&orig_mtt->ref_count);3554	put_res(dev, slave, orig_mtt->com.res_id, RES_MTT);3555	atomic_inc(&mtt->ref_count);3556	cq->mtt = mtt;3557	put_res(dev, slave, mtt->com.res_id, RES_MTT);3558	return 0;3559 3560ex_put1:3561	put_res(dev, slave, mtt->com.res_id, RES_MTT);3562ex_put:3563	put_res(dev, slave, orig_mtt->com.res_id, RES_MTT);3564 3565	return err;3566 3567}3568 3569int mlx4_MODIFY_CQ_wrapper(struct mlx4_dev *dev, int slave,3570			   struct mlx4_vhcr *vhcr,3571			   struct mlx4_cmd_mailbox *inbox,3572			   struct mlx4_cmd_mailbox *outbox,3573			   struct mlx4_cmd_info *cmd)3574{3575	int cqn = vhcr->in_modifier;3576	struct res_cq *cq;3577	int err;3578 3579	err = get_res(dev, slave, cqn, RES_CQ, &cq);3580	if (err)3581		return err;3582 3583	if (cq->com.from_state != RES_CQ_HW)3584		goto ex_put;3585 3586	if (vhcr->op_modifier == 0) {3587		err = handle_resize(dev, slave, vhcr, inbox, outbox, cmd, cq);3588		goto ex_put;3589	}3590 3591	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3592ex_put:3593	put_res(dev, slave, cqn, RES_CQ);3594 3595	return err;3596}3597 3598static int srq_get_mtt_size(struct mlx4_srq_context *srqc)3599{3600	int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf;3601	int log_rq_stride = srqc->logstride & 7;3602	int page_shift = (srqc->log_page_size & 0x3f) + 12;3603 3604	if (log_srq_size + log_rq_stride + 4 < page_shift)3605		return 1;3606 3607	return 1 << (log_srq_size + log_rq_stride + 4 - page_shift);3608}3609 3610int mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave,3611			   struct mlx4_vhcr *vhcr,3612			   struct mlx4_cmd_mailbox *inbox,3613			   struct mlx4_cmd_mailbox *outbox,3614			   struct mlx4_cmd_info *cmd)3615{3616	int err;3617	int srqn = vhcr->in_modifier;3618	struct res_mtt *mtt;3619	struct res_srq *srq = NULL;3620	struct mlx4_srq_context *srqc = inbox->buf;3621	int mtt_base = srq_get_mtt_addr(srqc) / dev->caps.mtt_entry_sz;3622 3623	if (srqn != (be32_to_cpu(srqc->state_logsize_srqn) & 0xffffff))3624		return -EINVAL;3625 3626	err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_HW, &srq);3627	if (err)3628		return err;3629	err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);3630	if (err)3631		goto ex_abort;3632	err = check_mtt_range(dev, slave, mtt_base, srq_get_mtt_size(srqc),3633			      mtt);3634	if (err)3635		goto ex_put_mtt;3636 3637	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3638	if (err)3639		goto ex_put_mtt;3640 3641	atomic_inc(&mtt->ref_count);3642	srq->mtt = mtt;3643	put_res(dev, slave, mtt->com.res_id, RES_MTT);3644	res_end_move(dev, slave, RES_SRQ, srqn);3645	return 0;3646 3647ex_put_mtt:3648	put_res(dev, slave, mtt->com.res_id, RES_MTT);3649ex_abort:3650	res_abort_move(dev, slave, RES_SRQ, srqn);3651 3652	return err;3653}3654 3655int mlx4_HW2SW_SRQ_wrapper(struct mlx4_dev *dev, int slave,3656			   struct mlx4_vhcr *vhcr,3657			   struct mlx4_cmd_mailbox *inbox,3658			   struct mlx4_cmd_mailbox *outbox,3659			   struct mlx4_cmd_info *cmd)3660{3661	int err;3662	int srqn = vhcr->in_modifier;3663	struct res_srq *srq = NULL;3664 3665	err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_ALLOCATED, &srq);3666	if (err)3667		return err;3668	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3669	if (err)3670		goto ex_abort;3671	atomic_dec(&srq->mtt->ref_count);3672	if (srq->cq)3673		atomic_dec(&srq->cq->ref_count);3674	res_end_move(dev, slave, RES_SRQ, srqn);3675 3676	return 0;3677 3678ex_abort:3679	res_abort_move(dev, slave, RES_SRQ, srqn);3680 3681	return err;3682}3683 3684int mlx4_QUERY_SRQ_wrapper(struct mlx4_dev *dev, int slave,3685			   struct mlx4_vhcr *vhcr,3686			   struct mlx4_cmd_mailbox *inbox,3687			   struct mlx4_cmd_mailbox *outbox,3688			   struct mlx4_cmd_info *cmd)3689{3690	int err;3691	int srqn = vhcr->in_modifier;3692	struct res_srq *srq;3693 3694	err = get_res(dev, slave, srqn, RES_SRQ, &srq);3695	if (err)3696		return err;3697	if (srq->com.from_state != RES_SRQ_HW) {3698		err = -EBUSY;3699		goto out;3700	}3701	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3702out:3703	put_res(dev, slave, srqn, RES_SRQ);3704	return err;3705}3706 3707int mlx4_ARM_SRQ_wrapper(struct mlx4_dev *dev, int slave,3708			 struct mlx4_vhcr *vhcr,3709			 struct mlx4_cmd_mailbox *inbox,3710			 struct mlx4_cmd_mailbox *outbox,3711			 struct mlx4_cmd_info *cmd)3712{3713	int err;3714	int srqn = vhcr->in_modifier;3715	struct res_srq *srq;3716 3717	err = get_res(dev, slave, srqn, RES_SRQ, &srq);3718	if (err)3719		return err;3720 3721	if (srq->com.from_state != RES_SRQ_HW) {3722		err = -EBUSY;3723		goto out;3724	}3725 3726	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3727out:3728	put_res(dev, slave, srqn, RES_SRQ);3729	return err;3730}3731 3732int mlx4_GEN_QP_wrapper(struct mlx4_dev *dev, int slave,3733			struct mlx4_vhcr *vhcr,3734			struct mlx4_cmd_mailbox *inbox,3735			struct mlx4_cmd_mailbox *outbox,3736			struct mlx4_cmd_info *cmd)3737{3738	int err;3739	int qpn = vhcr->in_modifier & 0x7fffff;3740	struct res_qp *qp;3741 3742	err = get_res(dev, slave, qpn, RES_QP, &qp);3743	if (err)3744		return err;3745	if (qp->com.from_state != RES_QP_HW) {3746		err = -EBUSY;3747		goto out;3748	}3749 3750	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3751out:3752	put_res(dev, slave, qpn, RES_QP);3753	return err;3754}3755 3756int mlx4_INIT2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,3757			      struct mlx4_vhcr *vhcr,3758			      struct mlx4_cmd_mailbox *inbox,3759			      struct mlx4_cmd_mailbox *outbox,3760			      struct mlx4_cmd_info *cmd)3761{3762	struct mlx4_qp_context *context = inbox->buf + 8;3763	adjust_proxy_tun_qkey(dev, vhcr, context);3764	update_pkey_index(dev, slave, inbox);3765	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3766}3767 3768static int adjust_qp_sched_queue(struct mlx4_dev *dev, int slave,3769				  struct mlx4_qp_context *qpc,3770				  struct mlx4_cmd_mailbox *inbox)3771{3772	enum mlx4_qp_optpar optpar = be32_to_cpu(*(__be32 *)inbox->buf);3773	u8 pri_sched_queue;3774	int port = mlx4_slave_convert_port(3775		   dev, slave, (qpc->pri_path.sched_queue >> 6 & 1) + 1) - 1;3776 3777	if (port < 0)3778		return -EINVAL;3779 3780	pri_sched_queue = (qpc->pri_path.sched_queue & ~(1 << 6)) |3781			  ((port & 1) << 6);3782 3783	if (optpar & (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH | MLX4_QP_OPTPAR_SCHED_QUEUE) ||3784	    qpc->pri_path.sched_queue || mlx4_is_eth(dev, port + 1)) {3785		qpc->pri_path.sched_queue = pri_sched_queue;3786	}3787 3788	if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) {3789		port = mlx4_slave_convert_port(3790				dev, slave, (qpc->alt_path.sched_queue >> 6 & 1)3791				+ 1) - 1;3792		if (port < 0)3793			return -EINVAL;3794		qpc->alt_path.sched_queue =3795			(qpc->alt_path.sched_queue & ~(1 << 6)) |3796			(port & 1) << 6;3797	}3798	return 0;3799}3800 3801static int roce_verify_mac(struct mlx4_dev *dev, int slave,3802				struct mlx4_qp_context *qpc,3803				struct mlx4_cmd_mailbox *inbox)3804{3805	u64 mac;3806	int port;3807	u32 ts = (be32_to_cpu(qpc->flags) >> 16) & 0xff;3808	u8 sched = *(u8 *)(inbox->buf + 64);3809	u8 smac_ix;3810 3811	port = (sched >> 6 & 1) + 1;3812	if (mlx4_is_eth(dev, port) && (ts != MLX4_QP_ST_MLX)) {3813		smac_ix = qpc->pri_path.grh_mylmc & 0x7f;3814		if (mac_find_smac_ix_in_slave(dev, slave, port, smac_ix, &mac))3815			return -ENOENT;3816	}3817	return 0;3818}3819 3820int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,3821			     struct mlx4_vhcr *vhcr,3822			     struct mlx4_cmd_mailbox *inbox,3823			     struct mlx4_cmd_mailbox *outbox,3824			     struct mlx4_cmd_info *cmd)3825{3826	int err;3827	struct mlx4_qp_context *qpc = inbox->buf + 8;3828	int qpn = vhcr->in_modifier & 0x7fffff;3829	struct res_qp *qp;3830	u8 orig_sched_queue;3831	u8 orig_vlan_control = qpc->pri_path.vlan_control;3832	u8 orig_fvl_rx = qpc->pri_path.fvl_rx;3833	u8 orig_pri_path_fl = qpc->pri_path.fl;3834	u8 orig_vlan_index = qpc->pri_path.vlan_index;3835	u8 orig_feup = qpc->pri_path.feup;3836 3837	err = adjust_qp_sched_queue(dev, slave, qpc, inbox);3838	if (err)3839		return err;3840	err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_INIT2RTR, slave);3841	if (err)3842		return err;3843 3844	if (roce_verify_mac(dev, slave, qpc, inbox))3845		return -EINVAL;3846 3847	update_pkey_index(dev, slave, inbox);3848	update_gid(dev, inbox, (u8)slave);3849	adjust_proxy_tun_qkey(dev, vhcr, qpc);3850	orig_sched_queue = qpc->pri_path.sched_queue;3851 3852	err = get_res(dev, slave, qpn, RES_QP, &qp);3853	if (err)3854		return err;3855	if (qp->com.from_state != RES_QP_HW) {3856		err = -EBUSY;3857		goto out;3858	}3859 3860	err = update_vport_qp_param(dev, inbox, slave, qpn);3861	if (err)3862		goto out;3863 3864	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3865out:3866	/* if no error, save sched queue value passed in by VF. This is3867	 * essentially the QOS value provided by the VF. This will be useful3868	 * if we allow dynamic changes from VST back to VGT3869	 */3870	if (!err) {3871		qp->sched_queue = orig_sched_queue;3872		qp->vlan_control = orig_vlan_control;3873		qp->fvl_rx	=  orig_fvl_rx;3874		qp->pri_path_fl = orig_pri_path_fl;3875		qp->vlan_index  = orig_vlan_index;3876		qp->feup	= orig_feup;3877	}3878	put_res(dev, slave, qpn, RES_QP);3879	return err;3880}3881 3882int mlx4_RTR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,3883			    struct mlx4_vhcr *vhcr,3884			    struct mlx4_cmd_mailbox *inbox,3885			    struct mlx4_cmd_mailbox *outbox,3886			    struct mlx4_cmd_info *cmd)3887{3888	int err;3889	struct mlx4_qp_context *context = inbox->buf + 8;3890 3891	err = adjust_qp_sched_queue(dev, slave, context, inbox);3892	if (err)3893		return err;3894	err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_RTR2RTS, slave);3895	if (err)3896		return err;3897 3898	update_pkey_index(dev, slave, inbox);3899	update_gid(dev, inbox, (u8)slave);3900	adjust_proxy_tun_qkey(dev, vhcr, context);3901	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3902}3903 3904int mlx4_RTS2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,3905			    struct mlx4_vhcr *vhcr,3906			    struct mlx4_cmd_mailbox *inbox,3907			    struct mlx4_cmd_mailbox *outbox,3908			    struct mlx4_cmd_info *cmd)3909{3910	int err;3911	struct mlx4_qp_context *context = inbox->buf + 8;3912 3913	err = adjust_qp_sched_queue(dev, slave, context, inbox);3914	if (err)3915		return err;3916	err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_RTS2RTS, slave);3917	if (err)3918		return err;3919 3920	update_pkey_index(dev, slave, inbox);3921	update_gid(dev, inbox, (u8)slave);3922	adjust_proxy_tun_qkey(dev, vhcr, context);3923	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3924}3925 3926 3927int mlx4_SQERR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,3928			      struct mlx4_vhcr *vhcr,3929			      struct mlx4_cmd_mailbox *inbox,3930			      struct mlx4_cmd_mailbox *outbox,3931			      struct mlx4_cmd_info *cmd)3932{3933	struct mlx4_qp_context *context = inbox->buf + 8;3934	int err = adjust_qp_sched_queue(dev, slave, context, inbox);3935	if (err)3936		return err;3937	adjust_proxy_tun_qkey(dev, vhcr, context);3938	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3939}3940 3941int mlx4_SQD2SQD_QP_wrapper(struct mlx4_dev *dev, int slave,3942			    struct mlx4_vhcr *vhcr,3943			    struct mlx4_cmd_mailbox *inbox,3944			    struct mlx4_cmd_mailbox *outbox,3945			    struct mlx4_cmd_info *cmd)3946{3947	int err;3948	struct mlx4_qp_context *context = inbox->buf + 8;3949 3950	err = adjust_qp_sched_queue(dev, slave, context, inbox);3951	if (err)3952		return err;3953	err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_SQD2SQD, slave);3954	if (err)3955		return err;3956 3957	adjust_proxy_tun_qkey(dev, vhcr, context);3958	update_gid(dev, inbox, (u8)slave);3959	update_pkey_index(dev, slave, inbox);3960	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3961}3962 3963int mlx4_SQD2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,3964			    struct mlx4_vhcr *vhcr,3965			    struct mlx4_cmd_mailbox *inbox,3966			    struct mlx4_cmd_mailbox *outbox,3967			    struct mlx4_cmd_info *cmd)3968{3969	int err;3970	struct mlx4_qp_context *context = inbox->buf + 8;3971 3972	err = adjust_qp_sched_queue(dev, slave, context, inbox);3973	if (err)3974		return err;3975	err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_SQD2RTS, slave);3976	if (err)3977		return err;3978 3979	adjust_proxy_tun_qkey(dev, vhcr, context);3980	update_gid(dev, inbox, (u8)slave);3981	update_pkey_index(dev, slave, inbox);3982	return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3983}3984 3985int mlx4_2RST_QP_wrapper(struct mlx4_dev *dev, int slave,3986			 struct mlx4_vhcr *vhcr,3987			 struct mlx4_cmd_mailbox *inbox,3988			 struct mlx4_cmd_mailbox *outbox,3989			 struct mlx4_cmd_info *cmd)3990{3991	int err;3992	int qpn = vhcr->in_modifier & 0x7fffff;3993	struct res_qp *qp;3994 3995	err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED, &qp, 0);3996	if (err)3997		return err;3998	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);3999	if (err)4000		goto ex_abort;4001 4002	atomic_dec(&qp->mtt->ref_count);4003	atomic_dec(&qp->rcq->ref_count);4004	atomic_dec(&qp->scq->ref_count);4005	if (qp->srq)4006		atomic_dec(&qp->srq->ref_count);4007	res_end_move(dev, slave, RES_QP, qpn);4008	return 0;4009 4010ex_abort:4011	res_abort_move(dev, slave, RES_QP, qpn);4012 4013	return err;4014}4015 4016static struct res_gid *find_gid(struct mlx4_dev *dev, int slave,4017				struct res_qp *rqp, u8 *gid)4018{4019	struct res_gid *res;4020 4021	list_for_each_entry(res, &rqp->mcg_list, list) {4022		if (!memcmp(res->gid, gid, 16))4023			return res;4024	}4025	return NULL;4026}4027 4028static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,4029		       u8 *gid, enum mlx4_protocol prot,4030		       enum mlx4_steer_type steer, u64 reg_id)4031{4032	struct res_gid *res;4033	int err;4034 4035	res = kzalloc(sizeof(*res), GFP_KERNEL);4036	if (!res)4037		return -ENOMEM;4038 4039	spin_lock_irq(&rqp->mcg_spl);4040	if (find_gid(dev, slave, rqp, gid)) {4041		kfree(res);4042		err = -EEXIST;4043	} else {4044		memcpy(res->gid, gid, 16);4045		res->prot = prot;4046		res->steer = steer;4047		res->reg_id = reg_id;4048		list_add_tail(&res->list, &rqp->mcg_list);4049		err = 0;4050	}4051	spin_unlock_irq(&rqp->mcg_spl);4052 4053	return err;4054}4055 4056static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,4057		       u8 *gid, enum mlx4_protocol prot,4058		       enum mlx4_steer_type steer, u64 *reg_id)4059{4060	struct res_gid *res;4061	int err;4062 4063	spin_lock_irq(&rqp->mcg_spl);4064	res = find_gid(dev, slave, rqp, gid);4065	if (!res || res->prot != prot || res->steer != steer)4066		err = -EINVAL;4067	else {4068		*reg_id = res->reg_id;4069		list_del(&res->list);4070		kfree(res);4071		err = 0;4072	}4073	spin_unlock_irq(&rqp->mcg_spl);4074 4075	return err;4076}4077 4078static int qp_attach(struct mlx4_dev *dev, int slave, struct mlx4_qp *qp,4079		     u8 gid[16], int block_loopback, enum mlx4_protocol prot,4080		     enum mlx4_steer_type type, u64 *reg_id)4081{4082	switch (dev->caps.steering_mode) {4083	case MLX4_STEERING_MODE_DEVICE_MANAGED: {4084		int port = mlx4_slave_convert_port(dev, slave, gid[5]);4085		if (port < 0)4086			return port;4087		return mlx4_trans_to_dmfs_attach(dev, qp, gid, port,4088						block_loopback, prot,4089						reg_id);4090	}4091	case MLX4_STEERING_MODE_B0:4092		if (prot == MLX4_PROT_ETH) {4093			int port = mlx4_slave_convert_port(dev, slave, gid[5]);4094			if (port < 0)4095				return port;4096			gid[5] = port;4097		}4098		return mlx4_qp_attach_common(dev, qp, gid,4099					    block_loopback, prot, type);4100	default:4101		return -EINVAL;4102	}4103}4104 4105static int qp_detach(struct mlx4_dev *dev, struct mlx4_qp *qp,4106		     u8 gid[16], enum mlx4_protocol prot,4107		     enum mlx4_steer_type type, u64 reg_id)4108{4109	switch (dev->caps.steering_mode) {4110	case MLX4_STEERING_MODE_DEVICE_MANAGED:4111		return mlx4_flow_detach(dev, reg_id);4112	case MLX4_STEERING_MODE_B0:4113		return mlx4_qp_detach_common(dev, qp, gid, prot, type);4114	default:4115		return -EINVAL;4116	}4117}4118 4119static int mlx4_adjust_port(struct mlx4_dev *dev, int slave,4120			    u8 *gid, enum mlx4_protocol prot)4121{4122	int real_port;4123 4124	if (prot != MLX4_PROT_ETH)4125		return 0;4126 4127	if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0 ||4128	    dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {4129		real_port = mlx4_slave_convert_port(dev, slave, gid[5]);4130		if (real_port < 0)4131			return -EINVAL;4132		gid[5] = real_port;4133	}4134 4135	return 0;4136}4137 4138int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,4139			       struct mlx4_vhcr *vhcr,4140			       struct mlx4_cmd_mailbox *inbox,4141			       struct mlx4_cmd_mailbox *outbox,4142			       struct mlx4_cmd_info *cmd)4143{4144	struct mlx4_qp qp; /* dummy for calling attach/detach */4145	u8 *gid = inbox->buf;4146	enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7;4147	int err;4148	int qpn;4149	struct res_qp *rqp;4150	u64 reg_id = 0;4151	int attach = vhcr->op_modifier;4152	int block_loopback = vhcr->in_modifier >> 31;4153	u8 steer_type_mask = 2;4154	enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1;4155 4156	qpn = vhcr->in_modifier & 0xffffff;4157	err = get_res(dev, slave, qpn, RES_QP, &rqp);4158	if (err)4159		return err;4160 4161	qp.qpn = qpn;4162	if (attach) {4163		err = qp_attach(dev, slave, &qp, gid, block_loopback, prot,4164				type, &reg_id);4165		if (err) {4166			pr_err("Fail to attach rule to qp 0x%x\n", qpn);4167			goto ex_put;4168		}4169		err = add_mcg_res(dev, slave, rqp, gid, prot, type, reg_id);4170		if (err)4171			goto ex_detach;4172	} else {4173		err = mlx4_adjust_port(dev, slave, gid, prot);4174		if (err)4175			goto ex_put;4176 4177		err = rem_mcg_res(dev, slave, rqp, gid, prot, type, &reg_id);4178		if (err)4179			goto ex_put;4180 4181		err = qp_detach(dev, &qp, gid, prot, type, reg_id);4182		if (err)4183			pr_err("Fail to detach rule from qp 0x%x reg_id = 0x%llx\n",4184			       qpn, reg_id);4185	}4186	put_res(dev, slave, qpn, RES_QP);4187	return err;4188 4189ex_detach:4190	qp_detach(dev, &qp, gid, prot, type, reg_id);4191ex_put:4192	put_res(dev, slave, qpn, RES_QP);4193	return err;4194}4195 4196/*4197 * MAC validation for Flow Steering rules.4198 * VF can attach rules only with a mac address which is assigned to it.4199 */4200static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header,4201				   struct list_head *rlist)4202{4203	struct mac_res *res, *tmp;4204	__be64 be_mac;4205 4206	/* make sure it isn't multicast or broadcast mac*/4207	if (!is_multicast_ether_addr(eth_header->eth.dst_mac) &&4208	    !is_broadcast_ether_addr(eth_header->eth.dst_mac)) {4209		list_for_each_entry_safe(res, tmp, rlist, list) {4210			be_mac = cpu_to_be64(res->mac << 16);4211			if (ether_addr_equal((u8 *)&be_mac, eth_header->eth.dst_mac))4212				return 0;4213		}4214		pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n",4215		       eth_header->eth.dst_mac, slave);4216		return -EINVAL;4217	}4218	return 0;4219}4220 4221/*4222 * In case of missing eth header, append eth header with a MAC address4223 * assigned to the VF.4224 */4225static int add_eth_header(struct mlx4_dev *dev, int slave,4226			  struct mlx4_cmd_mailbox *inbox,4227			  struct list_head *rlist, int header_id)4228{4229	struct mac_res *res, *tmp;4230	u8 port;4231	struct mlx4_net_trans_rule_hw_ctrl *ctrl;4232	struct mlx4_net_trans_rule_hw_eth *eth_header;4233	struct mlx4_net_trans_rule_hw_ipv4 *ip_header;4234	struct mlx4_net_trans_rule_hw_tcp_udp *l4_header;4235	__be64 be_mac = 0;4236	__be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);4237 4238	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;4239	port = ctrl->port;4240	eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1);4241 4242	/* Clear a space in the inbox for eth header */4243	switch (header_id) {4244	case MLX4_NET_TRANS_RULE_ID_IPV4:4245		ip_header =4246			(struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1);4247		memmove(ip_header, eth_header,4248			sizeof(*ip_header) + sizeof(*l4_header));4249		break;4250	case MLX4_NET_TRANS_RULE_ID_TCP:4251	case MLX4_NET_TRANS_RULE_ID_UDP:4252		l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *)4253			    (eth_header + 1);4254		memmove(l4_header, eth_header, sizeof(*l4_header));4255		break;4256	default:4257		return -EINVAL;4258	}4259	list_for_each_entry_safe(res, tmp, rlist, list) {4260		if (port == res->port) {4261			be_mac = cpu_to_be64(res->mac << 16);4262			break;4263		}4264	}4265	if (!be_mac) {4266		pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d\n",4267		       port);4268		return -EINVAL;4269	}4270 4271	memset(eth_header, 0, sizeof(*eth_header));4272	eth_header->size = sizeof(*eth_header) >> 2;4273	eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]);4274	memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN);4275	memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN);4276 4277	return 0;4278 4279}4280 4281#define MLX4_UPD_QP_PATH_MASK_SUPPORTED      (                                \4282	1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX                     |\4283	1ULL << MLX4_UPD_QP_PATH_MASK_ETH_SRC_CHECK_MC_LB)4284int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,4285			   struct mlx4_vhcr *vhcr,4286			   struct mlx4_cmd_mailbox *inbox,4287			   struct mlx4_cmd_mailbox *outbox,4288			   struct mlx4_cmd_info *cmd_info)4289{4290	int err;4291	u32 qpn = vhcr->in_modifier & 0xffffff;4292	struct res_qp *rqp;4293	u64 mac;4294	unsigned port;4295	u64 pri_addr_path_mask;4296	struct mlx4_update_qp_context *cmd;4297	int smac_index;4298 4299	cmd = (struct mlx4_update_qp_context *)inbox->buf;4300 4301	pri_addr_path_mask = be64_to_cpu(cmd->primary_addr_path_mask);4302	if (cmd->qp_mask || cmd->secondary_addr_path_mask ||4303	    (pri_addr_path_mask & ~MLX4_UPD_QP_PATH_MASK_SUPPORTED))4304		return -EPERM;4305 4306	if ((pri_addr_path_mask &4307	     (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_SRC_CHECK_MC_LB)) &&4308		!(dev->caps.flags2 &4309		  MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB)) {4310		mlx4_warn(dev, "Src check LB for slave %d isn't supported\n",4311			  slave);4312		return -EOPNOTSUPP;4313	}4314 4315	/* Just change the smac for the QP */4316	err = get_res(dev, slave, qpn, RES_QP, &rqp);4317	if (err) {4318		mlx4_err(dev, "Updating qpn 0x%x for slave %d rejected\n", qpn, slave);4319		return err;4320	}4321 4322	port = (rqp->sched_queue >> 6 & 1) + 1;4323 4324	if (pri_addr_path_mask & (1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX)) {4325		smac_index = cmd->qp_context.pri_path.grh_mylmc;4326		err = mac_find_smac_ix_in_slave(dev, slave, port,4327						smac_index, &mac);4328 4329		if (err) {4330			mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n",4331				 qpn, smac_index);4332			goto err_mac;4333		}4334	}4335 4336	err = mlx4_cmd(dev, inbox->dma,4337		       vhcr->in_modifier, 0,4338		       MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A,4339		       MLX4_CMD_NATIVE);4340	if (err) {4341		mlx4_err(dev, "Failed to update qpn on qpn 0x%x, command failed\n", qpn);4342		goto err_mac;4343	}4344 4345err_mac:4346	put_res(dev, slave, qpn, RES_QP);4347	return err;4348}4349 4350static u32 qp_attach_mbox_size(void *mbox)4351{4352	u32 size = sizeof(struct mlx4_net_trans_rule_hw_ctrl);4353	struct _rule_hw  *rule_header;4354 4355	rule_header = (struct _rule_hw *)(mbox + size);4356 4357	while (rule_header->size) {4358		size += rule_header->size * sizeof(u32);4359		rule_header += 1;4360	}4361	return size;4362}4363 4364static int mlx4_do_mirror_rule(struct mlx4_dev *dev, struct res_fs_rule *fs_rule);4365 4366int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,4367					 struct mlx4_vhcr *vhcr,4368					 struct mlx4_cmd_mailbox *inbox,4369					 struct mlx4_cmd_mailbox *outbox,4370					 struct mlx4_cmd_info *cmd)4371{4372 4373	struct mlx4_priv *priv = mlx4_priv(dev);4374	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;4375	struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];4376	int err;4377	int qpn;4378	struct res_qp *rqp;4379	struct mlx4_net_trans_rule_hw_ctrl *ctrl;4380	struct _rule_hw  *rule_header;4381	int header_id;4382	struct res_fs_rule *rrule;4383	u32 mbox_size;4384 4385	if (dev->caps.steering_mode !=4386	    MLX4_STEERING_MODE_DEVICE_MANAGED)4387		return -EOPNOTSUPP;4388 4389	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;4390	err = mlx4_slave_convert_port(dev, slave, ctrl->port);4391	if (err <= 0)4392		return -EINVAL;4393	ctrl->port = err;4394	qpn = be32_to_cpu(ctrl->qpn) & 0xffffff;4395	err = get_res(dev, slave, qpn, RES_QP, &rqp);4396	if (err) {4397		pr_err("Steering rule with qpn 0x%x rejected\n", qpn);4398		return err;4399	}4400	rule_header = (struct _rule_hw *)(ctrl + 1);4401	header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));4402 4403	if (header_id == MLX4_NET_TRANS_RULE_ID_ETH)4404		mlx4_handle_eth_header_mcast_prio(ctrl, rule_header);4405 4406	switch (header_id) {4407	case MLX4_NET_TRANS_RULE_ID_ETH:4408		if (validate_eth_header_mac(slave, rule_header, rlist)) {4409			err = -EINVAL;4410			goto err_put_qp;4411		}4412		break;4413	case MLX4_NET_TRANS_RULE_ID_IB:4414		break;4415	case MLX4_NET_TRANS_RULE_ID_IPV4:4416	case MLX4_NET_TRANS_RULE_ID_TCP:4417	case MLX4_NET_TRANS_RULE_ID_UDP:4418		pr_warn("Can't attach FS rule without L2 headers, adding L2 header\n");4419		if (add_eth_header(dev, slave, inbox, rlist, header_id)) {4420			err = -EINVAL;4421			goto err_put_qp;4422		}4423		vhcr->in_modifier +=4424			sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2;4425		break;4426	default:4427		pr_err("Corrupted mailbox\n");4428		err = -EINVAL;4429		goto err_put_qp;4430	}4431 4432	err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,4433			   vhcr->in_modifier, 0,4434			   MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,4435			   MLX4_CMD_NATIVE);4436	if (err)4437		goto err_put_qp;4438 4439 4440	err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, qpn);4441	if (err) {4442		mlx4_err(dev, "Fail to add flow steering resources\n");4443		goto err_detach;4444	}4445 4446	err = get_res(dev, slave, vhcr->out_param, RES_FS_RULE, &rrule);4447	if (err)4448		goto err_detach;4449 4450	mbox_size = qp_attach_mbox_size(inbox->buf);4451	rrule->mirr_mbox = kmalloc(mbox_size, GFP_KERNEL);4452	if (!rrule->mirr_mbox) {4453		err = -ENOMEM;4454		goto err_put_rule;4455	}4456	rrule->mirr_mbox_size = mbox_size;4457	rrule->mirr_rule_id = 0;4458	memcpy(rrule->mirr_mbox, inbox->buf, mbox_size);4459 4460	/* set different port */4461	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)rrule->mirr_mbox;4462	if (ctrl->port == 1)4463		ctrl->port = 2;4464	else4465		ctrl->port = 1;4466 4467	if (mlx4_is_bonded(dev))4468		mlx4_do_mirror_rule(dev, rrule);4469 4470	atomic_inc(&rqp->ref_count);4471 4472err_put_rule:4473	put_res(dev, slave, vhcr->out_param, RES_FS_RULE);4474err_detach:4475	/* detach rule on error */4476	if (err)4477		mlx4_cmd(dev, vhcr->out_param, 0, 0,4478			 MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,4479			 MLX4_CMD_NATIVE);4480err_put_qp:4481	put_res(dev, slave, qpn, RES_QP);4482	return err;4483}4484 4485static int mlx4_undo_mirror_rule(struct mlx4_dev *dev, struct res_fs_rule *fs_rule)4486{4487	int err;4488 4489	err = rem_res_range(dev, fs_rule->com.owner, fs_rule->com.res_id, 1, RES_FS_RULE, 0);4490	if (err) {4491		mlx4_err(dev, "Fail to remove flow steering resources\n");4492		return err;4493	}4494 4495	mlx4_cmd(dev, fs_rule->com.res_id, 0, 0, MLX4_QP_FLOW_STEERING_DETACH,4496		 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);4497	return 0;4498}4499 4500int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,4501					 struct mlx4_vhcr *vhcr,4502					 struct mlx4_cmd_mailbox *inbox,4503					 struct mlx4_cmd_mailbox *outbox,4504					 struct mlx4_cmd_info *cmd)4505{4506	int err;4507	struct res_qp *rqp;4508	struct res_fs_rule *rrule;4509	u64 mirr_reg_id;4510	int qpn;4511 4512	if (dev->caps.steering_mode !=4513	    MLX4_STEERING_MODE_DEVICE_MANAGED)4514		return -EOPNOTSUPP;4515 4516	err = get_res(dev, slave, vhcr->in_param, RES_FS_RULE, &rrule);4517	if (err)4518		return err;4519 4520	if (!rrule->mirr_mbox) {4521		mlx4_err(dev, "Mirror rules cannot be removed explicitly\n");4522		put_res(dev, slave, vhcr->in_param, RES_FS_RULE);4523		return -EINVAL;4524	}4525	mirr_reg_id = rrule->mirr_rule_id;4526	kfree(rrule->mirr_mbox);4527	qpn = rrule->qpn;4528 4529	/* Release the rule form busy state before removal */4530	put_res(dev, slave, vhcr->in_param, RES_FS_RULE);4531	err = get_res(dev, slave, qpn, RES_QP, &rqp);4532	if (err)4533		return err;4534 4535	if (mirr_reg_id && mlx4_is_bonded(dev)) {4536		err = get_res(dev, slave, mirr_reg_id, RES_FS_RULE, &rrule);4537		if (err) {4538			mlx4_err(dev, "Fail to get resource of mirror rule\n");4539		} else {4540			put_res(dev, slave, mirr_reg_id, RES_FS_RULE);4541			mlx4_undo_mirror_rule(dev, rrule);4542		}4543	}4544	err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0);4545	if (err) {4546		mlx4_err(dev, "Fail to remove flow steering resources\n");4547		goto out;4548	}4549 4550	err = mlx4_cmd(dev, vhcr->in_param, 0, 0,4551		       MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,4552		       MLX4_CMD_NATIVE);4553	if (!err)4554		atomic_dec(&rqp->ref_count);4555out:4556	put_res(dev, slave, qpn, RES_QP);4557	return err;4558}4559 4560enum {4561	BUSY_MAX_RETRIES = 104562};4563 4564int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave,4565			       struct mlx4_vhcr *vhcr,4566			       struct mlx4_cmd_mailbox *inbox,4567			       struct mlx4_cmd_mailbox *outbox,4568			       struct mlx4_cmd_info *cmd)4569{4570	int err;4571	int index = vhcr->in_modifier & 0xffff;4572 4573	err = get_res(dev, slave, index, RES_COUNTER, NULL);4574	if (err)4575		return err;4576 4577	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);4578	put_res(dev, slave, index, RES_COUNTER);4579	return err;4580}4581 4582static void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp)4583{4584	struct res_gid *rgid;4585	struct res_gid *tmp;4586	struct mlx4_qp qp; /* dummy for calling attach/detach */4587 4588	list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) {4589		switch (dev->caps.steering_mode) {4590		case MLX4_STEERING_MODE_DEVICE_MANAGED:4591			mlx4_flow_detach(dev, rgid->reg_id);4592			break;4593		case MLX4_STEERING_MODE_B0:4594			qp.qpn = rqp->local_qpn;4595			(void) mlx4_qp_detach_common(dev, &qp, rgid->gid,4596						     rgid->prot, rgid->steer);4597			break;4598		}4599		list_del(&rgid->list);4600		kfree(rgid);4601	}4602}4603 4604static int _move_all_busy(struct mlx4_dev *dev, int slave,4605			  enum mlx4_resource type, int print)4606{4607	struct mlx4_priv *priv = mlx4_priv(dev);4608	struct mlx4_resource_tracker *tracker =4609		&priv->mfunc.master.res_tracker;4610	struct list_head *rlist = &tracker->slave_list[slave].res_list[type];4611	struct res_common *r;4612	struct res_common *tmp;4613	int busy;4614 4615	busy = 0;4616	spin_lock_irq(mlx4_tlock(dev));4617	list_for_each_entry_safe(r, tmp, rlist, list) {4618		if (r->owner == slave) {4619			if (!r->removing) {4620				if (r->state == RES_ANY_BUSY) {4621					if (print)4622						mlx4_dbg(dev,4623							 "%s id 0x%llx is busy\n",4624							  resource_str(type),4625							  r->res_id);4626					++busy;4627				} else {4628					r->from_state = r->state;4629					r->state = RES_ANY_BUSY;4630					r->removing = 1;4631				}4632			}4633		}4634	}4635	spin_unlock_irq(mlx4_tlock(dev));4636 4637	return busy;4638}4639 4640static int move_all_busy(struct mlx4_dev *dev, int slave,4641			 enum mlx4_resource type)4642{4643	unsigned long begin;4644	int busy;4645 4646	begin = jiffies;4647	do {4648		busy = _move_all_busy(dev, slave, type, 0);4649		if (time_after(jiffies, begin + 5 * HZ))4650			break;4651		if (busy)4652			cond_resched();4653	} while (busy);4654 4655	if (busy)4656		busy = _move_all_busy(dev, slave, type, 1);4657 4658	return busy;4659}4660static void rem_slave_qps(struct mlx4_dev *dev, int slave)4661{4662	struct mlx4_priv *priv = mlx4_priv(dev);4663	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;4664	struct list_head *qp_list =4665		&tracker->slave_list[slave].res_list[RES_QP];4666	struct res_qp *qp;4667	struct res_qp *tmp;4668	int state;4669	u64 in_param;4670	int qpn;4671	int err;4672 4673	err = move_all_busy(dev, slave, RES_QP);4674	if (err)4675		mlx4_warn(dev, "rem_slave_qps: Could not move all qps to busy for slave %d\n",4676			  slave);4677 4678	spin_lock_irq(mlx4_tlock(dev));4679	list_for_each_entry_safe(qp, tmp, qp_list, com.list) {4680		spin_unlock_irq(mlx4_tlock(dev));4681		if (qp->com.owner == slave) {4682			qpn = qp->com.res_id;4683			detach_qp(dev, slave, qp);4684			state = qp->com.from_state;4685			while (state != 0) {4686				switch (state) {4687				case RES_QP_RESERVED:4688					spin_lock_irq(mlx4_tlock(dev));4689					rb_erase(&qp->com.node,4690						 &tracker->res_tree[RES_QP]);4691					list_del(&qp->com.list);4692					spin_unlock_irq(mlx4_tlock(dev));4693					if (!valid_reserved(dev, slave, qpn)) {4694						__mlx4_qp_release_range(dev, qpn, 1);4695						mlx4_release_resource(dev, slave,4696								      RES_QP, 1, 0);4697					}4698					kfree(qp);4699					state = 0;4700					break;4701				case RES_QP_MAPPED:4702					if (!valid_reserved(dev, slave, qpn))4703						__mlx4_qp_free_icm(dev, qpn);4704					state = RES_QP_RESERVED;4705					break;4706				case RES_QP_HW:4707					in_param = slave;4708					err = mlx4_cmd(dev, in_param,4709						       qp->local_qpn, 2,4710						       MLX4_CMD_2RST_QP,4711						       MLX4_CMD_TIME_CLASS_A,4712						       MLX4_CMD_NATIVE);4713					if (err)4714						mlx4_dbg(dev, "rem_slave_qps: failed to move slave %d qpn %d to reset\n",4715							 slave, qp->local_qpn);4716					atomic_dec(&qp->rcq->ref_count);4717					atomic_dec(&qp->scq->ref_count);4718					atomic_dec(&qp->mtt->ref_count);4719					if (qp->srq)4720						atomic_dec(&qp->srq->ref_count);4721					state = RES_QP_MAPPED;4722					break;4723				default:4724					state = 0;4725				}4726			}4727		}4728		spin_lock_irq(mlx4_tlock(dev));4729	}4730	spin_unlock_irq(mlx4_tlock(dev));4731}4732 4733static void rem_slave_srqs(struct mlx4_dev *dev, int slave)4734{4735	struct mlx4_priv *priv = mlx4_priv(dev);4736	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;4737	struct list_head *srq_list =4738		&tracker->slave_list[slave].res_list[RES_SRQ];4739	struct res_srq *srq;4740	struct res_srq *tmp;4741	int state;4742	u64 in_param;4743	int srqn;4744	int err;4745 4746	err = move_all_busy(dev, slave, RES_SRQ);4747	if (err)4748		mlx4_warn(dev, "rem_slave_srqs: Could not move all srqs - too busy for slave %d\n",4749			  slave);4750 4751	spin_lock_irq(mlx4_tlock(dev));4752	list_for_each_entry_safe(srq, tmp, srq_list, com.list) {4753		spin_unlock_irq(mlx4_tlock(dev));4754		if (srq->com.owner == slave) {4755			srqn = srq->com.res_id;4756			state = srq->com.from_state;4757			while (state != 0) {4758				switch (state) {4759				case RES_SRQ_ALLOCATED:4760					__mlx4_srq_free_icm(dev, srqn);4761					spin_lock_irq(mlx4_tlock(dev));4762					rb_erase(&srq->com.node,4763						 &tracker->res_tree[RES_SRQ]);4764					list_del(&srq->com.list);4765					spin_unlock_irq(mlx4_tlock(dev));4766					mlx4_release_resource(dev, slave,4767							      RES_SRQ, 1, 0);4768					kfree(srq);4769					state = 0;4770					break;4771 4772				case RES_SRQ_HW:4773					in_param = slave;4774					err = mlx4_cmd(dev, in_param, srqn, 1,4775						       MLX4_CMD_HW2SW_SRQ,4776						       MLX4_CMD_TIME_CLASS_A,4777						       MLX4_CMD_NATIVE);4778					if (err)4779						mlx4_dbg(dev, "rem_slave_srqs: failed to move slave %d srq %d to SW ownership\n",4780							 slave, srqn);4781 4782					atomic_dec(&srq->mtt->ref_count);4783					if (srq->cq)4784						atomic_dec(&srq->cq->ref_count);4785					state = RES_SRQ_ALLOCATED;4786					break;4787 4788				default:4789					state = 0;4790				}4791			}4792		}4793		spin_lock_irq(mlx4_tlock(dev));4794	}4795	spin_unlock_irq(mlx4_tlock(dev));4796}4797 4798static void rem_slave_cqs(struct mlx4_dev *dev, int slave)4799{4800	struct mlx4_priv *priv = mlx4_priv(dev);4801	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;4802	struct list_head *cq_list =4803		&tracker->slave_list[slave].res_list[RES_CQ];4804	struct res_cq *cq;4805	struct res_cq *tmp;4806	int state;4807	u64 in_param;4808	int cqn;4809	int err;4810 4811	err = move_all_busy(dev, slave, RES_CQ);4812	if (err)4813		mlx4_warn(dev, "rem_slave_cqs: Could not move all cqs - too busy for slave %d\n",4814			  slave);4815 4816	spin_lock_irq(mlx4_tlock(dev));4817	list_for_each_entry_safe(cq, tmp, cq_list, com.list) {4818		spin_unlock_irq(mlx4_tlock(dev));4819		if (cq->com.owner == slave && !atomic_read(&cq->ref_count)) {4820			cqn = cq->com.res_id;4821			state = cq->com.from_state;4822			while (state != 0) {4823				switch (state) {4824				case RES_CQ_ALLOCATED:4825					__mlx4_cq_free_icm(dev, cqn);4826					spin_lock_irq(mlx4_tlock(dev));4827					rb_erase(&cq->com.node,4828						 &tracker->res_tree[RES_CQ]);4829					list_del(&cq->com.list);4830					spin_unlock_irq(mlx4_tlock(dev));4831					mlx4_release_resource(dev, slave,4832							      RES_CQ, 1, 0);4833					kfree(cq);4834					state = 0;4835					break;4836 4837				case RES_CQ_HW:4838					in_param = slave;4839					err = mlx4_cmd(dev, in_param, cqn, 1,4840						       MLX4_CMD_HW2SW_CQ,4841						       MLX4_CMD_TIME_CLASS_A,4842						       MLX4_CMD_NATIVE);4843					if (err)4844						mlx4_dbg(dev, "rem_slave_cqs: failed to move slave %d cq %d to SW ownership\n",4845							 slave, cqn);4846					atomic_dec(&cq->mtt->ref_count);4847					state = RES_CQ_ALLOCATED;4848					break;4849 4850				default:4851					state = 0;4852				}4853			}4854		}4855		spin_lock_irq(mlx4_tlock(dev));4856	}4857	spin_unlock_irq(mlx4_tlock(dev));4858}4859 4860static void rem_slave_mrs(struct mlx4_dev *dev, int slave)4861{4862	struct mlx4_priv *priv = mlx4_priv(dev);4863	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;4864	struct list_head *mpt_list =4865		&tracker->slave_list[slave].res_list[RES_MPT];4866	struct res_mpt *mpt;4867	struct res_mpt *tmp;4868	int state;4869	u64 in_param;4870	int mptn;4871	int err;4872 4873	err = move_all_busy(dev, slave, RES_MPT);4874	if (err)4875		mlx4_warn(dev, "rem_slave_mrs: Could not move all mpts - too busy for slave %d\n",4876			  slave);4877 4878	spin_lock_irq(mlx4_tlock(dev));4879	list_for_each_entry_safe(mpt, tmp, mpt_list, com.list) {4880		spin_unlock_irq(mlx4_tlock(dev));4881		if (mpt->com.owner == slave) {4882			mptn = mpt->com.res_id;4883			state = mpt->com.from_state;4884			while (state != 0) {4885				switch (state) {4886				case RES_MPT_RESERVED:4887					__mlx4_mpt_release(dev, mpt->key);4888					spin_lock_irq(mlx4_tlock(dev));4889					rb_erase(&mpt->com.node,4890						 &tracker->res_tree[RES_MPT]);4891					list_del(&mpt->com.list);4892					spin_unlock_irq(mlx4_tlock(dev));4893					mlx4_release_resource(dev, slave,4894							      RES_MPT, 1, 0);4895					kfree(mpt);4896					state = 0;4897					break;4898 4899				case RES_MPT_MAPPED:4900					__mlx4_mpt_free_icm(dev, mpt->key);4901					state = RES_MPT_RESERVED;4902					break;4903 4904				case RES_MPT_HW:4905					in_param = slave;4906					err = mlx4_cmd(dev, in_param, mptn, 0,4907						     MLX4_CMD_HW2SW_MPT,4908						     MLX4_CMD_TIME_CLASS_A,4909						     MLX4_CMD_NATIVE);4910					if (err)4911						mlx4_dbg(dev, "rem_slave_mrs: failed to move slave %d mpt %d to SW ownership\n",4912							 slave, mptn);4913					if (mpt->mtt)4914						atomic_dec(&mpt->mtt->ref_count);4915					state = RES_MPT_MAPPED;4916					break;4917				default:4918					state = 0;4919				}4920			}4921		}4922		spin_lock_irq(mlx4_tlock(dev));4923	}4924	spin_unlock_irq(mlx4_tlock(dev));4925}4926 4927static void rem_slave_mtts(struct mlx4_dev *dev, int slave)4928{4929	struct mlx4_priv *priv = mlx4_priv(dev);4930	struct mlx4_resource_tracker *tracker =4931		&priv->mfunc.master.res_tracker;4932	struct list_head *mtt_list =4933		&tracker->slave_list[slave].res_list[RES_MTT];4934	struct res_mtt *mtt;4935	struct res_mtt *tmp;4936	int state;4937	int base;4938	int err;4939 4940	err = move_all_busy(dev, slave, RES_MTT);4941	if (err)4942		mlx4_warn(dev, "rem_slave_mtts: Could not move all mtts  - too busy for slave %d\n",4943			  slave);4944 4945	spin_lock_irq(mlx4_tlock(dev));4946	list_for_each_entry_safe(mtt, tmp, mtt_list, com.list) {4947		spin_unlock_irq(mlx4_tlock(dev));4948		if (mtt->com.owner == slave) {4949			base = mtt->com.res_id;4950			state = mtt->com.from_state;4951			while (state != 0) {4952				switch (state) {4953				case RES_MTT_ALLOCATED:4954					__mlx4_free_mtt_range(dev, base,4955							      mtt->order);4956					spin_lock_irq(mlx4_tlock(dev));4957					rb_erase(&mtt->com.node,4958						 &tracker->res_tree[RES_MTT]);4959					list_del(&mtt->com.list);4960					spin_unlock_irq(mlx4_tlock(dev));4961					mlx4_release_resource(dev, slave, RES_MTT,4962							      1 << mtt->order, 0);4963					kfree(mtt);4964					state = 0;4965					break;4966 4967				default:4968					state = 0;4969				}4970			}4971		}4972		spin_lock_irq(mlx4_tlock(dev));4973	}4974	spin_unlock_irq(mlx4_tlock(dev));4975}4976 4977static int mlx4_do_mirror_rule(struct mlx4_dev *dev, struct res_fs_rule *fs_rule)4978{4979	struct mlx4_cmd_mailbox *mailbox;4980	int err;4981	struct res_fs_rule *mirr_rule;4982	u64 reg_id;4983 4984	mailbox = mlx4_alloc_cmd_mailbox(dev);4985	if (IS_ERR(mailbox))4986		return PTR_ERR(mailbox);4987 4988	if (!fs_rule->mirr_mbox) {4989		mlx4_err(dev, "rule mirroring mailbox is null\n");4990		mlx4_free_cmd_mailbox(dev, mailbox);4991		return -EINVAL;4992	}4993	memcpy(mailbox->buf, fs_rule->mirr_mbox, fs_rule->mirr_mbox_size);4994	err = mlx4_cmd_imm(dev, mailbox->dma, &reg_id, fs_rule->mirr_mbox_size >> 2, 0,4995			   MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,4996			   MLX4_CMD_NATIVE);4997	mlx4_free_cmd_mailbox(dev, mailbox);4998 4999	if (err)5000		goto err;5001 5002	err = add_res_range(dev, fs_rule->com.owner, reg_id, 1, RES_FS_RULE, fs_rule->qpn);5003	if (err)5004		goto err_detach;5005 5006	err = get_res(dev, fs_rule->com.owner, reg_id, RES_FS_RULE, &mirr_rule);5007	if (err)5008		goto err_rem;5009 5010	fs_rule->mirr_rule_id = reg_id;5011	mirr_rule->mirr_rule_id = 0;5012	mirr_rule->mirr_mbox_size = 0;5013	mirr_rule->mirr_mbox = NULL;5014	put_res(dev, fs_rule->com.owner, reg_id, RES_FS_RULE);5015 5016	return 0;5017err_rem:5018	rem_res_range(dev, fs_rule->com.owner, reg_id, 1, RES_FS_RULE, 0);5019err_detach:5020	mlx4_cmd(dev, reg_id, 0, 0, MLX4_QP_FLOW_STEERING_DETACH,5021		 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);5022err:5023	return err;5024}5025 5026static int mlx4_mirror_fs_rules(struct mlx4_dev *dev, bool bond)5027{5028	struct mlx4_priv *priv = mlx4_priv(dev);5029	struct mlx4_resource_tracker *tracker =5030		&priv->mfunc.master.res_tracker;5031	struct rb_root *root = &tracker->res_tree[RES_FS_RULE];5032	struct rb_node *p;5033	struct res_fs_rule *fs_rule;5034	int err = 0;5035	LIST_HEAD(mirr_list);5036 5037	for (p = rb_first(root); p; p = rb_next(p)) {5038		fs_rule = rb_entry(p, struct res_fs_rule, com.node);5039		if ((bond && fs_rule->mirr_mbox_size) ||5040		    (!bond && !fs_rule->mirr_mbox_size))5041			list_add_tail(&fs_rule->mirr_list, &mirr_list);5042	}5043 5044	list_for_each_entry(fs_rule, &mirr_list, mirr_list) {5045		if (bond)5046			err += mlx4_do_mirror_rule(dev, fs_rule);5047		else5048			err += mlx4_undo_mirror_rule(dev, fs_rule);5049	}5050	return err;5051}5052 5053int mlx4_bond_fs_rules(struct mlx4_dev *dev)5054{5055	return mlx4_mirror_fs_rules(dev, true);5056}5057 5058int mlx4_unbond_fs_rules(struct mlx4_dev *dev)5059{5060	return mlx4_mirror_fs_rules(dev, false);5061}5062 5063static void rem_slave_fs_rule(struct mlx4_dev *dev, int slave)5064{5065	struct mlx4_priv *priv = mlx4_priv(dev);5066	struct mlx4_resource_tracker *tracker =5067		&priv->mfunc.master.res_tracker;5068	struct list_head *fs_rule_list =5069		&tracker->slave_list[slave].res_list[RES_FS_RULE];5070	struct res_fs_rule *fs_rule;5071	struct res_fs_rule *tmp;5072	int state;5073	u64 base;5074	int err;5075 5076	err = move_all_busy(dev, slave, RES_FS_RULE);5077	if (err)5078		mlx4_warn(dev, "rem_slave_fs_rule: Could not move all mtts to busy for slave %d\n",5079			  slave);5080 5081	spin_lock_irq(mlx4_tlock(dev));5082	list_for_each_entry_safe(fs_rule, tmp, fs_rule_list, com.list) {5083		spin_unlock_irq(mlx4_tlock(dev));5084		if (fs_rule->com.owner == slave) {5085			base = fs_rule->com.res_id;5086			state = fs_rule->com.from_state;5087			while (state != 0) {5088				switch (state) {5089				case RES_FS_RULE_ALLOCATED:5090					/* detach rule */5091					err = mlx4_cmd(dev, base, 0, 0,5092						       MLX4_QP_FLOW_STEERING_DETACH,5093						       MLX4_CMD_TIME_CLASS_A,5094						       MLX4_CMD_NATIVE);5095 5096					spin_lock_irq(mlx4_tlock(dev));5097					rb_erase(&fs_rule->com.node,5098						 &tracker->res_tree[RES_FS_RULE]);5099					list_del(&fs_rule->com.list);5100					spin_unlock_irq(mlx4_tlock(dev));5101					kfree(fs_rule->mirr_mbox);5102					kfree(fs_rule);5103					state = 0;5104					break;5105 5106				default:5107					state = 0;5108				}5109			}5110		}5111		spin_lock_irq(mlx4_tlock(dev));5112	}5113	spin_unlock_irq(mlx4_tlock(dev));5114}5115 5116static void rem_slave_eqs(struct mlx4_dev *dev, int slave)5117{5118	struct mlx4_priv *priv = mlx4_priv(dev);5119	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;5120	struct list_head *eq_list =5121		&tracker->slave_list[slave].res_list[RES_EQ];5122	struct res_eq *eq;5123	struct res_eq *tmp;5124	int err;5125	int state;5126	int eqn;5127 5128	err = move_all_busy(dev, slave, RES_EQ);5129	if (err)5130		mlx4_warn(dev, "rem_slave_eqs: Could not move all eqs - too busy for slave %d\n",5131			  slave);5132 5133	spin_lock_irq(mlx4_tlock(dev));5134	list_for_each_entry_safe(eq, tmp, eq_list, com.list) {5135		spin_unlock_irq(mlx4_tlock(dev));5136		if (eq->com.owner == slave) {5137			eqn = eq->com.res_id;5138			state = eq->com.from_state;5139			while (state != 0) {5140				switch (state) {5141				case RES_EQ_RESERVED:5142					spin_lock_irq(mlx4_tlock(dev));5143					rb_erase(&eq->com.node,5144						 &tracker->res_tree[RES_EQ]);5145					list_del(&eq->com.list);5146					spin_unlock_irq(mlx4_tlock(dev));5147					kfree(eq);5148					state = 0;5149					break;5150 5151				case RES_EQ_HW:5152					err = mlx4_cmd(dev, slave, eqn & 0x3ff,5153						       1, MLX4_CMD_HW2SW_EQ,5154						       MLX4_CMD_TIME_CLASS_A,5155						       MLX4_CMD_NATIVE);5156					if (err)5157						mlx4_dbg(dev, "rem_slave_eqs: failed to move slave %d eqs %d to SW ownership\n",5158							 slave, eqn & 0x3ff);5159					atomic_dec(&eq->mtt->ref_count);5160					state = RES_EQ_RESERVED;5161					break;5162 5163				default:5164					state = 0;5165				}5166			}5167		}5168		spin_lock_irq(mlx4_tlock(dev));5169	}5170	spin_unlock_irq(mlx4_tlock(dev));5171}5172 5173static void rem_slave_counters(struct mlx4_dev *dev, int slave)5174{5175	struct mlx4_priv *priv = mlx4_priv(dev);5176	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;5177	struct list_head *counter_list =5178		&tracker->slave_list[slave].res_list[RES_COUNTER];5179	struct res_counter *counter;5180	struct res_counter *tmp;5181	int err;5182	int *counters_arr = NULL;5183	int i, j;5184 5185	err = move_all_busy(dev, slave, RES_COUNTER);5186	if (err)5187		mlx4_warn(dev, "rem_slave_counters: Could not move all counters - too busy for slave %d\n",5188			  slave);5189 5190	counters_arr = kmalloc_array(dev->caps.max_counters,5191				     sizeof(*counters_arr), GFP_KERNEL);5192	if (!counters_arr)5193		return;5194 5195	do {5196		i = 0;5197		j = 0;5198		spin_lock_irq(mlx4_tlock(dev));5199		list_for_each_entry_safe(counter, tmp, counter_list, com.list) {5200			if (counter->com.owner == slave) {5201				counters_arr[i++] = counter->com.res_id;5202				rb_erase(&counter->com.node,5203					 &tracker->res_tree[RES_COUNTER]);5204				list_del(&counter->com.list);5205				kfree(counter);5206			}5207		}5208		spin_unlock_irq(mlx4_tlock(dev));5209 5210		while (j < i) {5211			__mlx4_counter_free(dev, counters_arr[j++]);5212			mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);5213		}5214	} while (i);5215 5216	kfree(counters_arr);5217}5218 5219static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)5220{5221	struct mlx4_priv *priv = mlx4_priv(dev);5222	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;5223	struct list_head *xrcdn_list =5224		&tracker->slave_list[slave].res_list[RES_XRCD];5225	struct res_xrcdn *xrcd;5226	struct res_xrcdn *tmp;5227	int err;5228	int xrcdn;5229 5230	err = move_all_busy(dev, slave, RES_XRCD);5231	if (err)5232		mlx4_warn(dev, "rem_slave_xrcdns: Could not move all xrcdns - too busy for slave %d\n",5233			  slave);5234 5235	spin_lock_irq(mlx4_tlock(dev));5236	list_for_each_entry_safe(xrcd, tmp, xrcdn_list, com.list) {5237		if (xrcd->com.owner == slave) {5238			xrcdn = xrcd->com.res_id;5239			rb_erase(&xrcd->com.node, &tracker->res_tree[RES_XRCD]);5240			list_del(&xrcd->com.list);5241			kfree(xrcd);5242			__mlx4_xrcd_free(dev, xrcdn);5243		}5244	}5245	spin_unlock_irq(mlx4_tlock(dev));5246}5247 5248void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)5249{5250	struct mlx4_priv *priv = mlx4_priv(dev);5251	mlx4_reset_roce_gids(dev, slave);5252	mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);5253	rem_slave_vlans(dev, slave);5254	rem_slave_macs(dev, slave);5255	rem_slave_fs_rule(dev, slave);5256	rem_slave_qps(dev, slave);5257	rem_slave_srqs(dev, slave);5258	rem_slave_cqs(dev, slave);5259	rem_slave_mrs(dev, slave);5260	rem_slave_eqs(dev, slave);5261	rem_slave_mtts(dev, slave);5262	rem_slave_counters(dev, slave);5263	rem_slave_xrcdns(dev, slave);5264	mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);5265}5266 5267static void update_qos_vpp(struct mlx4_update_qp_context *ctx,5268			   struct mlx4_vf_immed_vlan_work *work)5269{5270	ctx->qp_mask |= cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_QOS_VPP);5271	ctx->qp_context.qos_vport = work->qos_vport;5272}5273 5274void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)5275{5276	struct mlx4_vf_immed_vlan_work *work =5277		container_of(_work, struct mlx4_vf_immed_vlan_work, work);5278	struct mlx4_cmd_mailbox *mailbox;5279	struct mlx4_update_qp_context *upd_context;5280	struct mlx4_dev *dev = &work->priv->dev;5281	struct mlx4_resource_tracker *tracker =5282		&work->priv->mfunc.master.res_tracker;5283	struct list_head *qp_list =5284		&tracker->slave_list[work->slave].res_list[RES_QP];5285	struct res_qp *qp;5286	struct res_qp *tmp;5287	u64 qp_path_mask_vlan_ctrl =5288		       ((1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_UNTAGGED) |5289		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_1P) |5290		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_TAGGED) |5291		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_UNTAGGED) |5292		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_1P) |5293		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_TAGGED));5294 5295	u64 qp_path_mask = ((1ULL << MLX4_UPD_QP_PATH_MASK_VLAN_INDEX) |5296		       (1ULL << MLX4_UPD_QP_PATH_MASK_FVL) |5297		       (1ULL << MLX4_UPD_QP_PATH_MASK_CV) |5298		       (1ULL << MLX4_UPD_QP_PATH_MASK_SV) |5299		       (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_HIDE_CQE_VLAN) |5300		       (1ULL << MLX4_UPD_QP_PATH_MASK_FEUP) |5301		       (1ULL << MLX4_UPD_QP_PATH_MASK_FVL_RX) |5302		       (1ULL << MLX4_UPD_QP_PATH_MASK_SCHED_QUEUE));5303 5304	int err;5305	int port, errors = 0;5306	u8 vlan_control;5307 5308	if (mlx4_is_slave(dev)) {5309		mlx4_warn(dev, "Trying to update-qp in slave %d\n",5310			  work->slave);5311		goto out;5312	}5313 5314	mailbox = mlx4_alloc_cmd_mailbox(dev);5315	if (IS_ERR(mailbox))5316		goto out;5317	if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_LINK_DISABLE) /* block all */5318		vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |5319			MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED |5320			MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED |5321			MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |5322			MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED |5323			MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;5324	else if (!work->vlan_id)5325		vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |5326			MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;5327	else if (work->vlan_proto == htons(ETH_P_8021AD))5328		vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED |5329			MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |5330			MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |5331			MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;5332	else  /* vst 802.1Q */5333		vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |5334			MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |5335			MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;5336 5337	upd_context = mailbox->buf;5338	upd_context->qp_mask = cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_VSD);5339 5340	spin_lock_irq(mlx4_tlock(dev));5341	list_for_each_entry_safe(qp, tmp, qp_list, com.list) {5342		spin_unlock_irq(mlx4_tlock(dev));5343		if (qp->com.owner == work->slave) {5344			if (qp->com.from_state != RES_QP_HW ||5345			    !qp->sched_queue ||  /* no INIT2RTR trans yet */5346			    mlx4_is_qp_reserved(dev, qp->local_qpn) ||5347			    qp->qpc_flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET)) {5348				spin_lock_irq(mlx4_tlock(dev));5349				continue;5350			}5351			port = (qp->sched_queue >> 6 & 1) + 1;5352			if (port != work->port) {5353				spin_lock_irq(mlx4_tlock(dev));5354				continue;5355			}5356			if (MLX4_QP_ST_RC == ((qp->qpc_flags >> 16) & 0xff))5357				upd_context->primary_addr_path_mask = cpu_to_be64(qp_path_mask);5358			else5359				upd_context->primary_addr_path_mask =5360					cpu_to_be64(qp_path_mask | qp_path_mask_vlan_ctrl);5361			if (work->vlan_id == MLX4_VGT) {5362				upd_context->qp_context.param3 = qp->param3;5363				upd_context->qp_context.pri_path.vlan_control = qp->vlan_control;5364				upd_context->qp_context.pri_path.fvl_rx = qp->fvl_rx;5365				upd_context->qp_context.pri_path.vlan_index = qp->vlan_index;5366				upd_context->qp_context.pri_path.fl = qp->pri_path_fl;5367				upd_context->qp_context.pri_path.feup = qp->feup;5368				upd_context->qp_context.pri_path.sched_queue =5369					qp->sched_queue;5370			} else {5371				upd_context->qp_context.param3 = qp->param3 & ~cpu_to_be32(MLX4_STRIP_VLAN);5372				upd_context->qp_context.pri_path.vlan_control = vlan_control;5373				upd_context->qp_context.pri_path.vlan_index = work->vlan_ix;5374				upd_context->qp_context.pri_path.fvl_rx =5375					qp->fvl_rx | MLX4_FVL_RX_FORCE_ETH_VLAN;5376				upd_context->qp_context.pri_path.fl =5377					qp->pri_path_fl | MLX4_FL_ETH_HIDE_CQE_VLAN;5378				if (work->vlan_proto == htons(ETH_P_8021AD))5379					upd_context->qp_context.pri_path.fl |= MLX4_FL_SV;5380				else5381					upd_context->qp_context.pri_path.fl |= MLX4_FL_CV;5382				upd_context->qp_context.pri_path.feup =5383					qp->feup | MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN;5384				upd_context->qp_context.pri_path.sched_queue =5385					qp->sched_queue & 0xC7;5386				upd_context->qp_context.pri_path.sched_queue |=5387					((work->qos & 0x7) << 3);5388 5389				if (dev->caps.flags2 &5390				    MLX4_DEV_CAP_FLAG2_QOS_VPP)5391					update_qos_vpp(upd_context, work);5392			}5393 5394			err = mlx4_cmd(dev, mailbox->dma,5395				       qp->local_qpn & 0xffffff,5396				       0, MLX4_CMD_UPDATE_QP,5397				       MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);5398			if (err) {5399				mlx4_info(dev, "UPDATE_QP failed for slave %d, port %d, qpn %d (%d)\n",5400					  work->slave, port, qp->local_qpn, err);5401				errors++;5402			}5403		}5404		spin_lock_irq(mlx4_tlock(dev));5405	}5406	spin_unlock_irq(mlx4_tlock(dev));5407	mlx4_free_cmd_mailbox(dev, mailbox);5408 5409	if (errors)5410		mlx4_err(dev, "%d UPDATE_QP failures for slave %d, port %d\n",5411			 errors, work->slave, work->port);5412 5413	/* unregister previous vlan_id if needed and we had no errors5414	 * while updating the QPs5415	 */5416	if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN && !errors &&5417	    NO_INDX != work->orig_vlan_ix)5418		__mlx4_unregister_vlan(&work->priv->dev, work->port,5419				       work->orig_vlan_id);5420out:5421	kfree(work);5422	return;5423}5424