14ad79e13SYuval Mintz /* bnx2x_sp.c: Qlogic Everest network driver.
2adfc5217SJeff Kirsher  *
34ad79e13SYuval Mintz  * Copyright 2011-2013 Broadcom Corporation
44ad79e13SYuval Mintz  * Copyright (c) 2014 QLogic Corporation
54ad79e13SYuval Mintz  * All rights reserved
6adfc5217SJeff Kirsher  *
74ad79e13SYuval Mintz  * Unless you and Qlogic execute a separate written software license
8adfc5217SJeff Kirsher  * agreement governing use of this software, this software is licensed to you
9adfc5217SJeff Kirsher  * under the terms of the GNU General Public License version 2, available
104ad79e13SYuval Mintz  * at http://www.gnu.org/licenses/gpl-2.0.html (the "GPL").
11adfc5217SJeff Kirsher  *
12adfc5217SJeff Kirsher  * Notwithstanding the above, under no circumstances may you combine this
134ad79e13SYuval Mintz  * software in any way with any other Qlogic software provided under a
144ad79e13SYuval Mintz  * license other than the GPL, without Qlogic's express prior written
15adfc5217SJeff Kirsher  * consent.
16adfc5217SJeff Kirsher  *
1708f6dd89SAriel Elior  * Maintained by: Ariel Elior <ariel.elior@qlogic.com>
18adfc5217SJeff Kirsher  * Written by: Vladislav Zolotarov
19adfc5217SJeff Kirsher  *
20adfc5217SJeff Kirsher  */
21f1deab50SJoe Perches 
22f1deab50SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23f1deab50SJoe Perches 
24adfc5217SJeff Kirsher #include <linux/module.h>
25adfc5217SJeff Kirsher #include <linux/crc32.h>
26adfc5217SJeff Kirsher #include <linux/netdevice.h>
27adfc5217SJeff Kirsher #include <linux/etherdevice.h>
28adfc5217SJeff Kirsher #include <linux/crc32c.h>
29adfc5217SJeff Kirsher #include "bnx2x.h"
30adfc5217SJeff Kirsher #include "bnx2x_cmn.h"
31adfc5217SJeff Kirsher #include "bnx2x_sp.h"
32adfc5217SJeff Kirsher 
33adfc5217SJeff Kirsher #define BNX2X_MAX_EMUL_MULTI		16
34adfc5217SJeff Kirsher 
35adfc5217SJeff Kirsher /**** Exe Queue interfaces ****/
36adfc5217SJeff Kirsher 
37adfc5217SJeff Kirsher /**
38adfc5217SJeff Kirsher  * bnx2x_exe_queue_init - init the Exe Queue object
39adfc5217SJeff Kirsher  *
40d0ea5cbdSJesse Brandeburg  * @bp:		driver handle
4116a5fd92SYuval Mintz  * @o:		pointer to the object
42adfc5217SJeff Kirsher  * @exe_len:	length
4316a5fd92SYuval Mintz  * @owner:	pointer to the owner
44adfc5217SJeff Kirsher  * @validate:	validate function pointer
45d0ea5cbdSJesse Brandeburg  * @remove:	remove function pointer
46adfc5217SJeff Kirsher  * @optimize:	optimize function pointer
47adfc5217SJeff Kirsher  * @exec:	execute function pointer
48adfc5217SJeff Kirsher  * @get:	get function pointer
49adfc5217SJeff Kirsher  */
bnx2x_exe_queue_init(struct bnx2x * bp,struct bnx2x_exe_queue_obj * o,int exe_len,union bnx2x_qable_obj * owner,exe_q_validate validate,exe_q_remove remove,exe_q_optimize optimize,exe_q_execute exec,exe_q_get get)50adfc5217SJeff Kirsher static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
51adfc5217SJeff Kirsher 					struct bnx2x_exe_queue_obj *o,
52adfc5217SJeff Kirsher 					int exe_len,
53adfc5217SJeff Kirsher 					union bnx2x_qable_obj *owner,
54adfc5217SJeff Kirsher 					exe_q_validate validate,
55460a25cdSYuval Mintz 					exe_q_remove remove,
56adfc5217SJeff Kirsher 					exe_q_optimize optimize,
57adfc5217SJeff Kirsher 					exe_q_execute exec,
58adfc5217SJeff Kirsher 					exe_q_get get)
59adfc5217SJeff Kirsher {
60adfc5217SJeff Kirsher 	memset(o, 0, sizeof(*o));
61adfc5217SJeff Kirsher 
62adfc5217SJeff Kirsher 	INIT_LIST_HEAD(&o->exe_queue);
63adfc5217SJeff Kirsher 	INIT_LIST_HEAD(&o->pending_comp);
64adfc5217SJeff Kirsher 
65adfc5217SJeff Kirsher 	spin_lock_init(&o->lock);
66adfc5217SJeff Kirsher 
67adfc5217SJeff Kirsher 	o->exe_chunk_len = exe_len;
68adfc5217SJeff Kirsher 	o->owner         = owner;
69adfc5217SJeff Kirsher 
70adfc5217SJeff Kirsher 	/* Owner specific callbacks */
71adfc5217SJeff Kirsher 	o->validate      = validate;
72460a25cdSYuval Mintz 	o->remove        = remove;
73adfc5217SJeff Kirsher 	o->optimize      = optimize;
74adfc5217SJeff Kirsher 	o->execute       = exec;
75adfc5217SJeff Kirsher 	o->get           = get;
76adfc5217SJeff Kirsher 
7751c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "Setup the execution queue with the chunk length of %d\n",
7851c1a580SMerav Sicron 	   exe_len);
79adfc5217SJeff Kirsher }
80adfc5217SJeff Kirsher 
bnx2x_exe_queue_free_elem(struct bnx2x * bp,struct bnx2x_exeq_elem * elem)81adfc5217SJeff Kirsher static inline void bnx2x_exe_queue_free_elem(struct bnx2x *bp,
82adfc5217SJeff Kirsher 					     struct bnx2x_exeq_elem *elem)
83adfc5217SJeff Kirsher {
84adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Deleting an exe_queue element\n");
85adfc5217SJeff Kirsher 	kfree(elem);
86adfc5217SJeff Kirsher }
87adfc5217SJeff Kirsher 
bnx2x_exe_queue_length(struct bnx2x_exe_queue_obj * o)88adfc5217SJeff Kirsher static inline int bnx2x_exe_queue_length(struct bnx2x_exe_queue_obj *o)
89adfc5217SJeff Kirsher {
90adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem;
91adfc5217SJeff Kirsher 	int cnt = 0;
92adfc5217SJeff Kirsher 
93adfc5217SJeff Kirsher 	spin_lock_bh(&o->lock);
94adfc5217SJeff Kirsher 
95adfc5217SJeff Kirsher 	list_for_each_entry(elem, &o->exe_queue, link)
96adfc5217SJeff Kirsher 		cnt++;
97adfc5217SJeff Kirsher 
98adfc5217SJeff Kirsher 	spin_unlock_bh(&o->lock);
99adfc5217SJeff Kirsher 
100adfc5217SJeff Kirsher 	return cnt;
101adfc5217SJeff Kirsher }
102adfc5217SJeff Kirsher 
103adfc5217SJeff Kirsher /**
104adfc5217SJeff Kirsher  * bnx2x_exe_queue_add - add a new element to the execution queue
105adfc5217SJeff Kirsher  *
106adfc5217SJeff Kirsher  * @bp:		driver handle
107adfc5217SJeff Kirsher  * @o:		queue
108d0ea5cbdSJesse Brandeburg  * @elem:	new command to add
109adfc5217SJeff Kirsher  * @restore:	true - do not optimize the command
110adfc5217SJeff Kirsher  *
111adfc5217SJeff Kirsher  * If the element is optimized or is illegal, frees it.
112adfc5217SJeff Kirsher  */
bnx2x_exe_queue_add(struct bnx2x * bp,struct bnx2x_exe_queue_obj * o,struct bnx2x_exeq_elem * elem,bool restore)113adfc5217SJeff Kirsher static inline int bnx2x_exe_queue_add(struct bnx2x *bp,
114adfc5217SJeff Kirsher 				      struct bnx2x_exe_queue_obj *o,
115adfc5217SJeff Kirsher 				      struct bnx2x_exeq_elem *elem,
116adfc5217SJeff Kirsher 				      bool restore)
117adfc5217SJeff Kirsher {
118adfc5217SJeff Kirsher 	int rc;
119adfc5217SJeff Kirsher 
120adfc5217SJeff Kirsher 	spin_lock_bh(&o->lock);
121adfc5217SJeff Kirsher 
122adfc5217SJeff Kirsher 	if (!restore) {
123adfc5217SJeff Kirsher 		/* Try to cancel this element queue */
124adfc5217SJeff Kirsher 		rc = o->optimize(bp, o->owner, elem);
125adfc5217SJeff Kirsher 		if (rc)
126adfc5217SJeff Kirsher 			goto free_and_exit;
127adfc5217SJeff Kirsher 
128adfc5217SJeff Kirsher 		/* Check if this request is ok */
129adfc5217SJeff Kirsher 		rc = o->validate(bp, o->owner, elem);
130adfc5217SJeff Kirsher 		if (rc) {
1312384d6aaSDmitry Kravkov 			DP(BNX2X_MSG_SP, "Preamble failed: %d\n", rc);
132adfc5217SJeff Kirsher 			goto free_and_exit;
133adfc5217SJeff Kirsher 		}
134adfc5217SJeff Kirsher 	}
135adfc5217SJeff Kirsher 
136adfc5217SJeff Kirsher 	/* If so, add it to the execution queue */
137adfc5217SJeff Kirsher 	list_add_tail(&elem->link, &o->exe_queue);
138adfc5217SJeff Kirsher 
139adfc5217SJeff Kirsher 	spin_unlock_bh(&o->lock);
140adfc5217SJeff Kirsher 
141adfc5217SJeff Kirsher 	return 0;
142adfc5217SJeff Kirsher 
143adfc5217SJeff Kirsher free_and_exit:
144adfc5217SJeff Kirsher 	bnx2x_exe_queue_free_elem(bp, elem);
145adfc5217SJeff Kirsher 
146adfc5217SJeff Kirsher 	spin_unlock_bh(&o->lock);
147adfc5217SJeff Kirsher 
148adfc5217SJeff Kirsher 	return rc;
149adfc5217SJeff Kirsher }
150adfc5217SJeff Kirsher 
__bnx2x_exe_queue_reset_pending(struct bnx2x * bp,struct bnx2x_exe_queue_obj * o)151adfc5217SJeff Kirsher static inline void __bnx2x_exe_queue_reset_pending(
152adfc5217SJeff Kirsher 	struct bnx2x *bp,
153adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *o)
154adfc5217SJeff Kirsher {
155adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem;
156adfc5217SJeff Kirsher 
157adfc5217SJeff Kirsher 	while (!list_empty(&o->pending_comp)) {
158adfc5217SJeff Kirsher 		elem = list_first_entry(&o->pending_comp,
159adfc5217SJeff Kirsher 					struct bnx2x_exeq_elem, link);
160adfc5217SJeff Kirsher 
161adfc5217SJeff Kirsher 		list_del(&elem->link);
162adfc5217SJeff Kirsher 		bnx2x_exe_queue_free_elem(bp, elem);
163adfc5217SJeff Kirsher 	}
164adfc5217SJeff Kirsher }
165adfc5217SJeff Kirsher 
166adfc5217SJeff Kirsher /**
167adfc5217SJeff Kirsher  * bnx2x_exe_queue_step - execute one execution chunk atomically
168adfc5217SJeff Kirsher  *
169adfc5217SJeff Kirsher  * @bp:			driver handle
170adfc5217SJeff Kirsher  * @o:			queue
171adfc5217SJeff Kirsher  * @ramrod_flags:	flags
172adfc5217SJeff Kirsher  *
1738b09be5fSYuval Mintz  * (Should be called while holding the exe_queue->lock).
174adfc5217SJeff Kirsher  */
bnx2x_exe_queue_step(struct bnx2x * bp,struct bnx2x_exe_queue_obj * o,unsigned long * ramrod_flags)175adfc5217SJeff Kirsher static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
176adfc5217SJeff Kirsher 				       struct bnx2x_exe_queue_obj *o,
177adfc5217SJeff Kirsher 				       unsigned long *ramrod_flags)
178adfc5217SJeff Kirsher {
179adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem, spacer;
180adfc5217SJeff Kirsher 	int cur_len = 0, rc;
181adfc5217SJeff Kirsher 
182adfc5217SJeff Kirsher 	memset(&spacer, 0, sizeof(spacer));
183adfc5217SJeff Kirsher 
18416a5fd92SYuval Mintz 	/* Next step should not be performed until the current is finished,
185adfc5217SJeff Kirsher 	 * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
186adfc5217SJeff Kirsher 	 * properly clear object internals without sending any command to the FW
187adfc5217SJeff Kirsher 	 * which also implies there won't be any completion to clear the
188adfc5217SJeff Kirsher 	 * 'pending' list.
189adfc5217SJeff Kirsher 	 */
190adfc5217SJeff Kirsher 	if (!list_empty(&o->pending_comp)) {
191adfc5217SJeff Kirsher 		if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
19251c1a580SMerav Sicron 			DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: resetting a pending_comp list\n");
193adfc5217SJeff Kirsher 			__bnx2x_exe_queue_reset_pending(bp, o);
194adfc5217SJeff Kirsher 		} else {
195adfc5217SJeff Kirsher 			return 1;
196adfc5217SJeff Kirsher 		}
197adfc5217SJeff Kirsher 	}
198adfc5217SJeff Kirsher 
19916a5fd92SYuval Mintz 	/* Run through the pending commands list and create a next
200adfc5217SJeff Kirsher 	 * execution chunk.
201adfc5217SJeff Kirsher 	 */
202adfc5217SJeff Kirsher 	while (!list_empty(&o->exe_queue)) {
203adfc5217SJeff Kirsher 		elem = list_first_entry(&o->exe_queue, struct bnx2x_exeq_elem,
204adfc5217SJeff Kirsher 					link);
205adfc5217SJeff Kirsher 		WARN_ON(!elem->cmd_len);
206adfc5217SJeff Kirsher 
207adfc5217SJeff Kirsher 		if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
208adfc5217SJeff Kirsher 			cur_len += elem->cmd_len;
20916a5fd92SYuval Mintz 			/* Prevent from both lists being empty when moving an
210adfc5217SJeff Kirsher 			 * element. This will allow the call of
211adfc5217SJeff Kirsher 			 * bnx2x_exe_queue_empty() without locking.
212adfc5217SJeff Kirsher 			 */
213adfc5217SJeff Kirsher 			list_add_tail(&spacer.link, &o->pending_comp);
214adfc5217SJeff Kirsher 			mb();
2157933aa5cSWei Yongjun 			list_move_tail(&elem->link, &o->pending_comp);
216adfc5217SJeff Kirsher 			list_del(&spacer.link);
217adfc5217SJeff Kirsher 		} else
218adfc5217SJeff Kirsher 			break;
219adfc5217SJeff Kirsher 	}
220adfc5217SJeff Kirsher 
221adfc5217SJeff Kirsher 	/* Sanity check */
2228b09be5fSYuval Mintz 	if (!cur_len)
223adfc5217SJeff Kirsher 		return 0;
224adfc5217SJeff Kirsher 
225adfc5217SJeff Kirsher 	rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags);
226adfc5217SJeff Kirsher 	if (rc < 0)
22716a5fd92SYuval Mintz 		/* In case of an error return the commands back to the queue
228adfc5217SJeff Kirsher 		 * and reset the pending_comp.
229adfc5217SJeff Kirsher 		 */
230adfc5217SJeff Kirsher 		list_splice_init(&o->pending_comp, &o->exe_queue);
231adfc5217SJeff Kirsher 	else if (!rc)
23216a5fd92SYuval Mintz 		/* If zero is returned, means there are no outstanding pending
233adfc5217SJeff Kirsher 		 * completions and we may dismiss the pending list.
234adfc5217SJeff Kirsher 		 */
235adfc5217SJeff Kirsher 		__bnx2x_exe_queue_reset_pending(bp, o);
236adfc5217SJeff Kirsher 
237adfc5217SJeff Kirsher 	return rc;
238adfc5217SJeff Kirsher }
239adfc5217SJeff Kirsher 
bnx2x_exe_queue_empty(struct bnx2x_exe_queue_obj * o)240adfc5217SJeff Kirsher static inline bool bnx2x_exe_queue_empty(struct bnx2x_exe_queue_obj *o)
241adfc5217SJeff Kirsher {
242adfc5217SJeff Kirsher 	bool empty = list_empty(&o->exe_queue);
243adfc5217SJeff Kirsher 
244adfc5217SJeff Kirsher 	/* Don't reorder!!! */
245adfc5217SJeff Kirsher 	mb();
246adfc5217SJeff Kirsher 
247adfc5217SJeff Kirsher 	return empty && list_empty(&o->pending_comp);
248adfc5217SJeff Kirsher }
249adfc5217SJeff Kirsher 
bnx2x_exe_queue_alloc_elem(struct bnx2x * bp)250adfc5217SJeff Kirsher static inline struct bnx2x_exeq_elem *bnx2x_exe_queue_alloc_elem(
251adfc5217SJeff Kirsher 	struct bnx2x *bp)
252adfc5217SJeff Kirsher {
253adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Allocating a new exe_queue element\n");
254adfc5217SJeff Kirsher 	return kzalloc(sizeof(struct bnx2x_exeq_elem), GFP_ATOMIC);
255adfc5217SJeff Kirsher }
256adfc5217SJeff Kirsher 
257adfc5217SJeff Kirsher /************************ raw_obj functions ***********************************/
bnx2x_raw_check_pending(struct bnx2x_raw_obj * o)258adfc5217SJeff Kirsher static bool bnx2x_raw_check_pending(struct bnx2x_raw_obj *o)
259adfc5217SJeff Kirsher {
260adfc5217SJeff Kirsher 	return !!test_bit(o->state, o->pstate);
261adfc5217SJeff Kirsher }
262adfc5217SJeff Kirsher 
bnx2x_raw_clear_pending(struct bnx2x_raw_obj * o)263adfc5217SJeff Kirsher static void bnx2x_raw_clear_pending(struct bnx2x_raw_obj *o)
264adfc5217SJeff Kirsher {
2654e857c58SPeter Zijlstra 	smp_mb__before_atomic();
266adfc5217SJeff Kirsher 	clear_bit(o->state, o->pstate);
2674e857c58SPeter Zijlstra 	smp_mb__after_atomic();
268adfc5217SJeff Kirsher }
269adfc5217SJeff Kirsher 
bnx2x_raw_set_pending(struct bnx2x_raw_obj * o)270adfc5217SJeff Kirsher static void bnx2x_raw_set_pending(struct bnx2x_raw_obj *o)
271adfc5217SJeff Kirsher {
2724e857c58SPeter Zijlstra 	smp_mb__before_atomic();
273adfc5217SJeff Kirsher 	set_bit(o->state, o->pstate);
2744e857c58SPeter Zijlstra 	smp_mb__after_atomic();
275adfc5217SJeff Kirsher }
276adfc5217SJeff Kirsher 
277adfc5217SJeff Kirsher /**
278adfc5217SJeff Kirsher  * bnx2x_state_wait - wait until the given bit(state) is cleared
279adfc5217SJeff Kirsher  *
280adfc5217SJeff Kirsher  * @bp:		device handle
281adfc5217SJeff Kirsher  * @state:	state which is to be cleared
282d0ea5cbdSJesse Brandeburg  * @pstate:	state buffer
283adfc5217SJeff Kirsher  *
284adfc5217SJeff Kirsher  */
bnx2x_state_wait(struct bnx2x * bp,int state,unsigned long * pstate)285adfc5217SJeff Kirsher static inline int bnx2x_state_wait(struct bnx2x *bp, int state,
286adfc5217SJeff Kirsher 				   unsigned long *pstate)
287adfc5217SJeff Kirsher {
288adfc5217SJeff Kirsher 	/* can take a while if any port is running */
289adfc5217SJeff Kirsher 	int cnt = 5000;
290adfc5217SJeff Kirsher 
291adfc5217SJeff Kirsher 	if (CHIP_REV_IS_EMUL(bp))
292adfc5217SJeff Kirsher 		cnt *= 20;
293adfc5217SJeff Kirsher 
294adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "waiting for state to become %d\n", state);
295adfc5217SJeff Kirsher 
296adfc5217SJeff Kirsher 	might_sleep();
297adfc5217SJeff Kirsher 	while (cnt--) {
298adfc5217SJeff Kirsher 		if (!test_bit(state, pstate)) {
299adfc5217SJeff Kirsher #ifdef BNX2X_STOP_ON_ERROR
300adfc5217SJeff Kirsher 			DP(BNX2X_MSG_SP, "exit  (cnt %d)\n", 5000 - cnt);
301adfc5217SJeff Kirsher #endif
302adfc5217SJeff Kirsher 			return 0;
303adfc5217SJeff Kirsher 		}
304adfc5217SJeff Kirsher 
3050926d499SYuval Mintz 		usleep_range(1000, 2000);
306adfc5217SJeff Kirsher 
307adfc5217SJeff Kirsher 		if (bp->panic)
308adfc5217SJeff Kirsher 			return -EIO;
309adfc5217SJeff Kirsher 	}
310adfc5217SJeff Kirsher 
311adfc5217SJeff Kirsher 	/* timeout! */
312adfc5217SJeff Kirsher 	BNX2X_ERR("timeout waiting for state %d\n", state);
313adfc5217SJeff Kirsher #ifdef BNX2X_STOP_ON_ERROR
314adfc5217SJeff Kirsher 	bnx2x_panic();
315adfc5217SJeff Kirsher #endif
316adfc5217SJeff Kirsher 
317adfc5217SJeff Kirsher 	return -EBUSY;
318adfc5217SJeff Kirsher }
319adfc5217SJeff Kirsher 
bnx2x_raw_wait(struct bnx2x * bp,struct bnx2x_raw_obj * raw)320adfc5217SJeff Kirsher static int bnx2x_raw_wait(struct bnx2x *bp, struct bnx2x_raw_obj *raw)
321adfc5217SJeff Kirsher {
322adfc5217SJeff Kirsher 	return bnx2x_state_wait(bp, raw->state, raw->pstate);
323adfc5217SJeff Kirsher }
324adfc5217SJeff Kirsher 
325adfc5217SJeff Kirsher /***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
326adfc5217SJeff Kirsher /* credit handling callbacks */
bnx2x_get_cam_offset_mac(struct bnx2x_vlan_mac_obj * o,int * offset)327adfc5217SJeff Kirsher static bool bnx2x_get_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int *offset)
328adfc5217SJeff Kirsher {
329adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
330adfc5217SJeff Kirsher 
331adfc5217SJeff Kirsher 	WARN_ON(!mp);
332adfc5217SJeff Kirsher 
333adfc5217SJeff Kirsher 	return mp->get_entry(mp, offset);
334adfc5217SJeff Kirsher }
335adfc5217SJeff Kirsher 
bnx2x_get_credit_mac(struct bnx2x_vlan_mac_obj * o)336adfc5217SJeff Kirsher static bool bnx2x_get_credit_mac(struct bnx2x_vlan_mac_obj *o)
337adfc5217SJeff Kirsher {
338adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
339adfc5217SJeff Kirsher 
340adfc5217SJeff Kirsher 	WARN_ON(!mp);
341adfc5217SJeff Kirsher 
342adfc5217SJeff Kirsher 	return mp->get(mp, 1);
343adfc5217SJeff Kirsher }
344adfc5217SJeff Kirsher 
bnx2x_get_cam_offset_vlan(struct bnx2x_vlan_mac_obj * o,int * offset)345adfc5217SJeff Kirsher static bool bnx2x_get_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int *offset)
346adfc5217SJeff Kirsher {
347adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
348adfc5217SJeff Kirsher 
349adfc5217SJeff Kirsher 	WARN_ON(!vp);
350adfc5217SJeff Kirsher 
351adfc5217SJeff Kirsher 	return vp->get_entry(vp, offset);
352adfc5217SJeff Kirsher }
353adfc5217SJeff Kirsher 
bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj * o)354adfc5217SJeff Kirsher static bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o)
355adfc5217SJeff Kirsher {
356adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
357adfc5217SJeff Kirsher 
358adfc5217SJeff Kirsher 	WARN_ON(!vp);
359adfc5217SJeff Kirsher 
360adfc5217SJeff Kirsher 	return vp->get(vp, 1);
361adfc5217SJeff Kirsher }
36205cc5a39SYuval Mintz 
bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj * o)36305cc5a39SYuval Mintz static bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
36405cc5a39SYuval Mintz {
36505cc5a39SYuval Mintz 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
36605cc5a39SYuval Mintz 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
36705cc5a39SYuval Mintz 
36805cc5a39SYuval Mintz 	if (!mp->get(mp, 1))
36905cc5a39SYuval Mintz 		return false;
37005cc5a39SYuval Mintz 
37105cc5a39SYuval Mintz 	if (!vp->get(vp, 1)) {
37205cc5a39SYuval Mintz 		mp->put(mp, 1);
37305cc5a39SYuval Mintz 		return false;
37405cc5a39SYuval Mintz 	}
37505cc5a39SYuval Mintz 
37605cc5a39SYuval Mintz 	return true;
37705cc5a39SYuval Mintz }
37805cc5a39SYuval Mintz 
bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj * o,int offset)379adfc5217SJeff Kirsher static bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset)
380adfc5217SJeff Kirsher {
381adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
382adfc5217SJeff Kirsher 
383adfc5217SJeff Kirsher 	return mp->put_entry(mp, offset);
384adfc5217SJeff Kirsher }
385adfc5217SJeff Kirsher 
bnx2x_put_credit_mac(struct bnx2x_vlan_mac_obj * o)386adfc5217SJeff Kirsher static bool bnx2x_put_credit_mac(struct bnx2x_vlan_mac_obj *o)
387adfc5217SJeff Kirsher {
388adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
389adfc5217SJeff Kirsher 
390adfc5217SJeff Kirsher 	return mp->put(mp, 1);
391adfc5217SJeff Kirsher }
392adfc5217SJeff Kirsher 
bnx2x_put_cam_offset_vlan(struct bnx2x_vlan_mac_obj * o,int offset)393adfc5217SJeff Kirsher static bool bnx2x_put_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int offset)
394adfc5217SJeff Kirsher {
395adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
396adfc5217SJeff Kirsher 
397adfc5217SJeff Kirsher 	return vp->put_entry(vp, offset);
398adfc5217SJeff Kirsher }
399adfc5217SJeff Kirsher 
bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj * o)400adfc5217SJeff Kirsher static bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o)
401adfc5217SJeff Kirsher {
402adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
403adfc5217SJeff Kirsher 
404adfc5217SJeff Kirsher 	return vp->put(vp, 1);
405adfc5217SJeff Kirsher }
406adfc5217SJeff Kirsher 
bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj * o)40705cc5a39SYuval Mintz static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
40805cc5a39SYuval Mintz {
40905cc5a39SYuval Mintz 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
41005cc5a39SYuval Mintz 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
41105cc5a39SYuval Mintz 
41205cc5a39SYuval Mintz 	if (!mp->put(mp, 1))
41305cc5a39SYuval Mintz 		return false;
41405cc5a39SYuval Mintz 
41505cc5a39SYuval Mintz 	if (!vp->put(vp, 1)) {
41605cc5a39SYuval Mintz 		mp->get(mp, 1);
41705cc5a39SYuval Mintz 		return false;
41805cc5a39SYuval Mintz 	}
41905cc5a39SYuval Mintz 
42005cc5a39SYuval Mintz 	return true;
42105cc5a39SYuval Mintz }
42205cc5a39SYuval Mintz 
4238b09be5fSYuval Mintz /**
4248b09be5fSYuval Mintz  * __bnx2x_vlan_mac_h_write_trylock - try getting the vlan mac writer lock
4258b09be5fSYuval Mintz  *
4268b09be5fSYuval Mintz  * @bp:		device handle
4278b09be5fSYuval Mintz  * @o:		vlan_mac object
4288b09be5fSYuval Mintz  *
429d0ea5cbdSJesse Brandeburg  * Context: Non-blocking implementation; should be called under execution
4308b09be5fSYuval Mintz  *          queue lock.
4318b09be5fSYuval Mintz  */
__bnx2x_vlan_mac_h_write_trylock(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o)4328b09be5fSYuval Mintz static int __bnx2x_vlan_mac_h_write_trylock(struct bnx2x *bp,
4338b09be5fSYuval Mintz 					    struct bnx2x_vlan_mac_obj *o)
4348b09be5fSYuval Mintz {
4358b09be5fSYuval Mintz 	if (o->head_reader) {
4368b09be5fSYuval Mintz 		DP(BNX2X_MSG_SP, "vlan_mac_lock writer - There are readers; Busy\n");
4378b09be5fSYuval Mintz 		return -EBUSY;
4388b09be5fSYuval Mintz 	}
4398b09be5fSYuval Mintz 
4408b09be5fSYuval Mintz 	DP(BNX2X_MSG_SP, "vlan_mac_lock writer - Taken\n");
4418b09be5fSYuval Mintz 	return 0;
4428b09be5fSYuval Mintz }
4438b09be5fSYuval Mintz 
4448b09be5fSYuval Mintz /**
4458b09be5fSYuval Mintz  * __bnx2x_vlan_mac_h_exec_pending - execute step instead of a previous step
4468b09be5fSYuval Mintz  *
4478b09be5fSYuval Mintz  * @bp:		device handle
4488b09be5fSYuval Mintz  * @o:		vlan_mac object
4498b09be5fSYuval Mintz  *
450d0ea5cbdSJesse Brandeburg  * details Should be called under execution queue lock; notice it might release
4518b09be5fSYuval Mintz  *          and reclaim it during its run.
4528b09be5fSYuval Mintz  */
__bnx2x_vlan_mac_h_exec_pending(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o)4538b09be5fSYuval Mintz static void __bnx2x_vlan_mac_h_exec_pending(struct bnx2x *bp,
4548b09be5fSYuval Mintz 					    struct bnx2x_vlan_mac_obj *o)
4558b09be5fSYuval Mintz {
4568b09be5fSYuval Mintz 	int rc;
4578b09be5fSYuval Mintz 	unsigned long ramrod_flags = o->saved_ramrod_flags;
4588b09be5fSYuval Mintz 
4598b09be5fSYuval Mintz 	DP(BNX2X_MSG_SP, "vlan_mac_lock execute pending command with ramrod flags %lu\n",
4608b09be5fSYuval Mintz 	   ramrod_flags);
4618b09be5fSYuval Mintz 	o->head_exe_request = false;
4628b09be5fSYuval Mintz 	o->saved_ramrod_flags = 0;
4638b09be5fSYuval Mintz 	rc = bnx2x_exe_queue_step(bp, &o->exe_queue, &ramrod_flags);
4649d18d270SYuval Mintz 	if ((rc != 0) && (rc != 1)) {
4658b09be5fSYuval Mintz 		BNX2X_ERR("execution of pending commands failed with rc %d\n",
4668b09be5fSYuval Mintz 			  rc);
4678b09be5fSYuval Mintz #ifdef BNX2X_STOP_ON_ERROR
4688b09be5fSYuval Mintz 		bnx2x_panic();
4698b09be5fSYuval Mintz #endif
4708b09be5fSYuval Mintz 	}
4718b09be5fSYuval Mintz }
4728b09be5fSYuval Mintz 
4738b09be5fSYuval Mintz /**
4748b09be5fSYuval Mintz  * __bnx2x_vlan_mac_h_pend - Pend an execution step which couldn't run
4758b09be5fSYuval Mintz  *
4768b09be5fSYuval Mintz  * @bp:			device handle
4778b09be5fSYuval Mintz  * @o:			vlan_mac object
4788b09be5fSYuval Mintz  * @ramrod_flags:	ramrod flags of missed execution
4798b09be5fSYuval Mintz  *
480d0ea5cbdSJesse Brandeburg  * Context: Should be called under execution queue lock.
4818b09be5fSYuval Mintz  */
__bnx2x_vlan_mac_h_pend(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,unsigned long ramrod_flags)4828b09be5fSYuval Mintz static void __bnx2x_vlan_mac_h_pend(struct bnx2x *bp,
4838b09be5fSYuval Mintz 				    struct bnx2x_vlan_mac_obj *o,
4848b09be5fSYuval Mintz 				    unsigned long ramrod_flags)
4858b09be5fSYuval Mintz {
4868b09be5fSYuval Mintz 	o->head_exe_request = true;
4878b09be5fSYuval Mintz 	o->saved_ramrod_flags = ramrod_flags;
4888b09be5fSYuval Mintz 	DP(BNX2X_MSG_SP, "Placing pending execution with ramrod flags %lu\n",
4898b09be5fSYuval Mintz 	   ramrod_flags);
4908b09be5fSYuval Mintz }
4918b09be5fSYuval Mintz 
4928b09be5fSYuval Mintz /**
4938b09be5fSYuval Mintz  * __bnx2x_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock
4948b09be5fSYuval Mintz  *
4958b09be5fSYuval Mintz  * @bp:			device handle
4968b09be5fSYuval Mintz  * @o:			vlan_mac object
4978b09be5fSYuval Mintz  *
498d0ea5cbdSJesse Brandeburg  * Context: Should be called under execution queue lock. Notice if a pending
4998b09be5fSYuval Mintz  *          execution exists, it would perform it - possibly releasing and
5008b09be5fSYuval Mintz  *          reclaiming the execution queue lock.
5018b09be5fSYuval Mintz  */
__bnx2x_vlan_mac_h_write_unlock(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o)5028b09be5fSYuval Mintz static void __bnx2x_vlan_mac_h_write_unlock(struct bnx2x *bp,
5038b09be5fSYuval Mintz 					    struct bnx2x_vlan_mac_obj *o)
5048b09be5fSYuval Mintz {
5058b09be5fSYuval Mintz 	/* It's possible a new pending execution was added since this writer
5068b09be5fSYuval Mintz 	 * executed. If so, execute again. [Ad infinitum]
5078b09be5fSYuval Mintz 	 */
5088b09be5fSYuval Mintz 	while (o->head_exe_request) {
5098b09be5fSYuval Mintz 		DP(BNX2X_MSG_SP, "vlan_mac_lock - writer release encountered a pending request\n");
5108b09be5fSYuval Mintz 		__bnx2x_vlan_mac_h_exec_pending(bp, o);
5118b09be5fSYuval Mintz 	}
5128b09be5fSYuval Mintz }
5138b09be5fSYuval Mintz 
5148b09be5fSYuval Mintz 
5158b09be5fSYuval Mintz /**
5168b09be5fSYuval Mintz  * __bnx2x_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
5178b09be5fSYuval Mintz  *
5188b09be5fSYuval Mintz  * @bp:			device handle
5198b09be5fSYuval Mintz  * @o:			vlan_mac object
5208b09be5fSYuval Mintz  *
521d0ea5cbdSJesse Brandeburg  * Context: Should be called under the execution queue lock. May sleep. May
5228b09be5fSYuval Mintz  *          release and reclaim execution queue lock during its run.
5238b09be5fSYuval Mintz  */
__bnx2x_vlan_mac_h_read_lock(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o)5248b09be5fSYuval Mintz static int __bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
5258b09be5fSYuval Mintz 					struct bnx2x_vlan_mac_obj *o)
5268b09be5fSYuval Mintz {
5278b09be5fSYuval Mintz 	/* If we got here, we're holding lock --> no WRITER exists */
5288b09be5fSYuval Mintz 	o->head_reader++;
5298b09be5fSYuval Mintz 	DP(BNX2X_MSG_SP, "vlan_mac_lock - locked reader - number %d\n",
5308b09be5fSYuval Mintz 	   o->head_reader);
5318b09be5fSYuval Mintz 
5328b09be5fSYuval Mintz 	return 0;
5338b09be5fSYuval Mintz }
5348b09be5fSYuval Mintz 
5358b09be5fSYuval Mintz /**
5368b09be5fSYuval Mintz  * bnx2x_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
5378b09be5fSYuval Mintz  *
5388b09be5fSYuval Mintz  * @bp:			device handle
5398b09be5fSYuval Mintz  * @o:			vlan_mac object
5408b09be5fSYuval Mintz  *
541d0ea5cbdSJesse Brandeburg  * Context: May sleep. Claims and releases execution queue lock during its run.
5428b09be5fSYuval Mintz  */
bnx2x_vlan_mac_h_read_lock(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o)5438b09be5fSYuval Mintz int bnx2x_vlan_mac_h_read_lock(struct bnx2x *bp,
5448b09be5fSYuval Mintz 			       struct bnx2x_vlan_mac_obj *o)
5458b09be5fSYuval Mintz {
5468b09be5fSYuval Mintz 	int rc;
5478b09be5fSYuval Mintz 
5488b09be5fSYuval Mintz 	spin_lock_bh(&o->exe_queue.lock);
5498b09be5fSYuval Mintz 	rc = __bnx2x_vlan_mac_h_read_lock(bp, o);
5508b09be5fSYuval Mintz 	spin_unlock_bh(&o->exe_queue.lock);
5518b09be5fSYuval Mintz 
5528b09be5fSYuval Mintz 	return rc;
5538b09be5fSYuval Mintz }
5548b09be5fSYuval Mintz 
5558b09be5fSYuval Mintz /**
5568b09be5fSYuval Mintz  * __bnx2x_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
5578b09be5fSYuval Mintz  *
5588b09be5fSYuval Mintz  * @bp:			device handle
5598b09be5fSYuval Mintz  * @o:			vlan_mac object
5608b09be5fSYuval Mintz  *
561d0ea5cbdSJesse Brandeburg  * Context: Should be called under execution queue lock. Notice if a pending
5628b09be5fSYuval Mintz  *          execution exists, it would be performed if this was the last
5638b09be5fSYuval Mintz  *          reader. possibly releasing and reclaiming the execution queue lock.
5648b09be5fSYuval Mintz  */
__bnx2x_vlan_mac_h_read_unlock(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o)5658b09be5fSYuval Mintz static void __bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
5668b09be5fSYuval Mintz 					  struct bnx2x_vlan_mac_obj *o)
5678b09be5fSYuval Mintz {
5688b09be5fSYuval Mintz 	if (!o->head_reader) {
5698b09be5fSYuval Mintz 		BNX2X_ERR("Need to release vlan mac reader lock, but lock isn't taken\n");
5708b09be5fSYuval Mintz #ifdef BNX2X_STOP_ON_ERROR
5718b09be5fSYuval Mintz 		bnx2x_panic();
5728b09be5fSYuval Mintz #endif
5738b09be5fSYuval Mintz 	} else {
5748b09be5fSYuval Mintz 		o->head_reader--;
5758b09be5fSYuval Mintz 		DP(BNX2X_MSG_SP, "vlan_mac_lock - decreased readers to %d\n",
5768b09be5fSYuval Mintz 		   o->head_reader);
5778b09be5fSYuval Mintz 	}
5788b09be5fSYuval Mintz 
5798b09be5fSYuval Mintz 	/* It's possible a new pending execution was added, and that this reader
5808b09be5fSYuval Mintz 	 * was last - if so we need to execute the command.
5818b09be5fSYuval Mintz 	 */
5828b09be5fSYuval Mintz 	if (!o->head_reader && o->head_exe_request) {
5838b09be5fSYuval Mintz 		DP(BNX2X_MSG_SP, "vlan_mac_lock - reader release encountered a pending request\n");
5848b09be5fSYuval Mintz 
5858b09be5fSYuval Mintz 		/* Writer release will do the trick */
5868b09be5fSYuval Mintz 		__bnx2x_vlan_mac_h_write_unlock(bp, o);
5878b09be5fSYuval Mintz 	}
5888b09be5fSYuval Mintz }
5898b09be5fSYuval Mintz 
5908b09be5fSYuval Mintz /**
5918b09be5fSYuval Mintz  * bnx2x_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
5928b09be5fSYuval Mintz  *
5938b09be5fSYuval Mintz  * @bp:			device handle
5948b09be5fSYuval Mintz  * @o:			vlan_mac object
5958b09be5fSYuval Mintz  *
596d0ea5cbdSJesse Brandeburg  * Context: Notice if a pending execution exists, it would be performed if this
5978b09be5fSYuval Mintz  *          was the last reader. Claims and releases the execution queue lock
5988b09be5fSYuval Mintz  *          during its run.
5998b09be5fSYuval Mintz  */
bnx2x_vlan_mac_h_read_unlock(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o)6008b09be5fSYuval Mintz void bnx2x_vlan_mac_h_read_unlock(struct bnx2x *bp,
6018b09be5fSYuval Mintz 				  struct bnx2x_vlan_mac_obj *o)
6028b09be5fSYuval Mintz {
6038b09be5fSYuval Mintz 	spin_lock_bh(&o->exe_queue.lock);
6048b09be5fSYuval Mintz 	__bnx2x_vlan_mac_h_read_unlock(bp, o);
6058b09be5fSYuval Mintz 	spin_unlock_bh(&o->exe_queue.lock);
6068b09be5fSYuval Mintz }
6078b09be5fSYuval Mintz 
bnx2x_get_n_elements(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,int n,u8 * base,u8 stride,u8 size)608ed5162a0SAriel Elior static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
6093ec9f9caSAriel Elior 				int n, u8 *base, u8 stride, u8 size)
610ed5162a0SAriel Elior {
611ed5162a0SAriel Elior 	struct bnx2x_vlan_mac_registry_elem *pos;
6123ec9f9caSAriel Elior 	u8 *next = base;
613ed5162a0SAriel Elior 	int counter = 0;
6148b09be5fSYuval Mintz 	int read_lock;
6158b09be5fSYuval Mintz 
6168b09be5fSYuval Mintz 	DP(BNX2X_MSG_SP, "get_n_elements - taking vlan_mac_lock (reader)\n");
6178b09be5fSYuval Mintz 	read_lock = bnx2x_vlan_mac_h_read_lock(bp, o);
6188b09be5fSYuval Mintz 	if (read_lock != 0)
6198b09be5fSYuval Mintz 		BNX2X_ERR("get_n_elements failed to get vlan mac reader lock; Access without lock\n");
620ed5162a0SAriel Elior 
621ed5162a0SAriel Elior 	/* traverse list */
622ed5162a0SAriel Elior 	list_for_each_entry(pos, &o->head, link) {
623ed5162a0SAriel Elior 		if (counter < n) {
6243ec9f9caSAriel Elior 			memcpy(next, &pos->u, size);
625ed5162a0SAriel Elior 			counter++;
6263ec9f9caSAriel Elior 			DP(BNX2X_MSG_SP, "copied element number %d to address %p element was:\n",
6273ec9f9caSAriel Elior 			   counter, next);
6283ec9f9caSAriel Elior 			next += stride + size;
629ed5162a0SAriel Elior 		}
630ed5162a0SAriel Elior 	}
6318b09be5fSYuval Mintz 
6328b09be5fSYuval Mintz 	if (read_lock == 0) {
6338b09be5fSYuval Mintz 		DP(BNX2X_MSG_SP, "get_n_elements - releasing vlan_mac_lock (reader)\n");
6348b09be5fSYuval Mintz 		bnx2x_vlan_mac_h_read_unlock(bp, o);
6358b09be5fSYuval Mintz 	}
6368b09be5fSYuval Mintz 
637ed5162a0SAriel Elior 	return counter * ETH_ALEN;
638ed5162a0SAriel Elior }
639ed5162a0SAriel Elior 
640adfc5217SJeff Kirsher /* check_add() callbacks */
bnx2x_check_mac_add(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,union bnx2x_classification_ramrod_data * data)64151c1a580SMerav Sicron static int bnx2x_check_mac_add(struct bnx2x *bp,
64251c1a580SMerav Sicron 			       struct bnx2x_vlan_mac_obj *o,
643adfc5217SJeff Kirsher 			       union bnx2x_classification_ramrod_data *data)
644adfc5217SJeff Kirsher {
645adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
646adfc5217SJeff Kirsher 
64751c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "Checking MAC %pM for ADD command\n", data->mac.mac);
64851c1a580SMerav Sicron 
649adfc5217SJeff Kirsher 	if (!is_valid_ether_addr(data->mac.mac))
650adfc5217SJeff Kirsher 		return -EINVAL;
651adfc5217SJeff Kirsher 
652adfc5217SJeff Kirsher 	/* Check if a requested MAC already exists */
653adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
6548fd90de8Sdingtianhong 		if (ether_addr_equal(data->mac.mac, pos->u.mac.mac) &&
65591226790SDmitry Kravkov 		    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
656adfc5217SJeff Kirsher 			return -EEXIST;
657adfc5217SJeff Kirsher 
658adfc5217SJeff Kirsher 	return 0;
659adfc5217SJeff Kirsher }
660adfc5217SJeff Kirsher 
bnx2x_check_vlan_add(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,union bnx2x_classification_ramrod_data * data)66151c1a580SMerav Sicron static int bnx2x_check_vlan_add(struct bnx2x *bp,
66251c1a580SMerav Sicron 				struct bnx2x_vlan_mac_obj *o,
663adfc5217SJeff Kirsher 				union bnx2x_classification_ramrod_data *data)
664adfc5217SJeff Kirsher {
665adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
666adfc5217SJeff Kirsher 
66751c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "Checking VLAN %d for ADD command\n", data->vlan.vlan);
66851c1a580SMerav Sicron 
669adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
670adfc5217SJeff Kirsher 		if (data->vlan.vlan == pos->u.vlan.vlan)
671adfc5217SJeff Kirsher 			return -EEXIST;
672adfc5217SJeff Kirsher 
673adfc5217SJeff Kirsher 	return 0;
674adfc5217SJeff Kirsher }
675adfc5217SJeff Kirsher 
bnx2x_check_vlan_mac_add(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,union bnx2x_classification_ramrod_data * data)67605cc5a39SYuval Mintz static int bnx2x_check_vlan_mac_add(struct bnx2x *bp,
67705cc5a39SYuval Mintz 				    struct bnx2x_vlan_mac_obj *o,
67805cc5a39SYuval Mintz 				   union bnx2x_classification_ramrod_data *data)
67905cc5a39SYuval Mintz {
68005cc5a39SYuval Mintz 	struct bnx2x_vlan_mac_registry_elem *pos;
68105cc5a39SYuval Mintz 
68205cc5a39SYuval Mintz 	DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for ADD command\n",
68305cc5a39SYuval Mintz 	   data->vlan_mac.mac, data->vlan_mac.vlan);
68405cc5a39SYuval Mintz 
68505cc5a39SYuval Mintz 	list_for_each_entry(pos, &o->head, link)
68605cc5a39SYuval Mintz 		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
68705cc5a39SYuval Mintz 		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
68805cc5a39SYuval Mintz 				  ETH_ALEN)) &&
68905cc5a39SYuval Mintz 		    (data->vlan_mac.is_inner_mac ==
69005cc5a39SYuval Mintz 		     pos->u.vlan_mac.is_inner_mac))
69105cc5a39SYuval Mintz 			return -EEXIST;
69205cc5a39SYuval Mintz 
69305cc5a39SYuval Mintz 	return 0;
69405cc5a39SYuval Mintz }
69505cc5a39SYuval Mintz 
696adfc5217SJeff Kirsher /* check_del() callbacks */
697adfc5217SJeff Kirsher static struct bnx2x_vlan_mac_registry_elem *
bnx2x_check_mac_del(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,union bnx2x_classification_ramrod_data * data)69851c1a580SMerav Sicron 	bnx2x_check_mac_del(struct bnx2x *bp,
69951c1a580SMerav Sicron 			    struct bnx2x_vlan_mac_obj *o,
700adfc5217SJeff Kirsher 			    union bnx2x_classification_ramrod_data *data)
701adfc5217SJeff Kirsher {
702adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
703adfc5217SJeff Kirsher 
70451c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "Checking MAC %pM for DEL command\n", data->mac.mac);
70551c1a580SMerav Sicron 
706adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
7078fd90de8Sdingtianhong 		if (ether_addr_equal(data->mac.mac, pos->u.mac.mac) &&
70891226790SDmitry Kravkov 		    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
709adfc5217SJeff Kirsher 			return pos;
710adfc5217SJeff Kirsher 
711adfc5217SJeff Kirsher 	return NULL;
712adfc5217SJeff Kirsher }
713adfc5217SJeff Kirsher 
714adfc5217SJeff Kirsher static struct bnx2x_vlan_mac_registry_elem *
bnx2x_check_vlan_del(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,union bnx2x_classification_ramrod_data * data)71551c1a580SMerav Sicron 	bnx2x_check_vlan_del(struct bnx2x *bp,
71651c1a580SMerav Sicron 			     struct bnx2x_vlan_mac_obj *o,
717adfc5217SJeff Kirsher 			     union bnx2x_classification_ramrod_data *data)
718adfc5217SJeff Kirsher {
719adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
720adfc5217SJeff Kirsher 
72151c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "Checking VLAN %d for DEL command\n", data->vlan.vlan);
72251c1a580SMerav Sicron 
723adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
724adfc5217SJeff Kirsher 		if (data->vlan.vlan == pos->u.vlan.vlan)
725adfc5217SJeff Kirsher 			return pos;
726adfc5217SJeff Kirsher 
727adfc5217SJeff Kirsher 	return NULL;
728adfc5217SJeff Kirsher }
729adfc5217SJeff Kirsher 
73005cc5a39SYuval Mintz static struct bnx2x_vlan_mac_registry_elem *
bnx2x_check_vlan_mac_del(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,union bnx2x_classification_ramrod_data * data)73105cc5a39SYuval Mintz 	bnx2x_check_vlan_mac_del(struct bnx2x *bp,
73205cc5a39SYuval Mintz 				 struct bnx2x_vlan_mac_obj *o,
73305cc5a39SYuval Mintz 				 union bnx2x_classification_ramrod_data *data)
73405cc5a39SYuval Mintz {
73505cc5a39SYuval Mintz 	struct bnx2x_vlan_mac_registry_elem *pos;
73605cc5a39SYuval Mintz 
73705cc5a39SYuval Mintz 	DP(BNX2X_MSG_SP, "Checking VLAN_MAC (%pM, %d) for DEL command\n",
73805cc5a39SYuval Mintz 	   data->vlan_mac.mac, data->vlan_mac.vlan);
73905cc5a39SYuval Mintz 
74005cc5a39SYuval Mintz 	list_for_each_entry(pos, &o->head, link)
74105cc5a39SYuval Mintz 		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
74205cc5a39SYuval Mintz 		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
74305cc5a39SYuval Mintz 			     ETH_ALEN)) &&
74405cc5a39SYuval Mintz 		    (data->vlan_mac.is_inner_mac ==
74505cc5a39SYuval Mintz 		     pos->u.vlan_mac.is_inner_mac))
74605cc5a39SYuval Mintz 			return pos;
74705cc5a39SYuval Mintz 
74805cc5a39SYuval Mintz 	return NULL;
74905cc5a39SYuval Mintz }
75005cc5a39SYuval Mintz 
751adfc5217SJeff Kirsher /* check_move() callback */
bnx2x_check_move(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * src_o,struct bnx2x_vlan_mac_obj * dst_o,union bnx2x_classification_ramrod_data * data)75251c1a580SMerav Sicron static bool bnx2x_check_move(struct bnx2x *bp,
75351c1a580SMerav Sicron 			     struct bnx2x_vlan_mac_obj *src_o,
754adfc5217SJeff Kirsher 			     struct bnx2x_vlan_mac_obj *dst_o,
755adfc5217SJeff Kirsher 			     union bnx2x_classification_ramrod_data *data)
756adfc5217SJeff Kirsher {
757adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
758adfc5217SJeff Kirsher 	int rc;
759adfc5217SJeff Kirsher 
760adfc5217SJeff Kirsher 	/* Check if we can delete the requested configuration from the first
761adfc5217SJeff Kirsher 	 * object.
762adfc5217SJeff Kirsher 	 */
76351c1a580SMerav Sicron 	pos = src_o->check_del(bp, src_o, data);
764adfc5217SJeff Kirsher 
765adfc5217SJeff Kirsher 	/*  check if configuration can be added */
76651c1a580SMerav Sicron 	rc = dst_o->check_add(bp, dst_o, data);
767adfc5217SJeff Kirsher 
768adfc5217SJeff Kirsher 	/* If this classification can not be added (is already set)
769adfc5217SJeff Kirsher 	 * or can't be deleted - return an error.
770adfc5217SJeff Kirsher 	 */
771adfc5217SJeff Kirsher 	if (rc || !pos)
772adfc5217SJeff Kirsher 		return false;
773adfc5217SJeff Kirsher 
774adfc5217SJeff Kirsher 	return true;
775adfc5217SJeff Kirsher }
776adfc5217SJeff Kirsher 
bnx2x_check_move_always_err(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * src_o,struct bnx2x_vlan_mac_obj * dst_o,union bnx2x_classification_ramrod_data * data)777adfc5217SJeff Kirsher static bool bnx2x_check_move_always_err(
77851c1a580SMerav Sicron 	struct bnx2x *bp,
779adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *src_o,
780adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *dst_o,
781adfc5217SJeff Kirsher 	union bnx2x_classification_ramrod_data *data)
782adfc5217SJeff Kirsher {
783adfc5217SJeff Kirsher 	return false;
784adfc5217SJeff Kirsher }
785adfc5217SJeff Kirsher 
bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj * o)786adfc5217SJeff Kirsher static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
787adfc5217SJeff Kirsher {
788adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
789adfc5217SJeff Kirsher 	u8 rx_tx_flag = 0;
790adfc5217SJeff Kirsher 
791adfc5217SJeff Kirsher 	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
792adfc5217SJeff Kirsher 	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
793adfc5217SJeff Kirsher 		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD;
794adfc5217SJeff Kirsher 
795adfc5217SJeff Kirsher 	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
796adfc5217SJeff Kirsher 	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
797adfc5217SJeff Kirsher 		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD;
798adfc5217SJeff Kirsher 
799adfc5217SJeff Kirsher 	return rx_tx_flag;
800adfc5217SJeff Kirsher }
801adfc5217SJeff Kirsher 
bnx2x_set_mac_in_nig(struct bnx2x * bp,bool add,unsigned char * dev_addr,int index)802a8f47eb7Sstephen hemminger static void bnx2x_set_mac_in_nig(struct bnx2x *bp,
803adfc5217SJeff Kirsher 				 bool add, unsigned char *dev_addr, int index)
804adfc5217SJeff Kirsher {
805adfc5217SJeff Kirsher 	u32 wb_data[2];
806adfc5217SJeff Kirsher 	u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
807adfc5217SJeff Kirsher 			 NIG_REG_LLH0_FUNC_MEM;
808adfc5217SJeff Kirsher 
809a3348722SBarak Witkowski 	if (!IS_MF_SI(bp) && !IS_MF_AFEX(bp))
810a3348722SBarak Witkowski 		return;
811a3348722SBarak Witkowski 
812a3348722SBarak Witkowski 	if (index > BNX2X_LLH_CAM_MAX_PF_LINE)
813adfc5217SJeff Kirsher 		return;
814adfc5217SJeff Kirsher 
815adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Going to %s LLH configuration at entry %d\n",
816adfc5217SJeff Kirsher 			 (add ? "ADD" : "DELETE"), index);
817adfc5217SJeff Kirsher 
818adfc5217SJeff Kirsher 	if (add) {
819adfc5217SJeff Kirsher 		/* LLH_FUNC_MEM is a u64 WB register */
820adfc5217SJeff Kirsher 		reg_offset += 8*index;
821adfc5217SJeff Kirsher 
822adfc5217SJeff Kirsher 		wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
823adfc5217SJeff Kirsher 			      (dev_addr[4] <<  8) |  dev_addr[5]);
824adfc5217SJeff Kirsher 		wb_data[1] = ((dev_addr[0] <<  8) |  dev_addr[1]);
825adfc5217SJeff Kirsher 
826adfc5217SJeff Kirsher 		REG_WR_DMAE(bp, reg_offset, wb_data, 2);
827adfc5217SJeff Kirsher 	}
828adfc5217SJeff Kirsher 
829adfc5217SJeff Kirsher 	REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
830adfc5217SJeff Kirsher 				  NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*index, add);
831adfc5217SJeff Kirsher }
832adfc5217SJeff Kirsher 
833adfc5217SJeff Kirsher /**
834adfc5217SJeff Kirsher  * bnx2x_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod
835adfc5217SJeff Kirsher  *
836adfc5217SJeff Kirsher  * @bp:		device handle
837adfc5217SJeff Kirsher  * @o:		queue for which we want to configure this rule
838adfc5217SJeff Kirsher  * @add:	if true the command is an ADD command, DEL otherwise
839adfc5217SJeff Kirsher  * @opcode:	CLASSIFY_RULE_OPCODE_XXX
840adfc5217SJeff Kirsher  * @hdr:	pointer to a header to setup
841adfc5217SJeff Kirsher  *
842adfc5217SJeff Kirsher  */
bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,bool add,int opcode,struct eth_classify_cmd_header * hdr)843adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp,
844adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o, bool add, int opcode,
845adfc5217SJeff Kirsher 	struct eth_classify_cmd_header *hdr)
846adfc5217SJeff Kirsher {
847adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
848adfc5217SJeff Kirsher 
849adfc5217SJeff Kirsher 	hdr->client_id = raw->cl_id;
850adfc5217SJeff Kirsher 	hdr->func_id = raw->func_id;
851adfc5217SJeff Kirsher 
852adfc5217SJeff Kirsher 	/* Rx or/and Tx (internal switching) configuration ? */
853adfc5217SJeff Kirsher 	hdr->cmd_general_data |=
854adfc5217SJeff Kirsher 		bnx2x_vlan_mac_get_rx_tx_flag(o);
855adfc5217SJeff Kirsher 
856adfc5217SJeff Kirsher 	if (add)
857adfc5217SJeff Kirsher 		hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD;
858adfc5217SJeff Kirsher 
859adfc5217SJeff Kirsher 	hdr->cmd_general_data |=
860adfc5217SJeff Kirsher 		(opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT);
861adfc5217SJeff Kirsher }
862adfc5217SJeff Kirsher 
863adfc5217SJeff Kirsher /**
864adfc5217SJeff Kirsher  * bnx2x_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header
865adfc5217SJeff Kirsher  *
866adfc5217SJeff Kirsher  * @cid:	connection id
867adfc5217SJeff Kirsher  * @type:	BNX2X_FILTER_XXX_PENDING
86816a5fd92SYuval Mintz  * @hdr:	pointer to header to setup
869adfc5217SJeff Kirsher  * @rule_cnt:
870adfc5217SJeff Kirsher  *
871adfc5217SJeff Kirsher  * currently we always configure one rule and echo field to contain a CID and an
872adfc5217SJeff Kirsher  * opcode type.
873adfc5217SJeff Kirsher  */
bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid,int type,struct eth_classify_header * hdr,int rule_cnt)874adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type,
875adfc5217SJeff Kirsher 				struct eth_classify_header *hdr, int rule_cnt)
876adfc5217SJeff Kirsher {
87786564c3fSYuval Mintz 	hdr->echo = cpu_to_le32((cid & BNX2X_SWCID_MASK) |
87886564c3fSYuval Mintz 				(type << BNX2X_SWCID_SHIFT));
879adfc5217SJeff Kirsher 	hdr->rule_cnt = (u8)rule_cnt;
880adfc5217SJeff Kirsher }
881adfc5217SJeff Kirsher 
882adfc5217SJeff Kirsher /* hw_config() callbacks */
bnx2x_set_one_mac_e2(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,struct bnx2x_exeq_elem * elem,int rule_idx,int cam_offset)883adfc5217SJeff Kirsher static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
884adfc5217SJeff Kirsher 				 struct bnx2x_vlan_mac_obj *o,
885adfc5217SJeff Kirsher 				 struct bnx2x_exeq_elem *elem, int rule_idx,
886adfc5217SJeff Kirsher 				 int cam_offset)
887adfc5217SJeff Kirsher {
888adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
889adfc5217SJeff Kirsher 	struct eth_classify_rules_ramrod_data *data =
890adfc5217SJeff Kirsher 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
891adfc5217SJeff Kirsher 	int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd;
892adfc5217SJeff Kirsher 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
893*ae336f30SRuan Jinjie 	bool add = cmd == BNX2X_VLAN_MAC_ADD;
894adfc5217SJeff Kirsher 	unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags;
895adfc5217SJeff Kirsher 	u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac;
896adfc5217SJeff Kirsher 
89716a5fd92SYuval Mintz 	/* Set LLH CAM entry: currently only iSCSI and ETH macs are
898adfc5217SJeff Kirsher 	 * relevant. In addition, current implementation is tuned for a
899adfc5217SJeff Kirsher 	 * single ETH MAC.
900adfc5217SJeff Kirsher 	 *
901adfc5217SJeff Kirsher 	 * When multiple unicast ETH MACs PF configuration in switch
902adfc5217SJeff Kirsher 	 * independent mode is required (NetQ, multiple netdev MACs,
903adfc5217SJeff Kirsher 	 * etc.), consider better utilisation of 8 per function MAC
904adfc5217SJeff Kirsher 	 * entries in the LLH register. There is also
905adfc5217SJeff Kirsher 	 * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the
906adfc5217SJeff Kirsher 	 * total number of CAM entries to 16.
907adfc5217SJeff Kirsher 	 *
908adfc5217SJeff Kirsher 	 * Currently we won't configure NIG for MACs other than a primary ETH
909adfc5217SJeff Kirsher 	 * MAC and iSCSI L2 MAC.
910adfc5217SJeff Kirsher 	 *
911adfc5217SJeff Kirsher 	 * If this MAC is moving from one Queue to another, no need to change
912adfc5217SJeff Kirsher 	 * NIG configuration.
913adfc5217SJeff Kirsher 	 */
914adfc5217SJeff Kirsher 	if (cmd != BNX2X_VLAN_MAC_MOVE) {
915adfc5217SJeff Kirsher 		if (test_bit(BNX2X_ISCSI_ETH_MAC, vlan_mac_flags))
916adfc5217SJeff Kirsher 			bnx2x_set_mac_in_nig(bp, add, mac,
9170a52fd01SYuval Mintz 					     BNX2X_LLH_CAM_ISCSI_ETH_LINE);
918adfc5217SJeff Kirsher 		else if (test_bit(BNX2X_ETH_MAC, vlan_mac_flags))
9190a52fd01SYuval Mintz 			bnx2x_set_mac_in_nig(bp, add, mac,
9200a52fd01SYuval Mintz 					     BNX2X_LLH_CAM_ETH_LINE);
921adfc5217SJeff Kirsher 	}
922adfc5217SJeff Kirsher 
923adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer for the first rule */
924adfc5217SJeff Kirsher 	if (rule_idx == 0)
925adfc5217SJeff Kirsher 		memset(data, 0, sizeof(*data));
926adfc5217SJeff Kirsher 
927adfc5217SJeff Kirsher 	/* Setup a command header */
928adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_MAC,
929adfc5217SJeff Kirsher 				      &rule_entry->mac.header);
930adfc5217SJeff Kirsher 
9310f9dad10SJoe Perches 	DP(BNX2X_MSG_SP, "About to %s MAC %pM for Queue %d\n",
93251c1a580SMerav Sicron 	   (add ? "add" : "delete"), mac, raw->cl_id);
933adfc5217SJeff Kirsher 
934adfc5217SJeff Kirsher 	/* Set a MAC itself */
935adfc5217SJeff Kirsher 	bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
936adfc5217SJeff Kirsher 			      &rule_entry->mac.mac_mid,
937adfc5217SJeff Kirsher 			      &rule_entry->mac.mac_lsb, mac);
93891226790SDmitry Kravkov 	rule_entry->mac.inner_mac =
93991226790SDmitry Kravkov 		cpu_to_le16(elem->cmd_data.vlan_mac.u.mac.is_inner_mac);
940adfc5217SJeff Kirsher 
941adfc5217SJeff Kirsher 	/* MOVE: Add a rule that will add this MAC to the target Queue */
942adfc5217SJeff Kirsher 	if (cmd == BNX2X_VLAN_MAC_MOVE) {
943adfc5217SJeff Kirsher 		rule_entry++;
944adfc5217SJeff Kirsher 		rule_cnt++;
945adfc5217SJeff Kirsher 
946adfc5217SJeff Kirsher 		/* Setup ramrod data */
947adfc5217SJeff Kirsher 		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
948adfc5217SJeff Kirsher 					elem->cmd_data.vlan_mac.target_obj,
949adfc5217SJeff Kirsher 					      true, CLASSIFY_RULE_OPCODE_MAC,
950adfc5217SJeff Kirsher 					      &rule_entry->mac.header);
951adfc5217SJeff Kirsher 
952adfc5217SJeff Kirsher 		/* Set a MAC itself */
953adfc5217SJeff Kirsher 		bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
954adfc5217SJeff Kirsher 				      &rule_entry->mac.mac_mid,
955adfc5217SJeff Kirsher 				      &rule_entry->mac.mac_lsb, mac);
95691226790SDmitry Kravkov 		rule_entry->mac.inner_mac =
95791226790SDmitry Kravkov 			cpu_to_le16(elem->cmd_data.vlan_mac.
95891226790SDmitry Kravkov 						u.mac.is_inner_mac);
959adfc5217SJeff Kirsher 	}
960adfc5217SJeff Kirsher 
961adfc5217SJeff Kirsher 	/* Set the ramrod data header */
962adfc5217SJeff Kirsher 	/* TODO: take this to the higher level in order to prevent multiple
963adfc5217SJeff Kirsher 		 writing */
964adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
965adfc5217SJeff Kirsher 					rule_cnt);
966adfc5217SJeff Kirsher }
967adfc5217SJeff Kirsher 
968adfc5217SJeff Kirsher /**
969adfc5217SJeff Kirsher  * bnx2x_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod
970adfc5217SJeff Kirsher  *
971adfc5217SJeff Kirsher  * @bp:		device handle
972adfc5217SJeff Kirsher  * @o:		queue
973d0ea5cbdSJesse Brandeburg  * @type:	the type of echo
974adfc5217SJeff Kirsher  * @cam_offset:	offset in cam memory
975adfc5217SJeff Kirsher  * @hdr:	pointer to a header to setup
976adfc5217SJeff Kirsher  *
977adfc5217SJeff Kirsher  * E1/E1H
978adfc5217SJeff Kirsher  */
bnx2x_vlan_mac_set_rdata_hdr_e1x(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,int type,int cam_offset,struct mac_configuration_hdr * hdr)979adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_rdata_hdr_e1x(struct bnx2x *bp,
980adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset,
981adfc5217SJeff Kirsher 	struct mac_configuration_hdr *hdr)
982adfc5217SJeff Kirsher {
983adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
984adfc5217SJeff Kirsher 
985adfc5217SJeff Kirsher 	hdr->length = 1;
986adfc5217SJeff Kirsher 	hdr->offset = (u8)cam_offset;
98786564c3fSYuval Mintz 	hdr->client_id = cpu_to_le16(0xff);
98886564c3fSYuval Mintz 	hdr->echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) |
98986564c3fSYuval Mintz 				(type << BNX2X_SWCID_SHIFT));
990adfc5217SJeff Kirsher }
991adfc5217SJeff Kirsher 
bnx2x_vlan_mac_set_cfg_entry_e1x(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,bool add,int opcode,u8 * mac,u16 vlan_id,struct mac_configuration_entry * cfg_entry)992adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_cfg_entry_e1x(struct bnx2x *bp,
993adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o, bool add, int opcode, u8 *mac,
994adfc5217SJeff Kirsher 	u16 vlan_id, struct mac_configuration_entry *cfg_entry)
995adfc5217SJeff Kirsher {
996adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
997adfc5217SJeff Kirsher 	u32 cl_bit_vec = (1 << r->cl_id);
998adfc5217SJeff Kirsher 
999adfc5217SJeff Kirsher 	cfg_entry->clients_bit_vector = cpu_to_le32(cl_bit_vec);
1000adfc5217SJeff Kirsher 	cfg_entry->pf_id = r->func_id;
1001adfc5217SJeff Kirsher 	cfg_entry->vlan_id = cpu_to_le16(vlan_id);
1002adfc5217SJeff Kirsher 
1003adfc5217SJeff Kirsher 	if (add) {
1004adfc5217SJeff Kirsher 		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
1005adfc5217SJeff Kirsher 			 T_ETH_MAC_COMMAND_SET);
1006adfc5217SJeff Kirsher 		SET_FLAG(cfg_entry->flags,
1007adfc5217SJeff Kirsher 			 MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE, opcode);
1008adfc5217SJeff Kirsher 
1009adfc5217SJeff Kirsher 		/* Set a MAC in a ramrod data */
1010adfc5217SJeff Kirsher 		bnx2x_set_fw_mac_addr(&cfg_entry->msb_mac_addr,
1011adfc5217SJeff Kirsher 				      &cfg_entry->middle_mac_addr,
1012adfc5217SJeff Kirsher 				      &cfg_entry->lsb_mac_addr, mac);
1013adfc5217SJeff Kirsher 	} else
1014adfc5217SJeff Kirsher 		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
1015adfc5217SJeff Kirsher 			 T_ETH_MAC_COMMAND_INVALIDATE);
1016adfc5217SJeff Kirsher }
1017adfc5217SJeff Kirsher 
bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,int type,int cam_offset,bool add,u8 * mac,u16 vlan_id,int opcode,struct mac_configuration_cmd * config)1018adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp,
1019adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset, bool add,
1020adfc5217SJeff Kirsher 	u8 *mac, u16 vlan_id, int opcode, struct mac_configuration_cmd *config)
1021adfc5217SJeff Kirsher {
1022adfc5217SJeff Kirsher 	struct mac_configuration_entry *cfg_entry = &config->config_table[0];
1023adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
1024adfc5217SJeff Kirsher 
1025adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_rdata_hdr_e1x(bp, o, type, cam_offset,
1026adfc5217SJeff Kirsher 					 &config->hdr);
1027adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_cfg_entry_e1x(bp, o, add, opcode, mac, vlan_id,
1028adfc5217SJeff Kirsher 					 cfg_entry);
1029adfc5217SJeff Kirsher 
10300f9dad10SJoe Perches 	DP(BNX2X_MSG_SP, "%s MAC %pM CLID %d CAM offset %d\n",
103151c1a580SMerav Sicron 			 (add ? "setting" : "clearing"),
10320f9dad10SJoe Perches 			 mac, raw->cl_id, cam_offset);
1033adfc5217SJeff Kirsher }
1034adfc5217SJeff Kirsher 
1035adfc5217SJeff Kirsher /**
1036adfc5217SJeff Kirsher  * bnx2x_set_one_mac_e1x - fill a single MAC rule ramrod data
1037adfc5217SJeff Kirsher  *
1038adfc5217SJeff Kirsher  * @bp:		device handle
1039adfc5217SJeff Kirsher  * @o:		bnx2x_vlan_mac_obj
1040adfc5217SJeff Kirsher  * @elem:	bnx2x_exeq_elem
1041adfc5217SJeff Kirsher  * @rule_idx:	rule_idx
1042adfc5217SJeff Kirsher  * @cam_offset: cam_offset
1043adfc5217SJeff Kirsher  */
bnx2x_set_one_mac_e1x(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,struct bnx2x_exeq_elem * elem,int rule_idx,int cam_offset)1044adfc5217SJeff Kirsher static void bnx2x_set_one_mac_e1x(struct bnx2x *bp,
1045adfc5217SJeff Kirsher 				  struct bnx2x_vlan_mac_obj *o,
1046adfc5217SJeff Kirsher 				  struct bnx2x_exeq_elem *elem, int rule_idx,
1047adfc5217SJeff Kirsher 				  int cam_offset)
1048adfc5217SJeff Kirsher {
1049adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
1050adfc5217SJeff Kirsher 	struct mac_configuration_cmd *config =
1051adfc5217SJeff Kirsher 		(struct mac_configuration_cmd *)(raw->rdata);
105216a5fd92SYuval Mintz 	/* 57710 and 57711 do not support MOVE command,
1053adfc5217SJeff Kirsher 	 * so it's either ADD or DEL
1054adfc5217SJeff Kirsher 	 */
1055adfc5217SJeff Kirsher 	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
1056adfc5217SJeff Kirsher 		true : false;
1057adfc5217SJeff Kirsher 
1058adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer */
1059adfc5217SJeff Kirsher 	memset(config, 0, sizeof(*config));
1060adfc5217SJeff Kirsher 
106133ac338cSYuval Mintz 	bnx2x_vlan_mac_set_rdata_e1x(bp, o, raw->state,
1062adfc5217SJeff Kirsher 				     cam_offset, add,
1063adfc5217SJeff Kirsher 				     elem->cmd_data.vlan_mac.u.mac.mac, 0,
1064adfc5217SJeff Kirsher 				     ETH_VLAN_FILTER_ANY_VLAN, config);
1065adfc5217SJeff Kirsher }
1066adfc5217SJeff Kirsher 
bnx2x_set_one_vlan_e2(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,struct bnx2x_exeq_elem * elem,int rule_idx,int cam_offset)1067adfc5217SJeff Kirsher static void bnx2x_set_one_vlan_e2(struct bnx2x *bp,
1068adfc5217SJeff Kirsher 				  struct bnx2x_vlan_mac_obj *o,
1069adfc5217SJeff Kirsher 				  struct bnx2x_exeq_elem *elem, int rule_idx,
1070adfc5217SJeff Kirsher 				  int cam_offset)
1071adfc5217SJeff Kirsher {
1072adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
1073adfc5217SJeff Kirsher 	struct eth_classify_rules_ramrod_data *data =
1074adfc5217SJeff Kirsher 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
1075adfc5217SJeff Kirsher 	int rule_cnt = rule_idx + 1;
1076adfc5217SJeff Kirsher 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
107786564c3fSYuval Mintz 	enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
1078*ae336f30SRuan Jinjie 	bool add = cmd == BNX2X_VLAN_MAC_ADD;
1079adfc5217SJeff Kirsher 	u16 vlan = elem->cmd_data.vlan_mac.u.vlan.vlan;
1080adfc5217SJeff Kirsher 
1081adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer for the first rule */
1082adfc5217SJeff Kirsher 	if (rule_idx == 0)
1083adfc5217SJeff Kirsher 		memset(data, 0, sizeof(*data));
1084adfc5217SJeff Kirsher 
1085adfc5217SJeff Kirsher 	/* Set a rule header */
1086adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_VLAN,
1087adfc5217SJeff Kirsher 				      &rule_entry->vlan.header);
1088adfc5217SJeff Kirsher 
1089adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "About to %s VLAN %d\n", (add ? "add" : "delete"),
1090adfc5217SJeff Kirsher 			 vlan);
1091adfc5217SJeff Kirsher 
1092adfc5217SJeff Kirsher 	/* Set a VLAN itself */
1093adfc5217SJeff Kirsher 	rule_entry->vlan.vlan = cpu_to_le16(vlan);
1094adfc5217SJeff Kirsher 
1095adfc5217SJeff Kirsher 	/* MOVE: Add a rule that will add this MAC to the target Queue */
1096adfc5217SJeff Kirsher 	if (cmd == BNX2X_VLAN_MAC_MOVE) {
1097adfc5217SJeff Kirsher 		rule_entry++;
1098adfc5217SJeff Kirsher 		rule_cnt++;
1099adfc5217SJeff Kirsher 
1100adfc5217SJeff Kirsher 		/* Setup ramrod data */
1101adfc5217SJeff Kirsher 		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
1102adfc5217SJeff Kirsher 					elem->cmd_data.vlan_mac.target_obj,
1103adfc5217SJeff Kirsher 					      true, CLASSIFY_RULE_OPCODE_VLAN,
1104adfc5217SJeff Kirsher 					      &rule_entry->vlan.header);
1105adfc5217SJeff Kirsher 
1106adfc5217SJeff Kirsher 		/* Set a VLAN itself */
1107adfc5217SJeff Kirsher 		rule_entry->vlan.vlan = cpu_to_le16(vlan);
1108adfc5217SJeff Kirsher 	}
1109adfc5217SJeff Kirsher 
1110adfc5217SJeff Kirsher 	/* Set the ramrod data header */
1111adfc5217SJeff Kirsher 	/* TODO: take this to the higher level in order to prevent multiple
1112adfc5217SJeff Kirsher 		 writing */
1113adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
1114adfc5217SJeff Kirsher 					rule_cnt);
1115adfc5217SJeff Kirsher }
1116adfc5217SJeff Kirsher 
bnx2x_set_one_vlan_mac_e2(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,struct bnx2x_exeq_elem * elem,int rule_idx,int cam_offset)111705cc5a39SYuval Mintz static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
111805cc5a39SYuval Mintz 				      struct bnx2x_vlan_mac_obj *o,
111905cc5a39SYuval Mintz 				      struct bnx2x_exeq_elem *elem,
112005cc5a39SYuval Mintz 				      int rule_idx, int cam_offset)
112105cc5a39SYuval Mintz {
112205cc5a39SYuval Mintz 	struct bnx2x_raw_obj *raw = &o->raw;
112305cc5a39SYuval Mintz 	struct eth_classify_rules_ramrod_data *data =
112405cc5a39SYuval Mintz 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
112505cc5a39SYuval Mintz 	int rule_cnt = rule_idx + 1;
112605cc5a39SYuval Mintz 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
112705cc5a39SYuval Mintz 	enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
1128*ae336f30SRuan Jinjie 	bool add = cmd == BNX2X_VLAN_MAC_ADD;
112905cc5a39SYuval Mintz 	u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
113005cc5a39SYuval Mintz 	u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
113105cc5a39SYuval Mintz 	u16 inner_mac;
113205cc5a39SYuval Mintz 
113305cc5a39SYuval Mintz 	/* Reset the ramrod data buffer for the first rule */
113405cc5a39SYuval Mintz 	if (rule_idx == 0)
113505cc5a39SYuval Mintz 		memset(data, 0, sizeof(*data));
113605cc5a39SYuval Mintz 
113705cc5a39SYuval Mintz 	/* Set a rule header */
113805cc5a39SYuval Mintz 	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
113905cc5a39SYuval Mintz 				      &rule_entry->pair.header);
114005cc5a39SYuval Mintz 
114105cc5a39SYuval Mintz 	/* Set VLAN and MAC themselves */
114205cc5a39SYuval Mintz 	rule_entry->pair.vlan = cpu_to_le16(vlan);
114305cc5a39SYuval Mintz 	bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
114405cc5a39SYuval Mintz 			      &rule_entry->pair.mac_mid,
114505cc5a39SYuval Mintz 			      &rule_entry->pair.mac_lsb, mac);
114605cc5a39SYuval Mintz 	inner_mac = elem->cmd_data.vlan_mac.u.vlan_mac.is_inner_mac;
114705cc5a39SYuval Mintz 	rule_entry->pair.inner_mac = cpu_to_le16(inner_mac);
114805cc5a39SYuval Mintz 	/* MOVE: Add a rule that will add this MAC/VLAN to the target Queue */
114905cc5a39SYuval Mintz 	if (cmd == BNX2X_VLAN_MAC_MOVE) {
115005cc5a39SYuval Mintz 		struct bnx2x_vlan_mac_obj *target_obj;
115105cc5a39SYuval Mintz 
115205cc5a39SYuval Mintz 		rule_entry++;
115305cc5a39SYuval Mintz 		rule_cnt++;
115405cc5a39SYuval Mintz 
115505cc5a39SYuval Mintz 		/* Setup ramrod data */
115605cc5a39SYuval Mintz 		target_obj = elem->cmd_data.vlan_mac.target_obj;
115705cc5a39SYuval Mintz 		bnx2x_vlan_mac_set_cmd_hdr_e2(bp, target_obj,
115805cc5a39SYuval Mintz 					      true, CLASSIFY_RULE_OPCODE_PAIR,
115905cc5a39SYuval Mintz 					      &rule_entry->pair.header);
116005cc5a39SYuval Mintz 
116105cc5a39SYuval Mintz 		/* Set a VLAN itself */
116205cc5a39SYuval Mintz 		rule_entry->pair.vlan = cpu_to_le16(vlan);
116305cc5a39SYuval Mintz 		bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
116405cc5a39SYuval Mintz 				      &rule_entry->pair.mac_mid,
116505cc5a39SYuval Mintz 				      &rule_entry->pair.mac_lsb, mac);
116605cc5a39SYuval Mintz 		rule_entry->pair.inner_mac = cpu_to_le16(inner_mac);
116705cc5a39SYuval Mintz 	}
116805cc5a39SYuval Mintz 
116905cc5a39SYuval Mintz 	/* Set the ramrod data header */
117005cc5a39SYuval Mintz 	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
117105cc5a39SYuval Mintz 					rule_cnt);
117205cc5a39SYuval Mintz }
117305cc5a39SYuval Mintz 
117405cc5a39SYuval Mintz /**
117505cc5a39SYuval Mintz  * bnx2x_set_one_vlan_mac_e1h -
117605cc5a39SYuval Mintz  *
117705cc5a39SYuval Mintz  * @bp:		device handle
117805cc5a39SYuval Mintz  * @o:		bnx2x_vlan_mac_obj
117905cc5a39SYuval Mintz  * @elem:	bnx2x_exeq_elem
118005cc5a39SYuval Mintz  * @rule_idx:	rule_idx
118105cc5a39SYuval Mintz  * @cam_offset:	cam_offset
118205cc5a39SYuval Mintz  */
bnx2x_set_one_vlan_mac_e1h(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,struct bnx2x_exeq_elem * elem,int rule_idx,int cam_offset)118305cc5a39SYuval Mintz static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
118405cc5a39SYuval Mintz 				       struct bnx2x_vlan_mac_obj *o,
118505cc5a39SYuval Mintz 				       struct bnx2x_exeq_elem *elem,
118605cc5a39SYuval Mintz 				       int rule_idx, int cam_offset)
118705cc5a39SYuval Mintz {
118805cc5a39SYuval Mintz 	struct bnx2x_raw_obj *raw = &o->raw;
118905cc5a39SYuval Mintz 	struct mac_configuration_cmd *config =
119005cc5a39SYuval Mintz 		(struct mac_configuration_cmd *)(raw->rdata);
119105cc5a39SYuval Mintz 	/* 57710 and 57711 do not support MOVE command,
119205cc5a39SYuval Mintz 	 * so it's either ADD or DEL
119305cc5a39SYuval Mintz 	 */
119405cc5a39SYuval Mintz 	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
119505cc5a39SYuval Mintz 		true : false;
119605cc5a39SYuval Mintz 
119705cc5a39SYuval Mintz 	/* Reset the ramrod data buffer */
119805cc5a39SYuval Mintz 	memset(config, 0, sizeof(*config));
119905cc5a39SYuval Mintz 
120005cc5a39SYuval Mintz 	bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING,
120105cc5a39SYuval Mintz 				     cam_offset, add,
120205cc5a39SYuval Mintz 				     elem->cmd_data.vlan_mac.u.vlan_mac.mac,
120305cc5a39SYuval Mintz 				     elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
120405cc5a39SYuval Mintz 				     ETH_VLAN_FILTER_CLASSIFY, config);
120505cc5a39SYuval Mintz }
120605cc5a39SYuval Mintz 
1207adfc5217SJeff Kirsher /**
1208adfc5217SJeff Kirsher  * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
1209adfc5217SJeff Kirsher  *
1210adfc5217SJeff Kirsher  * @bp:		device handle
1211adfc5217SJeff Kirsher  * @p:		command parameters
121216a5fd92SYuval Mintz  * @ppos:	pointer to the cookie
1213adfc5217SJeff Kirsher  *
1214adfc5217SJeff Kirsher  * reconfigure next MAC/VLAN/VLAN-MAC element from the
1215adfc5217SJeff Kirsher  * previously configured elements list.
1216adfc5217SJeff Kirsher  *
1217adfc5217SJeff Kirsher  * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is	taken
1218adfc5217SJeff Kirsher  * into an account
1219adfc5217SJeff Kirsher  *
122016a5fd92SYuval Mintz  * pointer to the cookie  - that should be given back in the next call to make
1221adfc5217SJeff Kirsher  * function handle the next element. If *ppos is set to NULL it will restart the
1222adfc5217SJeff Kirsher  * iterator. If returned *ppos == NULL this means that the last element has been
1223adfc5217SJeff Kirsher  * handled.
1224adfc5217SJeff Kirsher  *
1225adfc5217SJeff Kirsher  */
bnx2x_vlan_mac_restore(struct bnx2x * bp,struct bnx2x_vlan_mac_ramrod_params * p,struct bnx2x_vlan_mac_registry_elem ** ppos)1226adfc5217SJeff Kirsher static int bnx2x_vlan_mac_restore(struct bnx2x *bp,
1227adfc5217SJeff Kirsher 			   struct bnx2x_vlan_mac_ramrod_params *p,
1228adfc5217SJeff Kirsher 			   struct bnx2x_vlan_mac_registry_elem **ppos)
1229adfc5217SJeff Kirsher {
1230adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
1231adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
1232adfc5217SJeff Kirsher 
1233adfc5217SJeff Kirsher 	/* If list is empty - there is nothing to do here */
1234adfc5217SJeff Kirsher 	if (list_empty(&o->head)) {
1235adfc5217SJeff Kirsher 		*ppos = NULL;
1236adfc5217SJeff Kirsher 		return 0;
1237adfc5217SJeff Kirsher 	}
1238adfc5217SJeff Kirsher 
1239adfc5217SJeff Kirsher 	/* make a step... */
1240adfc5217SJeff Kirsher 	if (*ppos == NULL)
1241adfc5217SJeff Kirsher 		*ppos = list_first_entry(&o->head,
1242adfc5217SJeff Kirsher 					 struct bnx2x_vlan_mac_registry_elem,
1243adfc5217SJeff Kirsher 					 link);
1244adfc5217SJeff Kirsher 	else
1245adfc5217SJeff Kirsher 		*ppos = list_next_entry(*ppos, link);
1246adfc5217SJeff Kirsher 
1247adfc5217SJeff Kirsher 	pos = *ppos;
1248adfc5217SJeff Kirsher 
1249adfc5217SJeff Kirsher 	/* If it's the last step - return NULL */
1250adfc5217SJeff Kirsher 	if (list_is_last(&pos->link, &o->head))
1251adfc5217SJeff Kirsher 		*ppos = NULL;
1252adfc5217SJeff Kirsher 
1253adfc5217SJeff Kirsher 	/* Prepare a 'user_req' */
1254adfc5217SJeff Kirsher 	memcpy(&p->user_req.u, &pos->u, sizeof(pos->u));
1255adfc5217SJeff Kirsher 
1256adfc5217SJeff Kirsher 	/* Set the command */
1257adfc5217SJeff Kirsher 	p->user_req.cmd = BNX2X_VLAN_MAC_ADD;
1258adfc5217SJeff Kirsher 
1259adfc5217SJeff Kirsher 	/* Set vlan_mac_flags */
1260adfc5217SJeff Kirsher 	p->user_req.vlan_mac_flags = pos->vlan_mac_flags;
1261adfc5217SJeff Kirsher 
1262adfc5217SJeff Kirsher 	/* Set a restore bit */
1263adfc5217SJeff Kirsher 	__set_bit(RAMROD_RESTORE, &p->ramrod_flags);
1264adfc5217SJeff Kirsher 
1265adfc5217SJeff Kirsher 	return bnx2x_config_vlan_mac(bp, p);
1266adfc5217SJeff Kirsher }
1267adfc5217SJeff Kirsher 
126816a5fd92SYuval Mintz /* bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a
1269adfc5217SJeff Kirsher  * pointer to an element with a specific criteria and NULL if such an element
1270adfc5217SJeff Kirsher  * hasn't been found.
1271adfc5217SJeff Kirsher  */
bnx2x_exeq_get_mac(struct bnx2x_exe_queue_obj * o,struct bnx2x_exeq_elem * elem)1272adfc5217SJeff Kirsher static struct bnx2x_exeq_elem *bnx2x_exeq_get_mac(
1273adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *o,
1274adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem)
1275adfc5217SJeff Kirsher {
1276adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *pos;
1277adfc5217SJeff Kirsher 	struct bnx2x_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac;
1278adfc5217SJeff Kirsher 
1279adfc5217SJeff Kirsher 	/* Check pending for execution commands */
1280adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->exe_queue, link)
1281adfc5217SJeff Kirsher 		if (!memcmp(&pos->cmd_data.vlan_mac.u.mac, data,
1282adfc5217SJeff Kirsher 			      sizeof(*data)) &&
1283adfc5217SJeff Kirsher 		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
1284adfc5217SJeff Kirsher 			return pos;
1285adfc5217SJeff Kirsher 
1286adfc5217SJeff Kirsher 	return NULL;
1287adfc5217SJeff Kirsher }
1288adfc5217SJeff Kirsher 
bnx2x_exeq_get_vlan(struct bnx2x_exe_queue_obj * o,struct bnx2x_exeq_elem * elem)1289adfc5217SJeff Kirsher static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan(
1290adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *o,
1291adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem)
1292adfc5217SJeff Kirsher {
1293adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *pos;
1294adfc5217SJeff Kirsher 	struct bnx2x_vlan_ramrod_data *data = &elem->cmd_data.vlan_mac.u.vlan;
1295adfc5217SJeff Kirsher 
1296adfc5217SJeff Kirsher 	/* Check pending for execution commands */
1297adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->exe_queue, link)
1298adfc5217SJeff Kirsher 		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan, data,
1299adfc5217SJeff Kirsher 			      sizeof(*data)) &&
1300adfc5217SJeff Kirsher 		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
1301adfc5217SJeff Kirsher 			return pos;
1302adfc5217SJeff Kirsher 
1303adfc5217SJeff Kirsher 	return NULL;
1304adfc5217SJeff Kirsher }
1305adfc5217SJeff Kirsher 
bnx2x_exeq_get_vlan_mac(struct bnx2x_exe_queue_obj * o,struct bnx2x_exeq_elem * elem)130605cc5a39SYuval Mintz static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac(
130705cc5a39SYuval Mintz 	struct bnx2x_exe_queue_obj *o,
130805cc5a39SYuval Mintz 	struct bnx2x_exeq_elem *elem)
130905cc5a39SYuval Mintz {
131005cc5a39SYuval Mintz 	struct bnx2x_exeq_elem *pos;
131105cc5a39SYuval Mintz 	struct bnx2x_vlan_mac_ramrod_data *data =
131205cc5a39SYuval Mintz 		&elem->cmd_data.vlan_mac.u.vlan_mac;
131305cc5a39SYuval Mintz 
131405cc5a39SYuval Mintz 	/* Check pending for execution commands */
131505cc5a39SYuval Mintz 	list_for_each_entry(pos, &o->exe_queue, link)
131605cc5a39SYuval Mintz 		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
131705cc5a39SYuval Mintz 			    sizeof(*data)) &&
131805cc5a39SYuval Mintz 		    (pos->cmd_data.vlan_mac.cmd ==
131905cc5a39SYuval Mintz 		     elem->cmd_data.vlan_mac.cmd))
132005cc5a39SYuval Mintz 			return pos;
132105cc5a39SYuval Mintz 
132205cc5a39SYuval Mintz 	return NULL;
132305cc5a39SYuval Mintz }
132405cc5a39SYuval Mintz 
1325adfc5217SJeff Kirsher /**
1326adfc5217SJeff Kirsher  * bnx2x_validate_vlan_mac_add - check if an ADD command can be executed
1327adfc5217SJeff Kirsher  *
1328adfc5217SJeff Kirsher  * @bp:		device handle
1329adfc5217SJeff Kirsher  * @qo:		bnx2x_qable_obj
1330adfc5217SJeff Kirsher  * @elem:	bnx2x_exeq_elem
1331adfc5217SJeff Kirsher  *
1332adfc5217SJeff Kirsher  * Checks that the requested configuration can be added. If yes and if
1333adfc5217SJeff Kirsher  * requested, consume CAM credit.
1334adfc5217SJeff Kirsher  *
1335adfc5217SJeff Kirsher  * The 'validate' is run after the 'optimize'.
1336adfc5217SJeff Kirsher  *
1337adfc5217SJeff Kirsher  */
bnx2x_validate_vlan_mac_add(struct bnx2x * bp,union bnx2x_qable_obj * qo,struct bnx2x_exeq_elem * elem)1338adfc5217SJeff Kirsher static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp,
1339adfc5217SJeff Kirsher 					      union bnx2x_qable_obj *qo,
1340adfc5217SJeff Kirsher 					      struct bnx2x_exeq_elem *elem)
1341adfc5217SJeff Kirsher {
1342adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
1343adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
1344adfc5217SJeff Kirsher 	int rc;
1345adfc5217SJeff Kirsher 
1346adfc5217SJeff Kirsher 	/* Check the registry */
134751c1a580SMerav Sicron 	rc = o->check_add(bp, o, &elem->cmd_data.vlan_mac.u);
1348adfc5217SJeff Kirsher 	if (rc) {
134951c1a580SMerav Sicron 		DP(BNX2X_MSG_SP, "ADD command is not allowed considering current registry state.\n");
1350adfc5217SJeff Kirsher 		return rc;
1351adfc5217SJeff Kirsher 	}
1352adfc5217SJeff Kirsher 
135316a5fd92SYuval Mintz 	/* Check if there is a pending ADD command for this
1354adfc5217SJeff Kirsher 	 * MAC/VLAN/VLAN-MAC. Return an error if there is.
1355adfc5217SJeff Kirsher 	 */
1356adfc5217SJeff Kirsher 	if (exeq->get(exeq, elem)) {
1357adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "There is a pending ADD command already\n");
1358adfc5217SJeff Kirsher 		return -EEXIST;
1359adfc5217SJeff Kirsher 	}
1360adfc5217SJeff Kirsher 
136116a5fd92SYuval Mintz 	/* TODO: Check the pending MOVE from other objects where this
1362adfc5217SJeff Kirsher 	 * object is a destination object.
1363adfc5217SJeff Kirsher 	 */
1364adfc5217SJeff Kirsher 
1365adfc5217SJeff Kirsher 	/* Consume the credit if not requested not to */
1366adfc5217SJeff Kirsher 	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
1367adfc5217SJeff Kirsher 		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
1368adfc5217SJeff Kirsher 	    o->get_credit(o)))
1369adfc5217SJeff Kirsher 		return -EINVAL;
1370adfc5217SJeff Kirsher 
1371adfc5217SJeff Kirsher 	return 0;
1372adfc5217SJeff Kirsher }
1373adfc5217SJeff Kirsher 
1374adfc5217SJeff Kirsher /**
1375adfc5217SJeff Kirsher  * bnx2x_validate_vlan_mac_del - check if the DEL command can be executed
1376adfc5217SJeff Kirsher  *
1377adfc5217SJeff Kirsher  * @bp:		device handle
1378adfc5217SJeff Kirsher  * @qo:		quable object to check
1379adfc5217SJeff Kirsher  * @elem:	element that needs to be deleted
1380adfc5217SJeff Kirsher  *
1381adfc5217SJeff Kirsher  * Checks that the requested configuration can be deleted. If yes and if
1382adfc5217SJeff Kirsher  * requested, returns a CAM credit.
1383adfc5217SJeff Kirsher  *
1384adfc5217SJeff Kirsher  * The 'validate' is run after the 'optimize'.
1385adfc5217SJeff Kirsher  */
bnx2x_validate_vlan_mac_del(struct bnx2x * bp,union bnx2x_qable_obj * qo,struct bnx2x_exeq_elem * elem)1386adfc5217SJeff Kirsher static inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp,
1387adfc5217SJeff Kirsher 					      union bnx2x_qable_obj *qo,
1388adfc5217SJeff Kirsher 					      struct bnx2x_exeq_elem *elem)
1389adfc5217SJeff Kirsher {
1390adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
1391adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
1392adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
1393adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem query_elem;
1394adfc5217SJeff Kirsher 
1395adfc5217SJeff Kirsher 	/* If this classification can not be deleted (doesn't exist)
1396adfc5217SJeff Kirsher 	 * - return a BNX2X_EXIST.
1397adfc5217SJeff Kirsher 	 */
139851c1a580SMerav Sicron 	pos = o->check_del(bp, o, &elem->cmd_data.vlan_mac.u);
1399adfc5217SJeff Kirsher 	if (!pos) {
140051c1a580SMerav Sicron 		DP(BNX2X_MSG_SP, "DEL command is not allowed considering current registry state\n");
1401adfc5217SJeff Kirsher 		return -EEXIST;
1402adfc5217SJeff Kirsher 	}
1403adfc5217SJeff Kirsher 
140416a5fd92SYuval Mintz 	/* Check if there are pending DEL or MOVE commands for this
1405adfc5217SJeff Kirsher 	 * MAC/VLAN/VLAN-MAC. Return an error if so.
1406adfc5217SJeff Kirsher 	 */
1407adfc5217SJeff Kirsher 	memcpy(&query_elem, elem, sizeof(query_elem));
1408adfc5217SJeff Kirsher 
1409adfc5217SJeff Kirsher 	/* Check for MOVE commands */
1410adfc5217SJeff Kirsher 	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_MOVE;
1411adfc5217SJeff Kirsher 	if (exeq->get(exeq, &query_elem)) {
1412adfc5217SJeff Kirsher 		BNX2X_ERR("There is a pending MOVE command already\n");
1413adfc5217SJeff Kirsher 		return -EINVAL;
1414adfc5217SJeff Kirsher 	}
1415adfc5217SJeff Kirsher 
1416adfc5217SJeff Kirsher 	/* Check for DEL commands */
1417adfc5217SJeff Kirsher 	if (exeq->get(exeq, elem)) {
1418adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "There is a pending DEL command already\n");
1419adfc5217SJeff Kirsher 		return -EEXIST;
1420adfc5217SJeff Kirsher 	}
1421adfc5217SJeff Kirsher 
1422adfc5217SJeff Kirsher 	/* Return the credit to the credit pool if not requested not to */
1423adfc5217SJeff Kirsher 	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
1424adfc5217SJeff Kirsher 		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
1425adfc5217SJeff Kirsher 	    o->put_credit(o))) {
1426adfc5217SJeff Kirsher 		BNX2X_ERR("Failed to return a credit\n");
1427adfc5217SJeff Kirsher 		return -EINVAL;
1428adfc5217SJeff Kirsher 	}
1429adfc5217SJeff Kirsher 
1430adfc5217SJeff Kirsher 	return 0;
1431adfc5217SJeff Kirsher }
1432adfc5217SJeff Kirsher 
1433adfc5217SJeff Kirsher /**
1434adfc5217SJeff Kirsher  * bnx2x_validate_vlan_mac_move - check if the MOVE command can be executed
1435adfc5217SJeff Kirsher  *
1436adfc5217SJeff Kirsher  * @bp:		device handle
1437adfc5217SJeff Kirsher  * @qo:		quable object to check (source)
1438adfc5217SJeff Kirsher  * @elem:	element that needs to be moved
1439adfc5217SJeff Kirsher  *
1440adfc5217SJeff Kirsher  * Checks that the requested configuration can be moved. If yes and if
1441adfc5217SJeff Kirsher  * requested, returns a CAM credit.
1442adfc5217SJeff Kirsher  *
1443adfc5217SJeff Kirsher  * The 'validate' is run after the 'optimize'.
1444adfc5217SJeff Kirsher  */
bnx2x_validate_vlan_mac_move(struct bnx2x * bp,union bnx2x_qable_obj * qo,struct bnx2x_exeq_elem * elem)1445adfc5217SJeff Kirsher static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp,
1446adfc5217SJeff Kirsher 					       union bnx2x_qable_obj *qo,
1447adfc5217SJeff Kirsher 					       struct bnx2x_exeq_elem *elem)
1448adfc5217SJeff Kirsher {
1449adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *src_o = &qo->vlan_mac;
1450adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj;
1451adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem query_elem;
1452adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue;
1453adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue;
1454adfc5217SJeff Kirsher 
145516a5fd92SYuval Mintz 	/* Check if we can perform this operation based on the current registry
1456adfc5217SJeff Kirsher 	 * state.
1457adfc5217SJeff Kirsher 	 */
145851c1a580SMerav Sicron 	if (!src_o->check_move(bp, src_o, dest_o,
145951c1a580SMerav Sicron 			       &elem->cmd_data.vlan_mac.u)) {
146051c1a580SMerav Sicron 		DP(BNX2X_MSG_SP, "MOVE command is not allowed considering current registry state\n");
1461adfc5217SJeff Kirsher 		return -EINVAL;
1462adfc5217SJeff Kirsher 	}
1463adfc5217SJeff Kirsher 
146416a5fd92SYuval Mintz 	/* Check if there is an already pending DEL or MOVE command for the
1465adfc5217SJeff Kirsher 	 * source object or ADD command for a destination object. Return an
1466adfc5217SJeff Kirsher 	 * error if so.
1467adfc5217SJeff Kirsher 	 */
1468adfc5217SJeff Kirsher 	memcpy(&query_elem, elem, sizeof(query_elem));
1469adfc5217SJeff Kirsher 
1470adfc5217SJeff Kirsher 	/* Check DEL on source */
1471adfc5217SJeff Kirsher 	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
1472adfc5217SJeff Kirsher 	if (src_exeq->get(src_exeq, &query_elem)) {
147351c1a580SMerav Sicron 		BNX2X_ERR("There is a pending DEL command on the source queue already\n");
1474adfc5217SJeff Kirsher 		return -EINVAL;
1475adfc5217SJeff Kirsher 	}
1476adfc5217SJeff Kirsher 
1477adfc5217SJeff Kirsher 	/* Check MOVE on source */
1478adfc5217SJeff Kirsher 	if (src_exeq->get(src_exeq, elem)) {
1479adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "There is a pending MOVE command already\n");
1480adfc5217SJeff Kirsher 		return -EEXIST;
1481adfc5217SJeff Kirsher 	}
1482adfc5217SJeff Kirsher 
1483adfc5217SJeff Kirsher 	/* Check ADD on destination */
1484adfc5217SJeff Kirsher 	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
1485adfc5217SJeff Kirsher 	if (dest_exeq->get(dest_exeq, &query_elem)) {
148651c1a580SMerav Sicron 		BNX2X_ERR("There is a pending ADD command on the destination queue already\n");
1487adfc5217SJeff Kirsher 		return -EINVAL;
1488adfc5217SJeff Kirsher 	}
1489adfc5217SJeff Kirsher 
1490adfc5217SJeff Kirsher 	/* Consume the credit if not requested not to */
1491adfc5217SJeff Kirsher 	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
1492adfc5217SJeff Kirsher 		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
1493adfc5217SJeff Kirsher 	    dest_o->get_credit(dest_o)))
1494adfc5217SJeff Kirsher 		return -EINVAL;
1495adfc5217SJeff Kirsher 
1496adfc5217SJeff Kirsher 	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
1497adfc5217SJeff Kirsher 		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
1498adfc5217SJeff Kirsher 	    src_o->put_credit(src_o))) {
1499adfc5217SJeff Kirsher 		/* return the credit taken from dest... */
1500adfc5217SJeff Kirsher 		dest_o->put_credit(dest_o);
1501adfc5217SJeff Kirsher 		return -EINVAL;
1502adfc5217SJeff Kirsher 	}
1503adfc5217SJeff Kirsher 
1504adfc5217SJeff Kirsher 	return 0;
1505adfc5217SJeff Kirsher }
1506adfc5217SJeff Kirsher 
bnx2x_validate_vlan_mac(struct bnx2x * bp,union bnx2x_qable_obj * qo,struct bnx2x_exeq_elem * elem)1507adfc5217SJeff Kirsher static int bnx2x_validate_vlan_mac(struct bnx2x *bp,
1508adfc5217SJeff Kirsher 				   union bnx2x_qable_obj *qo,
1509adfc5217SJeff Kirsher 				   struct bnx2x_exeq_elem *elem)
1510adfc5217SJeff Kirsher {
1511adfc5217SJeff Kirsher 	switch (elem->cmd_data.vlan_mac.cmd) {
1512adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_ADD:
1513adfc5217SJeff Kirsher 		return bnx2x_validate_vlan_mac_add(bp, qo, elem);
1514adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_DEL:
1515adfc5217SJeff Kirsher 		return bnx2x_validate_vlan_mac_del(bp, qo, elem);
1516adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_MOVE:
1517adfc5217SJeff Kirsher 		return bnx2x_validate_vlan_mac_move(bp, qo, elem);
1518adfc5217SJeff Kirsher 	default:
1519adfc5217SJeff Kirsher 		return -EINVAL;
1520adfc5217SJeff Kirsher 	}
1521adfc5217SJeff Kirsher }
1522adfc5217SJeff Kirsher 
bnx2x_remove_vlan_mac(struct bnx2x * bp,union bnx2x_qable_obj * qo,struct bnx2x_exeq_elem * elem)1523460a25cdSYuval Mintz static int bnx2x_remove_vlan_mac(struct bnx2x *bp,
1524460a25cdSYuval Mintz 				  union bnx2x_qable_obj *qo,
1525460a25cdSYuval Mintz 				  struct bnx2x_exeq_elem *elem)
1526460a25cdSYuval Mintz {
1527460a25cdSYuval Mintz 	int rc = 0;
1528460a25cdSYuval Mintz 
1529460a25cdSYuval Mintz 	/* If consumption wasn't required, nothing to do */
1530460a25cdSYuval Mintz 	if (test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
1531460a25cdSYuval Mintz 		     &elem->cmd_data.vlan_mac.vlan_mac_flags))
1532460a25cdSYuval Mintz 		return 0;
1533460a25cdSYuval Mintz 
1534460a25cdSYuval Mintz 	switch (elem->cmd_data.vlan_mac.cmd) {
1535460a25cdSYuval Mintz 	case BNX2X_VLAN_MAC_ADD:
1536460a25cdSYuval Mintz 	case BNX2X_VLAN_MAC_MOVE:
1537460a25cdSYuval Mintz 		rc = qo->vlan_mac.put_credit(&qo->vlan_mac);
1538460a25cdSYuval Mintz 		break;
1539460a25cdSYuval Mintz 	case BNX2X_VLAN_MAC_DEL:
1540460a25cdSYuval Mintz 		rc = qo->vlan_mac.get_credit(&qo->vlan_mac);
1541460a25cdSYuval Mintz 		break;
1542460a25cdSYuval Mintz 	default:
1543460a25cdSYuval Mintz 		return -EINVAL;
1544460a25cdSYuval Mintz 	}
1545460a25cdSYuval Mintz 
1546460a25cdSYuval Mintz 	if (rc != true)
1547460a25cdSYuval Mintz 		return -EINVAL;
1548460a25cdSYuval Mintz 
1549460a25cdSYuval Mintz 	return 0;
1550460a25cdSYuval Mintz }
1551460a25cdSYuval Mintz 
1552adfc5217SJeff Kirsher /**
155316a5fd92SYuval Mintz  * bnx2x_wait_vlan_mac - passively wait for 5 seconds until all work completes.
1554adfc5217SJeff Kirsher  *
1555adfc5217SJeff Kirsher  * @bp:		device handle
1556adfc5217SJeff Kirsher  * @o:		bnx2x_vlan_mac_obj
1557adfc5217SJeff Kirsher  *
1558adfc5217SJeff Kirsher  */
bnx2x_wait_vlan_mac(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o)1559adfc5217SJeff Kirsher static int bnx2x_wait_vlan_mac(struct bnx2x *bp,
1560adfc5217SJeff Kirsher 			       struct bnx2x_vlan_mac_obj *o)
1561adfc5217SJeff Kirsher {
1562adfc5217SJeff Kirsher 	int cnt = 5000, rc;
1563adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
1564adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
1565adfc5217SJeff Kirsher 
1566adfc5217SJeff Kirsher 	while (cnt--) {
1567adfc5217SJeff Kirsher 		/* Wait for the current command to complete */
1568adfc5217SJeff Kirsher 		rc = raw->wait_comp(bp, raw);
1569adfc5217SJeff Kirsher 		if (rc)
1570adfc5217SJeff Kirsher 			return rc;
1571adfc5217SJeff Kirsher 
1572adfc5217SJeff Kirsher 		/* Wait until there are no pending commands */
1573adfc5217SJeff Kirsher 		if (!bnx2x_exe_queue_empty(exeq))
15740926d499SYuval Mintz 			usleep_range(1000, 2000);
1575adfc5217SJeff Kirsher 		else
1576adfc5217SJeff Kirsher 			return 0;
1577adfc5217SJeff Kirsher 	}
1578adfc5217SJeff Kirsher 
1579adfc5217SJeff Kirsher 	return -EBUSY;
1580adfc5217SJeff Kirsher }
1581adfc5217SJeff Kirsher 
__bnx2x_vlan_mac_execute_step(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,unsigned long * ramrod_flags)15828b09be5fSYuval Mintz static int __bnx2x_vlan_mac_execute_step(struct bnx2x *bp,
15838b09be5fSYuval Mintz 					 struct bnx2x_vlan_mac_obj *o,
15848b09be5fSYuval Mintz 					 unsigned long *ramrod_flags)
15858b09be5fSYuval Mintz {
15868b09be5fSYuval Mintz 	int rc = 0;
15878b09be5fSYuval Mintz 
15888b09be5fSYuval Mintz 	spin_lock_bh(&o->exe_queue.lock);
15898b09be5fSYuval Mintz 
15908b09be5fSYuval Mintz 	DP(BNX2X_MSG_SP, "vlan_mac_execute_step - trying to take writer lock\n");
15918b09be5fSYuval Mintz 	rc = __bnx2x_vlan_mac_h_write_trylock(bp, o);
15928b09be5fSYuval Mintz 
15938b09be5fSYuval Mintz 	if (rc != 0) {
15948b09be5fSYuval Mintz 		__bnx2x_vlan_mac_h_pend(bp, o, *ramrod_flags);
15958b09be5fSYuval Mintz 
15968ac1ed79SJoe Perches 		/* Calling function should not differentiate between this case
15978b09be5fSYuval Mintz 		 * and the case in which there is already a pending ramrod
15988b09be5fSYuval Mintz 		 */
15998b09be5fSYuval Mintz 		rc = 1;
16008b09be5fSYuval Mintz 	} else {
16018b09be5fSYuval Mintz 		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
16028b09be5fSYuval Mintz 	}
16038b09be5fSYuval Mintz 	spin_unlock_bh(&o->exe_queue.lock);
16048b09be5fSYuval Mintz 
16058b09be5fSYuval Mintz 	return rc;
16068b09be5fSYuval Mintz }
16078b09be5fSYuval Mintz 
1608adfc5217SJeff Kirsher /**
1609adfc5217SJeff Kirsher  * bnx2x_complete_vlan_mac - complete one VLAN-MAC ramrod
1610adfc5217SJeff Kirsher  *
1611adfc5217SJeff Kirsher  * @bp:		device handle
1612adfc5217SJeff Kirsher  * @o:		bnx2x_vlan_mac_obj
1613d0ea5cbdSJesse Brandeburg  * @cqe:	completion element
1614d0ea5cbdSJesse Brandeburg  * @ramrod_flags: if set schedule next execution chunk
1615adfc5217SJeff Kirsher  *
1616adfc5217SJeff Kirsher  */
bnx2x_complete_vlan_mac(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,union event_ring_elem * cqe,unsigned long * ramrod_flags)1617adfc5217SJeff Kirsher static int bnx2x_complete_vlan_mac(struct bnx2x *bp,
1618adfc5217SJeff Kirsher 				   struct bnx2x_vlan_mac_obj *o,
1619adfc5217SJeff Kirsher 				   union event_ring_elem *cqe,
1620adfc5217SJeff Kirsher 				   unsigned long *ramrod_flags)
1621adfc5217SJeff Kirsher {
1622adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
1623adfc5217SJeff Kirsher 	int rc;
1624adfc5217SJeff Kirsher 
16258b09be5fSYuval Mintz 	/* Clearing the pending list & raw state should be made
16268b09be5fSYuval Mintz 	 * atomically (as execution flow assumes they represent the same).
16278b09be5fSYuval Mintz 	 */
16288b09be5fSYuval Mintz 	spin_lock_bh(&o->exe_queue.lock);
16298b09be5fSYuval Mintz 
1630adfc5217SJeff Kirsher 	/* Reset pending list */
16318b09be5fSYuval Mintz 	__bnx2x_exe_queue_reset_pending(bp, &o->exe_queue);
1632adfc5217SJeff Kirsher 
1633adfc5217SJeff Kirsher 	/* Clear pending */
1634adfc5217SJeff Kirsher 	r->clear_pending(r);
1635adfc5217SJeff Kirsher 
16368b09be5fSYuval Mintz 	spin_unlock_bh(&o->exe_queue.lock);
16378b09be5fSYuval Mintz 
1638adfc5217SJeff Kirsher 	/* If ramrod failed this is most likely a SW bug */
1639adfc5217SJeff Kirsher 	if (cqe->message.error)
1640adfc5217SJeff Kirsher 		return -EINVAL;
1641adfc5217SJeff Kirsher 
16422de67439SYuval Mintz 	/* Run the next bulk of pending commands if requested */
1643adfc5217SJeff Kirsher 	if (test_bit(RAMROD_CONT, ramrod_flags)) {
16448b09be5fSYuval Mintz 		rc = __bnx2x_vlan_mac_execute_step(bp, o, ramrod_flags);
16458b09be5fSYuval Mintz 
1646adfc5217SJeff Kirsher 		if (rc < 0)
1647adfc5217SJeff Kirsher 			return rc;
1648adfc5217SJeff Kirsher 	}
1649adfc5217SJeff Kirsher 
1650adfc5217SJeff Kirsher 	/* If there is more work to do return PENDING */
1651adfc5217SJeff Kirsher 	if (!bnx2x_exe_queue_empty(&o->exe_queue))
1652adfc5217SJeff Kirsher 		return 1;
1653adfc5217SJeff Kirsher 
1654adfc5217SJeff Kirsher 	return 0;
1655adfc5217SJeff Kirsher }
1656adfc5217SJeff Kirsher 
1657adfc5217SJeff Kirsher /**
1658adfc5217SJeff Kirsher  * bnx2x_optimize_vlan_mac - optimize ADD and DEL commands.
1659adfc5217SJeff Kirsher  *
1660adfc5217SJeff Kirsher  * @bp:		device handle
1661d0ea5cbdSJesse Brandeburg  * @qo:		bnx2x_qable_obj
1662adfc5217SJeff Kirsher  * @elem:	bnx2x_exeq_elem
1663adfc5217SJeff Kirsher  */
bnx2x_optimize_vlan_mac(struct bnx2x * bp,union bnx2x_qable_obj * qo,struct bnx2x_exeq_elem * elem)1664adfc5217SJeff Kirsher static int bnx2x_optimize_vlan_mac(struct bnx2x *bp,
1665adfc5217SJeff Kirsher 				   union bnx2x_qable_obj *qo,
1666adfc5217SJeff Kirsher 				   struct bnx2x_exeq_elem *elem)
1667adfc5217SJeff Kirsher {
1668adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem query, *pos;
1669adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
1670adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
1671adfc5217SJeff Kirsher 
1672adfc5217SJeff Kirsher 	memcpy(&query, elem, sizeof(query));
1673adfc5217SJeff Kirsher 
1674adfc5217SJeff Kirsher 	switch (elem->cmd_data.vlan_mac.cmd) {
1675adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_ADD:
1676adfc5217SJeff Kirsher 		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
1677adfc5217SJeff Kirsher 		break;
1678adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_DEL:
1679adfc5217SJeff Kirsher 		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
1680adfc5217SJeff Kirsher 		break;
1681adfc5217SJeff Kirsher 	default:
1682adfc5217SJeff Kirsher 		/* Don't handle anything other than ADD or DEL */
1683adfc5217SJeff Kirsher 		return 0;
1684adfc5217SJeff Kirsher 	}
1685adfc5217SJeff Kirsher 
1686adfc5217SJeff Kirsher 	/* If we found the appropriate element - delete it */
1687adfc5217SJeff Kirsher 	pos = exeq->get(exeq, &query);
1688adfc5217SJeff Kirsher 	if (pos) {
1689adfc5217SJeff Kirsher 
1690adfc5217SJeff Kirsher 		/* Return the credit of the optimized command */
1691adfc5217SJeff Kirsher 		if (!test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
1692adfc5217SJeff Kirsher 			      &pos->cmd_data.vlan_mac.vlan_mac_flags)) {
1693adfc5217SJeff Kirsher 			if ((query.cmd_data.vlan_mac.cmd ==
1694adfc5217SJeff Kirsher 			     BNX2X_VLAN_MAC_ADD) && !o->put_credit(o)) {
169551c1a580SMerav Sicron 				BNX2X_ERR("Failed to return the credit for the optimized ADD command\n");
1696adfc5217SJeff Kirsher 				return -EINVAL;
1697adfc5217SJeff Kirsher 			} else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */
169851c1a580SMerav Sicron 				BNX2X_ERR("Failed to recover the credit from the optimized DEL command\n");
1699adfc5217SJeff Kirsher 				return -EINVAL;
1700adfc5217SJeff Kirsher 			}
1701adfc5217SJeff Kirsher 		}
1702adfc5217SJeff Kirsher 
1703adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Optimizing %s command\n",
1704adfc5217SJeff Kirsher 			   (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
1705adfc5217SJeff Kirsher 			   "ADD" : "DEL");
1706adfc5217SJeff Kirsher 
1707adfc5217SJeff Kirsher 		list_del(&pos->link);
1708adfc5217SJeff Kirsher 		bnx2x_exe_queue_free_elem(bp, pos);
1709adfc5217SJeff Kirsher 		return 1;
1710adfc5217SJeff Kirsher 	}
1711adfc5217SJeff Kirsher 
1712adfc5217SJeff Kirsher 	return 0;
1713adfc5217SJeff Kirsher }
1714adfc5217SJeff Kirsher 
1715adfc5217SJeff Kirsher /**
1716adfc5217SJeff Kirsher  * bnx2x_vlan_mac_get_registry_elem - prepare a registry element
1717adfc5217SJeff Kirsher  *
1718adfc5217SJeff Kirsher  * @bp:	  device handle
1719d0ea5cbdSJesse Brandeburg  * @o:	vlan object
1720d0ea5cbdSJesse Brandeburg  * @elem: element
1721d0ea5cbdSJesse Brandeburg  * @restore: to restore or not
1722d0ea5cbdSJesse Brandeburg  * @re: registry
1723adfc5217SJeff Kirsher  *
1724adfc5217SJeff Kirsher  * prepare a registry element according to the current command request.
1725adfc5217SJeff Kirsher  */
bnx2x_vlan_mac_get_registry_elem(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,struct bnx2x_exeq_elem * elem,bool restore,struct bnx2x_vlan_mac_registry_elem ** re)1726adfc5217SJeff Kirsher static inline int bnx2x_vlan_mac_get_registry_elem(
1727adfc5217SJeff Kirsher 	struct bnx2x *bp,
1728adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o,
1729adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem,
1730adfc5217SJeff Kirsher 	bool restore,
1731adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem **re)
1732adfc5217SJeff Kirsher {
173386564c3fSYuval Mintz 	enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd;
1734adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *reg_elem;
1735adfc5217SJeff Kirsher 
1736adfc5217SJeff Kirsher 	/* Allocate a new registry element if needed. */
1737adfc5217SJeff Kirsher 	if (!restore &&
1738adfc5217SJeff Kirsher 	    ((cmd == BNX2X_VLAN_MAC_ADD) || (cmd == BNX2X_VLAN_MAC_MOVE))) {
1739adfc5217SJeff Kirsher 		reg_elem = kzalloc(sizeof(*reg_elem), GFP_ATOMIC);
1740adfc5217SJeff Kirsher 		if (!reg_elem)
1741adfc5217SJeff Kirsher 			return -ENOMEM;
1742adfc5217SJeff Kirsher 
1743adfc5217SJeff Kirsher 		/* Get a new CAM offset */
1744adfc5217SJeff Kirsher 		if (!o->get_cam_offset(o, &reg_elem->cam_offset)) {
174516a5fd92SYuval Mintz 			/* This shall never happen, because we have checked the
174616a5fd92SYuval Mintz 			 * CAM availability in the 'validate'.
1747adfc5217SJeff Kirsher 			 */
1748adfc5217SJeff Kirsher 			WARN_ON(1);
1749adfc5217SJeff Kirsher 			kfree(reg_elem);
1750adfc5217SJeff Kirsher 			return -EINVAL;
1751adfc5217SJeff Kirsher 		}
1752adfc5217SJeff Kirsher 
1753adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Got cam offset %d\n", reg_elem->cam_offset);
1754adfc5217SJeff Kirsher 
1755adfc5217SJeff Kirsher 		/* Set a VLAN-MAC data */
1756adfc5217SJeff Kirsher 		memcpy(&reg_elem->u, &elem->cmd_data.vlan_mac.u,
1757adfc5217SJeff Kirsher 			  sizeof(reg_elem->u));
1758adfc5217SJeff Kirsher 
1759adfc5217SJeff Kirsher 		/* Copy the flags (needed for DEL and RESTORE flows) */
1760adfc5217SJeff Kirsher 		reg_elem->vlan_mac_flags =
1761adfc5217SJeff Kirsher 			elem->cmd_data.vlan_mac.vlan_mac_flags;
1762adfc5217SJeff Kirsher 	} else /* DEL, RESTORE */
176351c1a580SMerav Sicron 		reg_elem = o->check_del(bp, o, &elem->cmd_data.vlan_mac.u);
1764adfc5217SJeff Kirsher 
1765adfc5217SJeff Kirsher 	*re = reg_elem;
1766adfc5217SJeff Kirsher 	return 0;
1767adfc5217SJeff Kirsher }
1768adfc5217SJeff Kirsher 
1769adfc5217SJeff Kirsher /**
1770adfc5217SJeff Kirsher  * bnx2x_execute_vlan_mac - execute vlan mac command
1771adfc5217SJeff Kirsher  *
1772adfc5217SJeff Kirsher  * @bp:			device handle
1773d0ea5cbdSJesse Brandeburg  * @qo:			bnx2x_qable_obj pointer
1774d0ea5cbdSJesse Brandeburg  * @exe_chunk:		chunk
1775d0ea5cbdSJesse Brandeburg  * @ramrod_flags:	flags
1776adfc5217SJeff Kirsher  *
1777adfc5217SJeff Kirsher  * go and send a ramrod!
1778adfc5217SJeff Kirsher  */
bnx2x_execute_vlan_mac(struct bnx2x * bp,union bnx2x_qable_obj * qo,struct list_head * exe_chunk,unsigned long * ramrod_flags)1779adfc5217SJeff Kirsher static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
1780adfc5217SJeff Kirsher 				  union bnx2x_qable_obj *qo,
1781adfc5217SJeff Kirsher 				  struct list_head *exe_chunk,
1782adfc5217SJeff Kirsher 				  unsigned long *ramrod_flags)
1783adfc5217SJeff Kirsher {
1784adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem;
1785adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj;
1786adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
1787adfc5217SJeff Kirsher 	int rc, idx = 0;
1788adfc5217SJeff Kirsher 	bool restore = test_bit(RAMROD_RESTORE, ramrod_flags);
1789adfc5217SJeff Kirsher 	bool drv_only = test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags);
1790adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *reg_elem;
179186564c3fSYuval Mintz 	enum bnx2x_vlan_mac_cmd cmd;
1792adfc5217SJeff Kirsher 
179316a5fd92SYuval Mintz 	/* If DRIVER_ONLY execution is requested, cleanup a registry
1794adfc5217SJeff Kirsher 	 * and exit. Otherwise send a ramrod to FW.
1795adfc5217SJeff Kirsher 	 */
1796adfc5217SJeff Kirsher 	if (!drv_only) {
1797adfc5217SJeff Kirsher 		WARN_ON(r->check_pending(r));
1798adfc5217SJeff Kirsher 
1799adfc5217SJeff Kirsher 		/* Set pending */
1800adfc5217SJeff Kirsher 		r->set_pending(r);
1801adfc5217SJeff Kirsher 
180216a5fd92SYuval Mintz 		/* Fill the ramrod data */
1803adfc5217SJeff Kirsher 		list_for_each_entry(elem, exe_chunk, link) {
1804adfc5217SJeff Kirsher 			cmd = elem->cmd_data.vlan_mac.cmd;
180516a5fd92SYuval Mintz 			/* We will add to the target object in MOVE command, so
1806adfc5217SJeff Kirsher 			 * change the object for a CAM search.
1807adfc5217SJeff Kirsher 			 */
1808adfc5217SJeff Kirsher 			if (cmd == BNX2X_VLAN_MAC_MOVE)
1809adfc5217SJeff Kirsher 				cam_obj = elem->cmd_data.vlan_mac.target_obj;
1810adfc5217SJeff Kirsher 			else
1811adfc5217SJeff Kirsher 				cam_obj = o;
1812adfc5217SJeff Kirsher 
1813adfc5217SJeff Kirsher 			rc = bnx2x_vlan_mac_get_registry_elem(bp, cam_obj,
1814adfc5217SJeff Kirsher 							      elem, restore,
1815adfc5217SJeff Kirsher 							      &reg_elem);
1816adfc5217SJeff Kirsher 			if (rc)
1817adfc5217SJeff Kirsher 				goto error_exit;
1818adfc5217SJeff Kirsher 
1819adfc5217SJeff Kirsher 			WARN_ON(!reg_elem);
1820adfc5217SJeff Kirsher 
1821adfc5217SJeff Kirsher 			/* Push a new entry into the registry */
1822adfc5217SJeff Kirsher 			if (!restore &&
1823adfc5217SJeff Kirsher 			    ((cmd == BNX2X_VLAN_MAC_ADD) ||
1824adfc5217SJeff Kirsher 			    (cmd == BNX2X_VLAN_MAC_MOVE)))
1825adfc5217SJeff Kirsher 				list_add(&reg_elem->link, &cam_obj->head);
1826adfc5217SJeff Kirsher 
1827adfc5217SJeff Kirsher 			/* Configure a single command in a ramrod data buffer */
1828adfc5217SJeff Kirsher 			o->set_one_rule(bp, o, elem, idx,
1829adfc5217SJeff Kirsher 					reg_elem->cam_offset);
1830adfc5217SJeff Kirsher 
1831adfc5217SJeff Kirsher 			/* MOVE command consumes 2 entries in the ramrod data */
1832adfc5217SJeff Kirsher 			if (cmd == BNX2X_VLAN_MAC_MOVE)
1833adfc5217SJeff Kirsher 				idx += 2;
1834adfc5217SJeff Kirsher 			else
1835adfc5217SJeff Kirsher 				idx++;
1836adfc5217SJeff Kirsher 		}
1837adfc5217SJeff Kirsher 
183816a5fd92SYuval Mintz 		/* No need for an explicit memory barrier here as long we would
1839adfc5217SJeff Kirsher 		 * need to ensure the ordering of writing to the SPQ element
1840adfc5217SJeff Kirsher 		 * and updating of the SPQ producer which involves a memory
1841adfc5217SJeff Kirsher 		 * read and we will have to put a full memory barrier there
1842adfc5217SJeff Kirsher 		 * (inside bnx2x_sp_post()).
1843adfc5217SJeff Kirsher 		 */
1844adfc5217SJeff Kirsher 
1845adfc5217SJeff Kirsher 		rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid,
1846adfc5217SJeff Kirsher 				   U64_HI(r->rdata_mapping),
1847adfc5217SJeff Kirsher 				   U64_LO(r->rdata_mapping),
1848adfc5217SJeff Kirsher 				   ETH_CONNECTION_TYPE);
1849adfc5217SJeff Kirsher 		if (rc)
1850adfc5217SJeff Kirsher 			goto error_exit;
1851adfc5217SJeff Kirsher 	}
1852adfc5217SJeff Kirsher 
1853adfc5217SJeff Kirsher 	/* Now, when we are done with the ramrod - clean up the registry */
1854adfc5217SJeff Kirsher 	list_for_each_entry(elem, exe_chunk, link) {
1855adfc5217SJeff Kirsher 		cmd = elem->cmd_data.vlan_mac.cmd;
1856adfc5217SJeff Kirsher 		if ((cmd == BNX2X_VLAN_MAC_DEL) ||
1857adfc5217SJeff Kirsher 		    (cmd == BNX2X_VLAN_MAC_MOVE)) {
185851c1a580SMerav Sicron 			reg_elem = o->check_del(bp, o,
185951c1a580SMerav Sicron 						&elem->cmd_data.vlan_mac.u);
1860adfc5217SJeff Kirsher 
1861adfc5217SJeff Kirsher 			WARN_ON(!reg_elem);
1862adfc5217SJeff Kirsher 
1863adfc5217SJeff Kirsher 			o->put_cam_offset(o, reg_elem->cam_offset);
1864adfc5217SJeff Kirsher 			list_del(&reg_elem->link);
1865adfc5217SJeff Kirsher 			kfree(reg_elem);
1866adfc5217SJeff Kirsher 		}
1867adfc5217SJeff Kirsher 	}
1868adfc5217SJeff Kirsher 
1869adfc5217SJeff Kirsher 	if (!drv_only)
1870adfc5217SJeff Kirsher 		return 1;
1871adfc5217SJeff Kirsher 	else
1872adfc5217SJeff Kirsher 		return 0;
1873adfc5217SJeff Kirsher 
1874adfc5217SJeff Kirsher error_exit:
1875adfc5217SJeff Kirsher 	r->clear_pending(r);
1876adfc5217SJeff Kirsher 
1877adfc5217SJeff Kirsher 	/* Cleanup a registry in case of a failure */
1878adfc5217SJeff Kirsher 	list_for_each_entry(elem, exe_chunk, link) {
1879adfc5217SJeff Kirsher 		cmd = elem->cmd_data.vlan_mac.cmd;
1880adfc5217SJeff Kirsher 
1881adfc5217SJeff Kirsher 		if (cmd == BNX2X_VLAN_MAC_MOVE)
1882adfc5217SJeff Kirsher 			cam_obj = elem->cmd_data.vlan_mac.target_obj;
1883adfc5217SJeff Kirsher 		else
1884adfc5217SJeff Kirsher 			cam_obj = o;
1885adfc5217SJeff Kirsher 
1886adfc5217SJeff Kirsher 		/* Delete all newly added above entries */
1887adfc5217SJeff Kirsher 		if (!restore &&
1888adfc5217SJeff Kirsher 		    ((cmd == BNX2X_VLAN_MAC_ADD) ||
1889adfc5217SJeff Kirsher 		    (cmd == BNX2X_VLAN_MAC_MOVE))) {
189051c1a580SMerav Sicron 			reg_elem = o->check_del(bp, cam_obj,
1891adfc5217SJeff Kirsher 						&elem->cmd_data.vlan_mac.u);
1892adfc5217SJeff Kirsher 			if (reg_elem) {
1893adfc5217SJeff Kirsher 				list_del(&reg_elem->link);
1894adfc5217SJeff Kirsher 				kfree(reg_elem);
1895adfc5217SJeff Kirsher 			}
1896adfc5217SJeff Kirsher 		}
1897adfc5217SJeff Kirsher 	}
1898adfc5217SJeff Kirsher 
1899adfc5217SJeff Kirsher 	return rc;
1900adfc5217SJeff Kirsher }
1901adfc5217SJeff Kirsher 
bnx2x_vlan_mac_push_new_cmd(struct bnx2x * bp,struct bnx2x_vlan_mac_ramrod_params * p)1902adfc5217SJeff Kirsher static inline int bnx2x_vlan_mac_push_new_cmd(
1903adfc5217SJeff Kirsher 	struct bnx2x *bp,
1904adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_ramrod_params *p)
1905adfc5217SJeff Kirsher {
1906adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem;
1907adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
1908adfc5217SJeff Kirsher 	bool restore = test_bit(RAMROD_RESTORE, &p->ramrod_flags);
1909adfc5217SJeff Kirsher 
1910adfc5217SJeff Kirsher 	/* Allocate the execution queue element */
1911adfc5217SJeff Kirsher 	elem = bnx2x_exe_queue_alloc_elem(bp);
1912adfc5217SJeff Kirsher 	if (!elem)
1913adfc5217SJeff Kirsher 		return -ENOMEM;
1914adfc5217SJeff Kirsher 
1915adfc5217SJeff Kirsher 	/* Set the command 'length' */
1916adfc5217SJeff Kirsher 	switch (p->user_req.cmd) {
1917adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_MOVE:
1918adfc5217SJeff Kirsher 		elem->cmd_len = 2;
1919adfc5217SJeff Kirsher 		break;
1920adfc5217SJeff Kirsher 	default:
1921adfc5217SJeff Kirsher 		elem->cmd_len = 1;
1922adfc5217SJeff Kirsher 	}
1923adfc5217SJeff Kirsher 
1924adfc5217SJeff Kirsher 	/* Fill the object specific info */
1925adfc5217SJeff Kirsher 	memcpy(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req));
1926adfc5217SJeff Kirsher 
1927adfc5217SJeff Kirsher 	/* Try to add a new command to the pending list */
1928adfc5217SJeff Kirsher 	return bnx2x_exe_queue_add(bp, &o->exe_queue, elem, restore);
1929adfc5217SJeff Kirsher }
1930adfc5217SJeff Kirsher 
1931adfc5217SJeff Kirsher /**
1932adfc5217SJeff Kirsher  * bnx2x_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules.
1933adfc5217SJeff Kirsher  *
1934adfc5217SJeff Kirsher  * @bp:	  device handle
1935adfc5217SJeff Kirsher  * @p:
1936adfc5217SJeff Kirsher  *
1937adfc5217SJeff Kirsher  */
bnx2x_config_vlan_mac(struct bnx2x * bp,struct bnx2x_vlan_mac_ramrod_params * p)19388b09be5fSYuval Mintz int bnx2x_config_vlan_mac(struct bnx2x *bp,
1939adfc5217SJeff Kirsher 			   struct bnx2x_vlan_mac_ramrod_params *p)
1940adfc5217SJeff Kirsher {
1941adfc5217SJeff Kirsher 	int rc = 0;
1942adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
1943adfc5217SJeff Kirsher 	unsigned long *ramrod_flags = &p->ramrod_flags;
1944adfc5217SJeff Kirsher 	bool cont = test_bit(RAMROD_CONT, ramrod_flags);
1945adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
1946adfc5217SJeff Kirsher 
1947adfc5217SJeff Kirsher 	/*
1948adfc5217SJeff Kirsher 	 * Add new elements to the execution list for commands that require it.
1949adfc5217SJeff Kirsher 	 */
1950adfc5217SJeff Kirsher 	if (!cont) {
1951adfc5217SJeff Kirsher 		rc = bnx2x_vlan_mac_push_new_cmd(bp, p);
1952adfc5217SJeff Kirsher 		if (rc)
1953adfc5217SJeff Kirsher 			return rc;
1954adfc5217SJeff Kirsher 	}
1955adfc5217SJeff Kirsher 
195616a5fd92SYuval Mintz 	/* If nothing will be executed further in this iteration we want to
1957adfc5217SJeff Kirsher 	 * return PENDING if there are pending commands
1958adfc5217SJeff Kirsher 	 */
1959adfc5217SJeff Kirsher 	if (!bnx2x_exe_queue_empty(&o->exe_queue))
1960adfc5217SJeff Kirsher 		rc = 1;
1961adfc5217SJeff Kirsher 
1962adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags))  {
196351c1a580SMerav Sicron 		DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: clearing a pending bit.\n");
1964adfc5217SJeff Kirsher 		raw->clear_pending(raw);
1965adfc5217SJeff Kirsher 	}
1966adfc5217SJeff Kirsher 
1967adfc5217SJeff Kirsher 	/* Execute commands if required */
1968adfc5217SJeff Kirsher 	if (cont || test_bit(RAMROD_EXEC, ramrod_flags) ||
1969adfc5217SJeff Kirsher 	    test_bit(RAMROD_COMP_WAIT, ramrod_flags)) {
19708b09be5fSYuval Mintz 		rc = __bnx2x_vlan_mac_execute_step(bp, p->vlan_mac_obj,
19718b09be5fSYuval Mintz 						   &p->ramrod_flags);
1972adfc5217SJeff Kirsher 		if (rc < 0)
1973adfc5217SJeff Kirsher 			return rc;
1974adfc5217SJeff Kirsher 	}
1975adfc5217SJeff Kirsher 
197616a5fd92SYuval Mintz 	/* RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
1977adfc5217SJeff Kirsher 	 * then user want to wait until the last command is done.
1978adfc5217SJeff Kirsher 	 */
1979adfc5217SJeff Kirsher 	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
198016a5fd92SYuval Mintz 		/* Wait maximum for the current exe_queue length iterations plus
1981adfc5217SJeff Kirsher 		 * one (for the current pending command).
1982adfc5217SJeff Kirsher 		 */
1983adfc5217SJeff Kirsher 		int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1;
1984adfc5217SJeff Kirsher 
1985adfc5217SJeff Kirsher 		while (!bnx2x_exe_queue_empty(&o->exe_queue) &&
1986adfc5217SJeff Kirsher 		       max_iterations--) {
1987adfc5217SJeff Kirsher 
1988adfc5217SJeff Kirsher 			/* Wait for the current command to complete */
1989adfc5217SJeff Kirsher 			rc = raw->wait_comp(bp, raw);
1990adfc5217SJeff Kirsher 			if (rc)
1991adfc5217SJeff Kirsher 				return rc;
1992adfc5217SJeff Kirsher 
1993adfc5217SJeff Kirsher 			/* Make a next step */
19948b09be5fSYuval Mintz 			rc = __bnx2x_vlan_mac_execute_step(bp,
19958b09be5fSYuval Mintz 							   p->vlan_mac_obj,
19968b09be5fSYuval Mintz 							   &p->ramrod_flags);
1997adfc5217SJeff Kirsher 			if (rc < 0)
1998adfc5217SJeff Kirsher 				return rc;
1999adfc5217SJeff Kirsher 		}
2000adfc5217SJeff Kirsher 
2001adfc5217SJeff Kirsher 		return 0;
2002adfc5217SJeff Kirsher 	}
2003adfc5217SJeff Kirsher 
2004adfc5217SJeff Kirsher 	return rc;
2005adfc5217SJeff Kirsher }
2006adfc5217SJeff Kirsher 
2007adfc5217SJeff Kirsher /**
2008adfc5217SJeff Kirsher  * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec
2009adfc5217SJeff Kirsher  *
2010adfc5217SJeff Kirsher  * @bp:			device handle
2011d0ea5cbdSJesse Brandeburg  * @o:			vlan object info
2012d0ea5cbdSJesse Brandeburg  * @vlan_mac_flags:	vlan flags
2013adfc5217SJeff Kirsher  * @ramrod_flags:	execution flags to be used for this deletion
2014adfc5217SJeff Kirsher  *
2015adfc5217SJeff Kirsher  * if the last operation has completed successfully and there are no
2016adfc5217SJeff Kirsher  * more elements left, positive value if the last operation has completed
2017adfc5217SJeff Kirsher  * successfully and there are more previously configured elements, negative
2018adfc5217SJeff Kirsher  * value is current operation has failed.
2019adfc5217SJeff Kirsher  */
bnx2x_vlan_mac_del_all(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * o,unsigned long * vlan_mac_flags,unsigned long * ramrod_flags)2020adfc5217SJeff Kirsher static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
2021adfc5217SJeff Kirsher 				  struct bnx2x_vlan_mac_obj *o,
2022adfc5217SJeff Kirsher 				  unsigned long *vlan_mac_flags,
2023adfc5217SJeff Kirsher 				  unsigned long *ramrod_flags)
2024adfc5217SJeff Kirsher {
2025adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos = NULL;
2026adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_ramrod_params p;
2027adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
2028adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
2029e8379c79SYuval Mintz 	unsigned long flags;
20308b09be5fSYuval Mintz 	int read_lock;
20318b09be5fSYuval Mintz 	int rc = 0;
2032adfc5217SJeff Kirsher 
2033adfc5217SJeff Kirsher 	/* Clear pending commands first */
2034adfc5217SJeff Kirsher 
2035adfc5217SJeff Kirsher 	spin_lock_bh(&exeq->lock);
2036adfc5217SJeff Kirsher 
2037adfc5217SJeff Kirsher 	list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
2038e8379c79SYuval Mintz 		flags = exeq_pos->cmd_data.vlan_mac.vlan_mac_flags;
2039e8379c79SYuval Mintz 		if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
2040e8379c79SYuval Mintz 		    BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
2041460a25cdSYuval Mintz 			rc = exeq->remove(bp, exeq->owner, exeq_pos);
2042460a25cdSYuval Mintz 			if (rc) {
2043460a25cdSYuval Mintz 				BNX2X_ERR("Failed to remove command\n");
2044a44acd55SDan Carpenter 				spin_unlock_bh(&exeq->lock);
2045460a25cdSYuval Mintz 				return rc;
2046460a25cdSYuval Mintz 			}
2047adfc5217SJeff Kirsher 			list_del(&exeq_pos->link);
204807ef7becSYuval Mintz 			bnx2x_exe_queue_free_elem(bp, exeq_pos);
2049adfc5217SJeff Kirsher 		}
2050460a25cdSYuval Mintz 	}
2051adfc5217SJeff Kirsher 
2052adfc5217SJeff Kirsher 	spin_unlock_bh(&exeq->lock);
2053adfc5217SJeff Kirsher 
2054adfc5217SJeff Kirsher 	/* Prepare a command request */
2055adfc5217SJeff Kirsher 	memset(&p, 0, sizeof(p));
2056adfc5217SJeff Kirsher 	p.vlan_mac_obj = o;
2057adfc5217SJeff Kirsher 	p.ramrod_flags = *ramrod_flags;
2058adfc5217SJeff Kirsher 	p.user_req.cmd = BNX2X_VLAN_MAC_DEL;
2059adfc5217SJeff Kirsher 
206016a5fd92SYuval Mintz 	/* Add all but the last VLAN-MAC to the execution queue without actually
2061adfc5217SJeff Kirsher 	 * execution anything.
2062adfc5217SJeff Kirsher 	 */
2063adfc5217SJeff Kirsher 	__clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags);
2064adfc5217SJeff Kirsher 	__clear_bit(RAMROD_EXEC, &p.ramrod_flags);
2065adfc5217SJeff Kirsher 	__clear_bit(RAMROD_CONT, &p.ramrod_flags);
2066adfc5217SJeff Kirsher 
20678b09be5fSYuval Mintz 	DP(BNX2X_MSG_SP, "vlan_mac_del_all -- taking vlan_mac_lock (reader)\n");
20688b09be5fSYuval Mintz 	read_lock = bnx2x_vlan_mac_h_read_lock(bp, o);
20698b09be5fSYuval Mintz 	if (read_lock != 0)
20708b09be5fSYuval Mintz 		return read_lock;
20718b09be5fSYuval Mintz 
2072adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link) {
2073e8379c79SYuval Mintz 		flags = pos->vlan_mac_flags;
2074e8379c79SYuval Mintz 		if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
2075e8379c79SYuval Mintz 		    BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
2076adfc5217SJeff Kirsher 			p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
2077adfc5217SJeff Kirsher 			memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
2078adfc5217SJeff Kirsher 			rc = bnx2x_config_vlan_mac(bp, &p);
2079adfc5217SJeff Kirsher 			if (rc < 0) {
2080adfc5217SJeff Kirsher 				BNX2X_ERR("Failed to add a new DEL command\n");
20818b09be5fSYuval Mintz 				bnx2x_vlan_mac_h_read_unlock(bp, o);
2082adfc5217SJeff Kirsher 				return rc;
2083adfc5217SJeff Kirsher 			}
2084adfc5217SJeff Kirsher 		}
2085adfc5217SJeff Kirsher 	}
2086adfc5217SJeff Kirsher 
20878b09be5fSYuval Mintz 	DP(BNX2X_MSG_SP, "vlan_mac_del_all -- releasing vlan_mac_lock (reader)\n");
20888b09be5fSYuval Mintz 	bnx2x_vlan_mac_h_read_unlock(bp, o);
20898b09be5fSYuval Mintz 
2090adfc5217SJeff Kirsher 	p.ramrod_flags = *ramrod_flags;
2091adfc5217SJeff Kirsher 	__set_bit(RAMROD_CONT, &p.ramrod_flags);
2092adfc5217SJeff Kirsher 
2093adfc5217SJeff Kirsher 	return bnx2x_config_vlan_mac(bp, &p);
2094adfc5217SJeff Kirsher }
2095adfc5217SJeff Kirsher 
bnx2x_init_raw_obj(struct bnx2x_raw_obj * raw,u8 cl_id,u32 cid,u8 func_id,void * rdata,dma_addr_t rdata_mapping,int state,unsigned long * pstate,bnx2x_obj_type type)2096adfc5217SJeff Kirsher static inline void bnx2x_init_raw_obj(struct bnx2x_raw_obj *raw, u8 cl_id,
2097adfc5217SJeff Kirsher 	u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping, int state,
2098adfc5217SJeff Kirsher 	unsigned long *pstate, bnx2x_obj_type type)
2099adfc5217SJeff Kirsher {
2100adfc5217SJeff Kirsher 	raw->func_id = func_id;
2101adfc5217SJeff Kirsher 	raw->cid = cid;
2102adfc5217SJeff Kirsher 	raw->cl_id = cl_id;
2103adfc5217SJeff Kirsher 	raw->rdata = rdata;
2104adfc5217SJeff Kirsher 	raw->rdata_mapping = rdata_mapping;
2105adfc5217SJeff Kirsher 	raw->state = state;
2106adfc5217SJeff Kirsher 	raw->pstate = pstate;
2107adfc5217SJeff Kirsher 	raw->obj_type = type;
2108adfc5217SJeff Kirsher 	raw->check_pending = bnx2x_raw_check_pending;
2109adfc5217SJeff Kirsher 	raw->clear_pending = bnx2x_raw_clear_pending;
2110adfc5217SJeff Kirsher 	raw->set_pending = bnx2x_raw_set_pending;
2111adfc5217SJeff Kirsher 	raw->wait_comp = bnx2x_raw_wait;
2112adfc5217SJeff Kirsher }
2113adfc5217SJeff Kirsher 
bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj * o,u8 cl_id,u32 cid,u8 func_id,void * rdata,dma_addr_t rdata_mapping,int state,unsigned long * pstate,bnx2x_obj_type type,struct bnx2x_credit_pool_obj * macs_pool,struct bnx2x_credit_pool_obj * vlans_pool)2114adfc5217SJeff Kirsher static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o,
2115adfc5217SJeff Kirsher 	u8 cl_id, u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping,
2116adfc5217SJeff Kirsher 	int state, unsigned long *pstate, bnx2x_obj_type type,
2117adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *macs_pool,
2118adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vlans_pool)
2119adfc5217SJeff Kirsher {
2120adfc5217SJeff Kirsher 	INIT_LIST_HEAD(&o->head);
21218b09be5fSYuval Mintz 	o->head_reader = 0;
21228b09be5fSYuval Mintz 	o->head_exe_request = false;
21238b09be5fSYuval Mintz 	o->saved_ramrod_flags = 0;
2124adfc5217SJeff Kirsher 
2125adfc5217SJeff Kirsher 	o->macs_pool = macs_pool;
2126adfc5217SJeff Kirsher 	o->vlans_pool = vlans_pool;
2127adfc5217SJeff Kirsher 
2128adfc5217SJeff Kirsher 	o->delete_all = bnx2x_vlan_mac_del_all;
2129adfc5217SJeff Kirsher 	o->restore = bnx2x_vlan_mac_restore;
2130adfc5217SJeff Kirsher 	o->complete = bnx2x_complete_vlan_mac;
2131adfc5217SJeff Kirsher 	o->wait = bnx2x_wait_vlan_mac;
2132adfc5217SJeff Kirsher 
2133adfc5217SJeff Kirsher 	bnx2x_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping,
2134adfc5217SJeff Kirsher 			   state, pstate, type);
2135adfc5217SJeff Kirsher }
2136adfc5217SJeff Kirsher 
bnx2x_init_mac_obj(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * mac_obj,u8 cl_id,u32 cid,u8 func_id,void * rdata,dma_addr_t rdata_mapping,int state,unsigned long * pstate,bnx2x_obj_type type,struct bnx2x_credit_pool_obj * macs_pool)2137adfc5217SJeff Kirsher void bnx2x_init_mac_obj(struct bnx2x *bp,
2138adfc5217SJeff Kirsher 			struct bnx2x_vlan_mac_obj *mac_obj,
2139adfc5217SJeff Kirsher 			u8 cl_id, u32 cid, u8 func_id, void *rdata,
2140adfc5217SJeff Kirsher 			dma_addr_t rdata_mapping, int state,
2141adfc5217SJeff Kirsher 			unsigned long *pstate, bnx2x_obj_type type,
2142adfc5217SJeff Kirsher 			struct bnx2x_credit_pool_obj *macs_pool)
2143adfc5217SJeff Kirsher {
2144adfc5217SJeff Kirsher 	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)mac_obj;
2145adfc5217SJeff Kirsher 
2146adfc5217SJeff Kirsher 	bnx2x_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata,
2147adfc5217SJeff Kirsher 				   rdata_mapping, state, pstate, type,
2148adfc5217SJeff Kirsher 				   macs_pool, NULL);
2149adfc5217SJeff Kirsher 
2150adfc5217SJeff Kirsher 	/* CAM credit pool handling */
2151adfc5217SJeff Kirsher 	mac_obj->get_credit = bnx2x_get_credit_mac;
2152adfc5217SJeff Kirsher 	mac_obj->put_credit = bnx2x_put_credit_mac;
2153adfc5217SJeff Kirsher 	mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
2154adfc5217SJeff Kirsher 	mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
2155adfc5217SJeff Kirsher 
2156adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp)) {
2157adfc5217SJeff Kirsher 		mac_obj->set_one_rule      = bnx2x_set_one_mac_e1x;
2158adfc5217SJeff Kirsher 		mac_obj->check_del         = bnx2x_check_mac_del;
2159adfc5217SJeff Kirsher 		mac_obj->check_add         = bnx2x_check_mac_add;
2160adfc5217SJeff Kirsher 		mac_obj->check_move        = bnx2x_check_move_always_err;
2161adfc5217SJeff Kirsher 		mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
2162adfc5217SJeff Kirsher 
2163adfc5217SJeff Kirsher 		/* Exe Queue */
2164adfc5217SJeff Kirsher 		bnx2x_exe_queue_init(bp,
2165adfc5217SJeff Kirsher 				     &mac_obj->exe_queue, 1, qable_obj,
2166adfc5217SJeff Kirsher 				     bnx2x_validate_vlan_mac,
2167460a25cdSYuval Mintz 				     bnx2x_remove_vlan_mac,
2168adfc5217SJeff Kirsher 				     bnx2x_optimize_vlan_mac,
2169adfc5217SJeff Kirsher 				     bnx2x_execute_vlan_mac,
2170adfc5217SJeff Kirsher 				     bnx2x_exeq_get_mac);
2171adfc5217SJeff Kirsher 	} else {
2172adfc5217SJeff Kirsher 		mac_obj->set_one_rule      = bnx2x_set_one_mac_e2;
2173adfc5217SJeff Kirsher 		mac_obj->check_del         = bnx2x_check_mac_del;
2174adfc5217SJeff Kirsher 		mac_obj->check_add         = bnx2x_check_mac_add;
2175adfc5217SJeff Kirsher 		mac_obj->check_move        = bnx2x_check_move;
2176adfc5217SJeff Kirsher 		mac_obj->ramrod_cmd        =
2177adfc5217SJeff Kirsher 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
2178ed5162a0SAriel Elior 		mac_obj->get_n_elements    = bnx2x_get_n_elements;
2179adfc5217SJeff Kirsher 
2180adfc5217SJeff Kirsher 		/* Exe Queue */
2181adfc5217SJeff Kirsher 		bnx2x_exe_queue_init(bp,
2182adfc5217SJeff Kirsher 				     &mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
2183adfc5217SJeff Kirsher 				     qable_obj, bnx2x_validate_vlan_mac,
2184460a25cdSYuval Mintz 				     bnx2x_remove_vlan_mac,
2185adfc5217SJeff Kirsher 				     bnx2x_optimize_vlan_mac,
2186adfc5217SJeff Kirsher 				     bnx2x_execute_vlan_mac,
2187adfc5217SJeff Kirsher 				     bnx2x_exeq_get_mac);
2188adfc5217SJeff Kirsher 	}
2189adfc5217SJeff Kirsher }
2190adfc5217SJeff Kirsher 
bnx2x_init_vlan_obj(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * vlan_obj,u8 cl_id,u32 cid,u8 func_id,void * rdata,dma_addr_t rdata_mapping,int state,unsigned long * pstate,bnx2x_obj_type type,struct bnx2x_credit_pool_obj * vlans_pool)2191adfc5217SJeff Kirsher void bnx2x_init_vlan_obj(struct bnx2x *bp,
2192adfc5217SJeff Kirsher 			 struct bnx2x_vlan_mac_obj *vlan_obj,
2193adfc5217SJeff Kirsher 			 u8 cl_id, u32 cid, u8 func_id, void *rdata,
2194adfc5217SJeff Kirsher 			 dma_addr_t rdata_mapping, int state,
2195adfc5217SJeff Kirsher 			 unsigned long *pstate, bnx2x_obj_type type,
2196adfc5217SJeff Kirsher 			 struct bnx2x_credit_pool_obj *vlans_pool)
2197adfc5217SJeff Kirsher {
2198adfc5217SJeff Kirsher 	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)vlan_obj;
2199adfc5217SJeff Kirsher 
2200adfc5217SJeff Kirsher 	bnx2x_init_vlan_mac_common(vlan_obj, cl_id, cid, func_id, rdata,
2201adfc5217SJeff Kirsher 				   rdata_mapping, state, pstate, type, NULL,
2202adfc5217SJeff Kirsher 				   vlans_pool);
2203adfc5217SJeff Kirsher 
2204adfc5217SJeff Kirsher 	vlan_obj->get_credit = bnx2x_get_credit_vlan;
2205adfc5217SJeff Kirsher 	vlan_obj->put_credit = bnx2x_put_credit_vlan;
2206adfc5217SJeff Kirsher 	vlan_obj->get_cam_offset = bnx2x_get_cam_offset_vlan;
2207adfc5217SJeff Kirsher 	vlan_obj->put_cam_offset = bnx2x_put_cam_offset_vlan;
2208adfc5217SJeff Kirsher 
2209adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp)) {
2210adfc5217SJeff Kirsher 		BNX2X_ERR("Do not support chips others than E2 and newer\n");
2211adfc5217SJeff Kirsher 		BUG();
2212adfc5217SJeff Kirsher 	} else {
2213adfc5217SJeff Kirsher 		vlan_obj->set_one_rule      = bnx2x_set_one_vlan_e2;
2214adfc5217SJeff Kirsher 		vlan_obj->check_del         = bnx2x_check_vlan_del;
2215adfc5217SJeff Kirsher 		vlan_obj->check_add         = bnx2x_check_vlan_add;
2216adfc5217SJeff Kirsher 		vlan_obj->check_move        = bnx2x_check_move;
2217adfc5217SJeff Kirsher 		vlan_obj->ramrod_cmd        =
2218adfc5217SJeff Kirsher 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
22193ec9f9caSAriel Elior 		vlan_obj->get_n_elements    = bnx2x_get_n_elements;
2220adfc5217SJeff Kirsher 
2221adfc5217SJeff Kirsher 		/* Exe Queue */
2222adfc5217SJeff Kirsher 		bnx2x_exe_queue_init(bp,
2223adfc5217SJeff Kirsher 				     &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
2224adfc5217SJeff Kirsher 				     qable_obj, bnx2x_validate_vlan_mac,
2225460a25cdSYuval Mintz 				     bnx2x_remove_vlan_mac,
2226adfc5217SJeff Kirsher 				     bnx2x_optimize_vlan_mac,
2227adfc5217SJeff Kirsher 				     bnx2x_execute_vlan_mac,
2228adfc5217SJeff Kirsher 				     bnx2x_exeq_get_vlan);
2229adfc5217SJeff Kirsher 	}
2230adfc5217SJeff Kirsher }
2231adfc5217SJeff Kirsher 
bnx2x_init_vlan_mac_obj(struct bnx2x * bp,struct bnx2x_vlan_mac_obj * vlan_mac_obj,u8 cl_id,u32 cid,u8 func_id,void * rdata,dma_addr_t rdata_mapping,int state,unsigned long * pstate,bnx2x_obj_type type,struct bnx2x_credit_pool_obj * macs_pool,struct bnx2x_credit_pool_obj * vlans_pool)223205cc5a39SYuval Mintz void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
223305cc5a39SYuval Mintz 			     struct bnx2x_vlan_mac_obj *vlan_mac_obj,
223405cc5a39SYuval Mintz 			     u8 cl_id, u32 cid, u8 func_id, void *rdata,
223505cc5a39SYuval Mintz 			     dma_addr_t rdata_mapping, int state,
223605cc5a39SYuval Mintz 			     unsigned long *pstate, bnx2x_obj_type type,
223705cc5a39SYuval Mintz 			     struct bnx2x_credit_pool_obj *macs_pool,
223805cc5a39SYuval Mintz 			     struct bnx2x_credit_pool_obj *vlans_pool)
223905cc5a39SYuval Mintz {
224005cc5a39SYuval Mintz 	union bnx2x_qable_obj *qable_obj =
224105cc5a39SYuval Mintz 		(union bnx2x_qable_obj *)vlan_mac_obj;
224205cc5a39SYuval Mintz 
224305cc5a39SYuval Mintz 	bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
224405cc5a39SYuval Mintz 				   rdata_mapping, state, pstate, type,
224505cc5a39SYuval Mintz 				   macs_pool, vlans_pool);
224605cc5a39SYuval Mintz 
224705cc5a39SYuval Mintz 	/* CAM pool handling */
224805cc5a39SYuval Mintz 	vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac;
224905cc5a39SYuval Mintz 	vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac;
225005cc5a39SYuval Mintz 	/* CAM offset is relevant for 57710 and 57711 chips only which have a
225105cc5a39SYuval Mintz 	 * single CAM for both MACs and VLAN-MAC pairs. So the offset
225205cc5a39SYuval Mintz 	 * will be taken from MACs' pool object only.
225305cc5a39SYuval Mintz 	 */
225405cc5a39SYuval Mintz 	vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
225505cc5a39SYuval Mintz 	vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
225605cc5a39SYuval Mintz 
225705cc5a39SYuval Mintz 	if (CHIP_IS_E1(bp)) {
225805cc5a39SYuval Mintz 		BNX2X_ERR("Do not support chips others than E2\n");
225905cc5a39SYuval Mintz 		BUG();
226005cc5a39SYuval Mintz 	} else if (CHIP_IS_E1H(bp)) {
226105cc5a39SYuval Mintz 		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e1h;
226205cc5a39SYuval Mintz 		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
226305cc5a39SYuval Mintz 		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
226405cc5a39SYuval Mintz 		vlan_mac_obj->check_move        = bnx2x_check_move_always_err;
226505cc5a39SYuval Mintz 		vlan_mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
226605cc5a39SYuval Mintz 
226705cc5a39SYuval Mintz 		/* Exe Queue */
226805cc5a39SYuval Mintz 		bnx2x_exe_queue_init(bp,
226905cc5a39SYuval Mintz 				     &vlan_mac_obj->exe_queue, 1, qable_obj,
227005cc5a39SYuval Mintz 				     bnx2x_validate_vlan_mac,
227105cc5a39SYuval Mintz 				     bnx2x_remove_vlan_mac,
227205cc5a39SYuval Mintz 				     bnx2x_optimize_vlan_mac,
227305cc5a39SYuval Mintz 				     bnx2x_execute_vlan_mac,
227405cc5a39SYuval Mintz 				     bnx2x_exeq_get_vlan_mac);
227505cc5a39SYuval Mintz 	} else {
227605cc5a39SYuval Mintz 		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e2;
227705cc5a39SYuval Mintz 		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
227805cc5a39SYuval Mintz 		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
227905cc5a39SYuval Mintz 		vlan_mac_obj->check_move        = bnx2x_check_move;
228005cc5a39SYuval Mintz 		vlan_mac_obj->ramrod_cmd        =
228105cc5a39SYuval Mintz 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
228205cc5a39SYuval Mintz 
228305cc5a39SYuval Mintz 		/* Exe Queue */
228405cc5a39SYuval Mintz 		bnx2x_exe_queue_init(bp,
228505cc5a39SYuval Mintz 				     &vlan_mac_obj->exe_queue,
228605cc5a39SYuval Mintz 				     CLASSIFY_RULES_COUNT,
228705cc5a39SYuval Mintz 				     qable_obj, bnx2x_validate_vlan_mac,
228805cc5a39SYuval Mintz 				     bnx2x_remove_vlan_mac,
228905cc5a39SYuval Mintz 				     bnx2x_optimize_vlan_mac,
229005cc5a39SYuval Mintz 				     bnx2x_execute_vlan_mac,
229105cc5a39SYuval Mintz 				     bnx2x_exeq_get_vlan_mac);
229205cc5a39SYuval Mintz 	}
229305cc5a39SYuval Mintz }
2294adfc5217SJeff Kirsher /* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
__storm_memset_mac_filters(struct bnx2x * bp,struct tstorm_eth_mac_filter_config * mac_filters,u16 pf_id)2295adfc5217SJeff Kirsher static inline void __storm_memset_mac_filters(struct bnx2x *bp,
2296adfc5217SJeff Kirsher 			struct tstorm_eth_mac_filter_config *mac_filters,
2297adfc5217SJeff Kirsher 			u16 pf_id)
2298adfc5217SJeff Kirsher {
2299adfc5217SJeff Kirsher 	size_t size = sizeof(struct tstorm_eth_mac_filter_config);
2300adfc5217SJeff Kirsher 
2301adfc5217SJeff Kirsher 	u32 addr = BAR_TSTRORM_INTMEM +
2302adfc5217SJeff Kirsher 			TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id);
2303adfc5217SJeff Kirsher 
2304adfc5217SJeff Kirsher 	__storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
2305adfc5217SJeff Kirsher }
2306adfc5217SJeff Kirsher 
bnx2x_set_rx_mode_e1x(struct bnx2x * bp,struct bnx2x_rx_mode_ramrod_params * p)2307adfc5217SJeff Kirsher static int bnx2x_set_rx_mode_e1x(struct bnx2x *bp,
2308adfc5217SJeff Kirsher 				 struct bnx2x_rx_mode_ramrod_params *p)
2309adfc5217SJeff Kirsher {
2310adfc5217SJeff Kirsher 	/* update the bp MAC filter structure */
2311adfc5217SJeff Kirsher 	u32 mask = (1 << p->cl_id);
2312adfc5217SJeff Kirsher 
2313adfc5217SJeff Kirsher 	struct tstorm_eth_mac_filter_config *mac_filters =
2314adfc5217SJeff Kirsher 		(struct tstorm_eth_mac_filter_config *)p->rdata;
2315adfc5217SJeff Kirsher 
231616a5fd92SYuval Mintz 	/* initial setting is drop-all */
2317adfc5217SJeff Kirsher 	u8 drop_all_ucast = 1, drop_all_mcast = 1;
2318adfc5217SJeff Kirsher 	u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
2319adfc5217SJeff Kirsher 	u8 unmatched_unicast = 0;
2320adfc5217SJeff Kirsher 
232116a5fd92SYuval Mintz     /* In e1x there we only take into account rx accept flag since tx switching
2322adfc5217SJeff Kirsher      * isn't enabled. */
2323adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags))
2324adfc5217SJeff Kirsher 		/* accept matched ucast */
2325adfc5217SJeff Kirsher 		drop_all_ucast = 0;
2326adfc5217SJeff Kirsher 
2327adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_MULTICAST, &p->rx_accept_flags))
2328adfc5217SJeff Kirsher 		/* accept matched mcast */
2329adfc5217SJeff Kirsher 		drop_all_mcast = 0;
2330adfc5217SJeff Kirsher 
2331adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) {
2332adfc5217SJeff Kirsher 		/* accept all mcast */
2333adfc5217SJeff Kirsher 		drop_all_ucast = 0;
2334adfc5217SJeff Kirsher 		accp_all_ucast = 1;
2335adfc5217SJeff Kirsher 	}
2336adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) {
2337adfc5217SJeff Kirsher 		/* accept all mcast */
2338adfc5217SJeff Kirsher 		drop_all_mcast = 0;
2339adfc5217SJeff Kirsher 		accp_all_mcast = 1;
2340adfc5217SJeff Kirsher 	}
2341adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_BROADCAST, &p->rx_accept_flags))
2342adfc5217SJeff Kirsher 		/* accept (all) bcast */
2343adfc5217SJeff Kirsher 		accp_all_bcast = 1;
2344adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_UNMATCHED, &p->rx_accept_flags))
2345adfc5217SJeff Kirsher 		/* accept unmatched unicasts */
2346adfc5217SJeff Kirsher 		unmatched_unicast = 1;
2347adfc5217SJeff Kirsher 
2348adfc5217SJeff Kirsher 	mac_filters->ucast_drop_all = drop_all_ucast ?
2349adfc5217SJeff Kirsher 		mac_filters->ucast_drop_all | mask :
2350adfc5217SJeff Kirsher 		mac_filters->ucast_drop_all & ~mask;
2351adfc5217SJeff Kirsher 
2352adfc5217SJeff Kirsher 	mac_filters->mcast_drop_all = drop_all_mcast ?
2353adfc5217SJeff Kirsher 		mac_filters->mcast_drop_all | mask :
2354adfc5217SJeff Kirsher 		mac_filters->mcast_drop_all & ~mask;
2355adfc5217SJeff Kirsher 
2356adfc5217SJeff Kirsher 	mac_filters->ucast_accept_all = accp_all_ucast ?
2357adfc5217SJeff Kirsher 		mac_filters->ucast_accept_all | mask :
2358adfc5217SJeff Kirsher 		mac_filters->ucast_accept_all & ~mask;
2359adfc5217SJeff Kirsher 
2360adfc5217SJeff Kirsher 	mac_filters->mcast_accept_all = accp_all_mcast ?
2361adfc5217SJeff Kirsher 		mac_filters->mcast_accept_all | mask :
2362adfc5217SJeff Kirsher 		mac_filters->mcast_accept_all & ~mask;
2363adfc5217SJeff Kirsher 
2364adfc5217SJeff Kirsher 	mac_filters->bcast_accept_all = accp_all_bcast ?
2365adfc5217SJeff Kirsher 		mac_filters->bcast_accept_all | mask :
2366adfc5217SJeff Kirsher 		mac_filters->bcast_accept_all & ~mask;
2367adfc5217SJeff Kirsher 
2368adfc5217SJeff Kirsher 	mac_filters->unmatched_unicast = unmatched_unicast ?
2369adfc5217SJeff Kirsher 		mac_filters->unmatched_unicast | mask :
2370adfc5217SJeff Kirsher 		mac_filters->unmatched_unicast & ~mask;
2371adfc5217SJeff Kirsher 
2372adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "drop_ucast 0x%x\ndrop_mcast 0x%x\n accp_ucast 0x%x\n"
2373adfc5217SJeff Kirsher 			 "accp_mcast 0x%x\naccp_bcast 0x%x\n",
237451c1a580SMerav Sicron 	   mac_filters->ucast_drop_all, mac_filters->mcast_drop_all,
237551c1a580SMerav Sicron 	   mac_filters->ucast_accept_all, mac_filters->mcast_accept_all,
2376adfc5217SJeff Kirsher 	   mac_filters->bcast_accept_all);
2377adfc5217SJeff Kirsher 
2378adfc5217SJeff Kirsher 	/* write the MAC filter structure*/
2379adfc5217SJeff Kirsher 	__storm_memset_mac_filters(bp, mac_filters, p->func_id);
2380adfc5217SJeff Kirsher 
2381adfc5217SJeff Kirsher 	/* The operation is completed */
2382adfc5217SJeff Kirsher 	clear_bit(p->state, p->pstate);
23834e857c58SPeter Zijlstra 	smp_mb__after_atomic();
2384adfc5217SJeff Kirsher 
2385adfc5217SJeff Kirsher 	return 0;
2386adfc5217SJeff Kirsher }
2387adfc5217SJeff Kirsher 
2388adfc5217SJeff Kirsher /* Setup ramrod data */
bnx2x_rx_mode_set_rdata_hdr_e2(u32 cid,struct eth_classify_header * hdr,u8 rule_cnt)2389adfc5217SJeff Kirsher static inline void bnx2x_rx_mode_set_rdata_hdr_e2(u32 cid,
2390adfc5217SJeff Kirsher 				struct eth_classify_header *hdr,
2391adfc5217SJeff Kirsher 				u8 rule_cnt)
2392adfc5217SJeff Kirsher {
239386564c3fSYuval Mintz 	hdr->echo = cpu_to_le32(cid);
2394adfc5217SJeff Kirsher 	hdr->rule_cnt = rule_cnt;
2395adfc5217SJeff Kirsher }
2396adfc5217SJeff Kirsher 
bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x * bp,unsigned long * accept_flags,struct eth_filter_rules_cmd * cmd,bool clear_accept_all)2397adfc5217SJeff Kirsher static inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp,
2398924d75abSYuval Mintz 				unsigned long *accept_flags,
2399adfc5217SJeff Kirsher 				struct eth_filter_rules_cmd *cmd,
2400adfc5217SJeff Kirsher 				bool clear_accept_all)
2401adfc5217SJeff Kirsher {
2402adfc5217SJeff Kirsher 	u16 state;
2403adfc5217SJeff Kirsher 
2404adfc5217SJeff Kirsher 	/* start with 'drop-all' */
2405adfc5217SJeff Kirsher 	state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL |
2406adfc5217SJeff Kirsher 		ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
2407adfc5217SJeff Kirsher 
2408924d75abSYuval Mintz 	if (test_bit(BNX2X_ACCEPT_UNICAST, accept_flags))
2409adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
2410adfc5217SJeff Kirsher 
2411924d75abSYuval Mintz 	if (test_bit(BNX2X_ACCEPT_MULTICAST, accept_flags))
2412adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
2413adfc5217SJeff Kirsher 
2414924d75abSYuval Mintz 	if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, accept_flags)) {
2415adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
2416adfc5217SJeff Kirsher 		state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
2417adfc5217SJeff Kirsher 	}
2418adfc5217SJeff Kirsher 
2419924d75abSYuval Mintz 	if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, accept_flags)) {
2420adfc5217SJeff Kirsher 		state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
2421adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
2422adfc5217SJeff Kirsher 	}
2423924d75abSYuval Mintz 
2424924d75abSYuval Mintz 	if (test_bit(BNX2X_ACCEPT_BROADCAST, accept_flags))
2425adfc5217SJeff Kirsher 		state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
2426adfc5217SJeff Kirsher 
2427924d75abSYuval Mintz 	if (test_bit(BNX2X_ACCEPT_UNMATCHED, accept_flags)) {
2428adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
2429adfc5217SJeff Kirsher 		state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
2430adfc5217SJeff Kirsher 	}
2431924d75abSYuval Mintz 
2432924d75abSYuval Mintz 	if (test_bit(BNX2X_ACCEPT_ANY_VLAN, accept_flags))
2433adfc5217SJeff Kirsher 		state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN;
2434adfc5217SJeff Kirsher 
2435adfc5217SJeff Kirsher 	/* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */
2436adfc5217SJeff Kirsher 	if (clear_accept_all) {
2437adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
2438adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
2439adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
2440adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
2441adfc5217SJeff Kirsher 	}
2442adfc5217SJeff Kirsher 
2443adfc5217SJeff Kirsher 	cmd->state = cpu_to_le16(state);
2444adfc5217SJeff Kirsher }
2445adfc5217SJeff Kirsher 
bnx2x_set_rx_mode_e2(struct bnx2x * bp,struct bnx2x_rx_mode_ramrod_params * p)2446adfc5217SJeff Kirsher static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
2447adfc5217SJeff Kirsher 				struct bnx2x_rx_mode_ramrod_params *p)
2448adfc5217SJeff Kirsher {
2449adfc5217SJeff Kirsher 	struct eth_filter_rules_ramrod_data *data = p->rdata;
2450adfc5217SJeff Kirsher 	int rc;
2451adfc5217SJeff Kirsher 	u8 rule_idx = 0;
2452adfc5217SJeff Kirsher 
2453adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer */
2454adfc5217SJeff Kirsher 	memset(data, 0, sizeof(*data));
2455adfc5217SJeff Kirsher 
2456adfc5217SJeff Kirsher 	/* Setup ramrod data */
2457adfc5217SJeff Kirsher 
2458adfc5217SJeff Kirsher 	/* Tx (internal switching) */
2459adfc5217SJeff Kirsher 	if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
2460adfc5217SJeff Kirsher 		data->rules[rule_idx].client_id = p->cl_id;
2461adfc5217SJeff Kirsher 		data->rules[rule_idx].func_id = p->func_id;
2462adfc5217SJeff Kirsher 
2463adfc5217SJeff Kirsher 		data->rules[rule_idx].cmd_general_data =
2464adfc5217SJeff Kirsher 			ETH_FILTER_RULES_CMD_TX_CMD;
2465adfc5217SJeff Kirsher 
2466924d75abSYuval Mintz 		bnx2x_rx_mode_set_cmd_state_e2(bp, &p->tx_accept_flags,
2467924d75abSYuval Mintz 					       &(data->rules[rule_idx++]),
2468924d75abSYuval Mintz 					       false);
2469adfc5217SJeff Kirsher 	}
2470adfc5217SJeff Kirsher 
2471adfc5217SJeff Kirsher 	/* Rx */
2472adfc5217SJeff Kirsher 	if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
2473adfc5217SJeff Kirsher 		data->rules[rule_idx].client_id = p->cl_id;
2474adfc5217SJeff Kirsher 		data->rules[rule_idx].func_id = p->func_id;
2475adfc5217SJeff Kirsher 
2476adfc5217SJeff Kirsher 		data->rules[rule_idx].cmd_general_data =
2477adfc5217SJeff Kirsher 			ETH_FILTER_RULES_CMD_RX_CMD;
2478adfc5217SJeff Kirsher 
2479924d75abSYuval Mintz 		bnx2x_rx_mode_set_cmd_state_e2(bp, &p->rx_accept_flags,
2480924d75abSYuval Mintz 					       &(data->rules[rule_idx++]),
2481924d75abSYuval Mintz 					       false);
2482adfc5217SJeff Kirsher 	}
2483adfc5217SJeff Kirsher 
248416a5fd92SYuval Mintz 	/* If FCoE Queue configuration has been requested configure the Rx and
2485adfc5217SJeff Kirsher 	 * internal switching modes for this queue in separate rules.
2486adfc5217SJeff Kirsher 	 *
2487adfc5217SJeff Kirsher 	 * FCoE queue shell never be set to ACCEPT_ALL packets of any sort:
2488adfc5217SJeff Kirsher 	 * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED.
2489adfc5217SJeff Kirsher 	 */
2490adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) {
2491adfc5217SJeff Kirsher 		/*  Tx (internal switching) */
2492adfc5217SJeff Kirsher 		if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
2493adfc5217SJeff Kirsher 			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
2494adfc5217SJeff Kirsher 			data->rules[rule_idx].func_id = p->func_id;
2495adfc5217SJeff Kirsher 
2496adfc5217SJeff Kirsher 			data->rules[rule_idx].cmd_general_data =
2497adfc5217SJeff Kirsher 						ETH_FILTER_RULES_CMD_TX_CMD;
2498adfc5217SJeff Kirsher 
2499924d75abSYuval Mintz 			bnx2x_rx_mode_set_cmd_state_e2(bp, &p->tx_accept_flags,
2500924d75abSYuval Mintz 						       &(data->rules[rule_idx]),
2501adfc5217SJeff Kirsher 						       true);
2502924d75abSYuval Mintz 			rule_idx++;
2503adfc5217SJeff Kirsher 		}
2504adfc5217SJeff Kirsher 
2505adfc5217SJeff Kirsher 		/* Rx */
2506adfc5217SJeff Kirsher 		if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
2507adfc5217SJeff Kirsher 			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
2508adfc5217SJeff Kirsher 			data->rules[rule_idx].func_id = p->func_id;
2509adfc5217SJeff Kirsher 
2510adfc5217SJeff Kirsher 			data->rules[rule_idx].cmd_general_data =
2511adfc5217SJeff Kirsher 						ETH_FILTER_RULES_CMD_RX_CMD;
2512adfc5217SJeff Kirsher 
2513924d75abSYuval Mintz 			bnx2x_rx_mode_set_cmd_state_e2(bp, &p->rx_accept_flags,
2514924d75abSYuval Mintz 						       &(data->rules[rule_idx]),
2515adfc5217SJeff Kirsher 						       true);
2516924d75abSYuval Mintz 			rule_idx++;
2517adfc5217SJeff Kirsher 		}
2518adfc5217SJeff Kirsher 	}
2519adfc5217SJeff Kirsher 
252016a5fd92SYuval Mintz 	/* Set the ramrod header (most importantly - number of rules to
2521adfc5217SJeff Kirsher 	 * configure).
2522adfc5217SJeff Kirsher 	 */
2523adfc5217SJeff Kirsher 	bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx);
2524adfc5217SJeff Kirsher 
252551c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "About to configure %d rules, rx_accept_flags 0x%lx, tx_accept_flags 0x%lx\n",
2526adfc5217SJeff Kirsher 			 data->header.rule_cnt, p->rx_accept_flags,
2527adfc5217SJeff Kirsher 			 p->tx_accept_flags);
2528adfc5217SJeff Kirsher 
252914a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
253014a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
2531adfc5217SJeff Kirsher 	 * and updating of the SPQ producer which involves a memory
253214a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
253314a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
2534adfc5217SJeff Kirsher 	 */
2535adfc5217SJeff Kirsher 
2536adfc5217SJeff Kirsher 	/* Send a ramrod */
2537adfc5217SJeff Kirsher 	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid,
2538adfc5217SJeff Kirsher 			   U64_HI(p->rdata_mapping),
2539adfc5217SJeff Kirsher 			   U64_LO(p->rdata_mapping),
2540adfc5217SJeff Kirsher 			   ETH_CONNECTION_TYPE);
2541adfc5217SJeff Kirsher 	if (rc)
2542adfc5217SJeff Kirsher 		return rc;
2543adfc5217SJeff Kirsher 
2544adfc5217SJeff Kirsher 	/* Ramrod completion is pending */
2545adfc5217SJeff Kirsher 	return 1;
2546adfc5217SJeff Kirsher }
2547adfc5217SJeff Kirsher 
bnx2x_wait_rx_mode_comp_e2(struct bnx2x * bp,struct bnx2x_rx_mode_ramrod_params * p)2548adfc5217SJeff Kirsher static int bnx2x_wait_rx_mode_comp_e2(struct bnx2x *bp,
2549adfc5217SJeff Kirsher 				      struct bnx2x_rx_mode_ramrod_params *p)
2550adfc5217SJeff Kirsher {
2551adfc5217SJeff Kirsher 	return bnx2x_state_wait(bp, p->state, p->pstate);
2552adfc5217SJeff Kirsher }
2553adfc5217SJeff Kirsher 
bnx2x_empty_rx_mode_wait(struct bnx2x * bp,struct bnx2x_rx_mode_ramrod_params * p)2554adfc5217SJeff Kirsher static int bnx2x_empty_rx_mode_wait(struct bnx2x *bp,
2555adfc5217SJeff Kirsher 				    struct bnx2x_rx_mode_ramrod_params *p)
2556adfc5217SJeff Kirsher {
2557adfc5217SJeff Kirsher 	/* Do nothing */
2558adfc5217SJeff Kirsher 	return 0;
2559adfc5217SJeff Kirsher }
2560adfc5217SJeff Kirsher 
bnx2x_config_rx_mode(struct bnx2x * bp,struct bnx2x_rx_mode_ramrod_params * p)2561adfc5217SJeff Kirsher int bnx2x_config_rx_mode(struct bnx2x *bp,
2562adfc5217SJeff Kirsher 			 struct bnx2x_rx_mode_ramrod_params *p)
2563adfc5217SJeff Kirsher {
2564adfc5217SJeff Kirsher 	int rc;
2565adfc5217SJeff Kirsher 
2566adfc5217SJeff Kirsher 	/* Configure the new classification in the chip */
2567adfc5217SJeff Kirsher 	rc = p->rx_mode_obj->config_rx_mode(bp, p);
2568adfc5217SJeff Kirsher 	if (rc < 0)
2569adfc5217SJeff Kirsher 		return rc;
2570adfc5217SJeff Kirsher 
2571adfc5217SJeff Kirsher 	/* Wait for a ramrod completion if was requested */
2572adfc5217SJeff Kirsher 	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
2573adfc5217SJeff Kirsher 		rc = p->rx_mode_obj->wait_comp(bp, p);
2574adfc5217SJeff Kirsher 		if (rc)
2575adfc5217SJeff Kirsher 			return rc;
2576adfc5217SJeff Kirsher 	}
2577adfc5217SJeff Kirsher 
2578adfc5217SJeff Kirsher 	return rc;
2579adfc5217SJeff Kirsher }
2580adfc5217SJeff Kirsher 
bnx2x_init_rx_mode_obj(struct bnx2x * bp,struct bnx2x_rx_mode_obj * o)2581adfc5217SJeff Kirsher void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
2582adfc5217SJeff Kirsher 			    struct bnx2x_rx_mode_obj *o)
2583adfc5217SJeff Kirsher {
2584adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp)) {
2585adfc5217SJeff Kirsher 		o->wait_comp      = bnx2x_empty_rx_mode_wait;
2586adfc5217SJeff Kirsher 		o->config_rx_mode = bnx2x_set_rx_mode_e1x;
2587adfc5217SJeff Kirsher 	} else {
2588adfc5217SJeff Kirsher 		o->wait_comp      = bnx2x_wait_rx_mode_comp_e2;
2589adfc5217SJeff Kirsher 		o->config_rx_mode = bnx2x_set_rx_mode_e2;
2590adfc5217SJeff Kirsher 	}
2591adfc5217SJeff Kirsher }
2592adfc5217SJeff Kirsher 
2593adfc5217SJeff Kirsher /********************* Multicast verbs: SET, CLEAR ****************************/
bnx2x_mcast_bin_from_mac(u8 * mac)2594adfc5217SJeff Kirsher static inline u8 bnx2x_mcast_bin_from_mac(u8 *mac)
2595adfc5217SJeff Kirsher {
2596adfc5217SJeff Kirsher 	return (crc32c_le(0, mac, ETH_ALEN) >> 24) & 0xff;
2597adfc5217SJeff Kirsher }
2598adfc5217SJeff Kirsher 
2599adfc5217SJeff Kirsher struct bnx2x_mcast_mac_elem {
2600adfc5217SJeff Kirsher 	struct list_head link;
2601adfc5217SJeff Kirsher 	u8 mac[ETH_ALEN];
2602adfc5217SJeff Kirsher 	u8 pad[2]; /* For a natural alignment of the following buffer */
2603adfc5217SJeff Kirsher };
2604adfc5217SJeff Kirsher 
2605c7b7b483SYuval Mintz struct bnx2x_mcast_bin_elem {
2606c7b7b483SYuval Mintz 	struct list_head link;
2607c7b7b483SYuval Mintz 	int bin;
2608c7b7b483SYuval Mintz 	int type; /* BNX2X_MCAST_CMD_SET_{ADD, DEL} */
2609c7b7b483SYuval Mintz };
2610c7b7b483SYuval Mintz 
26113129e159SJason Baron union bnx2x_mcast_elem {
26123129e159SJason Baron 	struct bnx2x_mcast_bin_elem bin_elem;
26133129e159SJason Baron 	struct bnx2x_mcast_mac_elem mac_elem;
26143129e159SJason Baron };
26153129e159SJason Baron 
26163129e159SJason Baron struct bnx2x_mcast_elem_group {
26173129e159SJason Baron 	struct list_head mcast_group_link;
26183129e159SJason Baron 	union bnx2x_mcast_elem mcast_elems[];
26193129e159SJason Baron };
26203129e159SJason Baron 
26213129e159SJason Baron #define MCAST_MAC_ELEMS_PER_PG \
26223129e159SJason Baron 	((PAGE_SIZE - sizeof(struct bnx2x_mcast_elem_group)) / \
26233129e159SJason Baron 	sizeof(union bnx2x_mcast_elem))
26243129e159SJason Baron 
2625adfc5217SJeff Kirsher struct bnx2x_pending_mcast_cmd {
2626adfc5217SJeff Kirsher 	struct list_head link;
26273129e159SJason Baron 	struct list_head group_head;
2628adfc5217SJeff Kirsher 	int type; /* BNX2X_MCAST_CMD_X */
2629adfc5217SJeff Kirsher 	union {
2630adfc5217SJeff Kirsher 		struct list_head macs_head;
2631adfc5217SJeff Kirsher 		u32 macs_num; /* Needed for DEL command */
2632adfc5217SJeff Kirsher 		int next_bin; /* Needed for RESTORE flow with aprox match */
2633adfc5217SJeff Kirsher 	} data;
2634adfc5217SJeff Kirsher 
2635c7b7b483SYuval Mintz 	bool set_convert; /* in case type == BNX2X_MCAST_CMD_SET, this is set
2636c7b7b483SYuval Mintz 			   * when macs_head had been converted to a list of
2637c7b7b483SYuval Mintz 			   * bnx2x_mcast_bin_elem.
2638c7b7b483SYuval Mintz 			   */
2639c7b7b483SYuval Mintz 
2640adfc5217SJeff Kirsher 	bool done; /* set to true, when the command has been handled,
2641adfc5217SJeff Kirsher 		    * practically used in 57712 handling only, where one pending
2642adfc5217SJeff Kirsher 		    * command may be handled in a few operations. As long as for
2643adfc5217SJeff Kirsher 		    * other chips every operation handling is completed in a
2644adfc5217SJeff Kirsher 		    * single ramrod, there is no need to utilize this field.
2645adfc5217SJeff Kirsher 		    */
2646adfc5217SJeff Kirsher };
2647adfc5217SJeff Kirsher 
bnx2x_mcast_wait(struct bnx2x * bp,struct bnx2x_mcast_obj * o)2648adfc5217SJeff Kirsher static int bnx2x_mcast_wait(struct bnx2x *bp,
2649adfc5217SJeff Kirsher 			    struct bnx2x_mcast_obj *o)
2650adfc5217SJeff Kirsher {
2651adfc5217SJeff Kirsher 	if (bnx2x_state_wait(bp, o->sched_state, o->raw.pstate) ||
2652adfc5217SJeff Kirsher 			o->raw.wait_comp(bp, &o->raw))
2653adfc5217SJeff Kirsher 		return -EBUSY;
2654adfc5217SJeff Kirsher 
2655adfc5217SJeff Kirsher 	return 0;
2656adfc5217SJeff Kirsher }
2657adfc5217SJeff Kirsher 
bnx2x_free_groups(struct list_head * mcast_group_list)26583129e159SJason Baron static void bnx2x_free_groups(struct list_head *mcast_group_list)
26593129e159SJason Baron {
26603129e159SJason Baron 	struct bnx2x_mcast_elem_group *current_mcast_group;
26613129e159SJason Baron 
26623129e159SJason Baron 	while (!list_empty(mcast_group_list)) {
26633129e159SJason Baron 		current_mcast_group = list_first_entry(mcast_group_list,
26643129e159SJason Baron 				      struct bnx2x_mcast_elem_group,
26653129e159SJason Baron 				      mcast_group_link);
26663129e159SJason Baron 		list_del(&current_mcast_group->mcast_group_link);
26673129e159SJason Baron 		free_page((unsigned long)current_mcast_group);
26683129e159SJason Baron 	}
26693129e159SJason Baron }
26703129e159SJason Baron 
bnx2x_mcast_enqueue_cmd(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_mcast_ramrod_params * p,enum bnx2x_mcast_cmd cmd)2671adfc5217SJeff Kirsher static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
2672adfc5217SJeff Kirsher 				   struct bnx2x_mcast_obj *o,
2673adfc5217SJeff Kirsher 				   struct bnx2x_mcast_ramrod_params *p,
267486564c3fSYuval Mintz 				   enum bnx2x_mcast_cmd cmd)
2675adfc5217SJeff Kirsher {
2676adfc5217SJeff Kirsher 	struct bnx2x_pending_mcast_cmd *new_cmd;
2677adfc5217SJeff Kirsher 	struct bnx2x_mcast_list_elem *pos;
26783129e159SJason Baron 	struct bnx2x_mcast_elem_group *elem_group;
26793129e159SJason Baron 	struct bnx2x_mcast_mac_elem *mac_elem;
26803129e159SJason Baron 	int total_elems = 0, macs_list_len = 0, offset = 0;
2681c7b7b483SYuval Mintz 
2682c7b7b483SYuval Mintz 	/* When adding MACs we'll need to store their values */
2683c7b7b483SYuval Mintz 	if (cmd == BNX2X_MCAST_CMD_ADD || cmd == BNX2X_MCAST_CMD_SET)
2684c7b7b483SYuval Mintz 		macs_list_len = p->mcast_list_len;
2685adfc5217SJeff Kirsher 
2686adfc5217SJeff Kirsher 	/* If the command is empty ("handle pending commands only"), break */
2687adfc5217SJeff Kirsher 	if (!p->mcast_list_len)
2688adfc5217SJeff Kirsher 		return 0;
2689adfc5217SJeff Kirsher 
2690adfc5217SJeff Kirsher 	/* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
26913129e159SJason Baron 	new_cmd = kzalloc(sizeof(*new_cmd), GFP_ATOMIC);
2692adfc5217SJeff Kirsher 	if (!new_cmd)
2693adfc5217SJeff Kirsher 		return -ENOMEM;
2694adfc5217SJeff Kirsher 
26953129e159SJason Baron 	INIT_LIST_HEAD(&new_cmd->data.macs_head);
26963129e159SJason Baron 	INIT_LIST_HEAD(&new_cmd->group_head);
26973129e159SJason Baron 	new_cmd->type = cmd;
26983129e159SJason Baron 	new_cmd->done = false;
26993129e159SJason Baron 
270051c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "About to enqueue a new %d command. macs_list_len=%d\n",
270151c1a580SMerav Sicron 	   cmd, macs_list_len);
2702adfc5217SJeff Kirsher 
2703adfc5217SJeff Kirsher 	switch (cmd) {
2704adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
2705c7b7b483SYuval Mintz 	case BNX2X_MCAST_CMD_SET:
27063129e159SJason Baron 		/* For a set command, we need to allocate sufficient memory for
27073129e159SJason Baron 		 * all the bins, since we can't analyze at this point how much
27083129e159SJason Baron 		 * memory would be required.
2709adfc5217SJeff Kirsher 		 */
27103129e159SJason Baron 		total_elems = macs_list_len;
27113129e159SJason Baron 		if (cmd == BNX2X_MCAST_CMD_SET) {
27123129e159SJason Baron 			if (total_elems < BNX2X_MCAST_BINS_NUM)
27133129e159SJason Baron 				total_elems = BNX2X_MCAST_BINS_NUM;
2714adfc5217SJeff Kirsher 		}
27153129e159SJason Baron 		while (total_elems > 0) {
27163129e159SJason Baron 			elem_group = (struct bnx2x_mcast_elem_group *)
27173129e159SJason Baron 				     __get_free_page(GFP_ATOMIC | __GFP_ZERO);
27183129e159SJason Baron 			if (!elem_group) {
27193129e159SJason Baron 				bnx2x_free_groups(&new_cmd->group_head);
2720e96e0edeSjbaron@akamai.com 				kfree(new_cmd);
27213129e159SJason Baron 				return -ENOMEM;
27223129e159SJason Baron 			}
27233129e159SJason Baron 			total_elems -= MCAST_MAC_ELEMS_PER_PG;
27243129e159SJason Baron 			list_add_tail(&elem_group->mcast_group_link,
27253129e159SJason Baron 				      &new_cmd->group_head);
27263129e159SJason Baron 		}
27273129e159SJason Baron 		elem_group = list_first_entry(&new_cmd->group_head,
27283129e159SJason Baron 					      struct bnx2x_mcast_elem_group,
27293129e159SJason Baron 					      mcast_group_link);
27303129e159SJason Baron 		list_for_each_entry(pos, &p->mcast_list, link) {
27313129e159SJason Baron 			mac_elem = &elem_group->mcast_elems[offset].mac_elem;
27323129e159SJason Baron 			memcpy(mac_elem->mac, pos->mac, ETH_ALEN);
27333129e159SJason Baron 			/* Push the MACs of the current command into the pending
27343129e159SJason Baron 			 * command MACs list: FIFO
27353129e159SJason Baron 			 */
27363129e159SJason Baron 			list_add_tail(&mac_elem->link,
27373129e159SJason Baron 				      &new_cmd->data.macs_head);
27383129e159SJason Baron 			offset++;
27393129e159SJason Baron 			if (offset == MCAST_MAC_ELEMS_PER_PG) {
27403129e159SJason Baron 				offset = 0;
27413129e159SJason Baron 				elem_group = list_next_entry(elem_group,
27423129e159SJason Baron 							     mcast_group_link);
27433129e159SJason Baron 			}
27443129e159SJason Baron 		}
2745adfc5217SJeff Kirsher 		break;
2746adfc5217SJeff Kirsher 
2747adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
2748adfc5217SJeff Kirsher 		new_cmd->data.macs_num = p->mcast_list_len;
2749adfc5217SJeff Kirsher 		break;
2750adfc5217SJeff Kirsher 
2751adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
2752adfc5217SJeff Kirsher 		new_cmd->data.next_bin = 0;
2753adfc5217SJeff Kirsher 		break;
2754adfc5217SJeff Kirsher 
2755adfc5217SJeff Kirsher 	default:
27568b6d5c09SJesper Juhl 		kfree(new_cmd);
2757adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
2758adfc5217SJeff Kirsher 		return -EINVAL;
2759adfc5217SJeff Kirsher 	}
2760adfc5217SJeff Kirsher 
2761adfc5217SJeff Kirsher 	/* Push the new pending command to the tail of the pending list: FIFO */
2762adfc5217SJeff Kirsher 	list_add_tail(&new_cmd->link, &o->pending_cmds_head);
2763adfc5217SJeff Kirsher 
2764adfc5217SJeff Kirsher 	o->set_sched(o);
2765adfc5217SJeff Kirsher 
2766adfc5217SJeff Kirsher 	return 1;
2767adfc5217SJeff Kirsher }
2768adfc5217SJeff Kirsher 
2769adfc5217SJeff Kirsher /**
2770adfc5217SJeff Kirsher  * bnx2x_mcast_get_next_bin - get the next set bin (index)
2771adfc5217SJeff Kirsher  *
2772d0ea5cbdSJesse Brandeburg  * @o:		multicast object info
2773adfc5217SJeff Kirsher  * @last:	index to start looking from (including)
2774adfc5217SJeff Kirsher  *
2775adfc5217SJeff Kirsher  * returns the next found (set) bin or a negative value if none is found.
2776adfc5217SJeff Kirsher  */
bnx2x_mcast_get_next_bin(struct bnx2x_mcast_obj * o,int last)2777adfc5217SJeff Kirsher static inline int bnx2x_mcast_get_next_bin(struct bnx2x_mcast_obj *o, int last)
2778adfc5217SJeff Kirsher {
2779adfc5217SJeff Kirsher 	int i, j, inner_start = last % BIT_VEC64_ELEM_SZ;
2780adfc5217SJeff Kirsher 
2781adfc5217SJeff Kirsher 	for (i = last / BIT_VEC64_ELEM_SZ; i < BNX2X_MCAST_VEC_SZ; i++) {
2782adfc5217SJeff Kirsher 		if (o->registry.aprox_match.vec[i])
2783adfc5217SJeff Kirsher 			for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) {
2784adfc5217SJeff Kirsher 				int cur_bit = j + BIT_VEC64_ELEM_SZ * i;
2785adfc5217SJeff Kirsher 				if (BIT_VEC64_TEST_BIT(o->registry.aprox_match.
2786adfc5217SJeff Kirsher 						       vec, cur_bit)) {
2787adfc5217SJeff Kirsher 					return cur_bit;
2788adfc5217SJeff Kirsher 				}
2789adfc5217SJeff Kirsher 			}
2790adfc5217SJeff Kirsher 		inner_start = 0;
2791adfc5217SJeff Kirsher 	}
2792adfc5217SJeff Kirsher 
2793adfc5217SJeff Kirsher 	/* None found */
2794adfc5217SJeff Kirsher 	return -1;
2795adfc5217SJeff Kirsher }
2796adfc5217SJeff Kirsher 
2797adfc5217SJeff Kirsher /**
2798adfc5217SJeff Kirsher  * bnx2x_mcast_clear_first_bin - find the first set bin and clear it
2799adfc5217SJeff Kirsher  *
2800adfc5217SJeff Kirsher  * @o:
2801adfc5217SJeff Kirsher  *
2802adfc5217SJeff Kirsher  * returns the index of the found bin or -1 if none is found
2803adfc5217SJeff Kirsher  */
bnx2x_mcast_clear_first_bin(struct bnx2x_mcast_obj * o)2804adfc5217SJeff Kirsher static inline int bnx2x_mcast_clear_first_bin(struct bnx2x_mcast_obj *o)
2805adfc5217SJeff Kirsher {
2806adfc5217SJeff Kirsher 	int cur_bit = bnx2x_mcast_get_next_bin(o, 0);
2807adfc5217SJeff Kirsher 
2808adfc5217SJeff Kirsher 	if (cur_bit >= 0)
2809adfc5217SJeff Kirsher 		BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit);
2810adfc5217SJeff Kirsher 
2811adfc5217SJeff Kirsher 	return cur_bit;
2812adfc5217SJeff Kirsher }
2813adfc5217SJeff Kirsher 
bnx2x_mcast_get_rx_tx_flag(struct bnx2x_mcast_obj * o)2814adfc5217SJeff Kirsher static inline u8 bnx2x_mcast_get_rx_tx_flag(struct bnx2x_mcast_obj *o)
2815adfc5217SJeff Kirsher {
2816adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
2817adfc5217SJeff Kirsher 	u8 rx_tx_flag = 0;
2818adfc5217SJeff Kirsher 
2819adfc5217SJeff Kirsher 	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
2820adfc5217SJeff Kirsher 	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
2821adfc5217SJeff Kirsher 		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD;
2822adfc5217SJeff Kirsher 
2823adfc5217SJeff Kirsher 	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
2824adfc5217SJeff Kirsher 	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
2825adfc5217SJeff Kirsher 		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD;
2826adfc5217SJeff Kirsher 
2827adfc5217SJeff Kirsher 	return rx_tx_flag;
2828adfc5217SJeff Kirsher }
2829adfc5217SJeff Kirsher 
bnx2x_mcast_set_one_rule_e2(struct bnx2x * bp,struct bnx2x_mcast_obj * o,int idx,union bnx2x_mcast_config_data * cfg_data,enum bnx2x_mcast_cmd cmd)2830adfc5217SJeff Kirsher static void bnx2x_mcast_set_one_rule_e2(struct bnx2x *bp,
2831adfc5217SJeff Kirsher 					struct bnx2x_mcast_obj *o, int idx,
2832adfc5217SJeff Kirsher 					union bnx2x_mcast_config_data *cfg_data,
283386564c3fSYuval Mintz 					enum bnx2x_mcast_cmd cmd)
2834adfc5217SJeff Kirsher {
2835adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
2836adfc5217SJeff Kirsher 	struct eth_multicast_rules_ramrod_data *data =
2837adfc5217SJeff Kirsher 		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
2838adfc5217SJeff Kirsher 	u8 func_id = r->func_id;
2839adfc5217SJeff Kirsher 	u8 rx_tx_add_flag = bnx2x_mcast_get_rx_tx_flag(o);
2840adfc5217SJeff Kirsher 	int bin;
2841adfc5217SJeff Kirsher 
2842c7b7b483SYuval Mintz 	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE) ||
2843c7b7b483SYuval Mintz 	    (cmd == BNX2X_MCAST_CMD_SET_ADD))
2844adfc5217SJeff Kirsher 		rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD;
2845adfc5217SJeff Kirsher 
2846adfc5217SJeff Kirsher 	data->rules[idx].cmd_general_data |= rx_tx_add_flag;
2847adfc5217SJeff Kirsher 
2848adfc5217SJeff Kirsher 	/* Get a bin and update a bins' vector */
2849adfc5217SJeff Kirsher 	switch (cmd) {
2850adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
2851adfc5217SJeff Kirsher 		bin = bnx2x_mcast_bin_from_mac(cfg_data->mac);
2852adfc5217SJeff Kirsher 		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
2853adfc5217SJeff Kirsher 		break;
2854adfc5217SJeff Kirsher 
2855adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
2856adfc5217SJeff Kirsher 		/* If there were no more bins to clear
2857adfc5217SJeff Kirsher 		 * (bnx2x_mcast_clear_first_bin() returns -1) then we would
2858adfc5217SJeff Kirsher 		 * clear any (0xff) bin.
2859adfc5217SJeff Kirsher 		 * See bnx2x_mcast_validate_e2() for explanation when it may
2860adfc5217SJeff Kirsher 		 * happen.
2861adfc5217SJeff Kirsher 		 */
2862adfc5217SJeff Kirsher 		bin = bnx2x_mcast_clear_first_bin(o);
2863adfc5217SJeff Kirsher 		break;
2864adfc5217SJeff Kirsher 
2865adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
2866adfc5217SJeff Kirsher 		bin = cfg_data->bin;
2867adfc5217SJeff Kirsher 		break;
2868adfc5217SJeff Kirsher 
2869c7b7b483SYuval Mintz 	case BNX2X_MCAST_CMD_SET_ADD:
2870c7b7b483SYuval Mintz 		bin = cfg_data->bin;
2871c7b7b483SYuval Mintz 		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
2872c7b7b483SYuval Mintz 		break;
2873c7b7b483SYuval Mintz 
2874c7b7b483SYuval Mintz 	case BNX2X_MCAST_CMD_SET_DEL:
2875c7b7b483SYuval Mintz 		bin = cfg_data->bin;
2876c7b7b483SYuval Mintz 		BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, bin);
2877c7b7b483SYuval Mintz 		break;
2878c7b7b483SYuval Mintz 
2879adfc5217SJeff Kirsher 	default:
2880adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
2881adfc5217SJeff Kirsher 		return;
2882adfc5217SJeff Kirsher 	}
2883adfc5217SJeff Kirsher 
2884adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "%s bin %d\n",
2885adfc5217SJeff Kirsher 			 ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ?
2886adfc5217SJeff Kirsher 			 "Setting"  : "Clearing"), bin);
2887adfc5217SJeff Kirsher 
2888adfc5217SJeff Kirsher 	data->rules[idx].bin_id    = (u8)bin;
2889adfc5217SJeff Kirsher 	data->rules[idx].func_id   = func_id;
2890adfc5217SJeff Kirsher 	data->rules[idx].engine_id = o->engine_id;
2891adfc5217SJeff Kirsher }
2892adfc5217SJeff Kirsher 
2893adfc5217SJeff Kirsher /**
2894adfc5217SJeff Kirsher  * bnx2x_mcast_handle_restore_cmd_e2 - restore configuration from the registry
2895adfc5217SJeff Kirsher  *
2896adfc5217SJeff Kirsher  * @bp:		device handle
2897d0ea5cbdSJesse Brandeburg  * @o:		multicast object info
2898adfc5217SJeff Kirsher  * @start_bin:	index in the registry to start from (including)
2899adfc5217SJeff Kirsher  * @rdata_idx:	index in the ramrod data to start from
2900adfc5217SJeff Kirsher  *
2901adfc5217SJeff Kirsher  * returns last handled bin index or -1 if all bins have been handled
2902adfc5217SJeff Kirsher  */
bnx2x_mcast_handle_restore_cmd_e2(struct bnx2x * bp,struct bnx2x_mcast_obj * o,int start_bin,int * rdata_idx)2903adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_restore_cmd_e2(
2904adfc5217SJeff Kirsher 	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_bin,
2905adfc5217SJeff Kirsher 	int *rdata_idx)
2906adfc5217SJeff Kirsher {
2907adfc5217SJeff Kirsher 	int cur_bin, cnt = *rdata_idx;
290886564c3fSYuval Mintz 	union bnx2x_mcast_config_data cfg_data = {NULL};
2909adfc5217SJeff Kirsher 
2910adfc5217SJeff Kirsher 	/* go through the registry and configure the bins from it */
2911adfc5217SJeff Kirsher 	for (cur_bin = bnx2x_mcast_get_next_bin(o, start_bin); cur_bin >= 0;
2912adfc5217SJeff Kirsher 	    cur_bin = bnx2x_mcast_get_next_bin(o, cur_bin + 1)) {
2913adfc5217SJeff Kirsher 
2914adfc5217SJeff Kirsher 		cfg_data.bin = (u8)cur_bin;
2915adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, &cfg_data,
2916adfc5217SJeff Kirsher 				BNX2X_MCAST_CMD_RESTORE);
2917adfc5217SJeff Kirsher 
2918adfc5217SJeff Kirsher 		cnt++;
2919adfc5217SJeff Kirsher 
2920adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "About to configure a bin %d\n", cur_bin);
2921adfc5217SJeff Kirsher 
2922adfc5217SJeff Kirsher 		/* Break if we reached the maximum number
2923adfc5217SJeff Kirsher 		 * of rules.
2924adfc5217SJeff Kirsher 		 */
2925adfc5217SJeff Kirsher 		if (cnt >= o->max_cmd_len)
2926adfc5217SJeff Kirsher 			break;
2927adfc5217SJeff Kirsher 	}
2928adfc5217SJeff Kirsher 
2929adfc5217SJeff Kirsher 	*rdata_idx = cnt;
2930adfc5217SJeff Kirsher 
2931adfc5217SJeff Kirsher 	return cur_bin;
2932adfc5217SJeff Kirsher }
2933adfc5217SJeff Kirsher 
bnx2x_mcast_hdl_pending_add_e2(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_pending_mcast_cmd * cmd_pos,int * line_idx)2934adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp,
2935adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
2936adfc5217SJeff Kirsher 	int *line_idx)
2937adfc5217SJeff Kirsher {
2938adfc5217SJeff Kirsher 	struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
2939adfc5217SJeff Kirsher 	int cnt = *line_idx;
294086564c3fSYuval Mintz 	union bnx2x_mcast_config_data cfg_data = {NULL};
2941adfc5217SJeff Kirsher 
2942adfc5217SJeff Kirsher 	list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head,
2943adfc5217SJeff Kirsher 				 link) {
2944adfc5217SJeff Kirsher 
2945adfc5217SJeff Kirsher 		cfg_data.mac = &pmac_pos->mac[0];
2946adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
2947adfc5217SJeff Kirsher 
2948adfc5217SJeff Kirsher 		cnt++;
2949adfc5217SJeff Kirsher 
29500f9dad10SJoe Perches 		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
29510f9dad10SJoe Perches 		   pmac_pos->mac);
2952adfc5217SJeff Kirsher 
2953adfc5217SJeff Kirsher 		list_del(&pmac_pos->link);
2954adfc5217SJeff Kirsher 
2955adfc5217SJeff Kirsher 		/* Break if we reached the maximum number
2956adfc5217SJeff Kirsher 		 * of rules.
2957adfc5217SJeff Kirsher 		 */
2958adfc5217SJeff Kirsher 		if (cnt >= o->max_cmd_len)
2959adfc5217SJeff Kirsher 			break;
2960adfc5217SJeff Kirsher 	}
2961adfc5217SJeff Kirsher 
2962adfc5217SJeff Kirsher 	*line_idx = cnt;
2963adfc5217SJeff Kirsher 
2964adfc5217SJeff Kirsher 	/* if no more MACs to configure - we are done */
2965adfc5217SJeff Kirsher 	if (list_empty(&cmd_pos->data.macs_head))
2966adfc5217SJeff Kirsher 		cmd_pos->done = true;
2967adfc5217SJeff Kirsher }
2968adfc5217SJeff Kirsher 
bnx2x_mcast_hdl_pending_del_e2(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_pending_mcast_cmd * cmd_pos,int * line_idx)2969adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp,
2970adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
2971adfc5217SJeff Kirsher 	int *line_idx)
2972adfc5217SJeff Kirsher {
2973adfc5217SJeff Kirsher 	int cnt = *line_idx;
2974adfc5217SJeff Kirsher 
2975adfc5217SJeff Kirsher 	while (cmd_pos->data.macs_num) {
2976adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, NULL, cmd_pos->type);
2977adfc5217SJeff Kirsher 
2978adfc5217SJeff Kirsher 		cnt++;
2979adfc5217SJeff Kirsher 
2980adfc5217SJeff Kirsher 		cmd_pos->data.macs_num--;
2981adfc5217SJeff Kirsher 
2982adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n",
2983adfc5217SJeff Kirsher 		   cmd_pos->data.macs_num, cnt);
2984adfc5217SJeff Kirsher 
2985adfc5217SJeff Kirsher 		/* Break if we reached the maximum
2986adfc5217SJeff Kirsher 		 * number of rules.
2987adfc5217SJeff Kirsher 		 */
2988adfc5217SJeff Kirsher 		if (cnt >= o->max_cmd_len)
2989adfc5217SJeff Kirsher 			break;
2990adfc5217SJeff Kirsher 	}
2991adfc5217SJeff Kirsher 
2992adfc5217SJeff Kirsher 	*line_idx = cnt;
2993adfc5217SJeff Kirsher 
2994adfc5217SJeff Kirsher 	/* If we cleared all bins - we are done */
2995adfc5217SJeff Kirsher 	if (!cmd_pos->data.macs_num)
2996adfc5217SJeff Kirsher 		cmd_pos->done = true;
2997adfc5217SJeff Kirsher }
2998adfc5217SJeff Kirsher 
bnx2x_mcast_hdl_pending_restore_e2(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_pending_mcast_cmd * cmd_pos,int * line_idx)2999adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_pending_restore_e2(struct bnx2x *bp,
3000adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
3001adfc5217SJeff Kirsher 	int *line_idx)
3002adfc5217SJeff Kirsher {
3003adfc5217SJeff Kirsher 	cmd_pos->data.next_bin = o->hdl_restore(bp, o, cmd_pos->data.next_bin,
3004adfc5217SJeff Kirsher 						line_idx);
3005adfc5217SJeff Kirsher 
3006adfc5217SJeff Kirsher 	if (cmd_pos->data.next_bin < 0)
3007adfc5217SJeff Kirsher 		/* If o->set_restore returned -1 we are done */
3008adfc5217SJeff Kirsher 		cmd_pos->done = true;
3009adfc5217SJeff Kirsher 	else
3010adfc5217SJeff Kirsher 		/* Start from the next bin next time */
3011adfc5217SJeff Kirsher 		cmd_pos->data.next_bin++;
3012adfc5217SJeff Kirsher }
3013adfc5217SJeff Kirsher 
3014c7b7b483SYuval Mintz static void
bnx2x_mcast_hdl_pending_set_e2_convert(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_pending_mcast_cmd * cmd_pos)3015c7b7b483SYuval Mintz bnx2x_mcast_hdl_pending_set_e2_convert(struct bnx2x *bp,
3016c7b7b483SYuval Mintz 				       struct bnx2x_mcast_obj *o,
3017c7b7b483SYuval Mintz 				       struct bnx2x_pending_mcast_cmd *cmd_pos)
3018c7b7b483SYuval Mintz {
3019c7b7b483SYuval Mintz 	u64 cur[BNX2X_MCAST_VEC_SZ], req[BNX2X_MCAST_VEC_SZ];
3020c7b7b483SYuval Mintz 	struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
3021c7b7b483SYuval Mintz 	struct bnx2x_mcast_bin_elem *p_item;
30223129e159SJason Baron 	struct bnx2x_mcast_elem_group *elem_group;
30233129e159SJason Baron 	int cnt = 0, mac_cnt = 0, offset = 0, i;
3024c7b7b483SYuval Mintz 
3025c7b7b483SYuval Mintz 	memset(req, 0, sizeof(u64) * BNX2X_MCAST_VEC_SZ);
3026c7b7b483SYuval Mintz 	memcpy(cur, o->registry.aprox_match.vec,
3027c7b7b483SYuval Mintz 	       sizeof(u64) * BNX2X_MCAST_VEC_SZ);
3028c7b7b483SYuval Mintz 
3029c7b7b483SYuval Mintz 	/* Fill `current' with the required set of bins to configure */
3030c7b7b483SYuval Mintz 	list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head,
3031c7b7b483SYuval Mintz 				 link) {
3032c7b7b483SYuval Mintz 		int bin = bnx2x_mcast_bin_from_mac(pmac_pos->mac);
3033c7b7b483SYuval Mintz 
3034c7b7b483SYuval Mintz 		DP(BNX2X_MSG_SP, "Set contains %pM mcast MAC\n",
3035c7b7b483SYuval Mintz 		   pmac_pos->mac);
3036c7b7b483SYuval Mintz 
3037c7b7b483SYuval Mintz 		BIT_VEC64_SET_BIT(req, bin);
3038c7b7b483SYuval Mintz 		list_del(&pmac_pos->link);
3039c7b7b483SYuval Mintz 		mac_cnt++;
3040c7b7b483SYuval Mintz 	}
3041c7b7b483SYuval Mintz 
3042c7b7b483SYuval Mintz 	/* We no longer have use for the MACs; Need to re-use memory for
3043c7b7b483SYuval Mintz 	 * a list that will be used to configure bins.
3044c7b7b483SYuval Mintz 	 */
3045c7b7b483SYuval Mintz 	cmd_pos->set_convert = true;
3046c7b7b483SYuval Mintz 	INIT_LIST_HEAD(&cmd_pos->data.macs_head);
30473129e159SJason Baron 	elem_group = list_first_entry(&cmd_pos->group_head,
30483129e159SJason Baron 				      struct bnx2x_mcast_elem_group,
30493129e159SJason Baron 				      mcast_group_link);
3050c7b7b483SYuval Mintz 	for (i = 0; i < BNX2X_MCAST_BINS_NUM; i++) {
3051c7b7b483SYuval Mintz 		bool b_current = !!BIT_VEC64_TEST_BIT(cur, i);
3052c7b7b483SYuval Mintz 		bool b_required = !!BIT_VEC64_TEST_BIT(req, i);
3053c7b7b483SYuval Mintz 
3054c7b7b483SYuval Mintz 		if (b_current == b_required)
3055c7b7b483SYuval Mintz 			continue;
3056c7b7b483SYuval Mintz 
30573129e159SJason Baron 		p_item = &elem_group->mcast_elems[offset].bin_elem;
3058c7b7b483SYuval Mintz 		p_item->bin = i;
3059c7b7b483SYuval Mintz 		p_item->type = b_required ? BNX2X_MCAST_CMD_SET_ADD
3060c7b7b483SYuval Mintz 					  : BNX2X_MCAST_CMD_SET_DEL;
3061c7b7b483SYuval Mintz 		list_add_tail(&p_item->link , &cmd_pos->data.macs_head);
3062c7b7b483SYuval Mintz 		cnt++;
30633129e159SJason Baron 		offset++;
30643129e159SJason Baron 		if (offset == MCAST_MAC_ELEMS_PER_PG) {
30653129e159SJason Baron 			offset = 0;
30663129e159SJason Baron 			elem_group = list_next_entry(elem_group,
30673129e159SJason Baron 						     mcast_group_link);
30683129e159SJason Baron 		}
3069c7b7b483SYuval Mintz 	}
3070c7b7b483SYuval Mintz 
3071c7b7b483SYuval Mintz 	/* We now definitely know how many commands are hiding here.
3072c7b7b483SYuval Mintz 	 * Also need to correct the disruption we've added to guarantee this
3073c7b7b483SYuval Mintz 	 * would be enqueued.
3074c7b7b483SYuval Mintz 	 */
3075c7b7b483SYuval Mintz 	o->total_pending_num -= (o->max_cmd_len + mac_cnt);
3076c7b7b483SYuval Mintz 	o->total_pending_num += cnt;
3077c7b7b483SYuval Mintz 
3078c7b7b483SYuval Mintz 	DP(BNX2X_MSG_SP, "o->total_pending_num=%d\n", o->total_pending_num);
3079c7b7b483SYuval Mintz }
3080c7b7b483SYuval Mintz 
3081c7b7b483SYuval Mintz static void
bnx2x_mcast_hdl_pending_set_e2(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_pending_mcast_cmd * cmd_pos,int * cnt)3082c7b7b483SYuval Mintz bnx2x_mcast_hdl_pending_set_e2(struct bnx2x *bp,
3083c7b7b483SYuval Mintz 			       struct bnx2x_mcast_obj *o,
3084c7b7b483SYuval Mintz 			       struct bnx2x_pending_mcast_cmd *cmd_pos,
3085c7b7b483SYuval Mintz 			       int *cnt)
3086c7b7b483SYuval Mintz {
3087c7b7b483SYuval Mintz 	union bnx2x_mcast_config_data cfg_data = {NULL};
3088c7b7b483SYuval Mintz 	struct bnx2x_mcast_bin_elem *p_item, *p_item_n;
3089c7b7b483SYuval Mintz 
3090c7b7b483SYuval Mintz 	/* This is actually a 2-part scheme - it starts by converting the MACs
3091c7b7b483SYuval Mintz 	 * into a list of bins to be added/removed, and correcting the numbers
3092c7b7b483SYuval Mintz 	 * on the object. this is now allowed, as we're now sure that all
3093c7b7b483SYuval Mintz 	 * previous configured requests have already applied.
3094c7b7b483SYuval Mintz 	 * The second part is actually adding rules for the newly introduced
3095c7b7b483SYuval Mintz 	 * entries [like all the rest of the hdl_pending functions].
3096c7b7b483SYuval Mintz 	 */
3097c7b7b483SYuval Mintz 	if (!cmd_pos->set_convert)
3098c7b7b483SYuval Mintz 		bnx2x_mcast_hdl_pending_set_e2_convert(bp, o, cmd_pos);
3099c7b7b483SYuval Mintz 
3100c7b7b483SYuval Mintz 	list_for_each_entry_safe(p_item, p_item_n, &cmd_pos->data.macs_head,
3101c7b7b483SYuval Mintz 				 link) {
3102c7b7b483SYuval Mintz 		cfg_data.bin = (u8)p_item->bin;
3103c7b7b483SYuval Mintz 		o->set_one_rule(bp, o, *cnt, &cfg_data, p_item->type);
3104c7b7b483SYuval Mintz 		(*cnt)++;
3105c7b7b483SYuval Mintz 
3106c7b7b483SYuval Mintz 		list_del(&p_item->link);
3107c7b7b483SYuval Mintz 
3108c7b7b483SYuval Mintz 		/* Break if we reached the maximum number of rules. */
3109c7b7b483SYuval Mintz 		if (*cnt >= o->max_cmd_len)
3110c7b7b483SYuval Mintz 			break;
3111c7b7b483SYuval Mintz 	}
3112c7b7b483SYuval Mintz 
3113c7b7b483SYuval Mintz 	/* if no more MACs to configure - we are done */
3114c7b7b483SYuval Mintz 	if (list_empty(&cmd_pos->data.macs_head))
3115c7b7b483SYuval Mintz 		cmd_pos->done = true;
3116c7b7b483SYuval Mintz }
3117c7b7b483SYuval Mintz 
bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p)3118adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x *bp,
3119adfc5217SJeff Kirsher 				struct bnx2x_mcast_ramrod_params *p)
3120adfc5217SJeff Kirsher {
3121adfc5217SJeff Kirsher 	struct bnx2x_pending_mcast_cmd *cmd_pos, *cmd_pos_n;
3122adfc5217SJeff Kirsher 	int cnt = 0;
3123adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3124adfc5217SJeff Kirsher 
3125adfc5217SJeff Kirsher 	list_for_each_entry_safe(cmd_pos, cmd_pos_n, &o->pending_cmds_head,
3126adfc5217SJeff Kirsher 				 link) {
3127adfc5217SJeff Kirsher 		switch (cmd_pos->type) {
3128adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_ADD:
3129adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_pending_add_e2(bp, o, cmd_pos, &cnt);
3130adfc5217SJeff Kirsher 			break;
3131adfc5217SJeff Kirsher 
3132adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_DEL:
3133adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_pending_del_e2(bp, o, cmd_pos, &cnt);
3134adfc5217SJeff Kirsher 			break;
3135adfc5217SJeff Kirsher 
3136adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_RESTORE:
3137adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_pending_restore_e2(bp, o, cmd_pos,
3138adfc5217SJeff Kirsher 							   &cnt);
3139adfc5217SJeff Kirsher 			break;
3140adfc5217SJeff Kirsher 
3141c7b7b483SYuval Mintz 		case BNX2X_MCAST_CMD_SET:
3142c7b7b483SYuval Mintz 			bnx2x_mcast_hdl_pending_set_e2(bp, o, cmd_pos, &cnt);
3143c7b7b483SYuval Mintz 			break;
3144c7b7b483SYuval Mintz 
3145adfc5217SJeff Kirsher 		default:
3146adfc5217SJeff Kirsher 			BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
3147adfc5217SJeff Kirsher 			return -EINVAL;
3148adfc5217SJeff Kirsher 		}
3149adfc5217SJeff Kirsher 
3150adfc5217SJeff Kirsher 		/* If the command has been completed - remove it from the list
3151adfc5217SJeff Kirsher 		 * and free the memory
3152adfc5217SJeff Kirsher 		 */
3153adfc5217SJeff Kirsher 		if (cmd_pos->done) {
3154adfc5217SJeff Kirsher 			list_del(&cmd_pos->link);
31553129e159SJason Baron 			bnx2x_free_groups(&cmd_pos->group_head);
3156adfc5217SJeff Kirsher 			kfree(cmd_pos);
3157adfc5217SJeff Kirsher 		}
3158adfc5217SJeff Kirsher 
3159adfc5217SJeff Kirsher 		/* Break if we reached the maximum number of rules */
3160adfc5217SJeff Kirsher 		if (cnt >= o->max_cmd_len)
3161adfc5217SJeff Kirsher 			break;
3162adfc5217SJeff Kirsher 	}
3163adfc5217SJeff Kirsher 
3164adfc5217SJeff Kirsher 	return cnt;
3165adfc5217SJeff Kirsher }
3166adfc5217SJeff Kirsher 
bnx2x_mcast_hdl_add(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_mcast_ramrod_params * p,int * line_idx)3167adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_add(struct bnx2x *bp,
3168adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
3169adfc5217SJeff Kirsher 	int *line_idx)
3170adfc5217SJeff Kirsher {
3171adfc5217SJeff Kirsher 	struct bnx2x_mcast_list_elem *mlist_pos;
317286564c3fSYuval Mintz 	union bnx2x_mcast_config_data cfg_data = {NULL};
3173adfc5217SJeff Kirsher 	int cnt = *line_idx;
3174adfc5217SJeff Kirsher 
3175adfc5217SJeff Kirsher 	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
3176adfc5217SJeff Kirsher 		cfg_data.mac = mlist_pos->mac;
3177adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, &cfg_data, BNX2X_MCAST_CMD_ADD);
3178adfc5217SJeff Kirsher 
3179adfc5217SJeff Kirsher 		cnt++;
3180adfc5217SJeff Kirsher 
31810f9dad10SJoe Perches 		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
31820f9dad10SJoe Perches 		   mlist_pos->mac);
3183adfc5217SJeff Kirsher 	}
3184adfc5217SJeff Kirsher 
3185adfc5217SJeff Kirsher 	*line_idx = cnt;
3186adfc5217SJeff Kirsher }
3187adfc5217SJeff Kirsher 
bnx2x_mcast_hdl_del(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_mcast_ramrod_params * p,int * line_idx)3188adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_del(struct bnx2x *bp,
3189adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
3190adfc5217SJeff Kirsher 	int *line_idx)
3191adfc5217SJeff Kirsher {
3192adfc5217SJeff Kirsher 	int cnt = *line_idx, i;
3193adfc5217SJeff Kirsher 
3194adfc5217SJeff Kirsher 	for (i = 0; i < p->mcast_list_len; i++) {
3195adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, NULL, BNX2X_MCAST_CMD_DEL);
3196adfc5217SJeff Kirsher 
3197adfc5217SJeff Kirsher 		cnt++;
3198adfc5217SJeff Kirsher 
3199adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Deleting MAC. %d left\n",
3200adfc5217SJeff Kirsher 				 p->mcast_list_len - i - 1);
3201adfc5217SJeff Kirsher 	}
3202adfc5217SJeff Kirsher 
3203adfc5217SJeff Kirsher 	*line_idx = cnt;
3204adfc5217SJeff Kirsher }
3205adfc5217SJeff Kirsher 
3206adfc5217SJeff Kirsher /**
3207d0ea5cbdSJesse Brandeburg  * bnx2x_mcast_handle_current_cmd - send command if room
3208adfc5217SJeff Kirsher  *
3209adfc5217SJeff Kirsher  * @bp:		device handle
3210d0ea5cbdSJesse Brandeburg  * @p:		ramrod mcast info
3211d0ea5cbdSJesse Brandeburg  * @cmd:	command
3212adfc5217SJeff Kirsher  * @start_cnt:	first line in the ramrod data that may be used
3213adfc5217SJeff Kirsher  *
3214adfc5217SJeff Kirsher  * This function is called iff there is enough place for the current command in
3215adfc5217SJeff Kirsher  * the ramrod data.
3216adfc5217SJeff Kirsher  * Returns number of lines filled in the ramrod data in total.
3217adfc5217SJeff Kirsher  */
bnx2x_mcast_handle_current_cmd(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,enum bnx2x_mcast_cmd cmd,int start_cnt)3218adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_current_cmd(struct bnx2x *bp,
321986564c3fSYuval Mintz 			struct bnx2x_mcast_ramrod_params *p,
322086564c3fSYuval Mintz 			enum bnx2x_mcast_cmd cmd,
3221adfc5217SJeff Kirsher 			int start_cnt)
3222adfc5217SJeff Kirsher {
3223adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3224adfc5217SJeff Kirsher 	int cnt = start_cnt;
3225adfc5217SJeff Kirsher 
3226adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
3227adfc5217SJeff Kirsher 
3228adfc5217SJeff Kirsher 	switch (cmd) {
3229adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
3230adfc5217SJeff Kirsher 		bnx2x_mcast_hdl_add(bp, o, p, &cnt);
3231adfc5217SJeff Kirsher 		break;
3232adfc5217SJeff Kirsher 
3233adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
3234adfc5217SJeff Kirsher 		bnx2x_mcast_hdl_del(bp, o, p, &cnt);
3235adfc5217SJeff Kirsher 		break;
3236adfc5217SJeff Kirsher 
3237adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
3238adfc5217SJeff Kirsher 		o->hdl_restore(bp, o, 0, &cnt);
3239adfc5217SJeff Kirsher 		break;
3240adfc5217SJeff Kirsher 
3241adfc5217SJeff Kirsher 	default:
3242adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
3243adfc5217SJeff Kirsher 		return -EINVAL;
3244adfc5217SJeff Kirsher 	}
3245adfc5217SJeff Kirsher 
3246adfc5217SJeff Kirsher 	/* The current command has been handled */
3247adfc5217SJeff Kirsher 	p->mcast_list_len = 0;
3248adfc5217SJeff Kirsher 
3249adfc5217SJeff Kirsher 	return cnt;
3250adfc5217SJeff Kirsher }
3251adfc5217SJeff Kirsher 
bnx2x_mcast_validate_e2(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,enum bnx2x_mcast_cmd cmd)3252adfc5217SJeff Kirsher static int bnx2x_mcast_validate_e2(struct bnx2x *bp,
3253adfc5217SJeff Kirsher 				   struct bnx2x_mcast_ramrod_params *p,
325486564c3fSYuval Mintz 				   enum bnx2x_mcast_cmd cmd)
3255adfc5217SJeff Kirsher {
3256adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3257adfc5217SJeff Kirsher 	int reg_sz = o->get_registry_size(o);
3258adfc5217SJeff Kirsher 
3259adfc5217SJeff Kirsher 	switch (cmd) {
3260adfc5217SJeff Kirsher 	/* DEL command deletes all currently configured MACs */
3261adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
3262adfc5217SJeff Kirsher 		o->set_registry_size(o, 0);
3263df561f66SGustavo A. R. Silva 		fallthrough;
3264adfc5217SJeff Kirsher 
3265adfc5217SJeff Kirsher 	/* RESTORE command will restore the entire multicast configuration */
3266adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
3267adfc5217SJeff Kirsher 		/* Here we set the approximate amount of work to do, which in
3268adfc5217SJeff Kirsher 		 * fact may be only less as some MACs in postponed ADD
3269adfc5217SJeff Kirsher 		 * command(s) scheduled before this command may fall into
3270adfc5217SJeff Kirsher 		 * the same bin and the actual number of bins set in the
3271adfc5217SJeff Kirsher 		 * registry would be less than we estimated here. See
3272adfc5217SJeff Kirsher 		 * bnx2x_mcast_set_one_rule_e2() for further details.
3273adfc5217SJeff Kirsher 		 */
3274adfc5217SJeff Kirsher 		p->mcast_list_len = reg_sz;
3275adfc5217SJeff Kirsher 		break;
3276adfc5217SJeff Kirsher 
3277adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
3278adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_CONT:
3279adfc5217SJeff Kirsher 		/* Here we assume that all new MACs will fall into new bins.
3280adfc5217SJeff Kirsher 		 * However we will correct the real registry size after we
3281adfc5217SJeff Kirsher 		 * handle all pending commands.
3282adfc5217SJeff Kirsher 		 */
3283adfc5217SJeff Kirsher 		o->set_registry_size(o, reg_sz + p->mcast_list_len);
3284adfc5217SJeff Kirsher 		break;
3285adfc5217SJeff Kirsher 
3286c7b7b483SYuval Mintz 	case BNX2X_MCAST_CMD_SET:
3287c7b7b483SYuval Mintz 		/* We can only learn how many commands would actually be used
3288c7b7b483SYuval Mintz 		 * when this is being configured. So for now, simply guarantee
3289c7b7b483SYuval Mintz 		 * the command will be enqueued [to refrain from adding logic
3290c7b7b483SYuval Mintz 		 * that handles this and THEN learns it needs several ramrods].
3291c7b7b483SYuval Mintz 		 * Just like for ADD/Cont, the mcast_list_len might be an over
3292c7b7b483SYuval Mintz 		 * estimation; or even more so, since we don't take into
3293c7b7b483SYuval Mintz 		 * account the possibility of removal of existing bins.
3294c7b7b483SYuval Mintz 		 */
3295c7b7b483SYuval Mintz 		o->set_registry_size(o, reg_sz + p->mcast_list_len);
3296c7b7b483SYuval Mintz 		o->total_pending_num += o->max_cmd_len;
3297c7b7b483SYuval Mintz 		break;
3298c7b7b483SYuval Mintz 
3299adfc5217SJeff Kirsher 	default:
3300adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
3301adfc5217SJeff Kirsher 		return -EINVAL;
3302adfc5217SJeff Kirsher 	}
3303adfc5217SJeff Kirsher 
3304adfc5217SJeff Kirsher 	/* Increase the total number of MACs pending to be configured */
3305adfc5217SJeff Kirsher 	o->total_pending_num += p->mcast_list_len;
3306adfc5217SJeff Kirsher 
3307adfc5217SJeff Kirsher 	return 0;
3308adfc5217SJeff Kirsher }
3309adfc5217SJeff Kirsher 
bnx2x_mcast_revert_e2(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,int old_num_bins,enum bnx2x_mcast_cmd cmd)3310adfc5217SJeff Kirsher static void bnx2x_mcast_revert_e2(struct bnx2x *bp,
3311adfc5217SJeff Kirsher 				      struct bnx2x_mcast_ramrod_params *p,
3312c7b7b483SYuval Mintz 				  int old_num_bins,
3313c7b7b483SYuval Mintz 				  enum bnx2x_mcast_cmd cmd)
3314adfc5217SJeff Kirsher {
3315adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3316adfc5217SJeff Kirsher 
3317adfc5217SJeff Kirsher 	o->set_registry_size(o, old_num_bins);
3318adfc5217SJeff Kirsher 	o->total_pending_num -= p->mcast_list_len;
3319c7b7b483SYuval Mintz 
3320c7b7b483SYuval Mintz 	if (cmd == BNX2X_MCAST_CMD_SET)
3321c7b7b483SYuval Mintz 		o->total_pending_num -= o->max_cmd_len;
3322adfc5217SJeff Kirsher }
3323adfc5217SJeff Kirsher 
3324adfc5217SJeff Kirsher /**
3325adfc5217SJeff Kirsher  * bnx2x_mcast_set_rdata_hdr_e2 - sets a header values
3326adfc5217SJeff Kirsher  *
3327adfc5217SJeff Kirsher  * @bp:		device handle
3328d0ea5cbdSJesse Brandeburg  * @p:		ramrod parameters
3329adfc5217SJeff Kirsher  * @len:	number of rules to handle
3330adfc5217SJeff Kirsher  */
bnx2x_mcast_set_rdata_hdr_e2(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,u8 len)3331adfc5217SJeff Kirsher static inline void bnx2x_mcast_set_rdata_hdr_e2(struct bnx2x *bp,
3332adfc5217SJeff Kirsher 					struct bnx2x_mcast_ramrod_params *p,
3333adfc5217SJeff Kirsher 					u8 len)
3334adfc5217SJeff Kirsher {
3335adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
3336adfc5217SJeff Kirsher 	struct eth_multicast_rules_ramrod_data *data =
3337adfc5217SJeff Kirsher 		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
3338adfc5217SJeff Kirsher 
333986564c3fSYuval Mintz 	data->header.echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) |
334086564c3fSYuval Mintz 					(BNX2X_FILTER_MCAST_PENDING <<
334186564c3fSYuval Mintz 					 BNX2X_SWCID_SHIFT));
3342adfc5217SJeff Kirsher 	data->header.rule_cnt = len;
3343adfc5217SJeff Kirsher }
3344adfc5217SJeff Kirsher 
3345adfc5217SJeff Kirsher /**
3346adfc5217SJeff Kirsher  * bnx2x_mcast_refresh_registry_e2 - recalculate the actual number of set bins
3347adfc5217SJeff Kirsher  *
3348adfc5217SJeff Kirsher  * @bp:		device handle
3349adfc5217SJeff Kirsher  * @o:
3350adfc5217SJeff Kirsher  *
3351adfc5217SJeff Kirsher  * Recalculate the actual number of set bins in the registry using Brian
3352adfc5217SJeff Kirsher  * Kernighan's algorithm: it's execution complexity is as a number of set bins.
3353adfc5217SJeff Kirsher  *
3354adfc5217SJeff Kirsher  * returns 0 for the compliance with bnx2x_mcast_refresh_registry_e1().
3355adfc5217SJeff Kirsher  */
bnx2x_mcast_refresh_registry_e2(struct bnx2x * bp,struct bnx2x_mcast_obj * o)3356adfc5217SJeff Kirsher static inline int bnx2x_mcast_refresh_registry_e2(struct bnx2x *bp,
3357adfc5217SJeff Kirsher 						  struct bnx2x_mcast_obj *o)
3358adfc5217SJeff Kirsher {
3359adfc5217SJeff Kirsher 	int i, cnt = 0;
3360adfc5217SJeff Kirsher 	u64 elem;
3361adfc5217SJeff Kirsher 
3362adfc5217SJeff Kirsher 	for (i = 0; i < BNX2X_MCAST_VEC_SZ; i++) {
3363adfc5217SJeff Kirsher 		elem = o->registry.aprox_match.vec[i];
3364adfc5217SJeff Kirsher 		for (; elem; cnt++)
3365adfc5217SJeff Kirsher 			elem &= elem - 1;
3366adfc5217SJeff Kirsher 	}
3367adfc5217SJeff Kirsher 
3368adfc5217SJeff Kirsher 	o->set_registry_size(o, cnt);
3369adfc5217SJeff Kirsher 
3370adfc5217SJeff Kirsher 	return 0;
3371adfc5217SJeff Kirsher }
3372adfc5217SJeff Kirsher 
bnx2x_mcast_setup_e2(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,enum bnx2x_mcast_cmd cmd)3373adfc5217SJeff Kirsher static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
3374adfc5217SJeff Kirsher 				struct bnx2x_mcast_ramrod_params *p,
337586564c3fSYuval Mintz 				enum bnx2x_mcast_cmd cmd)
3376adfc5217SJeff Kirsher {
3377adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &p->mcast_obj->raw;
3378adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3379adfc5217SJeff Kirsher 	struct eth_multicast_rules_ramrod_data *data =
3380adfc5217SJeff Kirsher 		(struct eth_multicast_rules_ramrod_data *)(raw->rdata);
3381adfc5217SJeff Kirsher 	int cnt = 0, rc;
3382adfc5217SJeff Kirsher 
3383adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer */
3384adfc5217SJeff Kirsher 	memset(data, 0, sizeof(*data));
3385adfc5217SJeff Kirsher 
3386adfc5217SJeff Kirsher 	cnt = bnx2x_mcast_handle_pending_cmds_e2(bp, p);
3387adfc5217SJeff Kirsher 
3388adfc5217SJeff Kirsher 	/* If there are no more pending commands - clear SCHEDULED state */
3389adfc5217SJeff Kirsher 	if (list_empty(&o->pending_cmds_head))
3390adfc5217SJeff Kirsher 		o->clear_sched(o);
3391adfc5217SJeff Kirsher 
3392adfc5217SJeff Kirsher 	/* The below may be true iff there was enough room in ramrod
3393adfc5217SJeff Kirsher 	 * data for all pending commands and for the current
3394adfc5217SJeff Kirsher 	 * command. Otherwise the current command would have been added
3395adfc5217SJeff Kirsher 	 * to the pending commands and p->mcast_list_len would have been
3396adfc5217SJeff Kirsher 	 * zeroed.
3397adfc5217SJeff Kirsher 	 */
3398adfc5217SJeff Kirsher 	if (p->mcast_list_len > 0)
3399adfc5217SJeff Kirsher 		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, cnt);
3400adfc5217SJeff Kirsher 
3401adfc5217SJeff Kirsher 	/* We've pulled out some MACs - update the total number of
3402adfc5217SJeff Kirsher 	 * outstanding.
3403adfc5217SJeff Kirsher 	 */
3404adfc5217SJeff Kirsher 	o->total_pending_num -= cnt;
3405adfc5217SJeff Kirsher 
3406adfc5217SJeff Kirsher 	/* send a ramrod */
3407adfc5217SJeff Kirsher 	WARN_ON(o->total_pending_num < 0);
3408adfc5217SJeff Kirsher 	WARN_ON(cnt > o->max_cmd_len);
3409adfc5217SJeff Kirsher 
3410adfc5217SJeff Kirsher 	bnx2x_mcast_set_rdata_hdr_e2(bp, p, (u8)cnt);
3411adfc5217SJeff Kirsher 
3412adfc5217SJeff Kirsher 	/* Update a registry size if there are no more pending operations.
3413adfc5217SJeff Kirsher 	 *
3414adfc5217SJeff Kirsher 	 * We don't want to change the value of the registry size if there are
3415adfc5217SJeff Kirsher 	 * pending operations because we want it to always be equal to the
3416adfc5217SJeff Kirsher 	 * exact or the approximate number (see bnx2x_mcast_validate_e2()) of
3417adfc5217SJeff Kirsher 	 * set bins after the last requested operation in order to properly
3418adfc5217SJeff Kirsher 	 * evaluate the size of the next DEL/RESTORE operation.
3419adfc5217SJeff Kirsher 	 *
3420adfc5217SJeff Kirsher 	 * Note that we update the registry itself during command(s) handling
3421adfc5217SJeff Kirsher 	 * - see bnx2x_mcast_set_one_rule_e2(). That's because for 57712 we
3422adfc5217SJeff Kirsher 	 * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but
3423adfc5217SJeff Kirsher 	 * with a limited amount of update commands (per MAC/bin) and we don't
3424adfc5217SJeff Kirsher 	 * know in this scope what the actual state of bins configuration is
3425adfc5217SJeff Kirsher 	 * going to be after this ramrod.
3426adfc5217SJeff Kirsher 	 */
3427adfc5217SJeff Kirsher 	if (!o->total_pending_num)
3428adfc5217SJeff Kirsher 		bnx2x_mcast_refresh_registry_e2(bp, o);
3429adfc5217SJeff Kirsher 
343016a5fd92SYuval Mintz 	/* If CLEAR_ONLY was requested - don't send a ramrod and clear
3431c7b7b483SYuval Mintz 	 * RAMROD_PENDING status immediately. due to the SET option, it's also
3432c7b7b483SYuval Mintz 	 * possible that after evaluating the differences there's no need for
3433c7b7b483SYuval Mintz 	 * a ramrod. In that case, we can skip it as well.
3434adfc5217SJeff Kirsher 	 */
3435c7b7b483SYuval Mintz 	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags) || !cnt) {
3436adfc5217SJeff Kirsher 		raw->clear_pending(raw);
3437adfc5217SJeff Kirsher 		return 0;
3438adfc5217SJeff Kirsher 	} else {
343914a94ebdSMichal Kalderon 		/* No need for an explicit memory barrier here as long as we
344014a94ebdSMichal Kalderon 		 * ensure the ordering of writing to the SPQ element
3441adfc5217SJeff Kirsher 		 * and updating of the SPQ producer which involves a memory
344214a94ebdSMichal Kalderon 		 * read. If the memory read is removed we will have to put a
344314a94ebdSMichal Kalderon 		 * full memory barrier there (inside bnx2x_sp_post()).
3444adfc5217SJeff Kirsher 		 */
3445adfc5217SJeff Kirsher 
3446adfc5217SJeff Kirsher 		/* Send a ramrod */
3447adfc5217SJeff Kirsher 		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES,
3448adfc5217SJeff Kirsher 				   raw->cid, U64_HI(raw->rdata_mapping),
3449adfc5217SJeff Kirsher 				   U64_LO(raw->rdata_mapping),
3450adfc5217SJeff Kirsher 				   ETH_CONNECTION_TYPE);
3451adfc5217SJeff Kirsher 		if (rc)
3452adfc5217SJeff Kirsher 			return rc;
3453adfc5217SJeff Kirsher 
3454adfc5217SJeff Kirsher 		/* Ramrod completion is pending */
3455adfc5217SJeff Kirsher 		return 1;
3456adfc5217SJeff Kirsher 	}
3457adfc5217SJeff Kirsher }
3458adfc5217SJeff Kirsher 
bnx2x_mcast_validate_e1h(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,enum bnx2x_mcast_cmd cmd)3459adfc5217SJeff Kirsher static int bnx2x_mcast_validate_e1h(struct bnx2x *bp,
3460adfc5217SJeff Kirsher 				    struct bnx2x_mcast_ramrod_params *p,
346186564c3fSYuval Mintz 				    enum bnx2x_mcast_cmd cmd)
3462adfc5217SJeff Kirsher {
3463c7b7b483SYuval Mintz 	if (cmd == BNX2X_MCAST_CMD_SET) {
3464c7b7b483SYuval Mintz 		BNX2X_ERR("Can't use `set' command on e1h!\n");
3465c7b7b483SYuval Mintz 		return -EINVAL;
3466c7b7b483SYuval Mintz 	}
3467c7b7b483SYuval Mintz 
3468adfc5217SJeff Kirsher 	/* Mark, that there is a work to do */
3469adfc5217SJeff Kirsher 	if ((cmd == BNX2X_MCAST_CMD_DEL) || (cmd == BNX2X_MCAST_CMD_RESTORE))
3470adfc5217SJeff Kirsher 		p->mcast_list_len = 1;
3471adfc5217SJeff Kirsher 
3472adfc5217SJeff Kirsher 	return 0;
3473adfc5217SJeff Kirsher }
3474adfc5217SJeff Kirsher 
bnx2x_mcast_revert_e1h(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,int old_num_bins,enum bnx2x_mcast_cmd cmd)3475adfc5217SJeff Kirsher static void bnx2x_mcast_revert_e1h(struct bnx2x *bp,
3476adfc5217SJeff Kirsher 				       struct bnx2x_mcast_ramrod_params *p,
3477c7b7b483SYuval Mintz 				       int old_num_bins,
3478c7b7b483SYuval Mintz 				       enum bnx2x_mcast_cmd cmd)
3479adfc5217SJeff Kirsher {
3480adfc5217SJeff Kirsher 	/* Do nothing */
3481adfc5217SJeff Kirsher }
3482adfc5217SJeff Kirsher 
3483adfc5217SJeff Kirsher #define BNX2X_57711_SET_MC_FILTER(filter, bit) \
3484adfc5217SJeff Kirsher do { \
3485adfc5217SJeff Kirsher 	(filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \
3486adfc5217SJeff Kirsher } while (0)
3487adfc5217SJeff Kirsher 
bnx2x_mcast_hdl_add_e1h(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_mcast_ramrod_params * p,u32 * mc_filter)3488adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp,
3489adfc5217SJeff Kirsher 					   struct bnx2x_mcast_obj *o,
3490adfc5217SJeff Kirsher 					   struct bnx2x_mcast_ramrod_params *p,
3491adfc5217SJeff Kirsher 					   u32 *mc_filter)
3492adfc5217SJeff Kirsher {
3493adfc5217SJeff Kirsher 	struct bnx2x_mcast_list_elem *mlist_pos;
3494adfc5217SJeff Kirsher 	int bit;
3495adfc5217SJeff Kirsher 
3496adfc5217SJeff Kirsher 	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
3497adfc5217SJeff Kirsher 		bit = bnx2x_mcast_bin_from_mac(mlist_pos->mac);
3498adfc5217SJeff Kirsher 		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
3499adfc5217SJeff Kirsher 
35000f9dad10SJoe Perches 		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC, bin %d\n",
35010f9dad10SJoe Perches 		   mlist_pos->mac, bit);
3502adfc5217SJeff Kirsher 
3503adfc5217SJeff Kirsher 		/* bookkeeping... */
3504adfc5217SJeff Kirsher 		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
3505adfc5217SJeff Kirsher 				  bit);
3506adfc5217SJeff Kirsher 	}
3507adfc5217SJeff Kirsher }
3508adfc5217SJeff Kirsher 
bnx2x_mcast_hdl_restore_e1h(struct bnx2x * bp,struct bnx2x_mcast_obj * o,struct bnx2x_mcast_ramrod_params * p,u32 * mc_filter)3509adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp,
3510adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
3511adfc5217SJeff Kirsher 	u32 *mc_filter)
3512adfc5217SJeff Kirsher {
3513adfc5217SJeff Kirsher 	int bit;
3514adfc5217SJeff Kirsher 
3515adfc5217SJeff Kirsher 	for (bit = bnx2x_mcast_get_next_bin(o, 0);
3516adfc5217SJeff Kirsher 	     bit >= 0;
3517adfc5217SJeff Kirsher 	     bit = bnx2x_mcast_get_next_bin(o, bit + 1)) {
3518adfc5217SJeff Kirsher 		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
3519adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "About to set bin %d\n", bit);
3520adfc5217SJeff Kirsher 	}
3521adfc5217SJeff Kirsher }
3522adfc5217SJeff Kirsher 
352316a5fd92SYuval Mintz /* On 57711 we write the multicast MACs' approximate match
3524adfc5217SJeff Kirsher  * table by directly into the TSTORM's internal RAM. So we don't
3525adfc5217SJeff Kirsher  * really need to handle any tricks to make it work.
3526adfc5217SJeff Kirsher  */
bnx2x_mcast_setup_e1h(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,enum bnx2x_mcast_cmd cmd)3527adfc5217SJeff Kirsher static int bnx2x_mcast_setup_e1h(struct bnx2x *bp,
3528adfc5217SJeff Kirsher 				 struct bnx2x_mcast_ramrod_params *p,
352986564c3fSYuval Mintz 				 enum bnx2x_mcast_cmd cmd)
3530adfc5217SJeff Kirsher {
3531adfc5217SJeff Kirsher 	int i;
3532adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3533adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
3534adfc5217SJeff Kirsher 
3535adfc5217SJeff Kirsher 	/* If CLEAR_ONLY has been requested - clear the registry
3536adfc5217SJeff Kirsher 	 * and clear a pending bit.
3537adfc5217SJeff Kirsher 	 */
3538adfc5217SJeff Kirsher 	if (!test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
3539adfc5217SJeff Kirsher 		u32 mc_filter[MC_HASH_SIZE] = {0};
3540adfc5217SJeff Kirsher 
3541adfc5217SJeff Kirsher 		/* Set the multicast filter bits before writing it into
3542adfc5217SJeff Kirsher 		 * the internal memory.
3543adfc5217SJeff Kirsher 		 */
3544adfc5217SJeff Kirsher 		switch (cmd) {
3545adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_ADD:
3546adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_add_e1h(bp, o, p, mc_filter);
3547adfc5217SJeff Kirsher 			break;
3548adfc5217SJeff Kirsher 
3549adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_DEL:
355094f05b0fSJoe Perches 			DP(BNX2X_MSG_SP,
355194f05b0fSJoe Perches 			   "Invalidating multicast MACs configuration\n");
3552adfc5217SJeff Kirsher 
3553adfc5217SJeff Kirsher 			/* clear the registry */
3554adfc5217SJeff Kirsher 			memset(o->registry.aprox_match.vec, 0,
3555adfc5217SJeff Kirsher 			       sizeof(o->registry.aprox_match.vec));
3556adfc5217SJeff Kirsher 			break;
3557adfc5217SJeff Kirsher 
3558adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_RESTORE:
3559adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_restore_e1h(bp, o, p, mc_filter);
3560adfc5217SJeff Kirsher 			break;
3561adfc5217SJeff Kirsher 
3562adfc5217SJeff Kirsher 		default:
3563adfc5217SJeff Kirsher 			BNX2X_ERR("Unknown command: %d\n", cmd);
3564adfc5217SJeff Kirsher 			return -EINVAL;
3565adfc5217SJeff Kirsher 		}
3566adfc5217SJeff Kirsher 
3567adfc5217SJeff Kirsher 		/* Set the mcast filter in the internal memory */
3568adfc5217SJeff Kirsher 		for (i = 0; i < MC_HASH_SIZE; i++)
3569adfc5217SJeff Kirsher 			REG_WR(bp, MC_HASH_OFFSET(bp, i), mc_filter[i]);
3570adfc5217SJeff Kirsher 	} else
3571adfc5217SJeff Kirsher 		/* clear the registry */
3572adfc5217SJeff Kirsher 		memset(o->registry.aprox_match.vec, 0,
3573adfc5217SJeff Kirsher 		       sizeof(o->registry.aprox_match.vec));
3574adfc5217SJeff Kirsher 
3575adfc5217SJeff Kirsher 	/* We are done */
3576adfc5217SJeff Kirsher 	r->clear_pending(r);
3577adfc5217SJeff Kirsher 
3578adfc5217SJeff Kirsher 	return 0;
3579adfc5217SJeff Kirsher }
3580adfc5217SJeff Kirsher 
bnx2x_mcast_validate_e1(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,enum bnx2x_mcast_cmd cmd)3581adfc5217SJeff Kirsher static int bnx2x_mcast_validate_e1(struct bnx2x *bp,
3582adfc5217SJeff Kirsher 				   struct bnx2x_mcast_ramrod_params *p,
358386564c3fSYuval Mintz 				   enum bnx2x_mcast_cmd cmd)
3584adfc5217SJeff Kirsher {
3585adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3586adfc5217SJeff Kirsher 	int reg_sz = o->get_registry_size(o);
3587adfc5217SJeff Kirsher 
3588c7b7b483SYuval Mintz 	if (cmd == BNX2X_MCAST_CMD_SET) {
3589c7b7b483SYuval Mintz 		BNX2X_ERR("Can't use `set' command on e1!\n");
3590c7b7b483SYuval Mintz 		return -EINVAL;
3591c7b7b483SYuval Mintz 	}
3592c7b7b483SYuval Mintz 
3593adfc5217SJeff Kirsher 	switch (cmd) {
3594adfc5217SJeff Kirsher 	/* DEL command deletes all currently configured MACs */
3595adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
3596adfc5217SJeff Kirsher 		o->set_registry_size(o, 0);
3597df561f66SGustavo A. R. Silva 		fallthrough;
3598adfc5217SJeff Kirsher 
3599adfc5217SJeff Kirsher 	/* RESTORE command will restore the entire multicast configuration */
3600adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
3601adfc5217SJeff Kirsher 		p->mcast_list_len = reg_sz;
3602adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n",
3603adfc5217SJeff Kirsher 		   cmd, p->mcast_list_len);
3604adfc5217SJeff Kirsher 		break;
3605adfc5217SJeff Kirsher 
3606adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
3607adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_CONT:
3608adfc5217SJeff Kirsher 		/* Multicast MACs on 57710 are configured as unicast MACs and
3609adfc5217SJeff Kirsher 		 * there is only a limited number of CAM entries for that
3610adfc5217SJeff Kirsher 		 * matter.
3611adfc5217SJeff Kirsher 		 */
3612adfc5217SJeff Kirsher 		if (p->mcast_list_len > o->max_cmd_len) {
361351c1a580SMerav Sicron 			BNX2X_ERR("Can't configure more than %d multicast MACs on 57710\n",
361451c1a580SMerav Sicron 				  o->max_cmd_len);
3615adfc5217SJeff Kirsher 			return -EINVAL;
3616adfc5217SJeff Kirsher 		}
3617adfc5217SJeff Kirsher 		/* Every configured MAC should be cleared if DEL command is
3618adfc5217SJeff Kirsher 		 * called. Only the last ADD command is relevant as long as
3619adfc5217SJeff Kirsher 		 * every ADD commands overrides the previous configuration.
3620adfc5217SJeff Kirsher 		 */
3621adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
3622adfc5217SJeff Kirsher 		if (p->mcast_list_len > 0)
3623adfc5217SJeff Kirsher 			o->set_registry_size(o, p->mcast_list_len);
3624adfc5217SJeff Kirsher 
3625adfc5217SJeff Kirsher 		break;
3626adfc5217SJeff Kirsher 
3627adfc5217SJeff Kirsher 	default:
3628adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
3629adfc5217SJeff Kirsher 		return -EINVAL;
3630adfc5217SJeff Kirsher 	}
3631adfc5217SJeff Kirsher 
3632adfc5217SJeff Kirsher 	/* We want to ensure that commands are executed one by one for 57710.
3633adfc5217SJeff Kirsher 	 * Therefore each none-empty command will consume o->max_cmd_len.
3634adfc5217SJeff Kirsher 	 */
3635adfc5217SJeff Kirsher 	if (p->mcast_list_len)
3636adfc5217SJeff Kirsher 		o->total_pending_num += o->max_cmd_len;
3637adfc5217SJeff Kirsher 
3638adfc5217SJeff Kirsher 	return 0;
3639adfc5217SJeff Kirsher }
3640adfc5217SJeff Kirsher 
bnx2x_mcast_revert_e1(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,int old_num_macs,enum bnx2x_mcast_cmd cmd)3641adfc5217SJeff Kirsher static void bnx2x_mcast_revert_e1(struct bnx2x *bp,
3642adfc5217SJeff Kirsher 				      struct bnx2x_mcast_ramrod_params *p,
3643c7b7b483SYuval Mintz 				   int old_num_macs,
3644c7b7b483SYuval Mintz 				   enum bnx2x_mcast_cmd cmd)
3645adfc5217SJeff Kirsher {
3646adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3647adfc5217SJeff Kirsher 
3648adfc5217SJeff Kirsher 	o->set_registry_size(o, old_num_macs);
3649adfc5217SJeff Kirsher 
3650adfc5217SJeff Kirsher 	/* If current command hasn't been handled yet and we are
3651adfc5217SJeff Kirsher 	 * here means that it's meant to be dropped and we have to
365216a5fd92SYuval Mintz 	 * update the number of outstanding MACs accordingly.
3653adfc5217SJeff Kirsher 	 */
3654adfc5217SJeff Kirsher 	if (p->mcast_list_len)
3655adfc5217SJeff Kirsher 		o->total_pending_num -= o->max_cmd_len;
3656adfc5217SJeff Kirsher }
3657adfc5217SJeff Kirsher 
bnx2x_mcast_set_one_rule_e1(struct bnx2x * bp,struct bnx2x_mcast_obj * o,int idx,union bnx2x_mcast_config_data * cfg_data,enum bnx2x_mcast_cmd cmd)3658adfc5217SJeff Kirsher static void bnx2x_mcast_set_one_rule_e1(struct bnx2x *bp,
3659adfc5217SJeff Kirsher 					struct bnx2x_mcast_obj *o, int idx,
3660adfc5217SJeff Kirsher 					union bnx2x_mcast_config_data *cfg_data,
366186564c3fSYuval Mintz 					enum bnx2x_mcast_cmd cmd)
3662adfc5217SJeff Kirsher {
3663adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
3664adfc5217SJeff Kirsher 	struct mac_configuration_cmd *data =
3665adfc5217SJeff Kirsher 		(struct mac_configuration_cmd *)(r->rdata);
3666adfc5217SJeff Kirsher 
3667adfc5217SJeff Kirsher 	/* copy mac */
3668adfc5217SJeff Kirsher 	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE)) {
3669adfc5217SJeff Kirsher 		bnx2x_set_fw_mac_addr(&data->config_table[idx].msb_mac_addr,
3670adfc5217SJeff Kirsher 				      &data->config_table[idx].middle_mac_addr,
3671adfc5217SJeff Kirsher 				      &data->config_table[idx].lsb_mac_addr,
3672adfc5217SJeff Kirsher 				      cfg_data->mac);
3673adfc5217SJeff Kirsher 
3674adfc5217SJeff Kirsher 		data->config_table[idx].vlan_id = 0;
3675adfc5217SJeff Kirsher 		data->config_table[idx].pf_id = r->func_id;
3676adfc5217SJeff Kirsher 		data->config_table[idx].clients_bit_vector =
3677adfc5217SJeff Kirsher 			cpu_to_le32(1 << r->cl_id);
3678adfc5217SJeff Kirsher 
3679adfc5217SJeff Kirsher 		SET_FLAG(data->config_table[idx].flags,
3680adfc5217SJeff Kirsher 			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
3681adfc5217SJeff Kirsher 			 T_ETH_MAC_COMMAND_SET);
3682adfc5217SJeff Kirsher 	}
3683adfc5217SJeff Kirsher }
3684adfc5217SJeff Kirsher 
3685adfc5217SJeff Kirsher /**
3686adfc5217SJeff Kirsher  * bnx2x_mcast_set_rdata_hdr_e1  - set header values in mac_configuration_cmd
3687adfc5217SJeff Kirsher  *
3688adfc5217SJeff Kirsher  * @bp:		device handle
3689d0ea5cbdSJesse Brandeburg  * @p:		ramrod parameters
3690adfc5217SJeff Kirsher  * @len:	number of rules to handle
3691adfc5217SJeff Kirsher  */
bnx2x_mcast_set_rdata_hdr_e1(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,u8 len)3692adfc5217SJeff Kirsher static inline void bnx2x_mcast_set_rdata_hdr_e1(struct bnx2x *bp,
3693adfc5217SJeff Kirsher 					struct bnx2x_mcast_ramrod_params *p,
3694adfc5217SJeff Kirsher 					u8 len)
3695adfc5217SJeff Kirsher {
3696adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
3697adfc5217SJeff Kirsher 	struct mac_configuration_cmd *data =
3698adfc5217SJeff Kirsher 		(struct mac_configuration_cmd *)(r->rdata);
3699adfc5217SJeff Kirsher 
3700adfc5217SJeff Kirsher 	u8 offset = (CHIP_REV_IS_SLOW(bp) ?
3701adfc5217SJeff Kirsher 		     BNX2X_MAX_EMUL_MULTI*(1 + r->func_id) :
3702adfc5217SJeff Kirsher 		     BNX2X_MAX_MULTICAST*(1 + r->func_id));
3703adfc5217SJeff Kirsher 
3704adfc5217SJeff Kirsher 	data->hdr.offset = offset;
370586564c3fSYuval Mintz 	data->hdr.client_id = cpu_to_le16(0xff);
370686564c3fSYuval Mintz 	data->hdr.echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) |
370786564c3fSYuval Mintz 				     (BNX2X_FILTER_MCAST_PENDING <<
370886564c3fSYuval Mintz 				      BNX2X_SWCID_SHIFT));
3709adfc5217SJeff Kirsher 	data->hdr.length = len;
3710adfc5217SJeff Kirsher }
3711adfc5217SJeff Kirsher 
3712adfc5217SJeff Kirsher /**
3713adfc5217SJeff Kirsher  * bnx2x_mcast_handle_restore_cmd_e1 - restore command for 57710
3714adfc5217SJeff Kirsher  *
3715adfc5217SJeff Kirsher  * @bp:		device handle
3716d0ea5cbdSJesse Brandeburg  * @o:		multicast info
3717adfc5217SJeff Kirsher  * @start_idx:	index in the registry to start from
3718adfc5217SJeff Kirsher  * @rdata_idx:	index in the ramrod data to start from
3719adfc5217SJeff Kirsher  *
3720adfc5217SJeff Kirsher  * restore command for 57710 is like all other commands - always a stand alone
3721adfc5217SJeff Kirsher  * command - start_idx and rdata_idx will always be 0. This function will always
3722adfc5217SJeff Kirsher  * succeed.
3723adfc5217SJeff Kirsher  * returns -1 to comply with 57712 variant.
3724adfc5217SJeff Kirsher  */
bnx2x_mcast_handle_restore_cmd_e1(struct bnx2x * bp,struct bnx2x_mcast_obj * o,int start_idx,int * rdata_idx)3725adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_restore_cmd_e1(
3726adfc5217SJeff Kirsher 	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_idx,
3727adfc5217SJeff Kirsher 	int *rdata_idx)
3728adfc5217SJeff Kirsher {
3729adfc5217SJeff Kirsher 	struct bnx2x_mcast_mac_elem *elem;
3730adfc5217SJeff Kirsher 	int i = 0;
373186564c3fSYuval Mintz 	union bnx2x_mcast_config_data cfg_data = {NULL};
3732adfc5217SJeff Kirsher 
3733adfc5217SJeff Kirsher 	/* go through the registry and configure the MACs from it. */
3734adfc5217SJeff Kirsher 	list_for_each_entry(elem, &o->registry.exact_match.macs, link) {
3735adfc5217SJeff Kirsher 		cfg_data.mac = &elem->mac[0];
3736adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, i, &cfg_data, BNX2X_MCAST_CMD_RESTORE);
3737adfc5217SJeff Kirsher 
3738adfc5217SJeff Kirsher 		i++;
3739adfc5217SJeff Kirsher 
37400f9dad10SJoe Perches 		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
37410f9dad10SJoe Perches 		   cfg_data.mac);
3742adfc5217SJeff Kirsher 	}
3743adfc5217SJeff Kirsher 
3744adfc5217SJeff Kirsher 	*rdata_idx = i;
3745adfc5217SJeff Kirsher 
3746adfc5217SJeff Kirsher 	return -1;
3747adfc5217SJeff Kirsher }
3748adfc5217SJeff Kirsher 
bnx2x_mcast_handle_pending_cmds_e1(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p)3749adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_pending_cmds_e1(
3750adfc5217SJeff Kirsher 	struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p)
3751adfc5217SJeff Kirsher {
3752adfc5217SJeff Kirsher 	struct bnx2x_pending_mcast_cmd *cmd_pos;
3753adfc5217SJeff Kirsher 	struct bnx2x_mcast_mac_elem *pmac_pos;
3754adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
375586564c3fSYuval Mintz 	union bnx2x_mcast_config_data cfg_data = {NULL};
3756adfc5217SJeff Kirsher 	int cnt = 0;
3757adfc5217SJeff Kirsher 
3758adfc5217SJeff Kirsher 	/* If nothing to be done - return */
3759adfc5217SJeff Kirsher 	if (list_empty(&o->pending_cmds_head))
3760adfc5217SJeff Kirsher 		return 0;
3761adfc5217SJeff Kirsher 
3762adfc5217SJeff Kirsher 	/* Handle the first command */
3763adfc5217SJeff Kirsher 	cmd_pos = list_first_entry(&o->pending_cmds_head,
3764adfc5217SJeff Kirsher 				   struct bnx2x_pending_mcast_cmd, link);
3765adfc5217SJeff Kirsher 
3766adfc5217SJeff Kirsher 	switch (cmd_pos->type) {
3767adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
3768adfc5217SJeff Kirsher 		list_for_each_entry(pmac_pos, &cmd_pos->data.macs_head, link) {
3769adfc5217SJeff Kirsher 			cfg_data.mac = &pmac_pos->mac[0];
3770adfc5217SJeff Kirsher 			o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
3771adfc5217SJeff Kirsher 
3772adfc5217SJeff Kirsher 			cnt++;
3773adfc5217SJeff Kirsher 
37740f9dad10SJoe Perches 			DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
37750f9dad10SJoe Perches 			   pmac_pos->mac);
3776adfc5217SJeff Kirsher 		}
3777adfc5217SJeff Kirsher 		break;
3778adfc5217SJeff Kirsher 
3779adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
3780adfc5217SJeff Kirsher 		cnt = cmd_pos->data.macs_num;
3781adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "About to delete %d multicast MACs\n", cnt);
3782adfc5217SJeff Kirsher 		break;
3783adfc5217SJeff Kirsher 
3784adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
3785adfc5217SJeff Kirsher 		o->hdl_restore(bp, o, 0, &cnt);
3786adfc5217SJeff Kirsher 		break;
3787adfc5217SJeff Kirsher 
3788adfc5217SJeff Kirsher 	default:
3789adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
3790adfc5217SJeff Kirsher 		return -EINVAL;
3791adfc5217SJeff Kirsher 	}
3792adfc5217SJeff Kirsher 
3793adfc5217SJeff Kirsher 	list_del(&cmd_pos->link);
37943129e159SJason Baron 	bnx2x_free_groups(&cmd_pos->group_head);
3795adfc5217SJeff Kirsher 	kfree(cmd_pos);
3796adfc5217SJeff Kirsher 
3797adfc5217SJeff Kirsher 	return cnt;
3798adfc5217SJeff Kirsher }
3799adfc5217SJeff Kirsher 
3800adfc5217SJeff Kirsher /**
3801adfc5217SJeff Kirsher  * bnx2x_get_fw_mac_addr - revert the bnx2x_set_fw_mac_addr().
3802adfc5217SJeff Kirsher  *
3803d0ea5cbdSJesse Brandeburg  * @fw_hi: address
3804d0ea5cbdSJesse Brandeburg  * @fw_mid: address
3805d0ea5cbdSJesse Brandeburg  * @fw_lo: address
3806d0ea5cbdSJesse Brandeburg  * @mac: mac address
3807adfc5217SJeff Kirsher  */
bnx2x_get_fw_mac_addr(__le16 * fw_hi,__le16 * fw_mid,__le16 * fw_lo,u8 * mac)3808adfc5217SJeff Kirsher static inline void bnx2x_get_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid,
3809adfc5217SJeff Kirsher 					 __le16 *fw_lo, u8 *mac)
3810adfc5217SJeff Kirsher {
3811adfc5217SJeff Kirsher 	mac[1] = ((u8 *)fw_hi)[0];
3812adfc5217SJeff Kirsher 	mac[0] = ((u8 *)fw_hi)[1];
3813adfc5217SJeff Kirsher 	mac[3] = ((u8 *)fw_mid)[0];
3814adfc5217SJeff Kirsher 	mac[2] = ((u8 *)fw_mid)[1];
3815adfc5217SJeff Kirsher 	mac[5] = ((u8 *)fw_lo)[0];
3816adfc5217SJeff Kirsher 	mac[4] = ((u8 *)fw_lo)[1];
3817adfc5217SJeff Kirsher }
3818adfc5217SJeff Kirsher 
3819adfc5217SJeff Kirsher /**
3820adfc5217SJeff Kirsher  * bnx2x_mcast_refresh_registry_e1 -
3821adfc5217SJeff Kirsher  *
3822adfc5217SJeff Kirsher  * @bp:		device handle
3823d0ea5cbdSJesse Brandeburg  * @o:		multicast info
3824adfc5217SJeff Kirsher  *
3825adfc5217SJeff Kirsher  * Check the ramrod data first entry flag to see if it's a DELETE or ADD command
3826adfc5217SJeff Kirsher  * and update the registry correspondingly: if ADD - allocate a memory and add
3827adfc5217SJeff Kirsher  * the entries to the registry (list), if DELETE - clear the registry and free
3828adfc5217SJeff Kirsher  * the memory.
3829adfc5217SJeff Kirsher  */
bnx2x_mcast_refresh_registry_e1(struct bnx2x * bp,struct bnx2x_mcast_obj * o)3830adfc5217SJeff Kirsher static inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp,
3831adfc5217SJeff Kirsher 						  struct bnx2x_mcast_obj *o)
3832adfc5217SJeff Kirsher {
3833adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
3834adfc5217SJeff Kirsher 	struct bnx2x_mcast_mac_elem *elem;
3835adfc5217SJeff Kirsher 	struct mac_configuration_cmd *data =
3836adfc5217SJeff Kirsher 			(struct mac_configuration_cmd *)(raw->rdata);
3837adfc5217SJeff Kirsher 
3838adfc5217SJeff Kirsher 	/* If first entry contains a SET bit - the command was ADD,
3839adfc5217SJeff Kirsher 	 * otherwise - DEL_ALL
3840adfc5217SJeff Kirsher 	 */
3841adfc5217SJeff Kirsher 	if (GET_FLAG(data->config_table[0].flags,
3842adfc5217SJeff Kirsher 			MAC_CONFIGURATION_ENTRY_ACTION_TYPE)) {
3843adfc5217SJeff Kirsher 		int i, len = data->hdr.length;
3844adfc5217SJeff Kirsher 
3845adfc5217SJeff Kirsher 		/* Break if it was a RESTORE command */
3846adfc5217SJeff Kirsher 		if (!list_empty(&o->registry.exact_match.macs))
3847adfc5217SJeff Kirsher 			return 0;
3848adfc5217SJeff Kirsher 
384901e23742SThomas Meyer 		elem = kcalloc(len, sizeof(*elem), GFP_ATOMIC);
3850adfc5217SJeff Kirsher 		if (!elem) {
3851adfc5217SJeff Kirsher 			BNX2X_ERR("Failed to allocate registry memory\n");
3852adfc5217SJeff Kirsher 			return -ENOMEM;
3853adfc5217SJeff Kirsher 		}
3854adfc5217SJeff Kirsher 
3855adfc5217SJeff Kirsher 		for (i = 0; i < len; i++, elem++) {
3856adfc5217SJeff Kirsher 			bnx2x_get_fw_mac_addr(
3857adfc5217SJeff Kirsher 				&data->config_table[i].msb_mac_addr,
3858adfc5217SJeff Kirsher 				&data->config_table[i].middle_mac_addr,
3859adfc5217SJeff Kirsher 				&data->config_table[i].lsb_mac_addr,
3860adfc5217SJeff Kirsher 				elem->mac);
38610f9dad10SJoe Perches 			DP(BNX2X_MSG_SP, "Adding registry entry for [%pM]\n",
38620f9dad10SJoe Perches 			   elem->mac);
3863adfc5217SJeff Kirsher 			list_add_tail(&elem->link,
3864adfc5217SJeff Kirsher 				      &o->registry.exact_match.macs);
3865adfc5217SJeff Kirsher 		}
3866adfc5217SJeff Kirsher 	} else {
3867adfc5217SJeff Kirsher 		elem = list_first_entry(&o->registry.exact_match.macs,
3868adfc5217SJeff Kirsher 					struct bnx2x_mcast_mac_elem, link);
3869adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Deleting a registry\n");
3870adfc5217SJeff Kirsher 		kfree(elem);
3871adfc5217SJeff Kirsher 		INIT_LIST_HEAD(&o->registry.exact_match.macs);
3872adfc5217SJeff Kirsher 	}
3873adfc5217SJeff Kirsher 
3874adfc5217SJeff Kirsher 	return 0;
3875adfc5217SJeff Kirsher }
3876adfc5217SJeff Kirsher 
bnx2x_mcast_setup_e1(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,enum bnx2x_mcast_cmd cmd)3877adfc5217SJeff Kirsher static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
3878adfc5217SJeff Kirsher 				struct bnx2x_mcast_ramrod_params *p,
387986564c3fSYuval Mintz 				enum bnx2x_mcast_cmd cmd)
3880adfc5217SJeff Kirsher {
3881adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3882adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
3883adfc5217SJeff Kirsher 	struct mac_configuration_cmd *data =
3884adfc5217SJeff Kirsher 		(struct mac_configuration_cmd *)(raw->rdata);
3885adfc5217SJeff Kirsher 	int cnt = 0, i, rc;
3886adfc5217SJeff Kirsher 
3887adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer */
3888adfc5217SJeff Kirsher 	memset(data, 0, sizeof(*data));
3889adfc5217SJeff Kirsher 
3890adfc5217SJeff Kirsher 	/* First set all entries as invalid */
3891adfc5217SJeff Kirsher 	for (i = 0; i < o->max_cmd_len ; i++)
3892adfc5217SJeff Kirsher 		SET_FLAG(data->config_table[i].flags,
3893adfc5217SJeff Kirsher 			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
3894adfc5217SJeff Kirsher 			 T_ETH_MAC_COMMAND_INVALIDATE);
3895adfc5217SJeff Kirsher 
3896adfc5217SJeff Kirsher 	/* Handle pending commands first */
3897adfc5217SJeff Kirsher 	cnt = bnx2x_mcast_handle_pending_cmds_e1(bp, p);
3898adfc5217SJeff Kirsher 
3899adfc5217SJeff Kirsher 	/* If there are no more pending commands - clear SCHEDULED state */
3900adfc5217SJeff Kirsher 	if (list_empty(&o->pending_cmds_head))
3901adfc5217SJeff Kirsher 		o->clear_sched(o);
3902adfc5217SJeff Kirsher 
3903adfc5217SJeff Kirsher 	/* The below may be true iff there were no pending commands */
3904adfc5217SJeff Kirsher 	if (!cnt)
3905adfc5217SJeff Kirsher 		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, 0);
3906adfc5217SJeff Kirsher 
3907adfc5217SJeff Kirsher 	/* For 57710 every command has o->max_cmd_len length to ensure that
3908adfc5217SJeff Kirsher 	 * commands are done one at a time.
3909adfc5217SJeff Kirsher 	 */
3910adfc5217SJeff Kirsher 	o->total_pending_num -= o->max_cmd_len;
3911adfc5217SJeff Kirsher 
3912adfc5217SJeff Kirsher 	/* send a ramrod */
3913adfc5217SJeff Kirsher 
3914adfc5217SJeff Kirsher 	WARN_ON(cnt > o->max_cmd_len);
3915adfc5217SJeff Kirsher 
3916adfc5217SJeff Kirsher 	/* Set ramrod header (in particular, a number of entries to update) */
3917adfc5217SJeff Kirsher 	bnx2x_mcast_set_rdata_hdr_e1(bp, p, (u8)cnt);
3918adfc5217SJeff Kirsher 
3919adfc5217SJeff Kirsher 	/* update a registry: we need the registry contents to be always up
3920adfc5217SJeff Kirsher 	 * to date in order to be able to execute a RESTORE opcode. Here
3921adfc5217SJeff Kirsher 	 * we use the fact that for 57710 we sent one command at a time
3922adfc5217SJeff Kirsher 	 * hence we may take the registry update out of the command handling
3923adfc5217SJeff Kirsher 	 * and do it in a simpler way here.
3924adfc5217SJeff Kirsher 	 */
3925adfc5217SJeff Kirsher 	rc = bnx2x_mcast_refresh_registry_e1(bp, o);
3926adfc5217SJeff Kirsher 	if (rc)
3927adfc5217SJeff Kirsher 		return rc;
3928adfc5217SJeff Kirsher 
392916a5fd92SYuval Mintz 	/* If CLEAR_ONLY was requested - don't send a ramrod and clear
3930adfc5217SJeff Kirsher 	 * RAMROD_PENDING status immediately.
3931adfc5217SJeff Kirsher 	 */
3932adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
3933adfc5217SJeff Kirsher 		raw->clear_pending(raw);
3934adfc5217SJeff Kirsher 		return 0;
3935adfc5217SJeff Kirsher 	} else {
393614a94ebdSMichal Kalderon 		/* No need for an explicit memory barrier here as long as we
393714a94ebdSMichal Kalderon 		 * ensure the ordering of writing to the SPQ element
3938adfc5217SJeff Kirsher 		 * and updating of the SPQ producer which involves a memory
393914a94ebdSMichal Kalderon 		 * read. If the memory read is removed we will have to put a
394014a94ebdSMichal Kalderon 		 * full memory barrier there (inside bnx2x_sp_post()).
3941adfc5217SJeff Kirsher 		 */
3942adfc5217SJeff Kirsher 
3943adfc5217SJeff Kirsher 		/* Send a ramrod */
3944adfc5217SJeff Kirsher 		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid,
3945adfc5217SJeff Kirsher 				   U64_HI(raw->rdata_mapping),
3946adfc5217SJeff Kirsher 				   U64_LO(raw->rdata_mapping),
3947adfc5217SJeff Kirsher 				   ETH_CONNECTION_TYPE);
3948adfc5217SJeff Kirsher 		if (rc)
3949adfc5217SJeff Kirsher 			return rc;
3950adfc5217SJeff Kirsher 
3951adfc5217SJeff Kirsher 		/* Ramrod completion is pending */
3952adfc5217SJeff Kirsher 		return 1;
3953adfc5217SJeff Kirsher 	}
3954adfc5217SJeff Kirsher }
3955adfc5217SJeff Kirsher 
bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj * o)3956adfc5217SJeff Kirsher static int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o)
3957adfc5217SJeff Kirsher {
3958adfc5217SJeff Kirsher 	return o->registry.exact_match.num_macs_set;
3959adfc5217SJeff Kirsher }
3960adfc5217SJeff Kirsher 
bnx2x_mcast_get_registry_size_aprox(struct bnx2x_mcast_obj * o)3961adfc5217SJeff Kirsher static int bnx2x_mcast_get_registry_size_aprox(struct bnx2x_mcast_obj *o)
3962adfc5217SJeff Kirsher {
3963adfc5217SJeff Kirsher 	return o->registry.aprox_match.num_bins_set;
3964adfc5217SJeff Kirsher }
3965adfc5217SJeff Kirsher 
bnx2x_mcast_set_registry_size_exact(struct bnx2x_mcast_obj * o,int n)3966adfc5217SJeff Kirsher static void bnx2x_mcast_set_registry_size_exact(struct bnx2x_mcast_obj *o,
3967adfc5217SJeff Kirsher 						int n)
3968adfc5217SJeff Kirsher {
3969adfc5217SJeff Kirsher 	o->registry.exact_match.num_macs_set = n;
3970adfc5217SJeff Kirsher }
3971adfc5217SJeff Kirsher 
bnx2x_mcast_set_registry_size_aprox(struct bnx2x_mcast_obj * o,int n)3972adfc5217SJeff Kirsher static void bnx2x_mcast_set_registry_size_aprox(struct bnx2x_mcast_obj *o,
3973adfc5217SJeff Kirsher 						int n)
3974adfc5217SJeff Kirsher {
3975adfc5217SJeff Kirsher 	o->registry.aprox_match.num_bins_set = n;
3976adfc5217SJeff Kirsher }
3977adfc5217SJeff Kirsher 
bnx2x_config_mcast(struct bnx2x * bp,struct bnx2x_mcast_ramrod_params * p,enum bnx2x_mcast_cmd cmd)3978adfc5217SJeff Kirsher int bnx2x_config_mcast(struct bnx2x *bp,
3979adfc5217SJeff Kirsher 		       struct bnx2x_mcast_ramrod_params *p,
398086564c3fSYuval Mintz 		       enum bnx2x_mcast_cmd cmd)
3981adfc5217SJeff Kirsher {
3982adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3983adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
3984adfc5217SJeff Kirsher 	int rc = 0, old_reg_size;
3985adfc5217SJeff Kirsher 
3986adfc5217SJeff Kirsher 	/* This is needed to recover number of currently configured mcast macs
3987adfc5217SJeff Kirsher 	 * in case of failure.
3988adfc5217SJeff Kirsher 	 */
3989adfc5217SJeff Kirsher 	old_reg_size = o->get_registry_size(o);
3990adfc5217SJeff Kirsher 
3991adfc5217SJeff Kirsher 	/* Do some calculations and checks */
3992adfc5217SJeff Kirsher 	rc = o->validate(bp, p, cmd);
3993adfc5217SJeff Kirsher 	if (rc)
3994adfc5217SJeff Kirsher 		return rc;
3995adfc5217SJeff Kirsher 
3996adfc5217SJeff Kirsher 	/* Return if there is no work to do */
3997adfc5217SJeff Kirsher 	if ((!p->mcast_list_len) && (!o->check_sched(o)))
3998adfc5217SJeff Kirsher 		return 0;
3999adfc5217SJeff Kirsher 
400051c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "o->total_pending_num=%d p->mcast_list_len=%d o->max_cmd_len=%d\n",
400151c1a580SMerav Sicron 	   o->total_pending_num, p->mcast_list_len, o->max_cmd_len);
4002adfc5217SJeff Kirsher 
4003adfc5217SJeff Kirsher 	/* Enqueue the current command to the pending list if we can't complete
4004adfc5217SJeff Kirsher 	 * it in the current iteration
4005adfc5217SJeff Kirsher 	 */
4006adfc5217SJeff Kirsher 	if (r->check_pending(r) ||
4007adfc5217SJeff Kirsher 	    ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) {
4008adfc5217SJeff Kirsher 		rc = o->enqueue_cmd(bp, p->mcast_obj, p, cmd);
4009adfc5217SJeff Kirsher 		if (rc < 0)
4010adfc5217SJeff Kirsher 			goto error_exit1;
4011adfc5217SJeff Kirsher 
4012adfc5217SJeff Kirsher 		/* As long as the current command is in a command list we
4013adfc5217SJeff Kirsher 		 * don't need to handle it separately.
4014adfc5217SJeff Kirsher 		 */
4015adfc5217SJeff Kirsher 		p->mcast_list_len = 0;
4016adfc5217SJeff Kirsher 	}
4017adfc5217SJeff Kirsher 
4018adfc5217SJeff Kirsher 	if (!r->check_pending(r)) {
4019adfc5217SJeff Kirsher 
4020adfc5217SJeff Kirsher 		/* Set 'pending' state */
4021adfc5217SJeff Kirsher 		r->set_pending(r);
4022adfc5217SJeff Kirsher 
4023adfc5217SJeff Kirsher 		/* Configure the new classification in the chip */
4024adfc5217SJeff Kirsher 		rc = o->config_mcast(bp, p, cmd);
4025adfc5217SJeff Kirsher 		if (rc < 0)
4026adfc5217SJeff Kirsher 			goto error_exit2;
4027adfc5217SJeff Kirsher 
4028adfc5217SJeff Kirsher 		/* Wait for a ramrod completion if was requested */
4029adfc5217SJeff Kirsher 		if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
4030adfc5217SJeff Kirsher 			rc = o->wait_comp(bp, o);
4031adfc5217SJeff Kirsher 	}
4032adfc5217SJeff Kirsher 
4033adfc5217SJeff Kirsher 	return rc;
4034adfc5217SJeff Kirsher 
4035adfc5217SJeff Kirsher error_exit2:
4036adfc5217SJeff Kirsher 	r->clear_pending(r);
4037adfc5217SJeff Kirsher 
4038adfc5217SJeff Kirsher error_exit1:
4039c7b7b483SYuval Mintz 	o->revert(bp, p, old_reg_size, cmd);
4040adfc5217SJeff Kirsher 
4041adfc5217SJeff Kirsher 	return rc;
4042adfc5217SJeff Kirsher }
4043adfc5217SJeff Kirsher 
bnx2x_mcast_clear_sched(struct bnx2x_mcast_obj * o)4044adfc5217SJeff Kirsher static void bnx2x_mcast_clear_sched(struct bnx2x_mcast_obj *o)
4045adfc5217SJeff Kirsher {
40464e857c58SPeter Zijlstra 	smp_mb__before_atomic();
4047adfc5217SJeff Kirsher 	clear_bit(o->sched_state, o->raw.pstate);
40484e857c58SPeter Zijlstra 	smp_mb__after_atomic();
4049adfc5217SJeff Kirsher }
4050adfc5217SJeff Kirsher 
bnx2x_mcast_set_sched(struct bnx2x_mcast_obj * o)4051adfc5217SJeff Kirsher static void bnx2x_mcast_set_sched(struct bnx2x_mcast_obj *o)
4052adfc5217SJeff Kirsher {
40534e857c58SPeter Zijlstra 	smp_mb__before_atomic();
4054adfc5217SJeff Kirsher 	set_bit(o->sched_state, o->raw.pstate);
40554e857c58SPeter Zijlstra 	smp_mb__after_atomic();
4056adfc5217SJeff Kirsher }
4057adfc5217SJeff Kirsher 
bnx2x_mcast_check_sched(struct bnx2x_mcast_obj * o)4058adfc5217SJeff Kirsher static bool bnx2x_mcast_check_sched(struct bnx2x_mcast_obj *o)
4059adfc5217SJeff Kirsher {
4060adfc5217SJeff Kirsher 	return !!test_bit(o->sched_state, o->raw.pstate);
4061adfc5217SJeff Kirsher }
4062adfc5217SJeff Kirsher 
bnx2x_mcast_check_pending(struct bnx2x_mcast_obj * o)4063adfc5217SJeff Kirsher static bool bnx2x_mcast_check_pending(struct bnx2x_mcast_obj *o)
4064adfc5217SJeff Kirsher {
4065adfc5217SJeff Kirsher 	return o->raw.check_pending(&o->raw) || o->check_sched(o);
4066adfc5217SJeff Kirsher }
4067adfc5217SJeff Kirsher 
bnx2x_init_mcast_obj(struct bnx2x * bp,struct bnx2x_mcast_obj * mcast_obj,u8 mcast_cl_id,u32 mcast_cid,u8 func_id,u8 engine_id,void * rdata,dma_addr_t rdata_mapping,int state,unsigned long * pstate,bnx2x_obj_type type)4068adfc5217SJeff Kirsher void bnx2x_init_mcast_obj(struct bnx2x *bp,
4069adfc5217SJeff Kirsher 			  struct bnx2x_mcast_obj *mcast_obj,
4070adfc5217SJeff Kirsher 			  u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
4071adfc5217SJeff Kirsher 			  u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
4072adfc5217SJeff Kirsher 			  int state, unsigned long *pstate, bnx2x_obj_type type)
4073adfc5217SJeff Kirsher {
4074adfc5217SJeff Kirsher 	memset(mcast_obj, 0, sizeof(*mcast_obj));
4075adfc5217SJeff Kirsher 
4076adfc5217SJeff Kirsher 	bnx2x_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id,
4077adfc5217SJeff Kirsher 			   rdata, rdata_mapping, state, pstate, type);
4078adfc5217SJeff Kirsher 
4079adfc5217SJeff Kirsher 	mcast_obj->engine_id = engine_id;
4080adfc5217SJeff Kirsher 
4081adfc5217SJeff Kirsher 	INIT_LIST_HEAD(&mcast_obj->pending_cmds_head);
4082adfc5217SJeff Kirsher 
4083adfc5217SJeff Kirsher 	mcast_obj->sched_state = BNX2X_FILTER_MCAST_SCHED;
4084adfc5217SJeff Kirsher 	mcast_obj->check_sched = bnx2x_mcast_check_sched;
4085adfc5217SJeff Kirsher 	mcast_obj->set_sched = bnx2x_mcast_set_sched;
4086adfc5217SJeff Kirsher 	mcast_obj->clear_sched = bnx2x_mcast_clear_sched;
4087adfc5217SJeff Kirsher 
4088adfc5217SJeff Kirsher 	if (CHIP_IS_E1(bp)) {
4089adfc5217SJeff Kirsher 		mcast_obj->config_mcast      = bnx2x_mcast_setup_e1;
4090adfc5217SJeff Kirsher 		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
4091adfc5217SJeff Kirsher 		mcast_obj->hdl_restore       =
4092adfc5217SJeff Kirsher 			bnx2x_mcast_handle_restore_cmd_e1;
4093adfc5217SJeff Kirsher 		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
4094adfc5217SJeff Kirsher 
4095adfc5217SJeff Kirsher 		if (CHIP_REV_IS_SLOW(bp))
4096adfc5217SJeff Kirsher 			mcast_obj->max_cmd_len = BNX2X_MAX_EMUL_MULTI;
4097adfc5217SJeff Kirsher 		else
4098adfc5217SJeff Kirsher 			mcast_obj->max_cmd_len = BNX2X_MAX_MULTICAST;
4099adfc5217SJeff Kirsher 
4100adfc5217SJeff Kirsher 		mcast_obj->wait_comp         = bnx2x_mcast_wait;
4101adfc5217SJeff Kirsher 		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e1;
4102adfc5217SJeff Kirsher 		mcast_obj->validate          = bnx2x_mcast_validate_e1;
4103adfc5217SJeff Kirsher 		mcast_obj->revert            = bnx2x_mcast_revert_e1;
4104adfc5217SJeff Kirsher 		mcast_obj->get_registry_size =
4105adfc5217SJeff Kirsher 			bnx2x_mcast_get_registry_size_exact;
4106adfc5217SJeff Kirsher 		mcast_obj->set_registry_size =
4107adfc5217SJeff Kirsher 			bnx2x_mcast_set_registry_size_exact;
4108adfc5217SJeff Kirsher 
4109adfc5217SJeff Kirsher 		/* 57710 is the only chip that uses the exact match for mcast
4110adfc5217SJeff Kirsher 		 * at the moment.
4111adfc5217SJeff Kirsher 		 */
4112adfc5217SJeff Kirsher 		INIT_LIST_HEAD(&mcast_obj->registry.exact_match.macs);
4113adfc5217SJeff Kirsher 
4114adfc5217SJeff Kirsher 	} else if (CHIP_IS_E1H(bp)) {
4115adfc5217SJeff Kirsher 		mcast_obj->config_mcast  = bnx2x_mcast_setup_e1h;
4116adfc5217SJeff Kirsher 		mcast_obj->enqueue_cmd   = NULL;
4117adfc5217SJeff Kirsher 		mcast_obj->hdl_restore   = NULL;
4118adfc5217SJeff Kirsher 		mcast_obj->check_pending = bnx2x_mcast_check_pending;
4119adfc5217SJeff Kirsher 
4120adfc5217SJeff Kirsher 		/* 57711 doesn't send a ramrod, so it has unlimited credit
4121adfc5217SJeff Kirsher 		 * for one command.
4122adfc5217SJeff Kirsher 		 */
4123adfc5217SJeff Kirsher 		mcast_obj->max_cmd_len       = -1;
4124adfc5217SJeff Kirsher 		mcast_obj->wait_comp         = bnx2x_mcast_wait;
4125adfc5217SJeff Kirsher 		mcast_obj->set_one_rule      = NULL;
4126adfc5217SJeff Kirsher 		mcast_obj->validate          = bnx2x_mcast_validate_e1h;
4127adfc5217SJeff Kirsher 		mcast_obj->revert            = bnx2x_mcast_revert_e1h;
4128adfc5217SJeff Kirsher 		mcast_obj->get_registry_size =
4129adfc5217SJeff Kirsher 			bnx2x_mcast_get_registry_size_aprox;
4130adfc5217SJeff Kirsher 		mcast_obj->set_registry_size =
4131adfc5217SJeff Kirsher 			bnx2x_mcast_set_registry_size_aprox;
4132adfc5217SJeff Kirsher 	} else {
4133adfc5217SJeff Kirsher 		mcast_obj->config_mcast      = bnx2x_mcast_setup_e2;
4134adfc5217SJeff Kirsher 		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
4135adfc5217SJeff Kirsher 		mcast_obj->hdl_restore       =
4136adfc5217SJeff Kirsher 			bnx2x_mcast_handle_restore_cmd_e2;
4137adfc5217SJeff Kirsher 		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
4138adfc5217SJeff Kirsher 		/* TODO: There should be a proper HSI define for this number!!!
4139adfc5217SJeff Kirsher 		 */
4140adfc5217SJeff Kirsher 		mcast_obj->max_cmd_len       = 16;
4141adfc5217SJeff Kirsher 		mcast_obj->wait_comp         = bnx2x_mcast_wait;
4142adfc5217SJeff Kirsher 		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e2;
4143adfc5217SJeff Kirsher 		mcast_obj->validate          = bnx2x_mcast_validate_e2;
4144adfc5217SJeff Kirsher 		mcast_obj->revert            = bnx2x_mcast_revert_e2;
4145adfc5217SJeff Kirsher 		mcast_obj->get_registry_size =
4146adfc5217SJeff Kirsher 			bnx2x_mcast_get_registry_size_aprox;
4147adfc5217SJeff Kirsher 		mcast_obj->set_registry_size =
4148adfc5217SJeff Kirsher 			bnx2x_mcast_set_registry_size_aprox;
4149adfc5217SJeff Kirsher 	}
4150adfc5217SJeff Kirsher }
4151adfc5217SJeff Kirsher 
4152adfc5217SJeff Kirsher /*************************** Credit handling **********************************/
4153adfc5217SJeff Kirsher 
4154adfc5217SJeff Kirsher /**
415576d85049SYang Shen  * __atomic_add_ifless - add if the result is less than a given value.
4156adfc5217SJeff Kirsher  *
4157adfc5217SJeff Kirsher  * @v:	pointer of type atomic_t
4158adfc5217SJeff Kirsher  * @a:	the amount to add to v...
4159adfc5217SJeff Kirsher  * @u:	...if (v + a) is less than u.
4160adfc5217SJeff Kirsher  *
4161adfc5217SJeff Kirsher  * returns true if (v + a) was less than u, and false otherwise.
4162adfc5217SJeff Kirsher  *
4163adfc5217SJeff Kirsher  */
__atomic_add_ifless(atomic_t * v,int a,int u)4164adfc5217SJeff Kirsher static inline bool __atomic_add_ifless(atomic_t *v, int a, int u)
4165adfc5217SJeff Kirsher {
4166adfc5217SJeff Kirsher 	int c, old;
4167adfc5217SJeff Kirsher 
4168adfc5217SJeff Kirsher 	c = atomic_read(v);
4169adfc5217SJeff Kirsher 	for (;;) {
4170adfc5217SJeff Kirsher 		if (unlikely(c + a >= u))
4171adfc5217SJeff Kirsher 			return false;
4172adfc5217SJeff Kirsher 
4173adfc5217SJeff Kirsher 		old = atomic_cmpxchg((v), c, c + a);
4174adfc5217SJeff Kirsher 		if (likely(old == c))
4175adfc5217SJeff Kirsher 			break;
4176adfc5217SJeff Kirsher 		c = old;
4177adfc5217SJeff Kirsher 	}
4178adfc5217SJeff Kirsher 
4179adfc5217SJeff Kirsher 	return true;
4180adfc5217SJeff Kirsher }
4181adfc5217SJeff Kirsher 
4182adfc5217SJeff Kirsher /**
418376d85049SYang Shen  * __atomic_dec_ifmoe - dec if the result is more or equal than a given value.
4184adfc5217SJeff Kirsher  *
4185adfc5217SJeff Kirsher  * @v:	pointer of type atomic_t
4186adfc5217SJeff Kirsher  * @a:	the amount to dec from v...
4187adfc5217SJeff Kirsher  * @u:	...if (v - a) is more or equal than u.
4188adfc5217SJeff Kirsher  *
4189adfc5217SJeff Kirsher  * returns true if (v - a) was more or equal than u, and false
4190adfc5217SJeff Kirsher  * otherwise.
4191adfc5217SJeff Kirsher  */
__atomic_dec_ifmoe(atomic_t * v,int a,int u)4192adfc5217SJeff Kirsher static inline bool __atomic_dec_ifmoe(atomic_t *v, int a, int u)
4193adfc5217SJeff Kirsher {
4194adfc5217SJeff Kirsher 	int c, old;
4195adfc5217SJeff Kirsher 
4196adfc5217SJeff Kirsher 	c = atomic_read(v);
4197adfc5217SJeff Kirsher 	for (;;) {
4198adfc5217SJeff Kirsher 		if (unlikely(c - a < u))
4199adfc5217SJeff Kirsher 			return false;
4200adfc5217SJeff Kirsher 
4201adfc5217SJeff Kirsher 		old = atomic_cmpxchg((v), c, c - a);
4202adfc5217SJeff Kirsher 		if (likely(old == c))
4203adfc5217SJeff Kirsher 			break;
4204adfc5217SJeff Kirsher 		c = old;
4205adfc5217SJeff Kirsher 	}
4206adfc5217SJeff Kirsher 
4207adfc5217SJeff Kirsher 	return true;
4208adfc5217SJeff Kirsher }
4209adfc5217SJeff Kirsher 
bnx2x_credit_pool_get(struct bnx2x_credit_pool_obj * o,int cnt)4210adfc5217SJeff Kirsher static bool bnx2x_credit_pool_get(struct bnx2x_credit_pool_obj *o, int cnt)
4211adfc5217SJeff Kirsher {
4212adfc5217SJeff Kirsher 	bool rc;
4213adfc5217SJeff Kirsher 
4214adfc5217SJeff Kirsher 	smp_mb();
4215adfc5217SJeff Kirsher 	rc = __atomic_dec_ifmoe(&o->credit, cnt, 0);
4216adfc5217SJeff Kirsher 	smp_mb();
4217adfc5217SJeff Kirsher 
4218adfc5217SJeff Kirsher 	return rc;
4219adfc5217SJeff Kirsher }
4220adfc5217SJeff Kirsher 
bnx2x_credit_pool_put(struct bnx2x_credit_pool_obj * o,int cnt)4221adfc5217SJeff Kirsher static bool bnx2x_credit_pool_put(struct bnx2x_credit_pool_obj *o, int cnt)
4222adfc5217SJeff Kirsher {
4223adfc5217SJeff Kirsher 	bool rc;
4224adfc5217SJeff Kirsher 
4225adfc5217SJeff Kirsher 	smp_mb();
4226adfc5217SJeff Kirsher 
4227adfc5217SJeff Kirsher 	/* Don't let to refill if credit + cnt > pool_sz */
4228adfc5217SJeff Kirsher 	rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1);
4229adfc5217SJeff Kirsher 
4230adfc5217SJeff Kirsher 	smp_mb();
4231adfc5217SJeff Kirsher 
4232adfc5217SJeff Kirsher 	return rc;
4233adfc5217SJeff Kirsher }
4234adfc5217SJeff Kirsher 
bnx2x_credit_pool_check(struct bnx2x_credit_pool_obj * o)4235adfc5217SJeff Kirsher static int bnx2x_credit_pool_check(struct bnx2x_credit_pool_obj *o)
4236adfc5217SJeff Kirsher {
4237adfc5217SJeff Kirsher 	int cur_credit;
4238adfc5217SJeff Kirsher 
4239adfc5217SJeff Kirsher 	smp_mb();
4240adfc5217SJeff Kirsher 	cur_credit = atomic_read(&o->credit);
4241adfc5217SJeff Kirsher 
4242adfc5217SJeff Kirsher 	return cur_credit;
4243adfc5217SJeff Kirsher }
4244adfc5217SJeff Kirsher 
bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj * o,int cnt)4245adfc5217SJeff Kirsher static bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o,
4246adfc5217SJeff Kirsher 					  int cnt)
4247adfc5217SJeff Kirsher {
4248adfc5217SJeff Kirsher 	return true;
4249adfc5217SJeff Kirsher }
4250adfc5217SJeff Kirsher 
bnx2x_credit_pool_get_entry(struct bnx2x_credit_pool_obj * o,int * offset)4251adfc5217SJeff Kirsher static bool bnx2x_credit_pool_get_entry(
4252adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *o,
4253adfc5217SJeff Kirsher 	int *offset)
4254adfc5217SJeff Kirsher {
4255adfc5217SJeff Kirsher 	int idx, vec, i;
4256adfc5217SJeff Kirsher 
4257adfc5217SJeff Kirsher 	*offset = -1;
4258adfc5217SJeff Kirsher 
4259adfc5217SJeff Kirsher 	/* Find "internal cam-offset" then add to base for this object... */
4260adfc5217SJeff Kirsher 	for (vec = 0; vec < BNX2X_POOL_VEC_SIZE; vec++) {
4261adfc5217SJeff Kirsher 
4262adfc5217SJeff Kirsher 		/* Skip the current vector if there are no free entries in it */
4263adfc5217SJeff Kirsher 		if (!o->pool_mirror[vec])
4264adfc5217SJeff Kirsher 			continue;
4265adfc5217SJeff Kirsher 
4266adfc5217SJeff Kirsher 		/* If we've got here we are going to find a free entry */
4267c54e9bd3SDmitry Kravkov 		for (idx = vec * BIT_VEC64_ELEM_SZ, i = 0;
4268adfc5217SJeff Kirsher 		      i < BIT_VEC64_ELEM_SZ; idx++, i++)
4269adfc5217SJeff Kirsher 
4270adfc5217SJeff Kirsher 			if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
4271adfc5217SJeff Kirsher 				/* Got one!! */
4272adfc5217SJeff Kirsher 				BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx);
4273adfc5217SJeff Kirsher 				*offset = o->base_pool_offset + idx;
4274adfc5217SJeff Kirsher 				return true;
4275adfc5217SJeff Kirsher 			}
4276adfc5217SJeff Kirsher 	}
4277adfc5217SJeff Kirsher 
4278adfc5217SJeff Kirsher 	return false;
4279adfc5217SJeff Kirsher }
4280adfc5217SJeff Kirsher 
bnx2x_credit_pool_put_entry(struct bnx2x_credit_pool_obj * o,int offset)4281adfc5217SJeff Kirsher static bool bnx2x_credit_pool_put_entry(
4282adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *o,
4283adfc5217SJeff Kirsher 	int offset)
4284adfc5217SJeff Kirsher {
4285adfc5217SJeff Kirsher 	if (offset < o->base_pool_offset)
4286adfc5217SJeff Kirsher 		return false;
4287adfc5217SJeff Kirsher 
4288adfc5217SJeff Kirsher 	offset -= o->base_pool_offset;
4289adfc5217SJeff Kirsher 
4290adfc5217SJeff Kirsher 	if (offset >= o->pool_sz)
4291adfc5217SJeff Kirsher 		return false;
4292adfc5217SJeff Kirsher 
4293adfc5217SJeff Kirsher 	/* Return the entry to the pool */
4294adfc5217SJeff Kirsher 	BIT_VEC64_SET_BIT(o->pool_mirror, offset);
4295adfc5217SJeff Kirsher 
4296adfc5217SJeff Kirsher 	return true;
4297adfc5217SJeff Kirsher }
4298adfc5217SJeff Kirsher 
bnx2x_credit_pool_put_entry_always_true(struct bnx2x_credit_pool_obj * o,int offset)4299adfc5217SJeff Kirsher static bool bnx2x_credit_pool_put_entry_always_true(
4300adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *o,
4301adfc5217SJeff Kirsher 	int offset)
4302adfc5217SJeff Kirsher {
4303adfc5217SJeff Kirsher 	return true;
4304adfc5217SJeff Kirsher }
4305adfc5217SJeff Kirsher 
bnx2x_credit_pool_get_entry_always_true(struct bnx2x_credit_pool_obj * o,int * offset)4306adfc5217SJeff Kirsher static bool bnx2x_credit_pool_get_entry_always_true(
4307adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *o,
4308adfc5217SJeff Kirsher 	int *offset)
4309adfc5217SJeff Kirsher {
4310adfc5217SJeff Kirsher 	*offset = -1;
4311adfc5217SJeff Kirsher 	return true;
4312adfc5217SJeff Kirsher }
4313adfc5217SJeff Kirsher /**
4314adfc5217SJeff Kirsher  * bnx2x_init_credit_pool - initialize credit pool internals.
4315adfc5217SJeff Kirsher  *
4316d0ea5cbdSJesse Brandeburg  * @p:		credit pool
4317adfc5217SJeff Kirsher  * @base:	Base entry in the CAM to use.
4318adfc5217SJeff Kirsher  * @credit:	pool size.
4319adfc5217SJeff Kirsher  *
4320adfc5217SJeff Kirsher  * If base is negative no CAM entries handling will be performed.
4321adfc5217SJeff Kirsher  * If credit is negative pool operations will always succeed (unlimited pool).
4322adfc5217SJeff Kirsher  *
4323adfc5217SJeff Kirsher  */
bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj * p,int base,int credit)432405cc5a39SYuval Mintz void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
4325adfc5217SJeff Kirsher 			    int base, int credit)
4326adfc5217SJeff Kirsher {
4327adfc5217SJeff Kirsher 	/* Zero the object first */
4328adfc5217SJeff Kirsher 	memset(p, 0, sizeof(*p));
4329adfc5217SJeff Kirsher 
4330adfc5217SJeff Kirsher 	/* Set the table to all 1s */
4331adfc5217SJeff Kirsher 	memset(&p->pool_mirror, 0xff, sizeof(p->pool_mirror));
4332adfc5217SJeff Kirsher 
4333adfc5217SJeff Kirsher 	/* Init a pool as full */
4334adfc5217SJeff Kirsher 	atomic_set(&p->credit, credit);
4335adfc5217SJeff Kirsher 
4336adfc5217SJeff Kirsher 	/* The total poll size */
4337adfc5217SJeff Kirsher 	p->pool_sz = credit;
4338adfc5217SJeff Kirsher 
4339adfc5217SJeff Kirsher 	p->base_pool_offset = base;
4340adfc5217SJeff Kirsher 
4341adfc5217SJeff Kirsher 	/* Commit the change */
4342adfc5217SJeff Kirsher 	smp_mb();
4343adfc5217SJeff Kirsher 
4344adfc5217SJeff Kirsher 	p->check = bnx2x_credit_pool_check;
4345adfc5217SJeff Kirsher 
4346adfc5217SJeff Kirsher 	/* if pool credit is negative - disable the checks */
4347adfc5217SJeff Kirsher 	if (credit >= 0) {
4348adfc5217SJeff Kirsher 		p->put      = bnx2x_credit_pool_put;
4349adfc5217SJeff Kirsher 		p->get      = bnx2x_credit_pool_get;
4350adfc5217SJeff Kirsher 		p->put_entry = bnx2x_credit_pool_put_entry;
4351adfc5217SJeff Kirsher 		p->get_entry = bnx2x_credit_pool_get_entry;
4352adfc5217SJeff Kirsher 	} else {
4353adfc5217SJeff Kirsher 		p->put      = bnx2x_credit_pool_always_true;
4354adfc5217SJeff Kirsher 		p->get      = bnx2x_credit_pool_always_true;
4355adfc5217SJeff Kirsher 		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
4356adfc5217SJeff Kirsher 		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
4357adfc5217SJeff Kirsher 	}
4358adfc5217SJeff Kirsher 
4359adfc5217SJeff Kirsher 	/* If base is negative - disable entries handling */
4360adfc5217SJeff Kirsher 	if (base < 0) {
4361adfc5217SJeff Kirsher 		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
4362adfc5217SJeff Kirsher 		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
4363adfc5217SJeff Kirsher 	}
4364adfc5217SJeff Kirsher }
4365adfc5217SJeff Kirsher 
bnx2x_init_mac_credit_pool(struct bnx2x * bp,struct bnx2x_credit_pool_obj * p,u8 func_id,u8 func_num)4366adfc5217SJeff Kirsher void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
4367adfc5217SJeff Kirsher 				struct bnx2x_credit_pool_obj *p, u8 func_id,
4368adfc5217SJeff Kirsher 				u8 func_num)
4369adfc5217SJeff Kirsher {
4370adfc5217SJeff Kirsher /* TODO: this will be defined in consts as well... */
4371adfc5217SJeff Kirsher #define BNX2X_CAM_SIZE_EMUL 5
4372adfc5217SJeff Kirsher 
4373adfc5217SJeff Kirsher 	int cam_sz;
4374adfc5217SJeff Kirsher 
4375adfc5217SJeff Kirsher 	if (CHIP_IS_E1(bp)) {
4376adfc5217SJeff Kirsher 		/* In E1, Multicast is saved in cam... */
4377adfc5217SJeff Kirsher 		if (!CHIP_REV_IS_SLOW(bp))
4378adfc5217SJeff Kirsher 			cam_sz = (MAX_MAC_CREDIT_E1 / 2) - BNX2X_MAX_MULTICAST;
4379adfc5217SJeff Kirsher 		else
4380adfc5217SJeff Kirsher 			cam_sz = BNX2X_CAM_SIZE_EMUL - BNX2X_MAX_EMUL_MULTI;
4381adfc5217SJeff Kirsher 
4382adfc5217SJeff Kirsher 		bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
4383adfc5217SJeff Kirsher 
4384adfc5217SJeff Kirsher 	} else if (CHIP_IS_E1H(bp)) {
4385adfc5217SJeff Kirsher 		/* CAM credit is equaly divided between all active functions
4386adfc5217SJeff Kirsher 		 * on the PORT!.
4387adfc5217SJeff Kirsher 		 */
4388adfc5217SJeff Kirsher 		if ((func_num > 0)) {
4389adfc5217SJeff Kirsher 			if (!CHIP_REV_IS_SLOW(bp))
4390adfc5217SJeff Kirsher 				cam_sz = (MAX_MAC_CREDIT_E1H / (2*func_num));
4391adfc5217SJeff Kirsher 			else
4392adfc5217SJeff Kirsher 				cam_sz = BNX2X_CAM_SIZE_EMUL;
4393adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
4394adfc5217SJeff Kirsher 		} else {
4395adfc5217SJeff Kirsher 			/* this should never happen! Block MAC operations. */
4396adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, 0, 0);
4397adfc5217SJeff Kirsher 		}
4398adfc5217SJeff Kirsher 
4399adfc5217SJeff Kirsher 	} else {
4400adfc5217SJeff Kirsher 
440116a5fd92SYuval Mintz 		/* CAM credit is equaly divided between all active functions
4402adfc5217SJeff Kirsher 		 * on the PATH.
4403adfc5217SJeff Kirsher 		 */
440405cc5a39SYuval Mintz 		if (func_num > 0) {
4405adfc5217SJeff Kirsher 			if (!CHIP_REV_IS_SLOW(bp))
440605cc5a39SYuval Mintz 				cam_sz = PF_MAC_CREDIT_E2(bp, func_num);
4407adfc5217SJeff Kirsher 			else
4408adfc5217SJeff Kirsher 				cam_sz = BNX2X_CAM_SIZE_EMUL;
4409adfc5217SJeff Kirsher 
441016a5fd92SYuval Mintz 			/* No need for CAM entries handling for 57712 and
4411adfc5217SJeff Kirsher 			 * newer.
4412adfc5217SJeff Kirsher 			 */
4413adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, -1, cam_sz);
4414adfc5217SJeff Kirsher 		} else {
4415adfc5217SJeff Kirsher 			/* this should never happen! Block MAC operations. */
4416adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, 0, 0);
4417adfc5217SJeff Kirsher 		}
4418adfc5217SJeff Kirsher 	}
4419adfc5217SJeff Kirsher }
4420adfc5217SJeff Kirsher 
bnx2x_init_vlan_credit_pool(struct bnx2x * bp,struct bnx2x_credit_pool_obj * p,u8 func_id,u8 func_num)4421adfc5217SJeff Kirsher void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
4422adfc5217SJeff Kirsher 				 struct bnx2x_credit_pool_obj *p,
4423adfc5217SJeff Kirsher 				 u8 func_id,
4424adfc5217SJeff Kirsher 				 u8 func_num)
4425adfc5217SJeff Kirsher {
4426adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp)) {
442716a5fd92SYuval Mintz 		/* There is no VLAN credit in HW on 57710 and 57711 only
4428adfc5217SJeff Kirsher 		 * MAC / MAC-VLAN can be set
4429adfc5217SJeff Kirsher 		 */
4430adfc5217SJeff Kirsher 		bnx2x_init_credit_pool(p, 0, -1);
4431adfc5217SJeff Kirsher 	} else {
443216a5fd92SYuval Mintz 		/* CAM credit is equally divided between all active functions
4433adfc5217SJeff Kirsher 		 * on the PATH.
4434adfc5217SJeff Kirsher 		 */
4435adfc5217SJeff Kirsher 		if (func_num > 0) {
443605cc5a39SYuval Mintz 			int credit = PF_VLAN_CREDIT_E2(bp, func_num);
443705cc5a39SYuval Mintz 
443805cc5a39SYuval Mintz 			bnx2x_init_credit_pool(p, -1/*unused for E2*/, credit);
4439adfc5217SJeff Kirsher 		} else
4440adfc5217SJeff Kirsher 			/* this should never happen! Block VLAN operations. */
4441adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, 0, 0);
4442adfc5217SJeff Kirsher 	}
4443adfc5217SJeff Kirsher }
4444adfc5217SJeff Kirsher 
4445adfc5217SJeff Kirsher /****************** RSS Configuration ******************/
4446adfc5217SJeff Kirsher /**
4447adfc5217SJeff Kirsher  * bnx2x_debug_print_ind_table - prints the indirection table configuration.
4448adfc5217SJeff Kirsher  *
444916a5fd92SYuval Mintz  * @bp:		driver handle
4450adfc5217SJeff Kirsher  * @p:		pointer to rss configuration
4451adfc5217SJeff Kirsher  *
4452adfc5217SJeff Kirsher  * Prints it when NETIF_MSG_IFUP debug level is configured.
4453adfc5217SJeff Kirsher  */
bnx2x_debug_print_ind_table(struct bnx2x * bp,struct bnx2x_config_rss_params * p)4454adfc5217SJeff Kirsher static inline void bnx2x_debug_print_ind_table(struct bnx2x *bp,
4455adfc5217SJeff Kirsher 					struct bnx2x_config_rss_params *p)
4456adfc5217SJeff Kirsher {
4457adfc5217SJeff Kirsher 	int i;
4458adfc5217SJeff Kirsher 
4459adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Setting indirection table to:\n");
4460adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "0x0000: ");
4461adfc5217SJeff Kirsher 	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
4462adfc5217SJeff Kirsher 		DP_CONT(BNX2X_MSG_SP, "0x%02x ", p->ind_table[i]);
4463adfc5217SJeff Kirsher 
4464adfc5217SJeff Kirsher 		/* Print 4 bytes in a line */
4465adfc5217SJeff Kirsher 		if ((i + 1 < T_ETH_INDIRECTION_TABLE_SIZE) &&
4466adfc5217SJeff Kirsher 		    (((i + 1) & 0x3) == 0)) {
4467adfc5217SJeff Kirsher 			DP_CONT(BNX2X_MSG_SP, "\n");
4468adfc5217SJeff Kirsher 			DP(BNX2X_MSG_SP, "0x%04x: ", i + 1);
4469adfc5217SJeff Kirsher 		}
4470adfc5217SJeff Kirsher 	}
4471adfc5217SJeff Kirsher 
4472adfc5217SJeff Kirsher 	DP_CONT(BNX2X_MSG_SP, "\n");
4473adfc5217SJeff Kirsher }
4474adfc5217SJeff Kirsher 
4475adfc5217SJeff Kirsher /**
4476adfc5217SJeff Kirsher  * bnx2x_setup_rss - configure RSS
4477adfc5217SJeff Kirsher  *
4478adfc5217SJeff Kirsher  * @bp:		device handle
4479adfc5217SJeff Kirsher  * @p:		rss configuration
4480adfc5217SJeff Kirsher  *
4481adfc5217SJeff Kirsher  * sends on UPDATE ramrod for that matter.
4482adfc5217SJeff Kirsher  */
bnx2x_setup_rss(struct bnx2x * bp,struct bnx2x_config_rss_params * p)4483adfc5217SJeff Kirsher static int bnx2x_setup_rss(struct bnx2x *bp,
4484adfc5217SJeff Kirsher 			   struct bnx2x_config_rss_params *p)
4485adfc5217SJeff Kirsher {
4486adfc5217SJeff Kirsher 	struct bnx2x_rss_config_obj *o = p->rss_obj;
4487adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
4488adfc5217SJeff Kirsher 	struct eth_rss_update_ramrod_data *data =
4489adfc5217SJeff Kirsher 		(struct eth_rss_update_ramrod_data *)(r->rdata);
4490e42780b6SDmitry Kravkov 	u16 caps = 0;
4491adfc5217SJeff Kirsher 	u8 rss_mode = 0;
4492adfc5217SJeff Kirsher 	int rc;
4493adfc5217SJeff Kirsher 
4494adfc5217SJeff Kirsher 	memset(data, 0, sizeof(*data));
4495adfc5217SJeff Kirsher 
4496adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Configuring RSS\n");
4497adfc5217SJeff Kirsher 
4498adfc5217SJeff Kirsher 	/* Set an echo field */
449986564c3fSYuval Mintz 	data->echo = cpu_to_le32((r->cid & BNX2X_SWCID_MASK) |
450086564c3fSYuval Mintz 				 (r->state << BNX2X_SWCID_SHIFT));
4501adfc5217SJeff Kirsher 
4502adfc5217SJeff Kirsher 	/* RSS mode */
4503adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_MODE_DISABLED, &p->rss_flags))
4504adfc5217SJeff Kirsher 		rss_mode = ETH_RSS_MODE_DISABLED;
4505adfc5217SJeff Kirsher 	else if (test_bit(BNX2X_RSS_MODE_REGULAR, &p->rss_flags))
4506adfc5217SJeff Kirsher 		rss_mode = ETH_RSS_MODE_REGULAR;
4507adfc5217SJeff Kirsher 
4508adfc5217SJeff Kirsher 	data->rss_mode = rss_mode;
4509adfc5217SJeff Kirsher 
4510adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "rss_mode=%d\n", rss_mode);
4511adfc5217SJeff Kirsher 
4512adfc5217SJeff Kirsher 	/* RSS capabilities */
4513adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_IPV4, &p->rss_flags))
4514e42780b6SDmitry Kravkov 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY;
4515adfc5217SJeff Kirsher 
4516adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_IPV4_TCP, &p->rss_flags))
4517e42780b6SDmitry Kravkov 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
4518adfc5217SJeff Kirsher 
45195d317c6aSMerav Sicron 	if (test_bit(BNX2X_RSS_IPV4_UDP, &p->rss_flags))
4520e42780b6SDmitry Kravkov 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY;
45215d317c6aSMerav Sicron 
4522adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags))
4523e42780b6SDmitry Kravkov 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
4524adfc5217SJeff Kirsher 
4525adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_IPV6_TCP, &p->rss_flags))
4526e42780b6SDmitry Kravkov 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
4527adfc5217SJeff Kirsher 
45285d317c6aSMerav Sicron 	if (test_bit(BNX2X_RSS_IPV6_UDP, &p->rss_flags))
4529e42780b6SDmitry Kravkov 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY;
4530e42780b6SDmitry Kravkov 
453128311f8eSYuval Mintz 	if (test_bit(BNX2X_RSS_IPV4_VXLAN, &p->rss_flags))
453228311f8eSYuval Mintz 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_VXLAN_CAPABILITY;
453328311f8eSYuval Mintz 
453428311f8eSYuval Mintz 	if (test_bit(BNX2X_RSS_IPV6_VXLAN, &p->rss_flags))
453528311f8eSYuval Mintz 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_VXLAN_CAPABILITY;
453628311f8eSYuval Mintz 
453728311f8eSYuval Mintz 	if (test_bit(BNX2X_RSS_TUNN_INNER_HDRS, &p->rss_flags))
453828311f8eSYuval Mintz 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_TUNN_INNER_HDRS_CAPABILITY;
4539e42780b6SDmitry Kravkov 
454056daf66dSYuval Mintz 	/* RSS keys */
454156daf66dSYuval Mintz 	if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
4542d682d2bdSEric Dumazet 		u8 *dst = (u8 *)(data->rss_key) + sizeof(data->rss_key);
4543d682d2bdSEric Dumazet 		const u8 *src = (const u8 *)p->rss_key;
4544d682d2bdSEric Dumazet 		int i;
4545d682d2bdSEric Dumazet 
4546d682d2bdSEric Dumazet 		/* Apparently, bnx2x reads this array in reverse order
4547d682d2bdSEric Dumazet 		 * We need to byte swap rss_key to comply with Toeplitz specs.
4548d682d2bdSEric Dumazet 		 */
4549d682d2bdSEric Dumazet 		for (i = 0; i < sizeof(data->rss_key); i++)
4550d682d2bdSEric Dumazet 			*--dst = *src++;
4551d682d2bdSEric Dumazet 
455256daf66dSYuval Mintz 		caps |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
455356daf66dSYuval Mintz 	}
455456daf66dSYuval Mintz 
4555e42780b6SDmitry Kravkov 	data->capabilities = cpu_to_le16(caps);
45565d317c6aSMerav Sicron 
4557adfc5217SJeff Kirsher 	/* Hashing mask */
4558adfc5217SJeff Kirsher 	data->rss_result_mask = p->rss_result_mask;
4559adfc5217SJeff Kirsher 
4560adfc5217SJeff Kirsher 	/* RSS engine ID */
4561adfc5217SJeff Kirsher 	data->rss_engine_id = o->engine_id;
4562adfc5217SJeff Kirsher 
4563adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "rss_engine_id=%d\n", data->rss_engine_id);
4564adfc5217SJeff Kirsher 
4565adfc5217SJeff Kirsher 	/* Indirection table */
4566adfc5217SJeff Kirsher 	memcpy(data->indirection_table, p->ind_table,
4567adfc5217SJeff Kirsher 		  T_ETH_INDIRECTION_TABLE_SIZE);
4568adfc5217SJeff Kirsher 
4569adfc5217SJeff Kirsher 	/* Remember the last configuration */
4570adfc5217SJeff Kirsher 	memcpy(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
4571adfc5217SJeff Kirsher 
4572adfc5217SJeff Kirsher 	/* Print the indirection table */
4573adfc5217SJeff Kirsher 	if (netif_msg_ifup(bp))
4574adfc5217SJeff Kirsher 		bnx2x_debug_print_ind_table(bp, p);
4575adfc5217SJeff Kirsher 
457614a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
457714a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
4578adfc5217SJeff Kirsher 	 * and updating of the SPQ producer which involves a memory
457914a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
458014a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
4581adfc5217SJeff Kirsher 	 */
4582adfc5217SJeff Kirsher 
4583adfc5217SJeff Kirsher 	/* Send a ramrod */
4584adfc5217SJeff Kirsher 	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid,
4585adfc5217SJeff Kirsher 			   U64_HI(r->rdata_mapping),
4586adfc5217SJeff Kirsher 			   U64_LO(r->rdata_mapping),
4587adfc5217SJeff Kirsher 			   ETH_CONNECTION_TYPE);
4588adfc5217SJeff Kirsher 
4589adfc5217SJeff Kirsher 	if (rc < 0)
4590adfc5217SJeff Kirsher 		return rc;
4591adfc5217SJeff Kirsher 
4592adfc5217SJeff Kirsher 	return 1;
4593adfc5217SJeff Kirsher }
4594adfc5217SJeff Kirsher 
bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj * rss_obj,u8 * ind_table)4595adfc5217SJeff Kirsher void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
4596adfc5217SJeff Kirsher 			     u8 *ind_table)
4597adfc5217SJeff Kirsher {
4598adfc5217SJeff Kirsher 	memcpy(ind_table, rss_obj->ind_table, sizeof(rss_obj->ind_table));
4599adfc5217SJeff Kirsher }
4600adfc5217SJeff Kirsher 
bnx2x_config_rss(struct bnx2x * bp,struct bnx2x_config_rss_params * p)4601adfc5217SJeff Kirsher int bnx2x_config_rss(struct bnx2x *bp,
4602adfc5217SJeff Kirsher 		     struct bnx2x_config_rss_params *p)
4603adfc5217SJeff Kirsher {
4604adfc5217SJeff Kirsher 	int rc;
4605adfc5217SJeff Kirsher 	struct bnx2x_rss_config_obj *o = p->rss_obj;
4606adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
4607adfc5217SJeff Kirsher 
4608adfc5217SJeff Kirsher 	/* Do nothing if only driver cleanup was requested */
46095b622918SMichal Kalderon 	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
46105b622918SMichal Kalderon 		DP(BNX2X_MSG_SP, "Not configuring RSS ramrod_flags=%lx\n",
46115b622918SMichal Kalderon 		   p->ramrod_flags);
4612adfc5217SJeff Kirsher 		return 0;
46135b622918SMichal Kalderon 	}
4614adfc5217SJeff Kirsher 
4615adfc5217SJeff Kirsher 	r->set_pending(r);
4616adfc5217SJeff Kirsher 
4617adfc5217SJeff Kirsher 	rc = o->config_rss(bp, p);
4618adfc5217SJeff Kirsher 	if (rc < 0) {
4619adfc5217SJeff Kirsher 		r->clear_pending(r);
4620adfc5217SJeff Kirsher 		return rc;
4621adfc5217SJeff Kirsher 	}
4622adfc5217SJeff Kirsher 
4623adfc5217SJeff Kirsher 	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
4624adfc5217SJeff Kirsher 		rc = r->wait_comp(bp, r);
4625adfc5217SJeff Kirsher 
4626adfc5217SJeff Kirsher 	return rc;
4627adfc5217SJeff Kirsher }
4628adfc5217SJeff Kirsher 
bnx2x_init_rss_config_obj(struct bnx2x * bp,struct bnx2x_rss_config_obj * rss_obj,u8 cl_id,u32 cid,u8 func_id,u8 engine_id,void * rdata,dma_addr_t rdata_mapping,int state,unsigned long * pstate,bnx2x_obj_type type)4629adfc5217SJeff Kirsher void bnx2x_init_rss_config_obj(struct bnx2x *bp,
4630adfc5217SJeff Kirsher 			       struct bnx2x_rss_config_obj *rss_obj,
4631adfc5217SJeff Kirsher 			       u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
4632adfc5217SJeff Kirsher 			       void *rdata, dma_addr_t rdata_mapping,
4633adfc5217SJeff Kirsher 			       int state, unsigned long *pstate,
4634adfc5217SJeff Kirsher 			       bnx2x_obj_type type)
4635adfc5217SJeff Kirsher {
4636adfc5217SJeff Kirsher 	bnx2x_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata,
4637adfc5217SJeff Kirsher 			   rdata_mapping, state, pstate, type);
4638adfc5217SJeff Kirsher 
4639adfc5217SJeff Kirsher 	rss_obj->engine_id  = engine_id;
4640adfc5217SJeff Kirsher 	rss_obj->config_rss = bnx2x_setup_rss;
4641adfc5217SJeff Kirsher }
4642adfc5217SJeff Kirsher 
4643adfc5217SJeff Kirsher /********************** Queue state object ***********************************/
4644adfc5217SJeff Kirsher 
4645adfc5217SJeff Kirsher /**
4646adfc5217SJeff Kirsher  * bnx2x_queue_state_change - perform Queue state change transition
4647adfc5217SJeff Kirsher  *
4648adfc5217SJeff Kirsher  * @bp:		device handle
4649adfc5217SJeff Kirsher  * @params:	parameters to perform the transition
4650adfc5217SJeff Kirsher  *
4651adfc5217SJeff Kirsher  * returns 0 in case of successfully completed transition, negative error
4652adfc5217SJeff Kirsher  * code in case of failure, positive (EBUSY) value if there is a completion
4653adfc5217SJeff Kirsher  * to that is still pending (possible only if RAMROD_COMP_WAIT is
4654adfc5217SJeff Kirsher  * not set in params->ramrod_flags for asynchronous commands).
4655adfc5217SJeff Kirsher  *
4656adfc5217SJeff Kirsher  */
bnx2x_queue_state_change(struct bnx2x * bp,struct bnx2x_queue_state_params * params)4657adfc5217SJeff Kirsher int bnx2x_queue_state_change(struct bnx2x *bp,
4658adfc5217SJeff Kirsher 			     struct bnx2x_queue_state_params *params)
4659adfc5217SJeff Kirsher {
4660adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4661adfc5217SJeff Kirsher 	int rc, pending_bit;
4662adfc5217SJeff Kirsher 	unsigned long *pending = &o->pending;
4663adfc5217SJeff Kirsher 
4664adfc5217SJeff Kirsher 	/* Check that the requested transition is legal */
466504c46736SYuval Mintz 	rc = o->check_transition(bp, o, params);
466604c46736SYuval Mintz 	if (rc) {
466704c46736SYuval Mintz 		BNX2X_ERR("check transition returned an error. rc %d\n", rc);
4668adfc5217SJeff Kirsher 		return -EINVAL;
466904c46736SYuval Mintz 	}
4670adfc5217SJeff Kirsher 
4671adfc5217SJeff Kirsher 	/* Set "pending" bit */
467204c46736SYuval Mintz 	DP(BNX2X_MSG_SP, "pending bit was=%lx\n", o->pending);
4673adfc5217SJeff Kirsher 	pending_bit = o->set_pending(o, params);
467404c46736SYuval Mintz 	DP(BNX2X_MSG_SP, "pending bit now=%lx\n", o->pending);
4675adfc5217SJeff Kirsher 
4676adfc5217SJeff Kirsher 	/* Don't send a command if only driver cleanup was requested */
4677adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags))
4678adfc5217SJeff Kirsher 		o->complete_cmd(bp, o, pending_bit);
4679adfc5217SJeff Kirsher 	else {
4680adfc5217SJeff Kirsher 		/* Send a ramrod */
4681adfc5217SJeff Kirsher 		rc = o->send_cmd(bp, params);
4682adfc5217SJeff Kirsher 		if (rc) {
4683adfc5217SJeff Kirsher 			o->next_state = BNX2X_Q_STATE_MAX;
4684adfc5217SJeff Kirsher 			clear_bit(pending_bit, pending);
46854e857c58SPeter Zijlstra 			smp_mb__after_atomic();
4686adfc5217SJeff Kirsher 			return rc;
4687adfc5217SJeff Kirsher 		}
4688adfc5217SJeff Kirsher 
4689adfc5217SJeff Kirsher 		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
4690adfc5217SJeff Kirsher 			rc = o->wait_comp(bp, o, pending_bit);
4691adfc5217SJeff Kirsher 			if (rc)
4692adfc5217SJeff Kirsher 				return rc;
4693adfc5217SJeff Kirsher 
4694adfc5217SJeff Kirsher 			return 0;
4695adfc5217SJeff Kirsher 		}
4696adfc5217SJeff Kirsher 	}
4697adfc5217SJeff Kirsher 
4698adfc5217SJeff Kirsher 	return !!test_bit(pending_bit, pending);
4699adfc5217SJeff Kirsher }
4700adfc5217SJeff Kirsher 
bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj * obj,struct bnx2x_queue_state_params * params)4701adfc5217SJeff Kirsher static int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj,
4702adfc5217SJeff Kirsher 				   struct bnx2x_queue_state_params *params)
4703adfc5217SJeff Kirsher {
4704adfc5217SJeff Kirsher 	enum bnx2x_queue_cmd cmd = params->cmd, bit;
4705adfc5217SJeff Kirsher 
4706adfc5217SJeff Kirsher 	/* ACTIVATE and DEACTIVATE commands are implemented on top of
4707adfc5217SJeff Kirsher 	 * UPDATE command.
4708adfc5217SJeff Kirsher 	 */
4709adfc5217SJeff Kirsher 	if ((cmd == BNX2X_Q_CMD_ACTIVATE) ||
4710adfc5217SJeff Kirsher 	    (cmd == BNX2X_Q_CMD_DEACTIVATE))
4711adfc5217SJeff Kirsher 		bit = BNX2X_Q_CMD_UPDATE;
4712adfc5217SJeff Kirsher 	else
4713adfc5217SJeff Kirsher 		bit = cmd;
4714adfc5217SJeff Kirsher 
4715adfc5217SJeff Kirsher 	set_bit(bit, &obj->pending);
4716adfc5217SJeff Kirsher 	return bit;
4717adfc5217SJeff Kirsher }
4718adfc5217SJeff Kirsher 
bnx2x_queue_wait_comp(struct bnx2x * bp,struct bnx2x_queue_sp_obj * o,enum bnx2x_queue_cmd cmd)4719adfc5217SJeff Kirsher static int bnx2x_queue_wait_comp(struct bnx2x *bp,
4720adfc5217SJeff Kirsher 				 struct bnx2x_queue_sp_obj *o,
4721adfc5217SJeff Kirsher 				 enum bnx2x_queue_cmd cmd)
4722adfc5217SJeff Kirsher {
4723adfc5217SJeff Kirsher 	return bnx2x_state_wait(bp, cmd, &o->pending);
4724adfc5217SJeff Kirsher }
4725adfc5217SJeff Kirsher 
4726adfc5217SJeff Kirsher /**
4727adfc5217SJeff Kirsher  * bnx2x_queue_comp_cmd - complete the state change command.
4728adfc5217SJeff Kirsher  *
4729adfc5217SJeff Kirsher  * @bp:		device handle
4730d0ea5cbdSJesse Brandeburg  * @o:		queue info
4731d0ea5cbdSJesse Brandeburg  * @cmd:	command to exec
4732adfc5217SJeff Kirsher  *
4733adfc5217SJeff Kirsher  * Checks that the arrived completion is expected.
4734adfc5217SJeff Kirsher  */
bnx2x_queue_comp_cmd(struct bnx2x * bp,struct bnx2x_queue_sp_obj * o,enum bnx2x_queue_cmd cmd)4735adfc5217SJeff Kirsher static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
4736adfc5217SJeff Kirsher 				struct bnx2x_queue_sp_obj *o,
4737adfc5217SJeff Kirsher 				enum bnx2x_queue_cmd cmd)
4738adfc5217SJeff Kirsher {
4739adfc5217SJeff Kirsher 	unsigned long cur_pending = o->pending;
4740adfc5217SJeff Kirsher 
4741adfc5217SJeff Kirsher 	if (!test_and_clear_bit(cmd, &cur_pending)) {
474251c1a580SMerav Sicron 		BNX2X_ERR("Bad MC reply %d for queue %d in state %d pending 0x%lx, next_state %d\n",
474351c1a580SMerav Sicron 			  cmd, o->cids[BNX2X_PRIMARY_CID_INDEX],
4744adfc5217SJeff Kirsher 			  o->state, cur_pending, o->next_state);
4745adfc5217SJeff Kirsher 		return -EINVAL;
4746adfc5217SJeff Kirsher 	}
4747adfc5217SJeff Kirsher 
4748adfc5217SJeff Kirsher 	if (o->next_tx_only >= o->max_cos)
474916a5fd92SYuval Mintz 		/* >= because tx only must always be smaller than cos since the
475002582e9bSMasanari Iida 		 * primary connection supports COS 0
4751adfc5217SJeff Kirsher 		 */
4752adfc5217SJeff Kirsher 		BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
4753adfc5217SJeff Kirsher 			   o->next_tx_only, o->max_cos);
4754adfc5217SJeff Kirsher 
475551c1a580SMerav Sicron 	DP(BNX2X_MSG_SP,
475651c1a580SMerav Sicron 	   "Completing command %d for queue %d, setting state to %d\n",
475751c1a580SMerav Sicron 	   cmd, o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state);
4758adfc5217SJeff Kirsher 
4759adfc5217SJeff Kirsher 	if (o->next_tx_only)  /* print num tx-only if any exist */
476094f05b0fSJoe Perches 		DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d\n",
4761adfc5217SJeff Kirsher 		   o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only);
4762adfc5217SJeff Kirsher 
4763adfc5217SJeff Kirsher 	o->state = o->next_state;
4764adfc5217SJeff Kirsher 	o->num_tx_only = o->next_tx_only;
4765adfc5217SJeff Kirsher 	o->next_state = BNX2X_Q_STATE_MAX;
4766adfc5217SJeff Kirsher 
4767adfc5217SJeff Kirsher 	/* It's important that o->state and o->next_state are
4768adfc5217SJeff Kirsher 	 * updated before o->pending.
4769adfc5217SJeff Kirsher 	 */
4770adfc5217SJeff Kirsher 	wmb();
4771adfc5217SJeff Kirsher 
4772adfc5217SJeff Kirsher 	clear_bit(cmd, &o->pending);
47734e857c58SPeter Zijlstra 	smp_mb__after_atomic();
4774adfc5217SJeff Kirsher 
4775adfc5217SJeff Kirsher 	return 0;
4776adfc5217SJeff Kirsher }
4777adfc5217SJeff Kirsher 
bnx2x_q_fill_setup_data_e2(struct bnx2x * bp,struct bnx2x_queue_state_params * cmd_params,struct client_init_ramrod_data * data)4778adfc5217SJeff Kirsher static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp,
4779adfc5217SJeff Kirsher 				struct bnx2x_queue_state_params *cmd_params,
4780adfc5217SJeff Kirsher 				struct client_init_ramrod_data *data)
4781adfc5217SJeff Kirsher {
4782adfc5217SJeff Kirsher 	struct bnx2x_queue_setup_params *params = &cmd_params->params.setup;
4783adfc5217SJeff Kirsher 
4784adfc5217SJeff Kirsher 	/* Rx data */
4785adfc5217SJeff Kirsher 
4786adfc5217SJeff Kirsher 	/* IPv6 TPA supported for E2 and above only */
4787adfc5217SJeff Kirsher 	data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, &params->flags) *
4788adfc5217SJeff Kirsher 				CLIENT_INIT_RX_DATA_TPA_EN_IPV6;
4789adfc5217SJeff Kirsher }
4790adfc5217SJeff Kirsher 
bnx2x_q_fill_init_general_data(struct bnx2x * bp,struct bnx2x_queue_sp_obj * o,struct bnx2x_general_setup_params * params,struct client_init_general_data * gen_data,unsigned long * flags)4791adfc5217SJeff Kirsher static void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
4792adfc5217SJeff Kirsher 				struct bnx2x_queue_sp_obj *o,
4793adfc5217SJeff Kirsher 				struct bnx2x_general_setup_params *params,
4794adfc5217SJeff Kirsher 				struct client_init_general_data *gen_data,
4795adfc5217SJeff Kirsher 				unsigned long *flags)
4796adfc5217SJeff Kirsher {
4797adfc5217SJeff Kirsher 	gen_data->client_id = o->cl_id;
4798adfc5217SJeff Kirsher 
4799adfc5217SJeff Kirsher 	if (test_bit(BNX2X_Q_FLG_STATS, flags)) {
4800adfc5217SJeff Kirsher 		gen_data->statistics_counter_id =
4801adfc5217SJeff Kirsher 					params->stat_id;
4802adfc5217SJeff Kirsher 		gen_data->statistics_en_flg = 1;
4803adfc5217SJeff Kirsher 		gen_data->statistics_zero_flg =
4804adfc5217SJeff Kirsher 			test_bit(BNX2X_Q_FLG_ZERO_STATS, flags);
4805adfc5217SJeff Kirsher 	} else
4806adfc5217SJeff Kirsher 		gen_data->statistics_counter_id =
4807adfc5217SJeff Kirsher 					DISABLE_STATISTIC_COUNTER_ID_VALUE;
4808adfc5217SJeff Kirsher 
4809adfc5217SJeff Kirsher 	gen_data->is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, flags);
4810adfc5217SJeff Kirsher 	gen_data->activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, flags);
4811adfc5217SJeff Kirsher 	gen_data->sp_client_id = params->spcl_id;
4812adfc5217SJeff Kirsher 	gen_data->mtu = cpu_to_le16(params->mtu);
4813adfc5217SJeff Kirsher 	gen_data->func_id = o->func_id;
4814adfc5217SJeff Kirsher 
4815adfc5217SJeff Kirsher 	gen_data->cos = params->cos;
4816adfc5217SJeff Kirsher 
4817adfc5217SJeff Kirsher 	gen_data->traffic_type =
4818adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_FCOE, flags) ?
4819adfc5217SJeff Kirsher 		LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
4820adfc5217SJeff Kirsher 
482102dc4025SYuval Mintz 	gen_data->fp_hsi_ver = params->fp_hsi;
4822e42780b6SDmitry Kravkov 
482394f05b0fSJoe Perches 	DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d\n",
4824adfc5217SJeff Kirsher 	   gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
4825adfc5217SJeff Kirsher }
4826adfc5217SJeff Kirsher 
bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj * o,struct bnx2x_txq_setup_params * params,struct client_init_tx_data * tx_data,unsigned long * flags)4827adfc5217SJeff Kirsher static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o,
4828adfc5217SJeff Kirsher 				struct bnx2x_txq_setup_params *params,
4829adfc5217SJeff Kirsher 				struct client_init_tx_data *tx_data,
4830adfc5217SJeff Kirsher 				unsigned long *flags)
4831adfc5217SJeff Kirsher {
4832adfc5217SJeff Kirsher 	tx_data->enforce_security_flg =
4833adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_TX_SEC, flags);
4834adfc5217SJeff Kirsher 	tx_data->default_vlan =
4835adfc5217SJeff Kirsher 		cpu_to_le16(params->default_vlan);
4836adfc5217SJeff Kirsher 	tx_data->default_vlan_flg =
4837adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_DEF_VLAN, flags);
4838adfc5217SJeff Kirsher 	tx_data->tx_switching_flg =
4839adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_TX_SWITCH, flags);
4840adfc5217SJeff Kirsher 	tx_data->anti_spoofing_flg =
4841adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags);
4842a3348722SBarak Witkowski 	tx_data->force_default_pri_flg =
4843a3348722SBarak Witkowski 		test_bit(BNX2X_Q_FLG_FORCE_DEFAULT_PRI, flags);
4844e42780b6SDmitry Kravkov 	tx_data->refuse_outband_vlan_flg =
4845e42780b6SDmitry Kravkov 		test_bit(BNX2X_Q_FLG_REFUSE_OUTBAND_VLAN, flags);
4846e287a75cSDmitry Kravkov 	tx_data->tunnel_lso_inc_ip_id =
4847e287a75cSDmitry Kravkov 		test_bit(BNX2X_Q_FLG_TUN_INC_INNER_IP_ID, flags);
484891226790SDmitry Kravkov 	tx_data->tunnel_non_lso_pcsum_location =
4849e42780b6SDmitry Kravkov 		test_bit(BNX2X_Q_FLG_PCSUM_ON_PKT, flags) ? CSUM_ON_PKT :
4850e42780b6SDmitry Kravkov 							    CSUM_ON_BD;
485191226790SDmitry Kravkov 
4852adfc5217SJeff Kirsher 	tx_data->tx_status_block_id = params->fw_sb_id;
4853adfc5217SJeff Kirsher 	tx_data->tx_sb_index_number = params->sb_cq_index;
4854adfc5217SJeff Kirsher 	tx_data->tss_leading_client_id = params->tss_leading_cl_id;
4855adfc5217SJeff Kirsher 
4856adfc5217SJeff Kirsher 	tx_data->tx_bd_page_base.lo =
4857adfc5217SJeff Kirsher 		cpu_to_le32(U64_LO(params->dscr_map));
4858adfc5217SJeff Kirsher 	tx_data->tx_bd_page_base.hi =
4859adfc5217SJeff Kirsher 		cpu_to_le32(U64_HI(params->dscr_map));
4860adfc5217SJeff Kirsher 
4861adfc5217SJeff Kirsher 	/* Don't configure any Tx switching mode during queue SETUP */
4862adfc5217SJeff Kirsher 	tx_data->state = 0;
4863adfc5217SJeff Kirsher }
4864adfc5217SJeff Kirsher 
bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj * o,struct rxq_pause_params * params,struct client_init_rx_data * rx_data)4865adfc5217SJeff Kirsher static void bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj *o,
4866adfc5217SJeff Kirsher 				struct rxq_pause_params *params,
4867adfc5217SJeff Kirsher 				struct client_init_rx_data *rx_data)
4868adfc5217SJeff Kirsher {
4869adfc5217SJeff Kirsher 	/* flow control data */
4870adfc5217SJeff Kirsher 	rx_data->cqe_pause_thr_low = cpu_to_le16(params->rcq_th_lo);
4871adfc5217SJeff Kirsher 	rx_data->cqe_pause_thr_high = cpu_to_le16(params->rcq_th_hi);
4872adfc5217SJeff Kirsher 	rx_data->bd_pause_thr_low = cpu_to_le16(params->bd_th_lo);
4873adfc5217SJeff Kirsher 	rx_data->bd_pause_thr_high = cpu_to_le16(params->bd_th_hi);
4874adfc5217SJeff Kirsher 	rx_data->sge_pause_thr_low = cpu_to_le16(params->sge_th_lo);
4875adfc5217SJeff Kirsher 	rx_data->sge_pause_thr_high = cpu_to_le16(params->sge_th_hi);
4876adfc5217SJeff Kirsher 	rx_data->rx_cos_mask = cpu_to_le16(params->pri_map);
4877adfc5217SJeff Kirsher }
4878adfc5217SJeff Kirsher 
bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj * o,struct bnx2x_rxq_setup_params * params,struct client_init_rx_data * rx_data,unsigned long * flags)4879adfc5217SJeff Kirsher static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o,
4880adfc5217SJeff Kirsher 				struct bnx2x_rxq_setup_params *params,
4881adfc5217SJeff Kirsher 				struct client_init_rx_data *rx_data,
4882adfc5217SJeff Kirsher 				unsigned long *flags)
4883adfc5217SJeff Kirsher {
4884adfc5217SJeff Kirsher 	rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) *
4885adfc5217SJeff Kirsher 				CLIENT_INIT_RX_DATA_TPA_EN_IPV4;
4886621b4d66SDmitry Kravkov 	rx_data->tpa_en |= test_bit(BNX2X_Q_FLG_TPA_GRO, flags) *
4887621b4d66SDmitry Kravkov 				CLIENT_INIT_RX_DATA_TPA_MODE;
4888adfc5217SJeff Kirsher 	rx_data->vmqueue_mode_en_flg = 0;
4889adfc5217SJeff Kirsher 
4890adfc5217SJeff Kirsher 	rx_data->cache_line_alignment_log_size =
4891adfc5217SJeff Kirsher 		params->cache_line_log;
4892adfc5217SJeff Kirsher 	rx_data->enable_dynamic_hc =
4893adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_DHC, flags);
4894adfc5217SJeff Kirsher 	rx_data->max_sges_for_packet = params->max_sges_pkt;
4895adfc5217SJeff Kirsher 	rx_data->client_qzone_id = params->cl_qzone_id;
4896adfc5217SJeff Kirsher 	rx_data->max_agg_size = cpu_to_le16(params->tpa_agg_sz);
4897adfc5217SJeff Kirsher 
4898adfc5217SJeff Kirsher 	/* Always start in DROP_ALL mode */
4899adfc5217SJeff Kirsher 	rx_data->state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL |
4900adfc5217SJeff Kirsher 				     CLIENT_INIT_RX_DATA_MCAST_DROP_ALL);
4901adfc5217SJeff Kirsher 
4902adfc5217SJeff Kirsher 	/* We don't set drop flags */
4903adfc5217SJeff Kirsher 	rx_data->drop_ip_cs_err_flg = 0;
4904adfc5217SJeff Kirsher 	rx_data->drop_tcp_cs_err_flg = 0;
4905adfc5217SJeff Kirsher 	rx_data->drop_ttl0_flg = 0;
4906adfc5217SJeff Kirsher 	rx_data->drop_udp_cs_err_flg = 0;
4907adfc5217SJeff Kirsher 	rx_data->inner_vlan_removal_enable_flg =
4908adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_VLAN, flags);
4909adfc5217SJeff Kirsher 	rx_data->outer_vlan_removal_enable_flg =
4910adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_OV, flags);
4911adfc5217SJeff Kirsher 	rx_data->status_block_id = params->fw_sb_id;
4912adfc5217SJeff Kirsher 	rx_data->rx_sb_index_number = params->sb_cq_index;
4913adfc5217SJeff Kirsher 	rx_data->max_tpa_queues = params->max_tpa_queues;
4914adfc5217SJeff Kirsher 	rx_data->max_bytes_on_bd = cpu_to_le16(params->buf_sz);
4915adfc5217SJeff Kirsher 	rx_data->sge_buff_size = cpu_to_le16(params->sge_buf_sz);
4916adfc5217SJeff Kirsher 	rx_data->bd_page_base.lo =
4917adfc5217SJeff Kirsher 		cpu_to_le32(U64_LO(params->dscr_map));
4918adfc5217SJeff Kirsher 	rx_data->bd_page_base.hi =
4919adfc5217SJeff Kirsher 		cpu_to_le32(U64_HI(params->dscr_map));
4920adfc5217SJeff Kirsher 	rx_data->sge_page_base.lo =
4921adfc5217SJeff Kirsher 		cpu_to_le32(U64_LO(params->sge_map));
4922adfc5217SJeff Kirsher 	rx_data->sge_page_base.hi =
4923adfc5217SJeff Kirsher 		cpu_to_le32(U64_HI(params->sge_map));
4924adfc5217SJeff Kirsher 	rx_data->cqe_page_base.lo =
4925adfc5217SJeff Kirsher 		cpu_to_le32(U64_LO(params->rcq_map));
4926adfc5217SJeff Kirsher 	rx_data->cqe_page_base.hi =
4927adfc5217SJeff Kirsher 		cpu_to_le32(U64_HI(params->rcq_map));
4928adfc5217SJeff Kirsher 	rx_data->is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, flags);
4929adfc5217SJeff Kirsher 
4930adfc5217SJeff Kirsher 	if (test_bit(BNX2X_Q_FLG_MCAST, flags)) {
4931259afa1fSYuval Mintz 		rx_data->approx_mcast_engine_id = params->mcast_engine_id;
4932adfc5217SJeff Kirsher 		rx_data->is_approx_mcast = 1;
4933adfc5217SJeff Kirsher 	}
4934adfc5217SJeff Kirsher 
4935adfc5217SJeff Kirsher 	rx_data->rss_engine_id = params->rss_engine_id;
4936adfc5217SJeff Kirsher 
4937adfc5217SJeff Kirsher 	/* silent vlan removal */
4938adfc5217SJeff Kirsher 	rx_data->silent_vlan_removal_flg =
4939adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, flags);
4940adfc5217SJeff Kirsher 	rx_data->silent_vlan_value =
4941adfc5217SJeff Kirsher 		cpu_to_le16(params->silent_removal_value);
4942adfc5217SJeff Kirsher 	rx_data->silent_vlan_mask =
4943adfc5217SJeff Kirsher 		cpu_to_le16(params->silent_removal_mask);
4944adfc5217SJeff Kirsher }
4945adfc5217SJeff Kirsher 
4946adfc5217SJeff Kirsher /* initialize the general, tx and rx parts of a queue object */
bnx2x_q_fill_setup_data_cmn(struct bnx2x * bp,struct bnx2x_queue_state_params * cmd_params,struct client_init_ramrod_data * data)4947adfc5217SJeff Kirsher static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp,
4948adfc5217SJeff Kirsher 				struct bnx2x_queue_state_params *cmd_params,
4949adfc5217SJeff Kirsher 				struct client_init_ramrod_data *data)
4950adfc5217SJeff Kirsher {
4951adfc5217SJeff Kirsher 	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
4952adfc5217SJeff Kirsher 				       &cmd_params->params.setup.gen_params,
4953adfc5217SJeff Kirsher 				       &data->general,
4954adfc5217SJeff Kirsher 				       &cmd_params->params.setup.flags);
4955adfc5217SJeff Kirsher 
4956adfc5217SJeff Kirsher 	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
4957adfc5217SJeff Kirsher 				  &cmd_params->params.setup.txq_params,
4958adfc5217SJeff Kirsher 				  &data->tx,
4959adfc5217SJeff Kirsher 				  &cmd_params->params.setup.flags);
4960adfc5217SJeff Kirsher 
4961adfc5217SJeff Kirsher 	bnx2x_q_fill_init_rx_data(cmd_params->q_obj,
4962adfc5217SJeff Kirsher 				  &cmd_params->params.setup.rxq_params,
4963adfc5217SJeff Kirsher 				  &data->rx,
4964adfc5217SJeff Kirsher 				  &cmd_params->params.setup.flags);
4965adfc5217SJeff Kirsher 
4966adfc5217SJeff Kirsher 	bnx2x_q_fill_init_pause_data(cmd_params->q_obj,
4967adfc5217SJeff Kirsher 				     &cmd_params->params.setup.pause_params,
4968adfc5217SJeff Kirsher 				     &data->rx);
4969adfc5217SJeff Kirsher }
4970adfc5217SJeff Kirsher 
4971adfc5217SJeff Kirsher /* initialize the general and tx parts of a tx-only queue object */
bnx2x_q_fill_setup_tx_only(struct bnx2x * bp,struct bnx2x_queue_state_params * cmd_params,struct tx_queue_init_ramrod_data * data)4972adfc5217SJeff Kirsher static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp,
4973adfc5217SJeff Kirsher 				struct bnx2x_queue_state_params *cmd_params,
4974adfc5217SJeff Kirsher 				struct tx_queue_init_ramrod_data *data)
4975adfc5217SJeff Kirsher {
4976adfc5217SJeff Kirsher 	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
4977adfc5217SJeff Kirsher 				       &cmd_params->params.tx_only.gen_params,
4978adfc5217SJeff Kirsher 				       &data->general,
4979adfc5217SJeff Kirsher 				       &cmd_params->params.tx_only.flags);
4980adfc5217SJeff Kirsher 
4981adfc5217SJeff Kirsher 	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
4982adfc5217SJeff Kirsher 				  &cmd_params->params.tx_only.txq_params,
4983adfc5217SJeff Kirsher 				  &data->tx,
4984adfc5217SJeff Kirsher 				  &cmd_params->params.tx_only.flags);
4985adfc5217SJeff Kirsher 
498651c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x",
498751c1a580SMerav Sicron 			 cmd_params->q_obj->cids[0],
498851c1a580SMerav Sicron 			 data->tx.tx_bd_page_base.lo,
498951c1a580SMerav Sicron 			 data->tx.tx_bd_page_base.hi);
4990adfc5217SJeff Kirsher }
4991adfc5217SJeff Kirsher 
4992adfc5217SJeff Kirsher /**
4993adfc5217SJeff Kirsher  * bnx2x_q_init - init HW/FW queue
4994adfc5217SJeff Kirsher  *
4995adfc5217SJeff Kirsher  * @bp:		device handle
4996adfc5217SJeff Kirsher  * @params:
4997adfc5217SJeff Kirsher  *
4998adfc5217SJeff Kirsher  * HW/FW initial Queue configuration:
4999adfc5217SJeff Kirsher  *      - HC: Rx and Tx
5000adfc5217SJeff Kirsher  *      - CDU context validation
5001adfc5217SJeff Kirsher  *
5002adfc5217SJeff Kirsher  */
bnx2x_q_init(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5003adfc5217SJeff Kirsher static inline int bnx2x_q_init(struct bnx2x *bp,
5004adfc5217SJeff Kirsher 			       struct bnx2x_queue_state_params *params)
5005adfc5217SJeff Kirsher {
5006adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
5007adfc5217SJeff Kirsher 	struct bnx2x_queue_init_params *init = &params->params.init;
5008adfc5217SJeff Kirsher 	u16 hc_usec;
5009adfc5217SJeff Kirsher 	u8 cos;
5010adfc5217SJeff Kirsher 
5011adfc5217SJeff Kirsher 	/* Tx HC configuration */
5012adfc5217SJeff Kirsher 	if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) &&
5013adfc5217SJeff Kirsher 	    test_bit(BNX2X_Q_FLG_HC, &init->tx.flags)) {
5014adfc5217SJeff Kirsher 		hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0;
5015adfc5217SJeff Kirsher 
5016adfc5217SJeff Kirsher 		bnx2x_update_coalesce_sb_index(bp, init->tx.fw_sb_id,
5017adfc5217SJeff Kirsher 			init->tx.sb_cq_index,
5018adfc5217SJeff Kirsher 			!test_bit(BNX2X_Q_FLG_HC_EN, &init->tx.flags),
5019adfc5217SJeff Kirsher 			hc_usec);
5020adfc5217SJeff Kirsher 	}
5021adfc5217SJeff Kirsher 
5022adfc5217SJeff Kirsher 	/* Rx HC configuration */
5023adfc5217SJeff Kirsher 	if (test_bit(BNX2X_Q_TYPE_HAS_RX, &o->type) &&
5024adfc5217SJeff Kirsher 	    test_bit(BNX2X_Q_FLG_HC, &init->rx.flags)) {
5025adfc5217SJeff Kirsher 		hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0;
5026adfc5217SJeff Kirsher 
5027adfc5217SJeff Kirsher 		bnx2x_update_coalesce_sb_index(bp, init->rx.fw_sb_id,
5028adfc5217SJeff Kirsher 			init->rx.sb_cq_index,
5029adfc5217SJeff Kirsher 			!test_bit(BNX2X_Q_FLG_HC_EN, &init->rx.flags),
5030adfc5217SJeff Kirsher 			hc_usec);
5031adfc5217SJeff Kirsher 	}
5032adfc5217SJeff Kirsher 
5033adfc5217SJeff Kirsher 	/* Set CDU context validation values */
5034adfc5217SJeff Kirsher 	for (cos = 0; cos < o->max_cos; cos++) {
503594f05b0fSJoe Perches 		DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d\n",
5036adfc5217SJeff Kirsher 				 o->cids[cos], cos);
503794f05b0fSJoe Perches 		DP(BNX2X_MSG_SP, "context pointer %p\n", init->cxts[cos]);
5038adfc5217SJeff Kirsher 		bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]);
5039adfc5217SJeff Kirsher 	}
5040adfc5217SJeff Kirsher 
5041adfc5217SJeff Kirsher 	/* As no ramrod is sent, complete the command immediately  */
5042adfc5217SJeff Kirsher 	o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT);
5043adfc5217SJeff Kirsher 
5044adfc5217SJeff Kirsher 	smp_mb();
5045adfc5217SJeff Kirsher 
5046adfc5217SJeff Kirsher 	return 0;
5047adfc5217SJeff Kirsher }
5048adfc5217SJeff Kirsher 
bnx2x_q_send_setup_e1x(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5049adfc5217SJeff Kirsher static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
5050adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
5051adfc5217SJeff Kirsher {
5052adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
5053adfc5217SJeff Kirsher 	struct client_init_ramrod_data *rdata =
5054adfc5217SJeff Kirsher 		(struct client_init_ramrod_data *)o->rdata;
5055adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
5056adfc5217SJeff Kirsher 	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
5057adfc5217SJeff Kirsher 
5058adfc5217SJeff Kirsher 	/* Clear the ramrod data */
5059adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
5060adfc5217SJeff Kirsher 
5061adfc5217SJeff Kirsher 	/* Fill the ramrod data */
5062adfc5217SJeff Kirsher 	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
5063adfc5217SJeff Kirsher 
506414a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
506514a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
5066adfc5217SJeff Kirsher 	 * and updating of the SPQ producer which involves a memory
506714a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
506814a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
5069adfc5217SJeff Kirsher 	 */
5070adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
5071adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
5072adfc5217SJeff Kirsher 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
5073adfc5217SJeff Kirsher }
5074adfc5217SJeff Kirsher 
bnx2x_q_send_setup_e2(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5075adfc5217SJeff Kirsher static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
5076adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
5077adfc5217SJeff Kirsher {
5078adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
5079adfc5217SJeff Kirsher 	struct client_init_ramrod_data *rdata =
5080adfc5217SJeff Kirsher 		(struct client_init_ramrod_data *)o->rdata;
5081adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
5082adfc5217SJeff Kirsher 	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
5083adfc5217SJeff Kirsher 
5084adfc5217SJeff Kirsher 	/* Clear the ramrod data */
5085adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
5086adfc5217SJeff Kirsher 
5087adfc5217SJeff Kirsher 	/* Fill the ramrod data */
5088adfc5217SJeff Kirsher 	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
5089adfc5217SJeff Kirsher 	bnx2x_q_fill_setup_data_e2(bp, params, rdata);
5090adfc5217SJeff Kirsher 
509114a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
509214a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
5093adfc5217SJeff Kirsher 	 * and updating of the SPQ producer which involves a memory
509414a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
509514a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
5096adfc5217SJeff Kirsher 	 */
5097adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
5098adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
5099adfc5217SJeff Kirsher 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
5100adfc5217SJeff Kirsher }
5101adfc5217SJeff Kirsher 
bnx2x_q_send_setup_tx_only(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5102adfc5217SJeff Kirsher static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
5103adfc5217SJeff Kirsher 				  struct bnx2x_queue_state_params *params)
5104adfc5217SJeff Kirsher {
5105adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
5106adfc5217SJeff Kirsher 	struct tx_queue_init_ramrod_data *rdata =
5107adfc5217SJeff Kirsher 		(struct tx_queue_init_ramrod_data *)o->rdata;
5108adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
5109adfc5217SJeff Kirsher 	int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP;
5110adfc5217SJeff Kirsher 	struct bnx2x_queue_setup_tx_only_params *tx_only_params =
5111adfc5217SJeff Kirsher 		&params->params.tx_only;
5112adfc5217SJeff Kirsher 	u8 cid_index = tx_only_params->cid_index;
5113adfc5217SJeff Kirsher 
5114adfc5217SJeff Kirsher 	if (cid_index >= o->max_cos) {
5115adfc5217SJeff Kirsher 		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
5116adfc5217SJeff Kirsher 			  o->cl_id, cid_index);
5117adfc5217SJeff Kirsher 		return -EINVAL;
5118adfc5217SJeff Kirsher 	}
5119adfc5217SJeff Kirsher 
512094f05b0fSJoe Perches 	DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d\n",
5121adfc5217SJeff Kirsher 			 tx_only_params->gen_params.cos,
5122adfc5217SJeff Kirsher 			 tx_only_params->gen_params.spcl_id);
5123adfc5217SJeff Kirsher 
5124adfc5217SJeff Kirsher 	/* Clear the ramrod data */
5125adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
5126adfc5217SJeff Kirsher 
5127adfc5217SJeff Kirsher 	/* Fill the ramrod data */
5128adfc5217SJeff Kirsher 	bnx2x_q_fill_setup_tx_only(bp, params, rdata);
5129adfc5217SJeff Kirsher 
513051c1a580SMerav Sicron 	DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d, sp-client id %d, cos %d\n",
513151c1a580SMerav Sicron 			 o->cids[cid_index], rdata->general.client_id,
5132adfc5217SJeff Kirsher 			 rdata->general.sp_client_id, rdata->general.cos);
5133adfc5217SJeff Kirsher 
513414a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
513514a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
5136adfc5217SJeff Kirsher 	 * and updating of the SPQ producer which involves a memory
513714a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
513814a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
5139adfc5217SJeff Kirsher 	 */
5140adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, ramrod, o->cids[cid_index],
5141adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
5142adfc5217SJeff Kirsher 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
5143adfc5217SJeff Kirsher }
5144adfc5217SJeff Kirsher 
bnx2x_q_fill_update_data(struct bnx2x * bp,struct bnx2x_queue_sp_obj * obj,struct bnx2x_queue_update_params * params,struct client_update_ramrod_data * data)5145adfc5217SJeff Kirsher static void bnx2x_q_fill_update_data(struct bnx2x *bp,
5146adfc5217SJeff Kirsher 				     struct bnx2x_queue_sp_obj *obj,
5147adfc5217SJeff Kirsher 				     struct bnx2x_queue_update_params *params,
5148adfc5217SJeff Kirsher 				     struct client_update_ramrod_data *data)
5149adfc5217SJeff Kirsher {
5150adfc5217SJeff Kirsher 	/* Client ID of the client to update */
5151adfc5217SJeff Kirsher 	data->client_id = obj->cl_id;
5152adfc5217SJeff Kirsher 
5153adfc5217SJeff Kirsher 	/* Function ID of the client to update */
5154adfc5217SJeff Kirsher 	data->func_id = obj->func_id;
5155adfc5217SJeff Kirsher 
5156adfc5217SJeff Kirsher 	/* Default VLAN value */
5157adfc5217SJeff Kirsher 	data->default_vlan = cpu_to_le16(params->def_vlan);
5158adfc5217SJeff Kirsher 
5159adfc5217SJeff Kirsher 	/* Inner VLAN stripping */
5160adfc5217SJeff Kirsher 	data->inner_vlan_removal_enable_flg =
5161adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM, &params->update_flags);
5162adfc5217SJeff Kirsher 	data->inner_vlan_removal_change_flg =
5163adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
5164adfc5217SJeff Kirsher 			 &params->update_flags);
5165adfc5217SJeff Kirsher 
516616a5fd92SYuval Mintz 	/* Outer VLAN stripping */
5167adfc5217SJeff Kirsher 	data->outer_vlan_removal_enable_flg =
5168adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, &params->update_flags);
5169adfc5217SJeff Kirsher 	data->outer_vlan_removal_change_flg =
5170adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
5171adfc5217SJeff Kirsher 			 &params->update_flags);
5172adfc5217SJeff Kirsher 
5173adfc5217SJeff Kirsher 	/* Drop packets that have source MAC that doesn't belong to this
5174adfc5217SJeff Kirsher 	 * Queue.
5175adfc5217SJeff Kirsher 	 */
5176adfc5217SJeff Kirsher 	data->anti_spoofing_enable_flg =
5177adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF, &params->update_flags);
5178adfc5217SJeff Kirsher 	data->anti_spoofing_change_flg =
5179adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG, &params->update_flags);
5180adfc5217SJeff Kirsher 
5181adfc5217SJeff Kirsher 	/* Activate/Deactivate */
5182adfc5217SJeff Kirsher 	data->activate_flg =
5183adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_ACTIVATE, &params->update_flags);
5184adfc5217SJeff Kirsher 	data->activate_change_flg =
5185adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &params->update_flags);
5186adfc5217SJeff Kirsher 
5187adfc5217SJeff Kirsher 	/* Enable default VLAN */
5188adfc5217SJeff Kirsher 	data->default_vlan_enable_flg =
5189adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, &params->update_flags);
5190adfc5217SJeff Kirsher 	data->default_vlan_change_flg =
5191adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
5192adfc5217SJeff Kirsher 			 &params->update_flags);
5193adfc5217SJeff Kirsher 
5194adfc5217SJeff Kirsher 	/* silent vlan removal */
5195adfc5217SJeff Kirsher 	data->silent_vlan_change_flg =
5196adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
5197adfc5217SJeff Kirsher 			 &params->update_flags);
5198adfc5217SJeff Kirsher 	data->silent_vlan_removal_flg =
5199adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, &params->update_flags);
5200adfc5217SJeff Kirsher 	data->silent_vlan_value = cpu_to_le16(params->silent_removal_value);
5201adfc5217SJeff Kirsher 	data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask);
5202c14db202SYuval Mintz 
5203c14db202SYuval Mintz 	/* tx switching */
5204c14db202SYuval Mintz 	data->tx_switching_flg =
5205c14db202SYuval Mintz 		test_bit(BNX2X_Q_UPDATE_TX_SWITCHING, &params->update_flags);
5206c14db202SYuval Mintz 	data->tx_switching_change_flg =
5207c14db202SYuval Mintz 		test_bit(BNX2X_Q_UPDATE_TX_SWITCHING_CHNG,
5208c14db202SYuval Mintz 			 &params->update_flags);
5209eeed018cSMichal Kalderon 
5210eeed018cSMichal Kalderon 	/* PTP */
5211eeed018cSMichal Kalderon 	data->handle_ptp_pkts_flg =
5212eeed018cSMichal Kalderon 		test_bit(BNX2X_Q_UPDATE_PTP_PKTS, &params->update_flags);
5213eeed018cSMichal Kalderon 	data->handle_ptp_pkts_change_flg =
5214eeed018cSMichal Kalderon 		test_bit(BNX2X_Q_UPDATE_PTP_PKTS_CHNG, &params->update_flags);
5215adfc5217SJeff Kirsher }
5216adfc5217SJeff Kirsher 
bnx2x_q_send_update(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5217adfc5217SJeff Kirsher static inline int bnx2x_q_send_update(struct bnx2x *bp,
5218adfc5217SJeff Kirsher 				      struct bnx2x_queue_state_params *params)
5219adfc5217SJeff Kirsher {
5220adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
5221adfc5217SJeff Kirsher 	struct client_update_ramrod_data *rdata =
5222adfc5217SJeff Kirsher 		(struct client_update_ramrod_data *)o->rdata;
5223adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
5224adfc5217SJeff Kirsher 	struct bnx2x_queue_update_params *update_params =
5225adfc5217SJeff Kirsher 		&params->params.update;
5226adfc5217SJeff Kirsher 	u8 cid_index = update_params->cid_index;
5227adfc5217SJeff Kirsher 
5228adfc5217SJeff Kirsher 	if (cid_index >= o->max_cos) {
5229adfc5217SJeff Kirsher 		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
5230adfc5217SJeff Kirsher 			  o->cl_id, cid_index);
5231adfc5217SJeff Kirsher 		return -EINVAL;
5232adfc5217SJeff Kirsher 	}
5233adfc5217SJeff Kirsher 
5234adfc5217SJeff Kirsher 	/* Clear the ramrod data */
5235adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
5236adfc5217SJeff Kirsher 
5237adfc5217SJeff Kirsher 	/* Fill the ramrod data */
5238adfc5217SJeff Kirsher 	bnx2x_q_fill_update_data(bp, o, update_params, rdata);
5239adfc5217SJeff Kirsher 
524014a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
524114a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
5242adfc5217SJeff Kirsher 	 * and updating of the SPQ producer which involves a memory
524314a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
524414a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
5245adfc5217SJeff Kirsher 	 */
5246adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
5247adfc5217SJeff Kirsher 			     o->cids[cid_index], U64_HI(data_mapping),
5248adfc5217SJeff Kirsher 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
5249adfc5217SJeff Kirsher }
5250adfc5217SJeff Kirsher 
5251adfc5217SJeff Kirsher /**
5252adfc5217SJeff Kirsher  * bnx2x_q_send_deactivate - send DEACTIVATE command
5253adfc5217SJeff Kirsher  *
5254adfc5217SJeff Kirsher  * @bp:		device handle
5255adfc5217SJeff Kirsher  * @params:
5256adfc5217SJeff Kirsher  *
5257adfc5217SJeff Kirsher  * implemented using the UPDATE command.
5258adfc5217SJeff Kirsher  */
bnx2x_q_send_deactivate(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5259adfc5217SJeff Kirsher static inline int bnx2x_q_send_deactivate(struct bnx2x *bp,
5260adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
5261adfc5217SJeff Kirsher {
5262adfc5217SJeff Kirsher 	struct bnx2x_queue_update_params *update = &params->params.update;
5263adfc5217SJeff Kirsher 
5264adfc5217SJeff Kirsher 	memset(update, 0, sizeof(*update));
5265adfc5217SJeff Kirsher 
5266adfc5217SJeff Kirsher 	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
5267adfc5217SJeff Kirsher 
5268adfc5217SJeff Kirsher 	return bnx2x_q_send_update(bp, params);
5269adfc5217SJeff Kirsher }
5270adfc5217SJeff Kirsher 
5271adfc5217SJeff Kirsher /**
5272adfc5217SJeff Kirsher  * bnx2x_q_send_activate - send ACTIVATE command
5273adfc5217SJeff Kirsher  *
5274adfc5217SJeff Kirsher  * @bp:		device handle
5275adfc5217SJeff Kirsher  * @params:
5276adfc5217SJeff Kirsher  *
5277adfc5217SJeff Kirsher  * implemented using the UPDATE command.
5278adfc5217SJeff Kirsher  */
bnx2x_q_send_activate(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5279adfc5217SJeff Kirsher static inline int bnx2x_q_send_activate(struct bnx2x *bp,
5280adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
5281adfc5217SJeff Kirsher {
5282adfc5217SJeff Kirsher 	struct bnx2x_queue_update_params *update = &params->params.update;
5283adfc5217SJeff Kirsher 
5284adfc5217SJeff Kirsher 	memset(update, 0, sizeof(*update));
5285adfc5217SJeff Kirsher 
5286adfc5217SJeff Kirsher 	__set_bit(BNX2X_Q_UPDATE_ACTIVATE, &update->update_flags);
5287adfc5217SJeff Kirsher 	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
5288adfc5217SJeff Kirsher 
5289adfc5217SJeff Kirsher 	return bnx2x_q_send_update(bp, params);
5290adfc5217SJeff Kirsher }
5291adfc5217SJeff Kirsher 
bnx2x_q_fill_update_tpa_data(struct bnx2x * bp,struct bnx2x_queue_sp_obj * obj,struct bnx2x_queue_update_tpa_params * params,struct tpa_update_ramrod_data * data)529214a94ebdSMichal Kalderon static void bnx2x_q_fill_update_tpa_data(struct bnx2x *bp,
529314a94ebdSMichal Kalderon 				struct bnx2x_queue_sp_obj *obj,
529414a94ebdSMichal Kalderon 				struct bnx2x_queue_update_tpa_params *params,
529514a94ebdSMichal Kalderon 				struct tpa_update_ramrod_data *data)
529614a94ebdSMichal Kalderon {
529714a94ebdSMichal Kalderon 	data->client_id = obj->cl_id;
529814a94ebdSMichal Kalderon 	data->complete_on_both_clients = params->complete_on_both_clients;
529914a94ebdSMichal Kalderon 	data->dont_verify_rings_pause_thr_flg =
530014a94ebdSMichal Kalderon 		params->dont_verify_thr;
530114a94ebdSMichal Kalderon 	data->max_agg_size = cpu_to_le16(params->max_agg_sz);
530214a94ebdSMichal Kalderon 	data->max_sges_for_packet = params->max_sges_pkt;
530314a94ebdSMichal Kalderon 	data->max_tpa_queues = params->max_tpa_queues;
530414a94ebdSMichal Kalderon 	data->sge_buff_size = cpu_to_le16(params->sge_buff_sz);
530514a94ebdSMichal Kalderon 	data->sge_page_base_hi = cpu_to_le32(U64_HI(params->sge_map));
530614a94ebdSMichal Kalderon 	data->sge_page_base_lo = cpu_to_le32(U64_LO(params->sge_map));
530714a94ebdSMichal Kalderon 	data->sge_pause_thr_high = cpu_to_le16(params->sge_pause_thr_high);
530814a94ebdSMichal Kalderon 	data->sge_pause_thr_low = cpu_to_le16(params->sge_pause_thr_low);
530914a94ebdSMichal Kalderon 	data->tpa_mode = params->tpa_mode;
531014a94ebdSMichal Kalderon 	data->update_ipv4 = params->update_ipv4;
531114a94ebdSMichal Kalderon 	data->update_ipv6 = params->update_ipv6;
531214a94ebdSMichal Kalderon }
531314a94ebdSMichal Kalderon 
bnx2x_q_send_update_tpa(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5314adfc5217SJeff Kirsher static inline int bnx2x_q_send_update_tpa(struct bnx2x *bp,
5315adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
5316adfc5217SJeff Kirsher {
531714a94ebdSMichal Kalderon 	struct bnx2x_queue_sp_obj *o = params->q_obj;
531814a94ebdSMichal Kalderon 	struct tpa_update_ramrod_data *rdata =
531914a94ebdSMichal Kalderon 		(struct tpa_update_ramrod_data *)o->rdata;
532014a94ebdSMichal Kalderon 	dma_addr_t data_mapping = o->rdata_mapping;
532114a94ebdSMichal Kalderon 	struct bnx2x_queue_update_tpa_params *update_tpa_params =
532214a94ebdSMichal Kalderon 		&params->params.update_tpa;
532314a94ebdSMichal Kalderon 	u16 type;
532414a94ebdSMichal Kalderon 
532514a94ebdSMichal Kalderon 	/* Clear the ramrod data */
532614a94ebdSMichal Kalderon 	memset(rdata, 0, sizeof(*rdata));
532714a94ebdSMichal Kalderon 
532814a94ebdSMichal Kalderon 	/* Fill the ramrod data */
532914a94ebdSMichal Kalderon 	bnx2x_q_fill_update_tpa_data(bp, o, update_tpa_params, rdata);
533014a94ebdSMichal Kalderon 
533114a94ebdSMichal Kalderon 	/* Add the function id inside the type, so that sp post function
533214a94ebdSMichal Kalderon 	 * doesn't automatically add the PF func-id, this is required
533314a94ebdSMichal Kalderon 	 * for operations done by PFs on behalf of their VFs
533414a94ebdSMichal Kalderon 	 */
533514a94ebdSMichal Kalderon 	type = ETH_CONNECTION_TYPE |
533614a94ebdSMichal Kalderon 		((o->func_id) << SPE_HDR_FUNCTION_ID_SHIFT);
533714a94ebdSMichal Kalderon 
533814a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
533914a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
534014a94ebdSMichal Kalderon 	 * and updating of the SPQ producer which involves a memory
534114a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
534214a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
534314a94ebdSMichal Kalderon 	 */
534414a94ebdSMichal Kalderon 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TPA_UPDATE,
534514a94ebdSMichal Kalderon 			     o->cids[BNX2X_PRIMARY_CID_INDEX],
534614a94ebdSMichal Kalderon 			     U64_HI(data_mapping),
534714a94ebdSMichal Kalderon 			     U64_LO(data_mapping), type);
5348adfc5217SJeff Kirsher }
5349adfc5217SJeff Kirsher 
bnx2x_q_send_halt(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5350adfc5217SJeff Kirsher static inline int bnx2x_q_send_halt(struct bnx2x *bp,
5351adfc5217SJeff Kirsher 				    struct bnx2x_queue_state_params *params)
5352adfc5217SJeff Kirsher {
5353adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
5354adfc5217SJeff Kirsher 
5355adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT,
5356adfc5217SJeff Kirsher 			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, o->cl_id,
5357adfc5217SJeff Kirsher 			     ETH_CONNECTION_TYPE);
5358adfc5217SJeff Kirsher }
5359adfc5217SJeff Kirsher 
bnx2x_q_send_cfc_del(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5360adfc5217SJeff Kirsher static inline int bnx2x_q_send_cfc_del(struct bnx2x *bp,
5361adfc5217SJeff Kirsher 				       struct bnx2x_queue_state_params *params)
5362adfc5217SJeff Kirsher {
5363adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
5364adfc5217SJeff Kirsher 	u8 cid_idx = params->params.cfc_del.cid_index;
5365adfc5217SJeff Kirsher 
5366adfc5217SJeff Kirsher 	if (cid_idx >= o->max_cos) {
5367adfc5217SJeff Kirsher 		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
5368adfc5217SJeff Kirsher 			  o->cl_id, cid_idx);
5369adfc5217SJeff Kirsher 		return -EINVAL;
5370adfc5217SJeff Kirsher 	}
5371adfc5217SJeff Kirsher 
5372adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL,
5373adfc5217SJeff Kirsher 			     o->cids[cid_idx], 0, 0, NONE_CONNECTION_TYPE);
5374adfc5217SJeff Kirsher }
5375adfc5217SJeff Kirsher 
bnx2x_q_send_terminate(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5376adfc5217SJeff Kirsher static inline int bnx2x_q_send_terminate(struct bnx2x *bp,
5377adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
5378adfc5217SJeff Kirsher {
5379adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
5380adfc5217SJeff Kirsher 	u8 cid_index = params->params.terminate.cid_index;
5381adfc5217SJeff Kirsher 
5382adfc5217SJeff Kirsher 	if (cid_index >= o->max_cos) {
5383adfc5217SJeff Kirsher 		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
5384adfc5217SJeff Kirsher 			  o->cl_id, cid_index);
5385adfc5217SJeff Kirsher 		return -EINVAL;
5386adfc5217SJeff Kirsher 	}
5387adfc5217SJeff Kirsher 
5388adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE,
5389adfc5217SJeff Kirsher 			     o->cids[cid_index], 0, 0, ETH_CONNECTION_TYPE);
5390adfc5217SJeff Kirsher }
5391adfc5217SJeff Kirsher 
bnx2x_q_send_empty(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5392adfc5217SJeff Kirsher static inline int bnx2x_q_send_empty(struct bnx2x *bp,
5393adfc5217SJeff Kirsher 				     struct bnx2x_queue_state_params *params)
5394adfc5217SJeff Kirsher {
5395adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
5396adfc5217SJeff Kirsher 
5397adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY,
5398adfc5217SJeff Kirsher 			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, 0,
5399adfc5217SJeff Kirsher 			     ETH_CONNECTION_TYPE);
5400adfc5217SJeff Kirsher }
5401adfc5217SJeff Kirsher 
bnx2x_queue_send_cmd_cmn(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5402adfc5217SJeff Kirsher static inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp,
5403adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
5404adfc5217SJeff Kirsher {
5405adfc5217SJeff Kirsher 	switch (params->cmd) {
5406adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_INIT:
5407adfc5217SJeff Kirsher 		return bnx2x_q_init(bp, params);
5408adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP_TX_ONLY:
5409adfc5217SJeff Kirsher 		return bnx2x_q_send_setup_tx_only(bp, params);
5410adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_DEACTIVATE:
5411adfc5217SJeff Kirsher 		return bnx2x_q_send_deactivate(bp, params);
5412adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_ACTIVATE:
5413adfc5217SJeff Kirsher 		return bnx2x_q_send_activate(bp, params);
5414adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE:
5415adfc5217SJeff Kirsher 		return bnx2x_q_send_update(bp, params);
5416adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE_TPA:
5417adfc5217SJeff Kirsher 		return bnx2x_q_send_update_tpa(bp, params);
5418adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_HALT:
5419adfc5217SJeff Kirsher 		return bnx2x_q_send_halt(bp, params);
5420adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_CFC_DEL:
5421adfc5217SJeff Kirsher 		return bnx2x_q_send_cfc_del(bp, params);
5422adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_TERMINATE:
5423adfc5217SJeff Kirsher 		return bnx2x_q_send_terminate(bp, params);
5424adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_EMPTY:
5425adfc5217SJeff Kirsher 		return bnx2x_q_send_empty(bp, params);
5426adfc5217SJeff Kirsher 	default:
5427adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", params->cmd);
5428adfc5217SJeff Kirsher 		return -EINVAL;
5429adfc5217SJeff Kirsher 	}
5430adfc5217SJeff Kirsher }
5431adfc5217SJeff Kirsher 
bnx2x_queue_send_cmd_e1x(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5432adfc5217SJeff Kirsher static int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp,
5433adfc5217SJeff Kirsher 				    struct bnx2x_queue_state_params *params)
5434adfc5217SJeff Kirsher {
5435adfc5217SJeff Kirsher 	switch (params->cmd) {
5436adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP:
5437adfc5217SJeff Kirsher 		return bnx2x_q_send_setup_e1x(bp, params);
5438adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_INIT:
5439adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP_TX_ONLY:
5440adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_DEACTIVATE:
5441adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_ACTIVATE:
5442adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE:
5443adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE_TPA:
5444adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_HALT:
5445adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_CFC_DEL:
5446adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_TERMINATE:
5447adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_EMPTY:
5448adfc5217SJeff Kirsher 		return bnx2x_queue_send_cmd_cmn(bp, params);
5449adfc5217SJeff Kirsher 	default:
5450adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", params->cmd);
5451adfc5217SJeff Kirsher 		return -EINVAL;
5452adfc5217SJeff Kirsher 	}
5453adfc5217SJeff Kirsher }
5454adfc5217SJeff Kirsher 
bnx2x_queue_send_cmd_e2(struct bnx2x * bp,struct bnx2x_queue_state_params * params)5455adfc5217SJeff Kirsher static int bnx2x_queue_send_cmd_e2(struct bnx2x *bp,
5456adfc5217SJeff Kirsher 				   struct bnx2x_queue_state_params *params)
5457adfc5217SJeff Kirsher {
5458adfc5217SJeff Kirsher 	switch (params->cmd) {
5459adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP:
5460adfc5217SJeff Kirsher 		return bnx2x_q_send_setup_e2(bp, params);
5461adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_INIT:
5462adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP_TX_ONLY:
5463adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_DEACTIVATE:
5464adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_ACTIVATE:
5465adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE:
5466adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE_TPA:
5467adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_HALT:
5468adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_CFC_DEL:
5469adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_TERMINATE:
5470adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_EMPTY:
5471adfc5217SJeff Kirsher 		return bnx2x_queue_send_cmd_cmn(bp, params);
5472adfc5217SJeff Kirsher 	default:
5473adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", params->cmd);
5474adfc5217SJeff Kirsher 		return -EINVAL;
5475adfc5217SJeff Kirsher 	}
5476adfc5217SJeff Kirsher }
5477adfc5217SJeff Kirsher 
5478adfc5217SJeff Kirsher /**
5479adfc5217SJeff Kirsher  * bnx2x_queue_chk_transition - check state machine of a regular Queue
5480adfc5217SJeff Kirsher  *
5481adfc5217SJeff Kirsher  * @bp:		device handle
5482d0ea5cbdSJesse Brandeburg  * @o:		queue info
5483d0ea5cbdSJesse Brandeburg  * @params:	queue state
5484adfc5217SJeff Kirsher  *
5485adfc5217SJeff Kirsher  * (not Forwarding)
5486adfc5217SJeff Kirsher  * It both checks if the requested command is legal in a current
5487adfc5217SJeff Kirsher  * state and, if it's legal, sets a `next_state' in the object
5488adfc5217SJeff Kirsher  * that will be used in the completion flow to set the `state'
5489adfc5217SJeff Kirsher  * of the object.
5490adfc5217SJeff Kirsher  *
5491adfc5217SJeff Kirsher  * returns 0 if a requested command is a legal transition,
5492adfc5217SJeff Kirsher  *         -EINVAL otherwise.
5493adfc5217SJeff Kirsher  */
bnx2x_queue_chk_transition(struct bnx2x * bp,struct bnx2x_queue_sp_obj * o,struct bnx2x_queue_state_params * params)5494adfc5217SJeff Kirsher static int bnx2x_queue_chk_transition(struct bnx2x *bp,
5495adfc5217SJeff Kirsher 				      struct bnx2x_queue_sp_obj *o,
5496adfc5217SJeff Kirsher 				      struct bnx2x_queue_state_params *params)
5497adfc5217SJeff Kirsher {
5498adfc5217SJeff Kirsher 	enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX;
5499adfc5217SJeff Kirsher 	enum bnx2x_queue_cmd cmd = params->cmd;
5500adfc5217SJeff Kirsher 	struct bnx2x_queue_update_params *update_params =
5501adfc5217SJeff Kirsher 		 &params->params.update;
5502adfc5217SJeff Kirsher 	u8 next_tx_only = o->num_tx_only;
5503adfc5217SJeff Kirsher 
550416a5fd92SYuval Mintz 	/* Forget all pending for completion commands if a driver only state
5505adfc5217SJeff Kirsher 	 * transition has been requested.
5506adfc5217SJeff Kirsher 	 */
5507adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
5508adfc5217SJeff Kirsher 		o->pending = 0;
5509adfc5217SJeff Kirsher 		o->next_state = BNX2X_Q_STATE_MAX;
5510adfc5217SJeff Kirsher 	}
5511adfc5217SJeff Kirsher 
551216a5fd92SYuval Mintz 	/* Don't allow a next state transition if we are in the middle of
5513adfc5217SJeff Kirsher 	 * the previous one.
5514adfc5217SJeff Kirsher 	 */
551504c46736SYuval Mintz 	if (o->pending) {
551604c46736SYuval Mintz 		BNX2X_ERR("Blocking transition since pending was %lx\n",
551704c46736SYuval Mintz 			  o->pending);
5518adfc5217SJeff Kirsher 		return -EBUSY;
551904c46736SYuval Mintz 	}
5520adfc5217SJeff Kirsher 
5521adfc5217SJeff Kirsher 	switch (state) {
5522adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_RESET:
5523adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_INIT)
5524adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_INITIALIZED;
5525adfc5217SJeff Kirsher 
5526adfc5217SJeff Kirsher 		break;
5527adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_INITIALIZED:
5528adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_SETUP) {
5529adfc5217SJeff Kirsher 			if (test_bit(BNX2X_Q_FLG_ACTIVE,
5530adfc5217SJeff Kirsher 				     &params->params.setup.flags))
5531adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_ACTIVE;
5532adfc5217SJeff Kirsher 			else
5533adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_INACTIVE;
5534adfc5217SJeff Kirsher 		}
5535adfc5217SJeff Kirsher 
5536adfc5217SJeff Kirsher 		break;
5537adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_ACTIVE:
5538adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_DEACTIVATE)
5539adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_INACTIVE;
5540adfc5217SJeff Kirsher 
5541adfc5217SJeff Kirsher 		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
5542adfc5217SJeff Kirsher 			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
5543adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_ACTIVE;
5544adfc5217SJeff Kirsher 
5545adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
5546adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_MULTI_COS;
5547adfc5217SJeff Kirsher 			next_tx_only = 1;
5548adfc5217SJeff Kirsher 		}
5549adfc5217SJeff Kirsher 
5550adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_HALT)
5551adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_STOPPED;
5552adfc5217SJeff Kirsher 
5553adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_UPDATE) {
5554adfc5217SJeff Kirsher 			/* If "active" state change is requested, update the
5555adfc5217SJeff Kirsher 			 *  state accordingly.
5556adfc5217SJeff Kirsher 			 */
5557adfc5217SJeff Kirsher 			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
5558adfc5217SJeff Kirsher 				     &update_params->update_flags) &&
5559adfc5217SJeff Kirsher 			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
5560adfc5217SJeff Kirsher 				      &update_params->update_flags))
5561adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_INACTIVE;
5562adfc5217SJeff Kirsher 			else
5563adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_ACTIVE;
5564adfc5217SJeff Kirsher 		}
5565adfc5217SJeff Kirsher 
5566adfc5217SJeff Kirsher 		break;
5567adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_MULTI_COS:
5568adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_TERMINATE)
5569adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_MCOS_TERMINATED;
5570adfc5217SJeff Kirsher 
5571adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
5572adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_MULTI_COS;
5573adfc5217SJeff Kirsher 			next_tx_only = o->num_tx_only + 1;
5574adfc5217SJeff Kirsher 		}
5575adfc5217SJeff Kirsher 
5576adfc5217SJeff Kirsher 		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
5577adfc5217SJeff Kirsher 			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
5578adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_MULTI_COS;
5579adfc5217SJeff Kirsher 
5580adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_UPDATE) {
5581adfc5217SJeff Kirsher 			/* If "active" state change is requested, update the
5582adfc5217SJeff Kirsher 			 *  state accordingly.
5583adfc5217SJeff Kirsher 			 */
5584adfc5217SJeff Kirsher 			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
5585adfc5217SJeff Kirsher 				     &update_params->update_flags) &&
5586adfc5217SJeff Kirsher 			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
5587adfc5217SJeff Kirsher 				      &update_params->update_flags))
5588adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_INACTIVE;
5589adfc5217SJeff Kirsher 			else
5590adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_MULTI_COS;
5591adfc5217SJeff Kirsher 		}
5592adfc5217SJeff Kirsher 
5593adfc5217SJeff Kirsher 		break;
5594adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_MCOS_TERMINATED:
5595adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_CFC_DEL) {
5596adfc5217SJeff Kirsher 			next_tx_only = o->num_tx_only - 1;
5597adfc5217SJeff Kirsher 			if (next_tx_only == 0)
5598adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_ACTIVE;
5599adfc5217SJeff Kirsher 			else
5600adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_MULTI_COS;
5601adfc5217SJeff Kirsher 		}
5602adfc5217SJeff Kirsher 
5603adfc5217SJeff Kirsher 		break;
5604adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_INACTIVE:
5605adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_ACTIVATE)
5606adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_ACTIVE;
5607adfc5217SJeff Kirsher 
5608adfc5217SJeff Kirsher 		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
5609adfc5217SJeff Kirsher 			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
5610adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_INACTIVE;
5611adfc5217SJeff Kirsher 
5612adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_HALT)
5613adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_STOPPED;
5614adfc5217SJeff Kirsher 
5615adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_UPDATE) {
5616adfc5217SJeff Kirsher 			/* If "active" state change is requested, update the
5617adfc5217SJeff Kirsher 			 * state accordingly.
5618adfc5217SJeff Kirsher 			 */
5619adfc5217SJeff Kirsher 			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
5620adfc5217SJeff Kirsher 				     &update_params->update_flags) &&
5621adfc5217SJeff Kirsher 			    test_bit(BNX2X_Q_UPDATE_ACTIVATE,
5622adfc5217SJeff Kirsher 				     &update_params->update_flags)){
5623adfc5217SJeff Kirsher 				if (o->num_tx_only == 0)
5624adfc5217SJeff Kirsher 					next_state = BNX2X_Q_STATE_ACTIVE;
5625adfc5217SJeff Kirsher 				else /* tx only queues exist for this queue */
5626adfc5217SJeff Kirsher 					next_state = BNX2X_Q_STATE_MULTI_COS;
5627adfc5217SJeff Kirsher 			} else
5628adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_INACTIVE;
5629adfc5217SJeff Kirsher 		}
5630adfc5217SJeff Kirsher 
5631adfc5217SJeff Kirsher 		break;
5632adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_STOPPED:
5633adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_TERMINATE)
5634adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_TERMINATED;
5635adfc5217SJeff Kirsher 
5636adfc5217SJeff Kirsher 		break;
5637adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_TERMINATED:
5638adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_CFC_DEL)
5639adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_RESET;
5640adfc5217SJeff Kirsher 
5641adfc5217SJeff Kirsher 		break;
5642adfc5217SJeff Kirsher 	default:
5643adfc5217SJeff Kirsher 		BNX2X_ERR("Illegal state: %d\n", state);
5644adfc5217SJeff Kirsher 	}
5645adfc5217SJeff Kirsher 
5646adfc5217SJeff Kirsher 	/* Transition is assured */
5647adfc5217SJeff Kirsher 	if (next_state != BNX2X_Q_STATE_MAX) {
5648adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n",
5649adfc5217SJeff Kirsher 				 state, cmd, next_state);
5650adfc5217SJeff Kirsher 		o->next_state = next_state;
5651adfc5217SJeff Kirsher 		o->next_tx_only = next_tx_only;
5652adfc5217SJeff Kirsher 		return 0;
5653adfc5217SJeff Kirsher 	}
5654adfc5217SJeff Kirsher 
5655adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Bad state transition request: %d %d\n", state, cmd);
5656adfc5217SJeff Kirsher 
5657adfc5217SJeff Kirsher 	return -EINVAL;
5658adfc5217SJeff Kirsher }
5659adfc5217SJeff Kirsher 
bnx2x_init_queue_obj(struct bnx2x * bp,struct bnx2x_queue_sp_obj * obj,u8 cl_id,u32 * cids,u8 cid_cnt,u8 func_id,void * rdata,dma_addr_t rdata_mapping,unsigned long type)5660adfc5217SJeff Kirsher void bnx2x_init_queue_obj(struct bnx2x *bp,
5661adfc5217SJeff Kirsher 			  struct bnx2x_queue_sp_obj *obj,
5662adfc5217SJeff Kirsher 			  u8 cl_id, u32 *cids, u8 cid_cnt, u8 func_id,
5663adfc5217SJeff Kirsher 			  void *rdata,
5664adfc5217SJeff Kirsher 			  dma_addr_t rdata_mapping, unsigned long type)
5665adfc5217SJeff Kirsher {
5666adfc5217SJeff Kirsher 	memset(obj, 0, sizeof(*obj));
5667adfc5217SJeff Kirsher 
5668adfc5217SJeff Kirsher 	/* We support only BNX2X_MULTI_TX_COS Tx CoS at the moment */
5669adfc5217SJeff Kirsher 	BUG_ON(BNX2X_MULTI_TX_COS < cid_cnt);
5670adfc5217SJeff Kirsher 
5671adfc5217SJeff Kirsher 	memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt);
5672adfc5217SJeff Kirsher 	obj->max_cos = cid_cnt;
5673adfc5217SJeff Kirsher 	obj->cl_id = cl_id;
5674adfc5217SJeff Kirsher 	obj->func_id = func_id;
5675adfc5217SJeff Kirsher 	obj->rdata = rdata;
5676adfc5217SJeff Kirsher 	obj->rdata_mapping = rdata_mapping;
5677adfc5217SJeff Kirsher 	obj->type = type;
5678adfc5217SJeff Kirsher 	obj->next_state = BNX2X_Q_STATE_MAX;
5679adfc5217SJeff Kirsher 
5680adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp))
5681adfc5217SJeff Kirsher 		obj->send_cmd = bnx2x_queue_send_cmd_e1x;
5682adfc5217SJeff Kirsher 	else
5683adfc5217SJeff Kirsher 		obj->send_cmd = bnx2x_queue_send_cmd_e2;
5684adfc5217SJeff Kirsher 
5685adfc5217SJeff Kirsher 	obj->check_transition = bnx2x_queue_chk_transition;
5686adfc5217SJeff Kirsher 
5687adfc5217SJeff Kirsher 	obj->complete_cmd = bnx2x_queue_comp_cmd;
5688adfc5217SJeff Kirsher 	obj->wait_comp = bnx2x_queue_wait_comp;
5689adfc5217SJeff Kirsher 	obj->set_pending = bnx2x_queue_set_pending;
5690adfc5217SJeff Kirsher }
5691adfc5217SJeff Kirsher 
569267c431a5SAriel Elior /* return a queue object's logical state*/
bnx2x_get_q_logical_state(struct bnx2x * bp,struct bnx2x_queue_sp_obj * obj)569367c431a5SAriel Elior int bnx2x_get_q_logical_state(struct bnx2x *bp,
569467c431a5SAriel Elior 			       struct bnx2x_queue_sp_obj *obj)
569567c431a5SAriel Elior {
569667c431a5SAriel Elior 	switch (obj->state) {
569767c431a5SAriel Elior 	case BNX2X_Q_STATE_ACTIVE:
569867c431a5SAriel Elior 	case BNX2X_Q_STATE_MULTI_COS:
569967c431a5SAriel Elior 		return BNX2X_Q_LOGICAL_STATE_ACTIVE;
570067c431a5SAriel Elior 	case BNX2X_Q_STATE_RESET:
570167c431a5SAriel Elior 	case BNX2X_Q_STATE_INITIALIZED:
570267c431a5SAriel Elior 	case BNX2X_Q_STATE_MCOS_TERMINATED:
570367c431a5SAriel Elior 	case BNX2X_Q_STATE_INACTIVE:
570467c431a5SAriel Elior 	case BNX2X_Q_STATE_STOPPED:
570567c431a5SAriel Elior 	case BNX2X_Q_STATE_TERMINATED:
570667c431a5SAriel Elior 	case BNX2X_Q_STATE_FLRED:
570767c431a5SAriel Elior 		return BNX2X_Q_LOGICAL_STATE_STOPPED;
570867c431a5SAriel Elior 	default:
570967c431a5SAriel Elior 		return -EINVAL;
571067c431a5SAriel Elior 	}
571167c431a5SAriel Elior }
571267c431a5SAriel Elior 
5713adfc5217SJeff Kirsher /********************** Function state object *********************************/
bnx2x_func_get_state(struct bnx2x * bp,struct bnx2x_func_sp_obj * o)5714adfc5217SJeff Kirsher enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
5715adfc5217SJeff Kirsher 					   struct bnx2x_func_sp_obj *o)
5716adfc5217SJeff Kirsher {
5717adfc5217SJeff Kirsher 	/* in the middle of transaction - return INVALID state */
5718adfc5217SJeff Kirsher 	if (o->pending)
5719adfc5217SJeff Kirsher 		return BNX2X_F_STATE_MAX;
5720adfc5217SJeff Kirsher 
572116a5fd92SYuval Mintz 	/* unsure the order of reading of o->pending and o->state
5722adfc5217SJeff Kirsher 	 * o->pending should be read first
5723adfc5217SJeff Kirsher 	 */
5724adfc5217SJeff Kirsher 	rmb();
5725adfc5217SJeff Kirsher 
5726adfc5217SJeff Kirsher 	return o->state;
5727adfc5217SJeff Kirsher }
5728adfc5217SJeff Kirsher 
bnx2x_func_wait_comp(struct bnx2x * bp,struct bnx2x_func_sp_obj * o,enum bnx2x_func_cmd cmd)5729adfc5217SJeff Kirsher static int bnx2x_func_wait_comp(struct bnx2x *bp,
5730adfc5217SJeff Kirsher 				struct bnx2x_func_sp_obj *o,
5731adfc5217SJeff Kirsher 				enum bnx2x_func_cmd cmd)
5732adfc5217SJeff Kirsher {
5733adfc5217SJeff Kirsher 	return bnx2x_state_wait(bp, cmd, &o->pending);
5734adfc5217SJeff Kirsher }
5735adfc5217SJeff Kirsher 
5736adfc5217SJeff Kirsher /**
5737adfc5217SJeff Kirsher  * bnx2x_func_state_change_comp - complete the state machine transition
5738adfc5217SJeff Kirsher  *
5739adfc5217SJeff Kirsher  * @bp:		device handle
5740d0ea5cbdSJesse Brandeburg  * @o:		function info
5741d0ea5cbdSJesse Brandeburg  * @cmd:	more info
5742adfc5217SJeff Kirsher  *
5743adfc5217SJeff Kirsher  * Called on state change transition. Completes the state
5744adfc5217SJeff Kirsher  * machine transition only - no HW interaction.
5745adfc5217SJeff Kirsher  */
bnx2x_func_state_change_comp(struct bnx2x * bp,struct bnx2x_func_sp_obj * o,enum bnx2x_func_cmd cmd)5746adfc5217SJeff Kirsher static inline int bnx2x_func_state_change_comp(struct bnx2x *bp,
5747adfc5217SJeff Kirsher 					       struct bnx2x_func_sp_obj *o,
5748adfc5217SJeff Kirsher 					       enum bnx2x_func_cmd cmd)
5749adfc5217SJeff Kirsher {
5750adfc5217SJeff Kirsher 	unsigned long cur_pending = o->pending;
5751adfc5217SJeff Kirsher 
5752adfc5217SJeff Kirsher 	if (!test_and_clear_bit(cmd, &cur_pending)) {
575351c1a580SMerav Sicron 		BNX2X_ERR("Bad MC reply %d for func %d in state %d pending 0x%lx, next_state %d\n",
575451c1a580SMerav Sicron 			  cmd, BP_FUNC(bp), o->state,
575551c1a580SMerav Sicron 			  cur_pending, o->next_state);
5756adfc5217SJeff Kirsher 		return -EINVAL;
5757adfc5217SJeff Kirsher 	}
5758adfc5217SJeff Kirsher 
575994f05b0fSJoe Perches 	DP(BNX2X_MSG_SP,
576094f05b0fSJoe Perches 	   "Completing command %d for func %d, setting state to %d\n",
576194f05b0fSJoe Perches 	   cmd, BP_FUNC(bp), o->next_state);
5762adfc5217SJeff Kirsher 
5763adfc5217SJeff Kirsher 	o->state = o->next_state;
5764adfc5217SJeff Kirsher 	o->next_state = BNX2X_F_STATE_MAX;
5765adfc5217SJeff Kirsher 
5766adfc5217SJeff Kirsher 	/* It's important that o->state and o->next_state are
5767adfc5217SJeff Kirsher 	 * updated before o->pending.
5768adfc5217SJeff Kirsher 	 */
5769adfc5217SJeff Kirsher 	wmb();
5770adfc5217SJeff Kirsher 
5771adfc5217SJeff Kirsher 	clear_bit(cmd, &o->pending);
57724e857c58SPeter Zijlstra 	smp_mb__after_atomic();
5773adfc5217SJeff Kirsher 
5774adfc5217SJeff Kirsher 	return 0;
5775adfc5217SJeff Kirsher }
5776adfc5217SJeff Kirsher 
5777adfc5217SJeff Kirsher /**
5778adfc5217SJeff Kirsher  * bnx2x_func_comp_cmd - complete the state change command
5779adfc5217SJeff Kirsher  *
5780adfc5217SJeff Kirsher  * @bp:		device handle
5781d0ea5cbdSJesse Brandeburg  * @o:		function info
5782d0ea5cbdSJesse Brandeburg  * @cmd:	more info
5783adfc5217SJeff Kirsher  *
5784adfc5217SJeff Kirsher  * Checks that the arrived completion is expected.
5785adfc5217SJeff Kirsher  */
bnx2x_func_comp_cmd(struct bnx2x * bp,struct bnx2x_func_sp_obj * o,enum bnx2x_func_cmd cmd)5786adfc5217SJeff Kirsher static int bnx2x_func_comp_cmd(struct bnx2x *bp,
5787adfc5217SJeff Kirsher 			       struct bnx2x_func_sp_obj *o,
5788adfc5217SJeff Kirsher 			       enum bnx2x_func_cmd cmd)
5789adfc5217SJeff Kirsher {
5790adfc5217SJeff Kirsher 	/* Complete the state machine part first, check if it's a
5791adfc5217SJeff Kirsher 	 * legal completion.
5792adfc5217SJeff Kirsher 	 */
5793adfc5217SJeff Kirsher 	int rc = bnx2x_func_state_change_comp(bp, o, cmd);
5794adfc5217SJeff Kirsher 	return rc;
5795adfc5217SJeff Kirsher }
5796adfc5217SJeff Kirsher 
5797adfc5217SJeff Kirsher /**
5798adfc5217SJeff Kirsher  * bnx2x_func_chk_transition - perform function state machine transition
5799adfc5217SJeff Kirsher  *
5800adfc5217SJeff Kirsher  * @bp:		device handle
5801d0ea5cbdSJesse Brandeburg  * @o:		function info
5802d0ea5cbdSJesse Brandeburg  * @params:	state parameters
5803adfc5217SJeff Kirsher  *
5804adfc5217SJeff Kirsher  * It both checks if the requested command is legal in a current
5805adfc5217SJeff Kirsher  * state and, if it's legal, sets a `next_state' in the object
5806adfc5217SJeff Kirsher  * that will be used in the completion flow to set the `state'
5807adfc5217SJeff Kirsher  * of the object.
5808adfc5217SJeff Kirsher  *
5809adfc5217SJeff Kirsher  * returns 0 if a requested command is a legal transition,
5810adfc5217SJeff Kirsher  *         -EINVAL otherwise.
5811adfc5217SJeff Kirsher  */
bnx2x_func_chk_transition(struct bnx2x * bp,struct bnx2x_func_sp_obj * o,struct bnx2x_func_state_params * params)5812adfc5217SJeff Kirsher static int bnx2x_func_chk_transition(struct bnx2x *bp,
5813adfc5217SJeff Kirsher 				     struct bnx2x_func_sp_obj *o,
5814adfc5217SJeff Kirsher 				     struct bnx2x_func_state_params *params)
5815adfc5217SJeff Kirsher {
5816adfc5217SJeff Kirsher 	enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
5817adfc5217SJeff Kirsher 	enum bnx2x_func_cmd cmd = params->cmd;
5818adfc5217SJeff Kirsher 
581916a5fd92SYuval Mintz 	/* Forget all pending for completion commands if a driver only state
5820adfc5217SJeff Kirsher 	 * transition has been requested.
5821adfc5217SJeff Kirsher 	 */
5822adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
5823adfc5217SJeff Kirsher 		o->pending = 0;
5824adfc5217SJeff Kirsher 		o->next_state = BNX2X_F_STATE_MAX;
5825adfc5217SJeff Kirsher 	}
5826adfc5217SJeff Kirsher 
582716a5fd92SYuval Mintz 	/* Don't allow a next state transition if we are in the middle of
5828adfc5217SJeff Kirsher 	 * the previous one.
5829adfc5217SJeff Kirsher 	 */
5830adfc5217SJeff Kirsher 	if (o->pending)
5831adfc5217SJeff Kirsher 		return -EBUSY;
5832adfc5217SJeff Kirsher 
5833adfc5217SJeff Kirsher 	switch (state) {
5834adfc5217SJeff Kirsher 	case BNX2X_F_STATE_RESET:
5835adfc5217SJeff Kirsher 		if (cmd == BNX2X_F_CMD_HW_INIT)
5836adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_INITIALIZED;
5837adfc5217SJeff Kirsher 
5838adfc5217SJeff Kirsher 		break;
5839adfc5217SJeff Kirsher 	case BNX2X_F_STATE_INITIALIZED:
5840adfc5217SJeff Kirsher 		if (cmd == BNX2X_F_CMD_START)
5841adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_STARTED;
5842adfc5217SJeff Kirsher 
5843adfc5217SJeff Kirsher 		else if (cmd == BNX2X_F_CMD_HW_RESET)
5844adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_RESET;
5845adfc5217SJeff Kirsher 
5846adfc5217SJeff Kirsher 		break;
5847adfc5217SJeff Kirsher 	case BNX2X_F_STATE_STARTED:
5848adfc5217SJeff Kirsher 		if (cmd == BNX2X_F_CMD_STOP)
5849adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_INITIALIZED;
5850a3348722SBarak Witkowski 		/* afex ramrods can be sent only in started mode, and only
5851a3348722SBarak Witkowski 		 * if not pending for function_stop ramrod completion
5852a3348722SBarak Witkowski 		 * for these events - next state remained STARTED.
5853a3348722SBarak Witkowski 		 */
5854a3348722SBarak Witkowski 		else if ((cmd == BNX2X_F_CMD_AFEX_UPDATE) &&
5855a3348722SBarak Witkowski 			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
5856a3348722SBarak Witkowski 			next_state = BNX2X_F_STATE_STARTED;
5857a3348722SBarak Witkowski 
5858a3348722SBarak Witkowski 		else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) &&
5859a3348722SBarak Witkowski 			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
5860a3348722SBarak Witkowski 			next_state = BNX2X_F_STATE_STARTED;
586155c11941SMerav Sicron 
586255c11941SMerav Sicron 		/* Switch_update ramrod can be sent in either started or
586355c11941SMerav Sicron 		 * tx_stopped state, and it doesn't change the state.
586455c11941SMerav Sicron 		 */
586555c11941SMerav Sicron 		else if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
586655c11941SMerav Sicron 			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
586755c11941SMerav Sicron 			next_state = BNX2X_F_STATE_STARTED;
586855c11941SMerav Sicron 
5869eeed018cSMichal Kalderon 		else if ((cmd == BNX2X_F_CMD_SET_TIMESYNC) &&
5870eeed018cSMichal Kalderon 			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
5871eeed018cSMichal Kalderon 			next_state = BNX2X_F_STATE_STARTED;
5872eeed018cSMichal Kalderon 
5873adfc5217SJeff Kirsher 		else if (cmd == BNX2X_F_CMD_TX_STOP)
5874adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_TX_STOPPED;
5875adfc5217SJeff Kirsher 
5876adfc5217SJeff Kirsher 		break;
5877adfc5217SJeff Kirsher 	case BNX2X_F_STATE_TX_STOPPED:
587855c11941SMerav Sicron 		if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
587955c11941SMerav Sicron 		    (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
588055c11941SMerav Sicron 			next_state = BNX2X_F_STATE_TX_STOPPED;
588155c11941SMerav Sicron 
5882eeed018cSMichal Kalderon 		else if ((cmd == BNX2X_F_CMD_SET_TIMESYNC) &&
5883eeed018cSMichal Kalderon 			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
5884eeed018cSMichal Kalderon 			next_state = BNX2X_F_STATE_TX_STOPPED;
5885eeed018cSMichal Kalderon 
588655c11941SMerav Sicron 		else if (cmd == BNX2X_F_CMD_TX_START)
5887adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_STARTED;
5888adfc5217SJeff Kirsher 
5889adfc5217SJeff Kirsher 		break;
5890adfc5217SJeff Kirsher 	default:
5891adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown state: %d\n", state);
5892adfc5217SJeff Kirsher 	}
5893adfc5217SJeff Kirsher 
5894adfc5217SJeff Kirsher 	/* Transition is assured */
5895adfc5217SJeff Kirsher 	if (next_state != BNX2X_F_STATE_MAX) {
5896adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Good function state transition: %d(%d)->%d\n",
5897adfc5217SJeff Kirsher 				 state, cmd, next_state);
5898adfc5217SJeff Kirsher 		o->next_state = next_state;
5899adfc5217SJeff Kirsher 		return 0;
5900adfc5217SJeff Kirsher 	}
5901adfc5217SJeff Kirsher 
5902adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Bad function state transition request: %d %d\n",
5903adfc5217SJeff Kirsher 			 state, cmd);
5904adfc5217SJeff Kirsher 
5905adfc5217SJeff Kirsher 	return -EINVAL;
5906adfc5217SJeff Kirsher }
5907adfc5217SJeff Kirsher 
5908adfc5217SJeff Kirsher /**
5909adfc5217SJeff Kirsher  * bnx2x_func_init_func - performs HW init at function stage
5910adfc5217SJeff Kirsher  *
5911adfc5217SJeff Kirsher  * @bp:		device handle
5912adfc5217SJeff Kirsher  * @drv:
5913adfc5217SJeff Kirsher  *
5914adfc5217SJeff Kirsher  * Init HW when the current phase is
5915adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only
5916adfc5217SJeff Kirsher  * HW blocks.
5917adfc5217SJeff Kirsher  */
bnx2x_func_init_func(struct bnx2x * bp,const struct bnx2x_func_sp_drv_ops * drv)5918adfc5217SJeff Kirsher static inline int bnx2x_func_init_func(struct bnx2x *bp,
5919adfc5217SJeff Kirsher 				       const struct bnx2x_func_sp_drv_ops *drv)
5920adfc5217SJeff Kirsher {
5921adfc5217SJeff Kirsher 	return drv->init_hw_func(bp);
5922adfc5217SJeff Kirsher }
5923adfc5217SJeff Kirsher 
5924adfc5217SJeff Kirsher /**
5925adfc5217SJeff Kirsher  * bnx2x_func_init_port - performs HW init at port stage
5926adfc5217SJeff Kirsher  *
5927adfc5217SJeff Kirsher  * @bp:		device handle
5928adfc5217SJeff Kirsher  * @drv:
5929adfc5217SJeff Kirsher  *
5930adfc5217SJeff Kirsher  * Init HW when the current phase is
5931adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and
5932adfc5217SJeff Kirsher  * FUNCTION-only HW blocks.
5933adfc5217SJeff Kirsher  *
5934adfc5217SJeff Kirsher  */
bnx2x_func_init_port(struct bnx2x * bp,const struct bnx2x_func_sp_drv_ops * drv)5935adfc5217SJeff Kirsher static inline int bnx2x_func_init_port(struct bnx2x *bp,
5936adfc5217SJeff Kirsher 				       const struct bnx2x_func_sp_drv_ops *drv)
5937adfc5217SJeff Kirsher {
5938adfc5217SJeff Kirsher 	int rc = drv->init_hw_port(bp);
5939adfc5217SJeff Kirsher 	if (rc)
5940adfc5217SJeff Kirsher 		return rc;
5941adfc5217SJeff Kirsher 
5942adfc5217SJeff Kirsher 	return bnx2x_func_init_func(bp, drv);
5943adfc5217SJeff Kirsher }
5944adfc5217SJeff Kirsher 
5945adfc5217SJeff Kirsher /**
5946adfc5217SJeff Kirsher  * bnx2x_func_init_cmn_chip - performs HW init at chip-common stage
5947adfc5217SJeff Kirsher  *
5948adfc5217SJeff Kirsher  * @bp:		device handle
5949adfc5217SJeff Kirsher  * @drv:
5950adfc5217SJeff Kirsher  *
5951adfc5217SJeff Kirsher  * Init HW when the current phase is
5952adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP,
5953adfc5217SJeff Kirsher  * PORT-only and FUNCTION-only HW blocks.
5954adfc5217SJeff Kirsher  */
bnx2x_func_init_cmn_chip(struct bnx2x * bp,const struct bnx2x_func_sp_drv_ops * drv)5955adfc5217SJeff Kirsher static inline int bnx2x_func_init_cmn_chip(struct bnx2x *bp,
5956adfc5217SJeff Kirsher 					const struct bnx2x_func_sp_drv_ops *drv)
5957adfc5217SJeff Kirsher {
5958adfc5217SJeff Kirsher 	int rc = drv->init_hw_cmn_chip(bp);
5959adfc5217SJeff Kirsher 	if (rc)
5960adfc5217SJeff Kirsher 		return rc;
5961adfc5217SJeff Kirsher 
5962adfc5217SJeff Kirsher 	return bnx2x_func_init_port(bp, drv);
5963adfc5217SJeff Kirsher }
5964adfc5217SJeff Kirsher 
5965adfc5217SJeff Kirsher /**
5966adfc5217SJeff Kirsher  * bnx2x_func_init_cmn - performs HW init at common stage
5967adfc5217SJeff Kirsher  *
5968adfc5217SJeff Kirsher  * @bp:		device handle
5969adfc5217SJeff Kirsher  * @drv:
5970adfc5217SJeff Kirsher  *
5971adfc5217SJeff Kirsher  * Init HW when the current phase is
5972adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON,
5973adfc5217SJeff Kirsher  * PORT-only and FUNCTION-only HW blocks.
5974adfc5217SJeff Kirsher  */
bnx2x_func_init_cmn(struct bnx2x * bp,const struct bnx2x_func_sp_drv_ops * drv)5975adfc5217SJeff Kirsher static inline int bnx2x_func_init_cmn(struct bnx2x *bp,
5976adfc5217SJeff Kirsher 				      const struct bnx2x_func_sp_drv_ops *drv)
5977adfc5217SJeff Kirsher {
5978adfc5217SJeff Kirsher 	int rc = drv->init_hw_cmn(bp);
5979adfc5217SJeff Kirsher 	if (rc)
5980adfc5217SJeff Kirsher 		return rc;
5981adfc5217SJeff Kirsher 
5982adfc5217SJeff Kirsher 	return bnx2x_func_init_port(bp, drv);
5983adfc5217SJeff Kirsher }
5984adfc5217SJeff Kirsher 
bnx2x_func_hw_init(struct bnx2x * bp,struct bnx2x_func_state_params * params)5985adfc5217SJeff Kirsher static int bnx2x_func_hw_init(struct bnx2x *bp,
5986adfc5217SJeff Kirsher 			      struct bnx2x_func_state_params *params)
5987adfc5217SJeff Kirsher {
5988adfc5217SJeff Kirsher 	u32 load_code = params->params.hw_init.load_phase;
5989adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
5990adfc5217SJeff Kirsher 	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
5991adfc5217SJeff Kirsher 	int rc = 0;
5992adfc5217SJeff Kirsher 
5993adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "function %d  load_code %x\n",
5994adfc5217SJeff Kirsher 			 BP_ABS_FUNC(bp), load_code);
5995adfc5217SJeff Kirsher 
5996adfc5217SJeff Kirsher 	/* Prepare buffers for unzipping the FW */
5997adfc5217SJeff Kirsher 	rc = drv->gunzip_init(bp);
5998adfc5217SJeff Kirsher 	if (rc)
5999adfc5217SJeff Kirsher 		return rc;
6000adfc5217SJeff Kirsher 
6001adfc5217SJeff Kirsher 	/* Prepare FW */
6002adfc5217SJeff Kirsher 	rc = drv->init_fw(bp);
6003adfc5217SJeff Kirsher 	if (rc) {
6004adfc5217SJeff Kirsher 		BNX2X_ERR("Error loading firmware\n");
6005eb2afd4aSDmitry Kravkov 		goto init_err;
6006adfc5217SJeff Kirsher 	}
6007adfc5217SJeff Kirsher 
600816a5fd92SYuval Mintz 	/* Handle the beginning of COMMON_XXX pases separately... */
6009adfc5217SJeff Kirsher 	switch (load_code) {
6010adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
6011adfc5217SJeff Kirsher 		rc = bnx2x_func_init_cmn_chip(bp, drv);
6012adfc5217SJeff Kirsher 		if (rc)
6013eb2afd4aSDmitry Kravkov 			goto init_err;
6014adfc5217SJeff Kirsher 
6015adfc5217SJeff Kirsher 		break;
6016adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_LOAD_COMMON:
6017adfc5217SJeff Kirsher 		rc = bnx2x_func_init_cmn(bp, drv);
6018adfc5217SJeff Kirsher 		if (rc)
6019eb2afd4aSDmitry Kravkov 			goto init_err;
6020adfc5217SJeff Kirsher 
6021adfc5217SJeff Kirsher 		break;
6022adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_LOAD_PORT:
6023adfc5217SJeff Kirsher 		rc = bnx2x_func_init_port(bp, drv);
6024adfc5217SJeff Kirsher 		if (rc)
6025eb2afd4aSDmitry Kravkov 			goto init_err;
6026adfc5217SJeff Kirsher 
6027adfc5217SJeff Kirsher 		break;
6028adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
6029adfc5217SJeff Kirsher 		rc = bnx2x_func_init_func(bp, drv);
6030adfc5217SJeff Kirsher 		if (rc)
6031eb2afd4aSDmitry Kravkov 			goto init_err;
6032adfc5217SJeff Kirsher 
6033adfc5217SJeff Kirsher 		break;
6034adfc5217SJeff Kirsher 	default:
6035adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
6036adfc5217SJeff Kirsher 		rc = -EINVAL;
6037adfc5217SJeff Kirsher 	}
6038adfc5217SJeff Kirsher 
6039eb2afd4aSDmitry Kravkov init_err:
6040adfc5217SJeff Kirsher 	drv->gunzip_end(bp);
6041adfc5217SJeff Kirsher 
604216a5fd92SYuval Mintz 	/* In case of success, complete the command immediately: no ramrods
6043adfc5217SJeff Kirsher 	 * have been sent.
6044adfc5217SJeff Kirsher 	 */
6045adfc5217SJeff Kirsher 	if (!rc)
6046adfc5217SJeff Kirsher 		o->complete_cmd(bp, o, BNX2X_F_CMD_HW_INIT);
6047adfc5217SJeff Kirsher 
6048adfc5217SJeff Kirsher 	return rc;
6049adfc5217SJeff Kirsher }
6050adfc5217SJeff Kirsher 
6051adfc5217SJeff Kirsher /**
6052adfc5217SJeff Kirsher  * bnx2x_func_reset_func - reset HW at function stage
6053adfc5217SJeff Kirsher  *
6054adfc5217SJeff Kirsher  * @bp:		device handle
6055adfc5217SJeff Kirsher  * @drv:
6056adfc5217SJeff Kirsher  *
6057adfc5217SJeff Kirsher  * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only
6058adfc5217SJeff Kirsher  * FUNCTION-only HW blocks.
6059adfc5217SJeff Kirsher  */
bnx2x_func_reset_func(struct bnx2x * bp,const struct bnx2x_func_sp_drv_ops * drv)6060adfc5217SJeff Kirsher static inline void bnx2x_func_reset_func(struct bnx2x *bp,
6061adfc5217SJeff Kirsher 					const struct bnx2x_func_sp_drv_ops *drv)
6062adfc5217SJeff Kirsher {
6063adfc5217SJeff Kirsher 	drv->reset_hw_func(bp);
6064adfc5217SJeff Kirsher }
6065adfc5217SJeff Kirsher 
6066adfc5217SJeff Kirsher /**
606716a5fd92SYuval Mintz  * bnx2x_func_reset_port - reset HW at port stage
6068adfc5217SJeff Kirsher  *
6069adfc5217SJeff Kirsher  * @bp:		device handle
6070adfc5217SJeff Kirsher  * @drv:
6071adfc5217SJeff Kirsher  *
6072adfc5217SJeff Kirsher  * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset
6073adfc5217SJeff Kirsher  * FUNCTION-only and PORT-only HW blocks.
6074adfc5217SJeff Kirsher  *
6075adfc5217SJeff Kirsher  *                 !!!IMPORTANT!!!
6076adfc5217SJeff Kirsher  *
6077adfc5217SJeff Kirsher  * It's important to call reset_port before reset_func() as the last thing
6078adfc5217SJeff Kirsher  * reset_func does is pf_disable() thus disabling PGLUE_B, which
6079adfc5217SJeff Kirsher  * makes impossible any DMAE transactions.
6080adfc5217SJeff Kirsher  */
bnx2x_func_reset_port(struct bnx2x * bp,const struct bnx2x_func_sp_drv_ops * drv)6081adfc5217SJeff Kirsher static inline void bnx2x_func_reset_port(struct bnx2x *bp,
6082adfc5217SJeff Kirsher 					const struct bnx2x_func_sp_drv_ops *drv)
6083adfc5217SJeff Kirsher {
6084adfc5217SJeff Kirsher 	drv->reset_hw_port(bp);
6085adfc5217SJeff Kirsher 	bnx2x_func_reset_func(bp, drv);
6086adfc5217SJeff Kirsher }
6087adfc5217SJeff Kirsher 
6088adfc5217SJeff Kirsher /**
608916a5fd92SYuval Mintz  * bnx2x_func_reset_cmn - reset HW at common stage
6090adfc5217SJeff Kirsher  *
6091adfc5217SJeff Kirsher  * @bp:		device handle
6092adfc5217SJeff Kirsher  * @drv:
6093adfc5217SJeff Kirsher  *
6094adfc5217SJeff Kirsher  * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and
6095adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON,
6096adfc5217SJeff Kirsher  * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks.
6097adfc5217SJeff Kirsher  */
bnx2x_func_reset_cmn(struct bnx2x * bp,const struct bnx2x_func_sp_drv_ops * drv)6098adfc5217SJeff Kirsher static inline void bnx2x_func_reset_cmn(struct bnx2x *bp,
6099adfc5217SJeff Kirsher 					const struct bnx2x_func_sp_drv_ops *drv)
6100adfc5217SJeff Kirsher {
6101adfc5217SJeff Kirsher 	bnx2x_func_reset_port(bp, drv);
6102adfc5217SJeff Kirsher 	drv->reset_hw_cmn(bp);
6103adfc5217SJeff Kirsher }
6104adfc5217SJeff Kirsher 
bnx2x_func_hw_reset(struct bnx2x * bp,struct bnx2x_func_state_params * params)6105adfc5217SJeff Kirsher static inline int bnx2x_func_hw_reset(struct bnx2x *bp,
6106adfc5217SJeff Kirsher 				      struct bnx2x_func_state_params *params)
6107adfc5217SJeff Kirsher {
6108adfc5217SJeff Kirsher 	u32 reset_phase = params->params.hw_reset.reset_phase;
6109adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
6110adfc5217SJeff Kirsher 	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
6111adfc5217SJeff Kirsher 
6112adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "function %d  reset_phase %x\n", BP_ABS_FUNC(bp),
6113adfc5217SJeff Kirsher 			 reset_phase);
6114adfc5217SJeff Kirsher 
6115adfc5217SJeff Kirsher 	switch (reset_phase) {
6116adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_UNLOAD_COMMON:
6117adfc5217SJeff Kirsher 		bnx2x_func_reset_cmn(bp, drv);
6118adfc5217SJeff Kirsher 		break;
6119adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_UNLOAD_PORT:
6120adfc5217SJeff Kirsher 		bnx2x_func_reset_port(bp, drv);
6121adfc5217SJeff Kirsher 		break;
6122adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
6123adfc5217SJeff Kirsher 		bnx2x_func_reset_func(bp, drv);
6124adfc5217SJeff Kirsher 		break;
6125adfc5217SJeff Kirsher 	default:
6126adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown reset_phase (0x%x) from MCP\n",
6127adfc5217SJeff Kirsher 			   reset_phase);
6128adfc5217SJeff Kirsher 		break;
6129adfc5217SJeff Kirsher 	}
6130adfc5217SJeff Kirsher 
613116a5fd92SYuval Mintz 	/* Complete the command immediately: no ramrods have been sent. */
6132adfc5217SJeff Kirsher 	o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET);
6133adfc5217SJeff Kirsher 
6134adfc5217SJeff Kirsher 	return 0;
6135adfc5217SJeff Kirsher }
6136adfc5217SJeff Kirsher 
bnx2x_func_send_start(struct bnx2x * bp,struct bnx2x_func_state_params * params)6137adfc5217SJeff Kirsher static inline int bnx2x_func_send_start(struct bnx2x *bp,
6138adfc5217SJeff Kirsher 					struct bnx2x_func_state_params *params)
6139adfc5217SJeff Kirsher {
6140adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
6141adfc5217SJeff Kirsher 	struct function_start_data *rdata =
6142adfc5217SJeff Kirsher 		(struct function_start_data *)o->rdata;
6143adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
6144adfc5217SJeff Kirsher 	struct bnx2x_func_start_params *start_params = &params->params.start;
6145adfc5217SJeff Kirsher 
6146adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
6147adfc5217SJeff Kirsher 
6148adfc5217SJeff Kirsher 	/* Fill the ramrod data with provided parameters */
614996bed4b9SYuval Mintz 	rdata->function_mode	= (u8)start_params->mf_mode;
6150ab4a7139SAriel Elior 	rdata->sd_vlan_tag	= cpu_to_le16(start_params->sd_vlan_tag);
6151adfc5217SJeff Kirsher 	rdata->path_id		= BP_PATH(bp);
6152adfc5217SJeff Kirsher 	rdata->network_cos_mode	= start_params->network_cos_mode;
615377e461d1SSudarsana Reddy Kalluru 	rdata->dmae_cmd_id	= BNX2X_FW_DMAE_C;
615428311f8eSYuval Mintz 
615528311f8eSYuval Mintz 	rdata->vxlan_dst_port	= cpu_to_le16(start_params->vxlan_dst_port);
615628311f8eSYuval Mintz 	rdata->geneve_dst_port	= cpu_to_le16(start_params->geneve_dst_port);
615728311f8eSYuval Mintz 	rdata->inner_clss_l2gre	= start_params->inner_clss_l2gre;
615828311f8eSYuval Mintz 	rdata->inner_clss_l2geneve = start_params->inner_clss_l2geneve;
615928311f8eSYuval Mintz 	rdata->inner_clss_vxlan	= start_params->inner_clss_vxlan;
616028311f8eSYuval Mintz 	rdata->inner_rss	= start_params->inner_rss;
616128311f8eSYuval Mintz 
61627609647eSYuval Mintz 	rdata->sd_accept_mf_clss_fail = start_params->class_fail;
61637609647eSYuval Mintz 	if (start_params->class_fail_ethtype) {
61647609647eSYuval Mintz 		rdata->sd_accept_mf_clss_fail_match_ethtype = 1;
61657609647eSYuval Mintz 		rdata->sd_accept_mf_clss_fail_ethtype =
61667609647eSYuval Mintz 			cpu_to_le16(start_params->class_fail_ethtype);
61677609647eSYuval Mintz 	}
6168adfc5217SJeff Kirsher 
61697609647eSYuval Mintz 	rdata->sd_vlan_force_pri_flg = start_params->sd_vlan_force_pri;
61707609647eSYuval Mintz 	rdata->sd_vlan_force_pri_val = start_params->sd_vlan_force_pri_val;
61717609647eSYuval Mintz 	if (start_params->sd_vlan_eth_type)
61727609647eSYuval Mintz 		rdata->sd_vlan_eth_type =
61737609647eSYuval Mintz 			cpu_to_le16(start_params->sd_vlan_eth_type);
61747609647eSYuval Mintz 	else
61757609647eSYuval Mintz 		rdata->sd_vlan_eth_type =
61767609647eSYuval Mintz 			cpu_to_le16(0x8100);
61777609647eSYuval Mintz 
61787609647eSYuval Mintz 	rdata->no_added_tags = start_params->no_added_tags;
617928311f8eSYuval Mintz 
618028311f8eSYuval Mintz 	rdata->c2s_pri_tt_valid = start_params->c2s_pri_valid;
618128311f8eSYuval Mintz 	if (rdata->c2s_pri_tt_valid) {
618228311f8eSYuval Mintz 		memcpy(rdata->c2s_pri_trans_table.val,
618328311f8eSYuval Mintz 		       start_params->c2s_pri,
618428311f8eSYuval Mintz 		       MAX_VLAN_PRIORITIES);
618528311f8eSYuval Mintz 		rdata->c2s_pri_default = start_params->c2s_pri_default;
618628311f8eSYuval Mintz 	}
61871bc277f7SDmitry Kravkov 	/* No need for an explicit memory barrier here as long we would
6188adfc5217SJeff Kirsher 	 * need to ensure the ordering of writing to the SPQ element
6189adfc5217SJeff Kirsher 	 * and updating of the SPQ producer which involves a memory
6190adfc5217SJeff Kirsher 	 * read and we will have to put a full memory barrier there
6191adfc5217SJeff Kirsher 	 * (inside bnx2x_sp_post()).
6192adfc5217SJeff Kirsher 	 */
6193adfc5217SJeff Kirsher 
6194adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0,
6195adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
6196adfc5217SJeff Kirsher 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
6197adfc5217SJeff Kirsher }
6198adfc5217SJeff Kirsher 
bnx2x_func_send_switch_update(struct bnx2x * bp,struct bnx2x_func_state_params * params)619955c11941SMerav Sicron static inline int bnx2x_func_send_switch_update(struct bnx2x *bp,
620055c11941SMerav Sicron 					struct bnx2x_func_state_params *params)
620155c11941SMerav Sicron {
620255c11941SMerav Sicron 	struct bnx2x_func_sp_obj *o = params->f_obj;
620355c11941SMerav Sicron 	struct function_update_data *rdata =
620455c11941SMerav Sicron 		(struct function_update_data *)o->rdata;
620555c11941SMerav Sicron 	dma_addr_t data_mapping = o->rdata_mapping;
620655c11941SMerav Sicron 	struct bnx2x_func_switch_update_params *switch_update_params =
620755c11941SMerav Sicron 		&params->params.switch_update;
620855c11941SMerav Sicron 
620955c11941SMerav Sicron 	memset(rdata, 0, sizeof(*rdata));
621055c11941SMerav Sicron 
621155c11941SMerav Sicron 	/* Fill the ramrod data with provided parameters */
6212e42780b6SDmitry Kravkov 	if (test_bit(BNX2X_F_UPDATE_TX_SWITCH_SUSPEND_CHNG,
6213e42780b6SDmitry Kravkov 		     &switch_update_params->changes)) {
621455c11941SMerav Sicron 		rdata->tx_switch_suspend_change_flg = 1;
6215e42780b6SDmitry Kravkov 		rdata->tx_switch_suspend =
6216e42780b6SDmitry Kravkov 			test_bit(BNX2X_F_UPDATE_TX_SWITCH_SUSPEND,
6217e42780b6SDmitry Kravkov 				 &switch_update_params->changes);
6218e42780b6SDmitry Kravkov 	}
6219e42780b6SDmitry Kravkov 
62207609647eSYuval Mintz 	if (test_bit(BNX2X_F_UPDATE_SD_VLAN_TAG_CHNG,
62217609647eSYuval Mintz 		     &switch_update_params->changes)) {
62227609647eSYuval Mintz 		rdata->sd_vlan_tag_change_flg = 1;
62237609647eSYuval Mintz 		rdata->sd_vlan_tag =
62247609647eSYuval Mintz 			cpu_to_le16(switch_update_params->vlan);
62257609647eSYuval Mintz 	}
62267609647eSYuval Mintz 
62277609647eSYuval Mintz 	if (test_bit(BNX2X_F_UPDATE_SD_VLAN_ETH_TYPE_CHNG,
62287609647eSYuval Mintz 		     &switch_update_params->changes)) {
62297609647eSYuval Mintz 		rdata->sd_vlan_eth_type_change_flg = 1;
62307609647eSYuval Mintz 		rdata->sd_vlan_eth_type =
62317609647eSYuval Mintz 			cpu_to_le16(switch_update_params->vlan_eth_type);
62327609647eSYuval Mintz 	}
62337609647eSYuval Mintz 
62347609647eSYuval Mintz 	if (test_bit(BNX2X_F_UPDATE_VLAN_FORCE_PRIO_CHNG,
62357609647eSYuval Mintz 		     &switch_update_params->changes)) {
62367609647eSYuval Mintz 		rdata->sd_vlan_force_pri_change_flg = 1;
62377609647eSYuval Mintz 		if (test_bit(BNX2X_F_UPDATE_VLAN_FORCE_PRIO_FLAG,
62387609647eSYuval Mintz 			     &switch_update_params->changes))
62397609647eSYuval Mintz 			rdata->sd_vlan_force_pri_flg = 1;
62407609647eSYuval Mintz 		rdata->sd_vlan_force_pri_flg =
62417609647eSYuval Mintz 			switch_update_params->vlan_force_prio;
62427609647eSYuval Mintz 	}
62437609647eSYuval Mintz 
6244e42780b6SDmitry Kravkov 	if (test_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG,
6245e42780b6SDmitry Kravkov 		     &switch_update_params->changes)) {
6246e42780b6SDmitry Kravkov 		rdata->update_tunn_cfg_flg = 1;
624728311f8eSYuval Mintz 		if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GRE,
6248e42780b6SDmitry Kravkov 			     &switch_update_params->changes))
624928311f8eSYuval Mintz 			rdata->inner_clss_l2gre = 1;
625028311f8eSYuval Mintz 		if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_VXLAN,
6251e42780b6SDmitry Kravkov 			     &switch_update_params->changes))
625228311f8eSYuval Mintz 			rdata->inner_clss_vxlan = 1;
625328311f8eSYuval Mintz 		if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_CLSS_L2GENEVE,
625428311f8eSYuval Mintz 			     &switch_update_params->changes))
625528311f8eSYuval Mintz 			rdata->inner_clss_l2geneve = 1;
625628311f8eSYuval Mintz 		if (test_bit(BNX2X_F_UPDATE_TUNNEL_INNER_RSS,
625728311f8eSYuval Mintz 			     &switch_update_params->changes))
625828311f8eSYuval Mintz 			rdata->inner_rss = 1;
625928311f8eSYuval Mintz 		rdata->vxlan_dst_port =
626028311f8eSYuval Mintz 			cpu_to_le16(switch_update_params->vxlan_dst_port);
626128311f8eSYuval Mintz 		rdata->geneve_dst_port =
626228311f8eSYuval Mintz 			cpu_to_le16(switch_update_params->geneve_dst_port);
6263e42780b6SDmitry Kravkov 	}
6264e42780b6SDmitry Kravkov 
626555c11941SMerav Sicron 	rdata->echo = SWITCH_UPDATE;
626655c11941SMerav Sicron 
626714a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
626814a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
626914a94ebdSMichal Kalderon 	 * and updating of the SPQ producer which involves a memory
627014a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
627114a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
627214a94ebdSMichal Kalderon 	 */
627355c11941SMerav Sicron 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
627455c11941SMerav Sicron 			     U64_HI(data_mapping),
627555c11941SMerav Sicron 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
627655c11941SMerav Sicron }
627755c11941SMerav Sicron 
bnx2x_func_send_afex_update(struct bnx2x * bp,struct bnx2x_func_state_params * params)6278a3348722SBarak Witkowski static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
6279a3348722SBarak Witkowski 					 struct bnx2x_func_state_params *params)
6280a3348722SBarak Witkowski {
6281a3348722SBarak Witkowski 	struct bnx2x_func_sp_obj *o = params->f_obj;
6282a3348722SBarak Witkowski 	struct function_update_data *rdata =
6283a3348722SBarak Witkowski 		(struct function_update_data *)o->afex_rdata;
6284a3348722SBarak Witkowski 	dma_addr_t data_mapping = o->afex_rdata_mapping;
6285a3348722SBarak Witkowski 	struct bnx2x_func_afex_update_params *afex_update_params =
6286a3348722SBarak Witkowski 		&params->params.afex_update;
6287a3348722SBarak Witkowski 
6288a3348722SBarak Witkowski 	memset(rdata, 0, sizeof(*rdata));
6289a3348722SBarak Witkowski 
6290a3348722SBarak Witkowski 	/* Fill the ramrod data with provided parameters */
6291a3348722SBarak Witkowski 	rdata->vif_id_change_flg = 1;
6292a3348722SBarak Witkowski 	rdata->vif_id = cpu_to_le16(afex_update_params->vif_id);
6293a3348722SBarak Witkowski 	rdata->afex_default_vlan_change_flg = 1;
6294a3348722SBarak Witkowski 	rdata->afex_default_vlan =
6295a3348722SBarak Witkowski 		cpu_to_le16(afex_update_params->afex_default_vlan);
6296a3348722SBarak Witkowski 	rdata->allowed_priorities_change_flg = 1;
6297a3348722SBarak Witkowski 	rdata->allowed_priorities = afex_update_params->allowed_priorities;
629855c11941SMerav Sicron 	rdata->echo = AFEX_UPDATE;
6299a3348722SBarak Witkowski 
630014a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
630114a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
6302a3348722SBarak Witkowski 	 * and updating of the SPQ producer which involves a memory
630314a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
630414a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
6305a3348722SBarak Witkowski 	 */
6306a3348722SBarak Witkowski 	DP(BNX2X_MSG_SP,
6307a3348722SBarak Witkowski 	   "afex: sending func_update vif_id 0x%x dvlan 0x%x prio 0x%x\n",
6308a3348722SBarak Witkowski 	   rdata->vif_id,
6309a3348722SBarak Witkowski 	   rdata->afex_default_vlan, rdata->allowed_priorities);
6310a3348722SBarak Witkowski 
6311a3348722SBarak Witkowski 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
6312a3348722SBarak Witkowski 			     U64_HI(data_mapping),
6313a3348722SBarak Witkowski 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
6314a3348722SBarak Witkowski }
6315a3348722SBarak Witkowski 
6316a3348722SBarak Witkowski static
bnx2x_func_send_afex_viflists(struct bnx2x * bp,struct bnx2x_func_state_params * params)6317a3348722SBarak Witkowski inline int bnx2x_func_send_afex_viflists(struct bnx2x *bp,
6318a3348722SBarak Witkowski 					 struct bnx2x_func_state_params *params)
6319a3348722SBarak Witkowski {
6320a3348722SBarak Witkowski 	struct bnx2x_func_sp_obj *o = params->f_obj;
6321a3348722SBarak Witkowski 	struct afex_vif_list_ramrod_data *rdata =
6322a3348722SBarak Witkowski 		(struct afex_vif_list_ramrod_data *)o->afex_rdata;
632386564c3fSYuval Mintz 	struct bnx2x_func_afex_viflists_params *afex_vif_params =
6324a3348722SBarak Witkowski 		&params->params.afex_viflists;
6325a3348722SBarak Witkowski 	u64 *p_rdata = (u64 *)rdata;
6326a3348722SBarak Witkowski 
6327a3348722SBarak Witkowski 	memset(rdata, 0, sizeof(*rdata));
6328a3348722SBarak Witkowski 
6329a3348722SBarak Witkowski 	/* Fill the ramrod data with provided parameters */
633086564c3fSYuval Mintz 	rdata->vif_list_index = cpu_to_le16(afex_vif_params->vif_list_index);
633186564c3fSYuval Mintz 	rdata->func_bit_map          = afex_vif_params->func_bit_map;
633286564c3fSYuval Mintz 	rdata->afex_vif_list_command = afex_vif_params->afex_vif_list_command;
633386564c3fSYuval Mintz 	rdata->func_to_clear         = afex_vif_params->func_to_clear;
6334a3348722SBarak Witkowski 
6335a3348722SBarak Witkowski 	/* send in echo type of sub command */
633686564c3fSYuval Mintz 	rdata->echo = afex_vif_params->afex_vif_list_command;
6337a3348722SBarak Witkowski 
6338a3348722SBarak Witkowski 	/*  No need for an explicit memory barrier here as long we would
6339a3348722SBarak Witkowski 	 *  need to ensure the ordering of writing to the SPQ element
6340a3348722SBarak Witkowski 	 *  and updating of the SPQ producer which involves a memory
6341a3348722SBarak Witkowski 	 *  read and we will have to put a full memory barrier there
6342a3348722SBarak Witkowski 	 *  (inside bnx2x_sp_post()).
6343a3348722SBarak Witkowski 	 */
6344a3348722SBarak Witkowski 
6345a3348722SBarak Witkowski 	DP(BNX2X_MSG_SP, "afex: ramrod lists, cmd 0x%x index 0x%x func_bit_map 0x%x func_to_clr 0x%x\n",
6346a3348722SBarak Witkowski 	   rdata->afex_vif_list_command, rdata->vif_list_index,
6347a3348722SBarak Witkowski 	   rdata->func_bit_map, rdata->func_to_clear);
6348a3348722SBarak Witkowski 
6349a3348722SBarak Witkowski 	/* this ramrod sends data directly and not through DMA mapping */
6350a3348722SBarak Witkowski 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_AFEX_VIF_LISTS, 0,
6351a3348722SBarak Witkowski 			     U64_HI(*p_rdata), U64_LO(*p_rdata),
6352a3348722SBarak Witkowski 			     NONE_CONNECTION_TYPE);
6353a3348722SBarak Witkowski }
6354a3348722SBarak Witkowski 
bnx2x_func_send_stop(struct bnx2x * bp,struct bnx2x_func_state_params * params)6355adfc5217SJeff Kirsher static inline int bnx2x_func_send_stop(struct bnx2x *bp,
6356adfc5217SJeff Kirsher 				       struct bnx2x_func_state_params *params)
6357adfc5217SJeff Kirsher {
6358adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0,
6359adfc5217SJeff Kirsher 			     NONE_CONNECTION_TYPE);
6360adfc5217SJeff Kirsher }
6361adfc5217SJeff Kirsher 
bnx2x_func_send_tx_stop(struct bnx2x * bp,struct bnx2x_func_state_params * params)6362adfc5217SJeff Kirsher static inline int bnx2x_func_send_tx_stop(struct bnx2x *bp,
6363adfc5217SJeff Kirsher 				       struct bnx2x_func_state_params *params)
6364adfc5217SJeff Kirsher {
6365adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0,
6366adfc5217SJeff Kirsher 			     NONE_CONNECTION_TYPE);
6367adfc5217SJeff Kirsher }
bnx2x_func_send_tx_start(struct bnx2x * bp,struct bnx2x_func_state_params * params)6368adfc5217SJeff Kirsher static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
6369adfc5217SJeff Kirsher 				       struct bnx2x_func_state_params *params)
6370adfc5217SJeff Kirsher {
6371adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
6372adfc5217SJeff Kirsher 	struct flow_control_configuration *rdata =
6373adfc5217SJeff Kirsher 		(struct flow_control_configuration *)o->rdata;
6374adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
6375adfc5217SJeff Kirsher 	struct bnx2x_func_tx_start_params *tx_start_params =
6376adfc5217SJeff Kirsher 		&params->params.tx_start;
6377adfc5217SJeff Kirsher 	int i;
6378adfc5217SJeff Kirsher 
6379adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
6380adfc5217SJeff Kirsher 
6381adfc5217SJeff Kirsher 	rdata->dcb_enabled = tx_start_params->dcb_enabled;
6382adfc5217SJeff Kirsher 	rdata->dcb_version = tx_start_params->dcb_version;
6383adfc5217SJeff Kirsher 	rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en;
6384adfc5217SJeff Kirsher 
6385adfc5217SJeff Kirsher 	for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++)
6386adfc5217SJeff Kirsher 		rdata->traffic_type_to_priority_cos[i] =
6387adfc5217SJeff Kirsher 			tx_start_params->traffic_type_to_priority_cos[i];
6388adfc5217SJeff Kirsher 
638928311f8eSYuval Mintz 	for (i = 0; i < MAX_TRAFFIC_TYPES; i++)
639028311f8eSYuval Mintz 		rdata->dcb_outer_pri[i] = tx_start_params->dcb_outer_pri[i];
639114a94ebdSMichal Kalderon 	/* No need for an explicit memory barrier here as long as we
639214a94ebdSMichal Kalderon 	 * ensure the ordering of writing to the SPQ element
639314a94ebdSMichal Kalderon 	 * and updating of the SPQ producer which involves a memory
639414a94ebdSMichal Kalderon 	 * read. If the memory read is removed we will have to put a
639514a94ebdSMichal Kalderon 	 * full memory barrier there (inside bnx2x_sp_post()).
639614a94ebdSMichal Kalderon 	 */
6397adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
6398adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
6399adfc5217SJeff Kirsher 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
6400adfc5217SJeff Kirsher }
6401adfc5217SJeff Kirsher 
6402eeed018cSMichal Kalderon static inline
bnx2x_func_send_set_timesync(struct bnx2x * bp,struct bnx2x_func_state_params * params)6403eeed018cSMichal Kalderon int bnx2x_func_send_set_timesync(struct bnx2x *bp,
6404eeed018cSMichal Kalderon 				 struct bnx2x_func_state_params *params)
6405eeed018cSMichal Kalderon {
6406eeed018cSMichal Kalderon 	struct bnx2x_func_sp_obj *o = params->f_obj;
6407eeed018cSMichal Kalderon 	struct set_timesync_ramrod_data *rdata =
6408eeed018cSMichal Kalderon 		(struct set_timesync_ramrod_data *)o->rdata;
6409eeed018cSMichal Kalderon 	dma_addr_t data_mapping = o->rdata_mapping;
6410eeed018cSMichal Kalderon 	struct bnx2x_func_set_timesync_params *set_timesync_params =
6411eeed018cSMichal Kalderon 		&params->params.set_timesync;
6412eeed018cSMichal Kalderon 
6413eeed018cSMichal Kalderon 	memset(rdata, 0, sizeof(*rdata));
6414eeed018cSMichal Kalderon 
6415eeed018cSMichal Kalderon 	/* Fill the ramrod data with provided parameters */
6416eeed018cSMichal Kalderon 	rdata->drift_adjust_cmd = set_timesync_params->drift_adjust_cmd;
6417eeed018cSMichal Kalderon 	rdata->offset_cmd = set_timesync_params->offset_cmd;
6418eeed018cSMichal Kalderon 	rdata->add_sub_drift_adjust_value =
6419eeed018cSMichal Kalderon 		set_timesync_params->add_sub_drift_adjust_value;
6420eeed018cSMichal Kalderon 	rdata->drift_adjust_value = set_timesync_params->drift_adjust_value;
6421eeed018cSMichal Kalderon 	rdata->drift_adjust_period = set_timesync_params->drift_adjust_period;
64228f15c613SMichal Kalderon 	rdata->offset_delta.lo =
64238f15c613SMichal Kalderon 		cpu_to_le32(U64_LO(set_timesync_params->offset_delta));
64248f15c613SMichal Kalderon 	rdata->offset_delta.hi =
64258f15c613SMichal Kalderon 		cpu_to_le32(U64_HI(set_timesync_params->offset_delta));
6426eeed018cSMichal Kalderon 
6427eeed018cSMichal Kalderon 	DP(BNX2X_MSG_SP, "Set timesync command params: drift_cmd = %d, offset_cmd = %d, add_sub_drift = %d, drift_val = %d, drift_period = %d, offset_lo = %d, offset_hi = %d\n",
6428eeed018cSMichal Kalderon 	   rdata->drift_adjust_cmd, rdata->offset_cmd,
6429eeed018cSMichal Kalderon 	   rdata->add_sub_drift_adjust_value, rdata->drift_adjust_value,
6430eeed018cSMichal Kalderon 	   rdata->drift_adjust_period, rdata->offset_delta.lo,
6431eeed018cSMichal Kalderon 	   rdata->offset_delta.hi);
6432eeed018cSMichal Kalderon 
6433eeed018cSMichal Kalderon 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_TIMESYNC, 0,
6434eeed018cSMichal Kalderon 			     U64_HI(data_mapping),
6435eeed018cSMichal Kalderon 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
6436eeed018cSMichal Kalderon }
6437eeed018cSMichal Kalderon 
bnx2x_func_send_cmd(struct bnx2x * bp,struct bnx2x_func_state_params * params)6438adfc5217SJeff Kirsher static int bnx2x_func_send_cmd(struct bnx2x *bp,
6439adfc5217SJeff Kirsher 			       struct bnx2x_func_state_params *params)
6440adfc5217SJeff Kirsher {
6441adfc5217SJeff Kirsher 	switch (params->cmd) {
6442adfc5217SJeff Kirsher 	case BNX2X_F_CMD_HW_INIT:
6443adfc5217SJeff Kirsher 		return bnx2x_func_hw_init(bp, params);
6444adfc5217SJeff Kirsher 	case BNX2X_F_CMD_START:
6445adfc5217SJeff Kirsher 		return bnx2x_func_send_start(bp, params);
6446adfc5217SJeff Kirsher 	case BNX2X_F_CMD_STOP:
6447adfc5217SJeff Kirsher 		return bnx2x_func_send_stop(bp, params);
6448adfc5217SJeff Kirsher 	case BNX2X_F_CMD_HW_RESET:
6449adfc5217SJeff Kirsher 		return bnx2x_func_hw_reset(bp, params);
6450a3348722SBarak Witkowski 	case BNX2X_F_CMD_AFEX_UPDATE:
6451a3348722SBarak Witkowski 		return bnx2x_func_send_afex_update(bp, params);
6452a3348722SBarak Witkowski 	case BNX2X_F_CMD_AFEX_VIFLISTS:
6453a3348722SBarak Witkowski 		return bnx2x_func_send_afex_viflists(bp, params);
6454adfc5217SJeff Kirsher 	case BNX2X_F_CMD_TX_STOP:
6455adfc5217SJeff Kirsher 		return bnx2x_func_send_tx_stop(bp, params);
6456adfc5217SJeff Kirsher 	case BNX2X_F_CMD_TX_START:
6457adfc5217SJeff Kirsher 		return bnx2x_func_send_tx_start(bp, params);
645855c11941SMerav Sicron 	case BNX2X_F_CMD_SWITCH_UPDATE:
645955c11941SMerav Sicron 		return bnx2x_func_send_switch_update(bp, params);
6460eeed018cSMichal Kalderon 	case BNX2X_F_CMD_SET_TIMESYNC:
6461eeed018cSMichal Kalderon 		return bnx2x_func_send_set_timesync(bp, params);
6462adfc5217SJeff Kirsher 	default:
6463adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", params->cmd);
6464adfc5217SJeff Kirsher 		return -EINVAL;
6465adfc5217SJeff Kirsher 	}
6466adfc5217SJeff Kirsher }
6467adfc5217SJeff Kirsher 
bnx2x_init_func_obj(struct bnx2x * bp,struct bnx2x_func_sp_obj * obj,void * rdata,dma_addr_t rdata_mapping,void * afex_rdata,dma_addr_t afex_rdata_mapping,struct bnx2x_func_sp_drv_ops * drv_iface)6468adfc5217SJeff Kirsher void bnx2x_init_func_obj(struct bnx2x *bp,
6469adfc5217SJeff Kirsher 			 struct bnx2x_func_sp_obj *obj,
6470adfc5217SJeff Kirsher 			 void *rdata, dma_addr_t rdata_mapping,
6471a3348722SBarak Witkowski 			 void *afex_rdata, dma_addr_t afex_rdata_mapping,
6472adfc5217SJeff Kirsher 			 struct bnx2x_func_sp_drv_ops *drv_iface)
6473adfc5217SJeff Kirsher {
6474adfc5217SJeff Kirsher 	memset(obj, 0, sizeof(*obj));
6475adfc5217SJeff Kirsher 
6476adfc5217SJeff Kirsher 	mutex_init(&obj->one_pending_mutex);
6477adfc5217SJeff Kirsher 
6478adfc5217SJeff Kirsher 	obj->rdata = rdata;
6479adfc5217SJeff Kirsher 	obj->rdata_mapping = rdata_mapping;
6480a3348722SBarak Witkowski 	obj->afex_rdata = afex_rdata;
6481a3348722SBarak Witkowski 	obj->afex_rdata_mapping = afex_rdata_mapping;
6482adfc5217SJeff Kirsher 	obj->send_cmd = bnx2x_func_send_cmd;
6483adfc5217SJeff Kirsher 	obj->check_transition = bnx2x_func_chk_transition;
6484adfc5217SJeff Kirsher 	obj->complete_cmd = bnx2x_func_comp_cmd;
6485adfc5217SJeff Kirsher 	obj->wait_comp = bnx2x_func_wait_comp;
6486adfc5217SJeff Kirsher 
6487adfc5217SJeff Kirsher 	obj->drv = drv_iface;
6488adfc5217SJeff Kirsher }
6489adfc5217SJeff Kirsher 
6490adfc5217SJeff Kirsher /**
6491adfc5217SJeff Kirsher  * bnx2x_func_state_change - perform Function state change transition
6492adfc5217SJeff Kirsher  *
6493adfc5217SJeff Kirsher  * @bp:		device handle
6494adfc5217SJeff Kirsher  * @params:	parameters to perform the transaction
6495adfc5217SJeff Kirsher  *
6496adfc5217SJeff Kirsher  * returns 0 in case of successfully completed transition,
6497adfc5217SJeff Kirsher  *         negative error code in case of failure, positive
6498adfc5217SJeff Kirsher  *         (EBUSY) value if there is a completion to that is
6499adfc5217SJeff Kirsher  *         still pending (possible only if RAMROD_COMP_WAIT is
6500adfc5217SJeff Kirsher  *         not set in params->ramrod_flags for asynchronous
6501adfc5217SJeff Kirsher  *         commands).
6502adfc5217SJeff Kirsher  */
bnx2x_func_state_change(struct bnx2x * bp,struct bnx2x_func_state_params * params)6503adfc5217SJeff Kirsher int bnx2x_func_state_change(struct bnx2x *bp,
6504adfc5217SJeff Kirsher 			    struct bnx2x_func_state_params *params)
6505adfc5217SJeff Kirsher {
6506adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
650755c11941SMerav Sicron 	int rc, cnt = 300;
6508adfc5217SJeff Kirsher 	enum bnx2x_func_cmd cmd = params->cmd;
6509adfc5217SJeff Kirsher 	unsigned long *pending = &o->pending;
6510adfc5217SJeff Kirsher 
6511adfc5217SJeff Kirsher 	mutex_lock(&o->one_pending_mutex);
6512adfc5217SJeff Kirsher 
6513adfc5217SJeff Kirsher 	/* Check that the requested transition is legal */
651455c11941SMerav Sicron 	rc = o->check_transition(bp, o, params);
651555c11941SMerav Sicron 	if ((rc == -EBUSY) &&
651655c11941SMerav Sicron 	    (test_bit(RAMROD_RETRY, &params->ramrod_flags))) {
651755c11941SMerav Sicron 		while ((rc == -EBUSY) && (--cnt > 0)) {
6518adfc5217SJeff Kirsher 			mutex_unlock(&o->one_pending_mutex);
651955c11941SMerav Sicron 			msleep(10);
652055c11941SMerav Sicron 			mutex_lock(&o->one_pending_mutex);
652155c11941SMerav Sicron 			rc = o->check_transition(bp, o, params);
652255c11941SMerav Sicron 		}
652355c11941SMerav Sicron 		if (rc == -EBUSY) {
652455c11941SMerav Sicron 			mutex_unlock(&o->one_pending_mutex);
652555c11941SMerav Sicron 			BNX2X_ERR("timeout waiting for previous ramrod completion\n");
652655c11941SMerav Sicron 			return rc;
652755c11941SMerav Sicron 		}
652855c11941SMerav Sicron 	} else if (rc) {
652955c11941SMerav Sicron 		mutex_unlock(&o->one_pending_mutex);
653055c11941SMerav Sicron 		return rc;
6531adfc5217SJeff Kirsher 	}
6532adfc5217SJeff Kirsher 
6533adfc5217SJeff Kirsher 	/* Set "pending" bit */
6534adfc5217SJeff Kirsher 	set_bit(cmd, pending);
6535adfc5217SJeff Kirsher 
6536adfc5217SJeff Kirsher 	/* Don't send a command if only driver cleanup was requested */
6537adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
6538adfc5217SJeff Kirsher 		bnx2x_func_state_change_comp(bp, o, cmd);
6539adfc5217SJeff Kirsher 		mutex_unlock(&o->one_pending_mutex);
6540adfc5217SJeff Kirsher 	} else {
6541adfc5217SJeff Kirsher 		/* Send a ramrod */
6542adfc5217SJeff Kirsher 		rc = o->send_cmd(bp, params);
6543adfc5217SJeff Kirsher 
6544adfc5217SJeff Kirsher 		mutex_unlock(&o->one_pending_mutex);
6545adfc5217SJeff Kirsher 
6546adfc5217SJeff Kirsher 		if (rc) {
6547adfc5217SJeff Kirsher 			o->next_state = BNX2X_F_STATE_MAX;
6548adfc5217SJeff Kirsher 			clear_bit(cmd, pending);
65494e857c58SPeter Zijlstra 			smp_mb__after_atomic();
6550adfc5217SJeff Kirsher 			return rc;
6551adfc5217SJeff Kirsher 		}
6552adfc5217SJeff Kirsher 
6553adfc5217SJeff Kirsher 		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
6554adfc5217SJeff Kirsher 			rc = o->wait_comp(bp, o, cmd);
6555adfc5217SJeff Kirsher 			if (rc)
6556adfc5217SJeff Kirsher 				return rc;
6557adfc5217SJeff Kirsher 
6558adfc5217SJeff Kirsher 			return 0;
6559adfc5217SJeff Kirsher 		}
6560adfc5217SJeff Kirsher 	}
6561adfc5217SJeff Kirsher 
6562adfc5217SJeff Kirsher 	return !!test_bit(cmd, pending);
6563adfc5217SJeff Kirsher }
6564