1adfc5217SJeff Kirsher /* bnx2x_sp.c: Broadcom Everest network driver.
2adfc5217SJeff Kirsher  *
3adfc5217SJeff Kirsher  * Copyright 2011 Broadcom Corporation
4adfc5217SJeff Kirsher  *
5adfc5217SJeff Kirsher  * Unless you and Broadcom execute a separate written software license
6adfc5217SJeff Kirsher  * agreement governing use of this software, this software is licensed to you
7adfc5217SJeff Kirsher  * under the terms of the GNU General Public License version 2, available
8adfc5217SJeff Kirsher  * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
9adfc5217SJeff Kirsher  *
10adfc5217SJeff Kirsher  * Notwithstanding the above, under no circumstances may you combine this
11adfc5217SJeff Kirsher  * software in any way with any other Broadcom software provided under a
12adfc5217SJeff Kirsher  * license other than the GPL, without Broadcom's express prior written
13adfc5217SJeff Kirsher  * consent.
14adfc5217SJeff Kirsher  *
15adfc5217SJeff Kirsher  * Maintained by: Eilon Greenstein <eilong@broadcom.com>
16adfc5217SJeff Kirsher  * Written by: Vladislav Zolotarov
17adfc5217SJeff Kirsher  *
18adfc5217SJeff Kirsher  */
19f1deab50SJoe Perches 
20f1deab50SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21f1deab50SJoe Perches 
22adfc5217SJeff Kirsher #include <linux/module.h>
23adfc5217SJeff Kirsher #include <linux/crc32.h>
24adfc5217SJeff Kirsher #include <linux/netdevice.h>
25adfc5217SJeff Kirsher #include <linux/etherdevice.h>
26adfc5217SJeff Kirsher #include <linux/crc32c.h>
27adfc5217SJeff Kirsher #include "bnx2x.h"
28adfc5217SJeff Kirsher #include "bnx2x_cmn.h"
29adfc5217SJeff Kirsher #include "bnx2x_sp.h"
30adfc5217SJeff Kirsher 
31adfc5217SJeff Kirsher #define BNX2X_MAX_EMUL_MULTI		16
32adfc5217SJeff Kirsher 
33adfc5217SJeff Kirsher /**** Exe Queue interfaces ****/
34adfc5217SJeff Kirsher 
35adfc5217SJeff Kirsher /**
36adfc5217SJeff Kirsher  * bnx2x_exe_queue_init - init the Exe Queue object
37adfc5217SJeff Kirsher  *
38adfc5217SJeff Kirsher  * @o:		poiter to the object
39adfc5217SJeff Kirsher  * @exe_len:	length
40adfc5217SJeff Kirsher  * @owner:	poiter to the owner
41adfc5217SJeff Kirsher  * @validate:	validate function pointer
42adfc5217SJeff Kirsher  * @optimize:	optimize function pointer
43adfc5217SJeff Kirsher  * @exec:	execute function pointer
44adfc5217SJeff Kirsher  * @get:	get function pointer
45adfc5217SJeff Kirsher  */
46adfc5217SJeff Kirsher static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
47adfc5217SJeff Kirsher 					struct bnx2x_exe_queue_obj *o,
48adfc5217SJeff Kirsher 					int exe_len,
49adfc5217SJeff Kirsher 					union bnx2x_qable_obj *owner,
50adfc5217SJeff Kirsher 					exe_q_validate validate,
51adfc5217SJeff Kirsher 					exe_q_optimize optimize,
52adfc5217SJeff Kirsher 					exe_q_execute exec,
53adfc5217SJeff Kirsher 					exe_q_get get)
54adfc5217SJeff Kirsher {
55adfc5217SJeff Kirsher 	memset(o, 0, sizeof(*o));
56adfc5217SJeff Kirsher 
57adfc5217SJeff Kirsher 	INIT_LIST_HEAD(&o->exe_queue);
58adfc5217SJeff Kirsher 	INIT_LIST_HEAD(&o->pending_comp);
59adfc5217SJeff Kirsher 
60adfc5217SJeff Kirsher 	spin_lock_init(&o->lock);
61adfc5217SJeff Kirsher 
62adfc5217SJeff Kirsher 	o->exe_chunk_len = exe_len;
63adfc5217SJeff Kirsher 	o->owner         = owner;
64adfc5217SJeff Kirsher 
65adfc5217SJeff Kirsher 	/* Owner specific callbacks */
66adfc5217SJeff Kirsher 	o->validate      = validate;
67adfc5217SJeff Kirsher 	o->optimize      = optimize;
68adfc5217SJeff Kirsher 	o->execute       = exec;
69adfc5217SJeff Kirsher 	o->get           = get;
70adfc5217SJeff Kirsher 
71adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Setup the execution queue with the chunk "
72adfc5217SJeff Kirsher 			 "length of %d\n", exe_len);
73adfc5217SJeff Kirsher }
74adfc5217SJeff Kirsher 
75adfc5217SJeff Kirsher static inline void bnx2x_exe_queue_free_elem(struct bnx2x *bp,
76adfc5217SJeff Kirsher 					     struct bnx2x_exeq_elem *elem)
77adfc5217SJeff Kirsher {
78adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Deleting an exe_queue element\n");
79adfc5217SJeff Kirsher 	kfree(elem);
80adfc5217SJeff Kirsher }
81adfc5217SJeff Kirsher 
82adfc5217SJeff Kirsher static inline int bnx2x_exe_queue_length(struct bnx2x_exe_queue_obj *o)
83adfc5217SJeff Kirsher {
84adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem;
85adfc5217SJeff Kirsher 	int cnt = 0;
86adfc5217SJeff Kirsher 
87adfc5217SJeff Kirsher 	spin_lock_bh(&o->lock);
88adfc5217SJeff Kirsher 
89adfc5217SJeff Kirsher 	list_for_each_entry(elem, &o->exe_queue, link)
90adfc5217SJeff Kirsher 		cnt++;
91adfc5217SJeff Kirsher 
92adfc5217SJeff Kirsher 	spin_unlock_bh(&o->lock);
93adfc5217SJeff Kirsher 
94adfc5217SJeff Kirsher 	return cnt;
95adfc5217SJeff Kirsher }
96adfc5217SJeff Kirsher 
97adfc5217SJeff Kirsher /**
98adfc5217SJeff Kirsher  * bnx2x_exe_queue_add - add a new element to the execution queue
99adfc5217SJeff Kirsher  *
100adfc5217SJeff Kirsher  * @bp:		driver handle
101adfc5217SJeff Kirsher  * @o:		queue
102adfc5217SJeff Kirsher  * @cmd:	new command to add
103adfc5217SJeff Kirsher  * @restore:	true - do not optimize the command
104adfc5217SJeff Kirsher  *
105adfc5217SJeff Kirsher  * If the element is optimized or is illegal, frees it.
106adfc5217SJeff Kirsher  */
107adfc5217SJeff Kirsher static inline int bnx2x_exe_queue_add(struct bnx2x *bp,
108adfc5217SJeff Kirsher 				      struct bnx2x_exe_queue_obj *o,
109adfc5217SJeff Kirsher 				      struct bnx2x_exeq_elem *elem,
110adfc5217SJeff Kirsher 				      bool restore)
111adfc5217SJeff Kirsher {
112adfc5217SJeff Kirsher 	int rc;
113adfc5217SJeff Kirsher 
114adfc5217SJeff Kirsher 	spin_lock_bh(&o->lock);
115adfc5217SJeff Kirsher 
116adfc5217SJeff Kirsher 	if (!restore) {
117adfc5217SJeff Kirsher 		/* Try to cancel this element queue */
118adfc5217SJeff Kirsher 		rc = o->optimize(bp, o->owner, elem);
119adfc5217SJeff Kirsher 		if (rc)
120adfc5217SJeff Kirsher 			goto free_and_exit;
121adfc5217SJeff Kirsher 
122adfc5217SJeff Kirsher 		/* Check if this request is ok */
123adfc5217SJeff Kirsher 		rc = o->validate(bp, o->owner, elem);
124adfc5217SJeff Kirsher 		if (rc) {
125adfc5217SJeff Kirsher 			BNX2X_ERR("Preamble failed: %d\n", rc);
126adfc5217SJeff Kirsher 			goto free_and_exit;
127adfc5217SJeff Kirsher 		}
128adfc5217SJeff Kirsher 	}
129adfc5217SJeff Kirsher 
130adfc5217SJeff Kirsher 	/* If so, add it to the execution queue */
131adfc5217SJeff Kirsher 	list_add_tail(&elem->link, &o->exe_queue);
132adfc5217SJeff Kirsher 
133adfc5217SJeff Kirsher 	spin_unlock_bh(&o->lock);
134adfc5217SJeff Kirsher 
135adfc5217SJeff Kirsher 	return 0;
136adfc5217SJeff Kirsher 
137adfc5217SJeff Kirsher free_and_exit:
138adfc5217SJeff Kirsher 	bnx2x_exe_queue_free_elem(bp, elem);
139adfc5217SJeff Kirsher 
140adfc5217SJeff Kirsher 	spin_unlock_bh(&o->lock);
141adfc5217SJeff Kirsher 
142adfc5217SJeff Kirsher 	return rc;
143adfc5217SJeff Kirsher 
144adfc5217SJeff Kirsher }
145adfc5217SJeff Kirsher 
146adfc5217SJeff Kirsher static inline void __bnx2x_exe_queue_reset_pending(
147adfc5217SJeff Kirsher 	struct bnx2x *bp,
148adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *o)
149adfc5217SJeff Kirsher {
150adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem;
151adfc5217SJeff Kirsher 
152adfc5217SJeff Kirsher 	while (!list_empty(&o->pending_comp)) {
153adfc5217SJeff Kirsher 		elem = list_first_entry(&o->pending_comp,
154adfc5217SJeff Kirsher 					struct bnx2x_exeq_elem, link);
155adfc5217SJeff Kirsher 
156adfc5217SJeff Kirsher 		list_del(&elem->link);
157adfc5217SJeff Kirsher 		bnx2x_exe_queue_free_elem(bp, elem);
158adfc5217SJeff Kirsher 	}
159adfc5217SJeff Kirsher }
160adfc5217SJeff Kirsher 
161adfc5217SJeff Kirsher static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp,
162adfc5217SJeff Kirsher 						 struct bnx2x_exe_queue_obj *o)
163adfc5217SJeff Kirsher {
164adfc5217SJeff Kirsher 
165adfc5217SJeff Kirsher 	spin_lock_bh(&o->lock);
166adfc5217SJeff Kirsher 
167adfc5217SJeff Kirsher 	__bnx2x_exe_queue_reset_pending(bp, o);
168adfc5217SJeff Kirsher 
169adfc5217SJeff Kirsher 	spin_unlock_bh(&o->lock);
170adfc5217SJeff Kirsher 
171adfc5217SJeff Kirsher }
172adfc5217SJeff Kirsher 
173adfc5217SJeff Kirsher /**
174adfc5217SJeff Kirsher  * bnx2x_exe_queue_step - execute one execution chunk atomically
175adfc5217SJeff Kirsher  *
176adfc5217SJeff Kirsher  * @bp:			driver handle
177adfc5217SJeff Kirsher  * @o:			queue
178adfc5217SJeff Kirsher  * @ramrod_flags:	flags
179adfc5217SJeff Kirsher  *
180adfc5217SJeff Kirsher  * (Atomicy is ensured using the exe_queue->lock).
181adfc5217SJeff Kirsher  */
182adfc5217SJeff Kirsher static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
183adfc5217SJeff Kirsher 				       struct bnx2x_exe_queue_obj *o,
184adfc5217SJeff Kirsher 				       unsigned long *ramrod_flags)
185adfc5217SJeff Kirsher {
186adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem, spacer;
187adfc5217SJeff Kirsher 	int cur_len = 0, rc;
188adfc5217SJeff Kirsher 
189adfc5217SJeff Kirsher 	memset(&spacer, 0, sizeof(spacer));
190adfc5217SJeff Kirsher 
191adfc5217SJeff Kirsher 	spin_lock_bh(&o->lock);
192adfc5217SJeff Kirsher 
193adfc5217SJeff Kirsher 	/*
194adfc5217SJeff Kirsher 	 * Next step should not be performed until the current is finished,
195adfc5217SJeff Kirsher 	 * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
196adfc5217SJeff Kirsher 	 * properly clear object internals without sending any command to the FW
197adfc5217SJeff Kirsher 	 * which also implies there won't be any completion to clear the
198adfc5217SJeff Kirsher 	 * 'pending' list.
199adfc5217SJeff Kirsher 	 */
200adfc5217SJeff Kirsher 	if (!list_empty(&o->pending_comp)) {
201adfc5217SJeff Kirsher 		if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
202adfc5217SJeff Kirsher 			DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: "
203adfc5217SJeff Kirsher 					 "resetting pending_comp\n");
204adfc5217SJeff Kirsher 			__bnx2x_exe_queue_reset_pending(bp, o);
205adfc5217SJeff Kirsher 		} else {
206adfc5217SJeff Kirsher 			spin_unlock_bh(&o->lock);
207adfc5217SJeff Kirsher 			return 1;
208adfc5217SJeff Kirsher 		}
209adfc5217SJeff Kirsher 	}
210adfc5217SJeff Kirsher 
211adfc5217SJeff Kirsher 	/*
212adfc5217SJeff Kirsher 	 * Run through the pending commands list and create a next
213adfc5217SJeff Kirsher 	 * execution chunk.
214adfc5217SJeff Kirsher 	 */
215adfc5217SJeff Kirsher 	while (!list_empty(&o->exe_queue)) {
216adfc5217SJeff Kirsher 		elem = list_first_entry(&o->exe_queue, struct bnx2x_exeq_elem,
217adfc5217SJeff Kirsher 					link);
218adfc5217SJeff Kirsher 		WARN_ON(!elem->cmd_len);
219adfc5217SJeff Kirsher 
220adfc5217SJeff Kirsher 		if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
221adfc5217SJeff Kirsher 			cur_len += elem->cmd_len;
222adfc5217SJeff Kirsher 			/*
223adfc5217SJeff Kirsher 			 * Prevent from both lists being empty when moving an
224adfc5217SJeff Kirsher 			 * element. This will allow the call of
225adfc5217SJeff Kirsher 			 * bnx2x_exe_queue_empty() without locking.
226adfc5217SJeff Kirsher 			 */
227adfc5217SJeff Kirsher 			list_add_tail(&spacer.link, &o->pending_comp);
228adfc5217SJeff Kirsher 			mb();
229adfc5217SJeff Kirsher 			list_del(&elem->link);
230adfc5217SJeff Kirsher 			list_add_tail(&elem->link, &o->pending_comp);
231adfc5217SJeff Kirsher 			list_del(&spacer.link);
232adfc5217SJeff Kirsher 		} else
233adfc5217SJeff Kirsher 			break;
234adfc5217SJeff Kirsher 	}
235adfc5217SJeff Kirsher 
236adfc5217SJeff Kirsher 	/* Sanity check */
237adfc5217SJeff Kirsher 	if (!cur_len) {
238adfc5217SJeff Kirsher 		spin_unlock_bh(&o->lock);
239adfc5217SJeff Kirsher 		return 0;
240adfc5217SJeff Kirsher 	}
241adfc5217SJeff Kirsher 
242adfc5217SJeff Kirsher 	rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags);
243adfc5217SJeff Kirsher 	if (rc < 0)
244adfc5217SJeff Kirsher 		/*
245adfc5217SJeff Kirsher 		 *  In case of an error return the commands back to the queue
246adfc5217SJeff Kirsher 		 *  and reset the pending_comp.
247adfc5217SJeff Kirsher 		 */
248adfc5217SJeff Kirsher 		list_splice_init(&o->pending_comp, &o->exe_queue);
249adfc5217SJeff Kirsher 	else if (!rc)
250adfc5217SJeff Kirsher 		/*
251adfc5217SJeff Kirsher 		 * If zero is returned, means there are no outstanding pending
252adfc5217SJeff Kirsher 		 * completions and we may dismiss the pending list.
253adfc5217SJeff Kirsher 		 */
254adfc5217SJeff Kirsher 		__bnx2x_exe_queue_reset_pending(bp, o);
255adfc5217SJeff Kirsher 
256adfc5217SJeff Kirsher 	spin_unlock_bh(&o->lock);
257adfc5217SJeff Kirsher 	return rc;
258adfc5217SJeff Kirsher }
259adfc5217SJeff Kirsher 
260adfc5217SJeff Kirsher static inline bool bnx2x_exe_queue_empty(struct bnx2x_exe_queue_obj *o)
261adfc5217SJeff Kirsher {
262adfc5217SJeff Kirsher 	bool empty = list_empty(&o->exe_queue);
263adfc5217SJeff Kirsher 
264adfc5217SJeff Kirsher 	/* Don't reorder!!! */
265adfc5217SJeff Kirsher 	mb();
266adfc5217SJeff Kirsher 
267adfc5217SJeff Kirsher 	return empty && list_empty(&o->pending_comp);
268adfc5217SJeff Kirsher }
269adfc5217SJeff Kirsher 
270adfc5217SJeff Kirsher static inline struct bnx2x_exeq_elem *bnx2x_exe_queue_alloc_elem(
271adfc5217SJeff Kirsher 	struct bnx2x *bp)
272adfc5217SJeff Kirsher {
273adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Allocating a new exe_queue element\n");
274adfc5217SJeff Kirsher 	return kzalloc(sizeof(struct bnx2x_exeq_elem), GFP_ATOMIC);
275adfc5217SJeff Kirsher }
276adfc5217SJeff Kirsher 
277adfc5217SJeff Kirsher /************************ raw_obj functions ***********************************/
278adfc5217SJeff Kirsher static bool bnx2x_raw_check_pending(struct bnx2x_raw_obj *o)
279adfc5217SJeff Kirsher {
280adfc5217SJeff Kirsher 	return !!test_bit(o->state, o->pstate);
281adfc5217SJeff Kirsher }
282adfc5217SJeff Kirsher 
283adfc5217SJeff Kirsher static void bnx2x_raw_clear_pending(struct bnx2x_raw_obj *o)
284adfc5217SJeff Kirsher {
285adfc5217SJeff Kirsher 	smp_mb__before_clear_bit();
286adfc5217SJeff Kirsher 	clear_bit(o->state, o->pstate);
287adfc5217SJeff Kirsher 	smp_mb__after_clear_bit();
288adfc5217SJeff Kirsher }
289adfc5217SJeff Kirsher 
290adfc5217SJeff Kirsher static void bnx2x_raw_set_pending(struct bnx2x_raw_obj *o)
291adfc5217SJeff Kirsher {
292adfc5217SJeff Kirsher 	smp_mb__before_clear_bit();
293adfc5217SJeff Kirsher 	set_bit(o->state, o->pstate);
294adfc5217SJeff Kirsher 	smp_mb__after_clear_bit();
295adfc5217SJeff Kirsher }
296adfc5217SJeff Kirsher 
297adfc5217SJeff Kirsher /**
298adfc5217SJeff Kirsher  * bnx2x_state_wait - wait until the given bit(state) is cleared
299adfc5217SJeff Kirsher  *
300adfc5217SJeff Kirsher  * @bp:		device handle
301adfc5217SJeff Kirsher  * @state:	state which is to be cleared
302adfc5217SJeff Kirsher  * @state_p:	state buffer
303adfc5217SJeff Kirsher  *
304adfc5217SJeff Kirsher  */
305adfc5217SJeff Kirsher static inline int bnx2x_state_wait(struct bnx2x *bp, int state,
306adfc5217SJeff Kirsher 				   unsigned long *pstate)
307adfc5217SJeff Kirsher {
308adfc5217SJeff Kirsher 	/* can take a while if any port is running */
309adfc5217SJeff Kirsher 	int cnt = 5000;
310adfc5217SJeff Kirsher 
311adfc5217SJeff Kirsher 
312adfc5217SJeff Kirsher 	if (CHIP_REV_IS_EMUL(bp))
313adfc5217SJeff Kirsher 		cnt *= 20;
314adfc5217SJeff Kirsher 
315adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "waiting for state to become %d\n", state);
316adfc5217SJeff Kirsher 
317adfc5217SJeff Kirsher 	might_sleep();
318adfc5217SJeff Kirsher 	while (cnt--) {
319adfc5217SJeff Kirsher 		if (!test_bit(state, pstate)) {
320adfc5217SJeff Kirsher #ifdef BNX2X_STOP_ON_ERROR
321adfc5217SJeff Kirsher 			DP(BNX2X_MSG_SP, "exit  (cnt %d)\n", 5000 - cnt);
322adfc5217SJeff Kirsher #endif
323adfc5217SJeff Kirsher 			return 0;
324adfc5217SJeff Kirsher 		}
325adfc5217SJeff Kirsher 
326adfc5217SJeff Kirsher 		usleep_range(1000, 1000);
327adfc5217SJeff Kirsher 
328adfc5217SJeff Kirsher 		if (bp->panic)
329adfc5217SJeff Kirsher 			return -EIO;
330adfc5217SJeff Kirsher 	}
331adfc5217SJeff Kirsher 
332adfc5217SJeff Kirsher 	/* timeout! */
333adfc5217SJeff Kirsher 	BNX2X_ERR("timeout waiting for state %d\n", state);
334adfc5217SJeff Kirsher #ifdef BNX2X_STOP_ON_ERROR
335adfc5217SJeff Kirsher 	bnx2x_panic();
336adfc5217SJeff Kirsher #endif
337adfc5217SJeff Kirsher 
338adfc5217SJeff Kirsher 	return -EBUSY;
339adfc5217SJeff Kirsher }
340adfc5217SJeff Kirsher 
341adfc5217SJeff Kirsher static int bnx2x_raw_wait(struct bnx2x *bp, struct bnx2x_raw_obj *raw)
342adfc5217SJeff Kirsher {
343adfc5217SJeff Kirsher 	return bnx2x_state_wait(bp, raw->state, raw->pstate);
344adfc5217SJeff Kirsher }
345adfc5217SJeff Kirsher 
346adfc5217SJeff Kirsher /***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
347adfc5217SJeff Kirsher /* credit handling callbacks */
348adfc5217SJeff Kirsher static bool bnx2x_get_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int *offset)
349adfc5217SJeff Kirsher {
350adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
351adfc5217SJeff Kirsher 
352adfc5217SJeff Kirsher 	WARN_ON(!mp);
353adfc5217SJeff Kirsher 
354adfc5217SJeff Kirsher 	return mp->get_entry(mp, offset);
355adfc5217SJeff Kirsher }
356adfc5217SJeff Kirsher 
357adfc5217SJeff Kirsher static bool bnx2x_get_credit_mac(struct bnx2x_vlan_mac_obj *o)
358adfc5217SJeff Kirsher {
359adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
360adfc5217SJeff Kirsher 
361adfc5217SJeff Kirsher 	WARN_ON(!mp);
362adfc5217SJeff Kirsher 
363adfc5217SJeff Kirsher 	return mp->get(mp, 1);
364adfc5217SJeff Kirsher }
365adfc5217SJeff Kirsher 
366adfc5217SJeff Kirsher static bool bnx2x_get_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int *offset)
367adfc5217SJeff Kirsher {
368adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
369adfc5217SJeff Kirsher 
370adfc5217SJeff Kirsher 	WARN_ON(!vp);
371adfc5217SJeff Kirsher 
372adfc5217SJeff Kirsher 	return vp->get_entry(vp, offset);
373adfc5217SJeff Kirsher }
374adfc5217SJeff Kirsher 
375adfc5217SJeff Kirsher static bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o)
376adfc5217SJeff Kirsher {
377adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
378adfc5217SJeff Kirsher 
379adfc5217SJeff Kirsher 	WARN_ON(!vp);
380adfc5217SJeff Kirsher 
381adfc5217SJeff Kirsher 	return vp->get(vp, 1);
382adfc5217SJeff Kirsher }
383adfc5217SJeff Kirsher 
384adfc5217SJeff Kirsher static bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
385adfc5217SJeff Kirsher {
386adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
387adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
388adfc5217SJeff Kirsher 
389adfc5217SJeff Kirsher 	if (!mp->get(mp, 1))
390adfc5217SJeff Kirsher 		return false;
391adfc5217SJeff Kirsher 
392adfc5217SJeff Kirsher 	if (!vp->get(vp, 1)) {
393adfc5217SJeff Kirsher 		mp->put(mp, 1);
394adfc5217SJeff Kirsher 		return false;
395adfc5217SJeff Kirsher 	}
396adfc5217SJeff Kirsher 
397adfc5217SJeff Kirsher 	return true;
398adfc5217SJeff Kirsher }
399adfc5217SJeff Kirsher 
400adfc5217SJeff Kirsher static bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset)
401adfc5217SJeff Kirsher {
402adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
403adfc5217SJeff Kirsher 
404adfc5217SJeff Kirsher 	return mp->put_entry(mp, offset);
405adfc5217SJeff Kirsher }
406adfc5217SJeff Kirsher 
407adfc5217SJeff Kirsher static bool bnx2x_put_credit_mac(struct bnx2x_vlan_mac_obj *o)
408adfc5217SJeff Kirsher {
409adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
410adfc5217SJeff Kirsher 
411adfc5217SJeff Kirsher 	return mp->put(mp, 1);
412adfc5217SJeff Kirsher }
413adfc5217SJeff Kirsher 
414adfc5217SJeff Kirsher static bool bnx2x_put_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int offset)
415adfc5217SJeff Kirsher {
416adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
417adfc5217SJeff Kirsher 
418adfc5217SJeff Kirsher 	return vp->put_entry(vp, offset);
419adfc5217SJeff Kirsher }
420adfc5217SJeff Kirsher 
421adfc5217SJeff Kirsher static bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o)
422adfc5217SJeff Kirsher {
423adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
424adfc5217SJeff Kirsher 
425adfc5217SJeff Kirsher 	return vp->put(vp, 1);
426adfc5217SJeff Kirsher }
427adfc5217SJeff Kirsher 
428adfc5217SJeff Kirsher static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
429adfc5217SJeff Kirsher {
430adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
431adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
432adfc5217SJeff Kirsher 
433adfc5217SJeff Kirsher 	if (!mp->put(mp, 1))
434adfc5217SJeff Kirsher 		return false;
435adfc5217SJeff Kirsher 
436adfc5217SJeff Kirsher 	if (!vp->put(vp, 1)) {
437adfc5217SJeff Kirsher 		mp->get(mp, 1);
438adfc5217SJeff Kirsher 		return false;
439adfc5217SJeff Kirsher 	}
440adfc5217SJeff Kirsher 
441adfc5217SJeff Kirsher 	return true;
442adfc5217SJeff Kirsher }
443adfc5217SJeff Kirsher 
444adfc5217SJeff Kirsher /* check_add() callbacks */
445adfc5217SJeff Kirsher static int bnx2x_check_mac_add(struct bnx2x_vlan_mac_obj *o,
446adfc5217SJeff Kirsher 			       union bnx2x_classification_ramrod_data *data)
447adfc5217SJeff Kirsher {
448adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
449adfc5217SJeff Kirsher 
450adfc5217SJeff Kirsher 	if (!is_valid_ether_addr(data->mac.mac))
451adfc5217SJeff Kirsher 		return -EINVAL;
452adfc5217SJeff Kirsher 
453adfc5217SJeff Kirsher 	/* Check if a requested MAC already exists */
454adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
455adfc5217SJeff Kirsher 		if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
456adfc5217SJeff Kirsher 			return -EEXIST;
457adfc5217SJeff Kirsher 
458adfc5217SJeff Kirsher 	return 0;
459adfc5217SJeff Kirsher }
460adfc5217SJeff Kirsher 
461adfc5217SJeff Kirsher static int bnx2x_check_vlan_add(struct bnx2x_vlan_mac_obj *o,
462adfc5217SJeff Kirsher 				union bnx2x_classification_ramrod_data *data)
463adfc5217SJeff Kirsher {
464adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
465adfc5217SJeff Kirsher 
466adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
467adfc5217SJeff Kirsher 		if (data->vlan.vlan == pos->u.vlan.vlan)
468adfc5217SJeff Kirsher 			return -EEXIST;
469adfc5217SJeff Kirsher 
470adfc5217SJeff Kirsher 	return 0;
471adfc5217SJeff Kirsher }
472adfc5217SJeff Kirsher 
473adfc5217SJeff Kirsher static int bnx2x_check_vlan_mac_add(struct bnx2x_vlan_mac_obj *o,
474adfc5217SJeff Kirsher 				   union bnx2x_classification_ramrod_data *data)
475adfc5217SJeff Kirsher {
476adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
477adfc5217SJeff Kirsher 
478adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
479adfc5217SJeff Kirsher 		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
480adfc5217SJeff Kirsher 		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
481adfc5217SJeff Kirsher 			     ETH_ALEN)))
482adfc5217SJeff Kirsher 			return -EEXIST;
483adfc5217SJeff Kirsher 
484adfc5217SJeff Kirsher 	return 0;
485adfc5217SJeff Kirsher }
486adfc5217SJeff Kirsher 
487adfc5217SJeff Kirsher 
488adfc5217SJeff Kirsher /* check_del() callbacks */
489adfc5217SJeff Kirsher static struct bnx2x_vlan_mac_registry_elem *
490adfc5217SJeff Kirsher 	bnx2x_check_mac_del(struct bnx2x_vlan_mac_obj *o,
491adfc5217SJeff Kirsher 			    union bnx2x_classification_ramrod_data *data)
492adfc5217SJeff Kirsher {
493adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
494adfc5217SJeff Kirsher 
495adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
496adfc5217SJeff Kirsher 		if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
497adfc5217SJeff Kirsher 			return pos;
498adfc5217SJeff Kirsher 
499adfc5217SJeff Kirsher 	return NULL;
500adfc5217SJeff Kirsher }
501adfc5217SJeff Kirsher 
502adfc5217SJeff Kirsher static struct bnx2x_vlan_mac_registry_elem *
503adfc5217SJeff Kirsher 	bnx2x_check_vlan_del(struct bnx2x_vlan_mac_obj *o,
504adfc5217SJeff Kirsher 			     union bnx2x_classification_ramrod_data *data)
505adfc5217SJeff Kirsher {
506adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
507adfc5217SJeff Kirsher 
508adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
509adfc5217SJeff Kirsher 		if (data->vlan.vlan == pos->u.vlan.vlan)
510adfc5217SJeff Kirsher 			return pos;
511adfc5217SJeff Kirsher 
512adfc5217SJeff Kirsher 	return NULL;
513adfc5217SJeff Kirsher }
514adfc5217SJeff Kirsher 
515adfc5217SJeff Kirsher static struct bnx2x_vlan_mac_registry_elem *
516adfc5217SJeff Kirsher 	bnx2x_check_vlan_mac_del(struct bnx2x_vlan_mac_obj *o,
517adfc5217SJeff Kirsher 				 union bnx2x_classification_ramrod_data *data)
518adfc5217SJeff Kirsher {
519adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
520adfc5217SJeff Kirsher 
521adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link)
522adfc5217SJeff Kirsher 		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
523adfc5217SJeff Kirsher 		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
524adfc5217SJeff Kirsher 			     ETH_ALEN)))
525adfc5217SJeff Kirsher 			return pos;
526adfc5217SJeff Kirsher 
527adfc5217SJeff Kirsher 	return NULL;
528adfc5217SJeff Kirsher }
529adfc5217SJeff Kirsher 
530adfc5217SJeff Kirsher /* check_move() callback */
531adfc5217SJeff Kirsher static bool bnx2x_check_move(struct bnx2x_vlan_mac_obj *src_o,
532adfc5217SJeff Kirsher 			     struct bnx2x_vlan_mac_obj *dst_o,
533adfc5217SJeff Kirsher 			     union bnx2x_classification_ramrod_data *data)
534adfc5217SJeff Kirsher {
535adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
536adfc5217SJeff Kirsher 	int rc;
537adfc5217SJeff Kirsher 
538adfc5217SJeff Kirsher 	/* Check if we can delete the requested configuration from the first
539adfc5217SJeff Kirsher 	 * object.
540adfc5217SJeff Kirsher 	 */
541adfc5217SJeff Kirsher 	pos = src_o->check_del(src_o, data);
542adfc5217SJeff Kirsher 
543adfc5217SJeff Kirsher 	/*  check if configuration can be added */
544adfc5217SJeff Kirsher 	rc = dst_o->check_add(dst_o, data);
545adfc5217SJeff Kirsher 
546adfc5217SJeff Kirsher 	/* If this classification can not be added (is already set)
547adfc5217SJeff Kirsher 	 * or can't be deleted - return an error.
548adfc5217SJeff Kirsher 	 */
549adfc5217SJeff Kirsher 	if (rc || !pos)
550adfc5217SJeff Kirsher 		return false;
551adfc5217SJeff Kirsher 
552adfc5217SJeff Kirsher 	return true;
553adfc5217SJeff Kirsher }
554adfc5217SJeff Kirsher 
555adfc5217SJeff Kirsher static bool bnx2x_check_move_always_err(
556adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *src_o,
557adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *dst_o,
558adfc5217SJeff Kirsher 	union bnx2x_classification_ramrod_data *data)
559adfc5217SJeff Kirsher {
560adfc5217SJeff Kirsher 	return false;
561adfc5217SJeff Kirsher }
562adfc5217SJeff Kirsher 
563adfc5217SJeff Kirsher 
564adfc5217SJeff Kirsher static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
565adfc5217SJeff Kirsher {
566adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
567adfc5217SJeff Kirsher 	u8 rx_tx_flag = 0;
568adfc5217SJeff Kirsher 
569adfc5217SJeff Kirsher 	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
570adfc5217SJeff Kirsher 	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
571adfc5217SJeff Kirsher 		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD;
572adfc5217SJeff Kirsher 
573adfc5217SJeff Kirsher 	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
574adfc5217SJeff Kirsher 	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
575adfc5217SJeff Kirsher 		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD;
576adfc5217SJeff Kirsher 
577adfc5217SJeff Kirsher 	return rx_tx_flag;
578adfc5217SJeff Kirsher }
579adfc5217SJeff Kirsher 
580adfc5217SJeff Kirsher /* LLH CAM line allocations */
581adfc5217SJeff Kirsher enum {
582adfc5217SJeff Kirsher 	LLH_CAM_ISCSI_ETH_LINE = 0,
583adfc5217SJeff Kirsher 	LLH_CAM_ETH_LINE,
584adfc5217SJeff Kirsher 	LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE / 2
585adfc5217SJeff Kirsher };
586adfc5217SJeff Kirsher 
587adfc5217SJeff Kirsher static inline void bnx2x_set_mac_in_nig(struct bnx2x *bp,
588adfc5217SJeff Kirsher 				 bool add, unsigned char *dev_addr, int index)
589adfc5217SJeff Kirsher {
590adfc5217SJeff Kirsher 	u32 wb_data[2];
591adfc5217SJeff Kirsher 	u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
592adfc5217SJeff Kirsher 			 NIG_REG_LLH0_FUNC_MEM;
593adfc5217SJeff Kirsher 
594adfc5217SJeff Kirsher 	if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE)
595adfc5217SJeff Kirsher 		return;
596adfc5217SJeff Kirsher 
597adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Going to %s LLH configuration at entry %d\n",
598adfc5217SJeff Kirsher 			 (add ? "ADD" : "DELETE"), index);
599adfc5217SJeff Kirsher 
600adfc5217SJeff Kirsher 	if (add) {
601adfc5217SJeff Kirsher 		/* LLH_FUNC_MEM is a u64 WB register */
602adfc5217SJeff Kirsher 		reg_offset += 8*index;
603adfc5217SJeff Kirsher 
604adfc5217SJeff Kirsher 		wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
605adfc5217SJeff Kirsher 			      (dev_addr[4] <<  8) |  dev_addr[5]);
606adfc5217SJeff Kirsher 		wb_data[1] = ((dev_addr[0] <<  8) |  dev_addr[1]);
607adfc5217SJeff Kirsher 
608adfc5217SJeff Kirsher 		REG_WR_DMAE(bp, reg_offset, wb_data, 2);
609adfc5217SJeff Kirsher 	}
610adfc5217SJeff Kirsher 
611adfc5217SJeff Kirsher 	REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
612adfc5217SJeff Kirsher 				  NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*index, add);
613adfc5217SJeff Kirsher }
614adfc5217SJeff Kirsher 
615adfc5217SJeff Kirsher /**
616adfc5217SJeff Kirsher  * bnx2x_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod
617adfc5217SJeff Kirsher  *
618adfc5217SJeff Kirsher  * @bp:		device handle
619adfc5217SJeff Kirsher  * @o:		queue for which we want to configure this rule
620adfc5217SJeff Kirsher  * @add:	if true the command is an ADD command, DEL otherwise
621adfc5217SJeff Kirsher  * @opcode:	CLASSIFY_RULE_OPCODE_XXX
622adfc5217SJeff Kirsher  * @hdr:	pointer to a header to setup
623adfc5217SJeff Kirsher  *
624adfc5217SJeff Kirsher  */
625adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp,
626adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o, bool add, int opcode,
627adfc5217SJeff Kirsher 	struct eth_classify_cmd_header *hdr)
628adfc5217SJeff Kirsher {
629adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
630adfc5217SJeff Kirsher 
631adfc5217SJeff Kirsher 	hdr->client_id = raw->cl_id;
632adfc5217SJeff Kirsher 	hdr->func_id = raw->func_id;
633adfc5217SJeff Kirsher 
634adfc5217SJeff Kirsher 	/* Rx or/and Tx (internal switching) configuration ? */
635adfc5217SJeff Kirsher 	hdr->cmd_general_data |=
636adfc5217SJeff Kirsher 		bnx2x_vlan_mac_get_rx_tx_flag(o);
637adfc5217SJeff Kirsher 
638adfc5217SJeff Kirsher 	if (add)
639adfc5217SJeff Kirsher 		hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD;
640adfc5217SJeff Kirsher 
641adfc5217SJeff Kirsher 	hdr->cmd_general_data |=
642adfc5217SJeff Kirsher 		(opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT);
643adfc5217SJeff Kirsher }
644adfc5217SJeff Kirsher 
645adfc5217SJeff Kirsher /**
646adfc5217SJeff Kirsher  * bnx2x_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header
647adfc5217SJeff Kirsher  *
648adfc5217SJeff Kirsher  * @cid:	connection id
649adfc5217SJeff Kirsher  * @type:	BNX2X_FILTER_XXX_PENDING
650adfc5217SJeff Kirsher  * @hdr:	poiter to header to setup
651adfc5217SJeff Kirsher  * @rule_cnt:
652adfc5217SJeff Kirsher  *
653adfc5217SJeff Kirsher  * currently we always configure one rule and echo field to contain a CID and an
654adfc5217SJeff Kirsher  * opcode type.
655adfc5217SJeff Kirsher  */
656adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type,
657adfc5217SJeff Kirsher 				struct eth_classify_header *hdr, int rule_cnt)
658adfc5217SJeff Kirsher {
659adfc5217SJeff Kirsher 	hdr->echo = (cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT);
660adfc5217SJeff Kirsher 	hdr->rule_cnt = (u8)rule_cnt;
661adfc5217SJeff Kirsher }
662adfc5217SJeff Kirsher 
663adfc5217SJeff Kirsher 
664adfc5217SJeff Kirsher /* hw_config() callbacks */
665adfc5217SJeff Kirsher static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
666adfc5217SJeff Kirsher 				 struct bnx2x_vlan_mac_obj *o,
667adfc5217SJeff Kirsher 				 struct bnx2x_exeq_elem *elem, int rule_idx,
668adfc5217SJeff Kirsher 				 int cam_offset)
669adfc5217SJeff Kirsher {
670adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
671adfc5217SJeff Kirsher 	struct eth_classify_rules_ramrod_data *data =
672adfc5217SJeff Kirsher 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
673adfc5217SJeff Kirsher 	int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd;
674adfc5217SJeff Kirsher 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
675adfc5217SJeff Kirsher 	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
676adfc5217SJeff Kirsher 	unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags;
677adfc5217SJeff Kirsher 	u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac;
678adfc5217SJeff Kirsher 
679adfc5217SJeff Kirsher 	/*
680adfc5217SJeff Kirsher 	 * Set LLH CAM entry: currently only iSCSI and ETH macs are
681adfc5217SJeff Kirsher 	 * relevant. In addition, current implementation is tuned for a
682adfc5217SJeff Kirsher 	 * single ETH MAC.
683adfc5217SJeff Kirsher 	 *
684adfc5217SJeff Kirsher 	 * When multiple unicast ETH MACs PF configuration in switch
685adfc5217SJeff Kirsher 	 * independent mode is required (NetQ, multiple netdev MACs,
686adfc5217SJeff Kirsher 	 * etc.), consider better utilisation of 8 per function MAC
687adfc5217SJeff Kirsher 	 * entries in the LLH register. There is also
688adfc5217SJeff Kirsher 	 * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the
689adfc5217SJeff Kirsher 	 * total number of CAM entries to 16.
690adfc5217SJeff Kirsher 	 *
691adfc5217SJeff Kirsher 	 * Currently we won't configure NIG for MACs other than a primary ETH
692adfc5217SJeff Kirsher 	 * MAC and iSCSI L2 MAC.
693adfc5217SJeff Kirsher 	 *
694adfc5217SJeff Kirsher 	 * If this MAC is moving from one Queue to another, no need to change
695adfc5217SJeff Kirsher 	 * NIG configuration.
696adfc5217SJeff Kirsher 	 */
697adfc5217SJeff Kirsher 	if (cmd != BNX2X_VLAN_MAC_MOVE) {
698adfc5217SJeff Kirsher 		if (test_bit(BNX2X_ISCSI_ETH_MAC, vlan_mac_flags))
699adfc5217SJeff Kirsher 			bnx2x_set_mac_in_nig(bp, add, mac,
700adfc5217SJeff Kirsher 					     LLH_CAM_ISCSI_ETH_LINE);
701adfc5217SJeff Kirsher 		else if (test_bit(BNX2X_ETH_MAC, vlan_mac_flags))
702adfc5217SJeff Kirsher 			bnx2x_set_mac_in_nig(bp, add, mac, LLH_CAM_ETH_LINE);
703adfc5217SJeff Kirsher 	}
704adfc5217SJeff Kirsher 
705adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer for the first rule */
706adfc5217SJeff Kirsher 	if (rule_idx == 0)
707adfc5217SJeff Kirsher 		memset(data, 0, sizeof(*data));
708adfc5217SJeff Kirsher 
709adfc5217SJeff Kirsher 	/* Setup a command header */
710adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_MAC,
711adfc5217SJeff Kirsher 				      &rule_entry->mac.header);
712adfc5217SJeff Kirsher 
7130f9dad10SJoe Perches 	DP(BNX2X_MSG_SP, "About to %s MAC %pM for Queue %d\n",
7140f9dad10SJoe Perches 			 add ? "add" : "delete", mac, raw->cl_id);
715adfc5217SJeff Kirsher 
716adfc5217SJeff Kirsher 	/* Set a MAC itself */
717adfc5217SJeff Kirsher 	bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
718adfc5217SJeff Kirsher 			      &rule_entry->mac.mac_mid,
719adfc5217SJeff Kirsher 			      &rule_entry->mac.mac_lsb, mac);
720adfc5217SJeff Kirsher 
721adfc5217SJeff Kirsher 	/* MOVE: Add a rule that will add this MAC to the target Queue */
722adfc5217SJeff Kirsher 	if (cmd == BNX2X_VLAN_MAC_MOVE) {
723adfc5217SJeff Kirsher 		rule_entry++;
724adfc5217SJeff Kirsher 		rule_cnt++;
725adfc5217SJeff Kirsher 
726adfc5217SJeff Kirsher 		/* Setup ramrod data */
727adfc5217SJeff Kirsher 		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
728adfc5217SJeff Kirsher 					elem->cmd_data.vlan_mac.target_obj,
729adfc5217SJeff Kirsher 					      true, CLASSIFY_RULE_OPCODE_MAC,
730adfc5217SJeff Kirsher 					      &rule_entry->mac.header);
731adfc5217SJeff Kirsher 
732adfc5217SJeff Kirsher 		/* Set a MAC itself */
733adfc5217SJeff Kirsher 		bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
734adfc5217SJeff Kirsher 				      &rule_entry->mac.mac_mid,
735adfc5217SJeff Kirsher 				      &rule_entry->mac.mac_lsb, mac);
736adfc5217SJeff Kirsher 	}
737adfc5217SJeff Kirsher 
738adfc5217SJeff Kirsher 	/* Set the ramrod data header */
739adfc5217SJeff Kirsher 	/* TODO: take this to the higher level in order to prevent multiple
740adfc5217SJeff Kirsher 		 writing */
741adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
742adfc5217SJeff Kirsher 					rule_cnt);
743adfc5217SJeff Kirsher }
744adfc5217SJeff Kirsher 
745adfc5217SJeff Kirsher /**
746adfc5217SJeff Kirsher  * bnx2x_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod
747adfc5217SJeff Kirsher  *
748adfc5217SJeff Kirsher  * @bp:		device handle
749adfc5217SJeff Kirsher  * @o:		queue
750adfc5217SJeff Kirsher  * @type:
751adfc5217SJeff Kirsher  * @cam_offset:	offset in cam memory
752adfc5217SJeff Kirsher  * @hdr:	pointer to a header to setup
753adfc5217SJeff Kirsher  *
754adfc5217SJeff Kirsher  * E1/E1H
755adfc5217SJeff Kirsher  */
756adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_rdata_hdr_e1x(struct bnx2x *bp,
757adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset,
758adfc5217SJeff Kirsher 	struct mac_configuration_hdr *hdr)
759adfc5217SJeff Kirsher {
760adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
761adfc5217SJeff Kirsher 
762adfc5217SJeff Kirsher 	hdr->length = 1;
763adfc5217SJeff Kirsher 	hdr->offset = (u8)cam_offset;
764adfc5217SJeff Kirsher 	hdr->client_id = 0xff;
765adfc5217SJeff Kirsher 	hdr->echo = ((r->cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT));
766adfc5217SJeff Kirsher }
767adfc5217SJeff Kirsher 
768adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_cfg_entry_e1x(struct bnx2x *bp,
769adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o, bool add, int opcode, u8 *mac,
770adfc5217SJeff Kirsher 	u16 vlan_id, struct mac_configuration_entry *cfg_entry)
771adfc5217SJeff Kirsher {
772adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
773adfc5217SJeff Kirsher 	u32 cl_bit_vec = (1 << r->cl_id);
774adfc5217SJeff Kirsher 
775adfc5217SJeff Kirsher 	cfg_entry->clients_bit_vector = cpu_to_le32(cl_bit_vec);
776adfc5217SJeff Kirsher 	cfg_entry->pf_id = r->func_id;
777adfc5217SJeff Kirsher 	cfg_entry->vlan_id = cpu_to_le16(vlan_id);
778adfc5217SJeff Kirsher 
779adfc5217SJeff Kirsher 	if (add) {
780adfc5217SJeff Kirsher 		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
781adfc5217SJeff Kirsher 			 T_ETH_MAC_COMMAND_SET);
782adfc5217SJeff Kirsher 		SET_FLAG(cfg_entry->flags,
783adfc5217SJeff Kirsher 			 MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE, opcode);
784adfc5217SJeff Kirsher 
785adfc5217SJeff Kirsher 		/* Set a MAC in a ramrod data */
786adfc5217SJeff Kirsher 		bnx2x_set_fw_mac_addr(&cfg_entry->msb_mac_addr,
787adfc5217SJeff Kirsher 				      &cfg_entry->middle_mac_addr,
788adfc5217SJeff Kirsher 				      &cfg_entry->lsb_mac_addr, mac);
789adfc5217SJeff Kirsher 	} else
790adfc5217SJeff Kirsher 		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
791adfc5217SJeff Kirsher 			 T_ETH_MAC_COMMAND_INVALIDATE);
792adfc5217SJeff Kirsher }
793adfc5217SJeff Kirsher 
794adfc5217SJeff Kirsher static inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp,
795adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset, bool add,
796adfc5217SJeff Kirsher 	u8 *mac, u16 vlan_id, int opcode, struct mac_configuration_cmd *config)
797adfc5217SJeff Kirsher {
798adfc5217SJeff Kirsher 	struct mac_configuration_entry *cfg_entry = &config->config_table[0];
799adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
800adfc5217SJeff Kirsher 
801adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_rdata_hdr_e1x(bp, o, type, cam_offset,
802adfc5217SJeff Kirsher 					 &config->hdr);
803adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_cfg_entry_e1x(bp, o, add, opcode, mac, vlan_id,
804adfc5217SJeff Kirsher 					 cfg_entry);
805adfc5217SJeff Kirsher 
8060f9dad10SJoe Perches 	DP(BNX2X_MSG_SP, "%s MAC %pM CLID %d CAM offset %d\n",
8070f9dad10SJoe Perches 			 add ? "setting" : "clearing",
8080f9dad10SJoe Perches 			 mac, raw->cl_id, cam_offset);
809adfc5217SJeff Kirsher }
810adfc5217SJeff Kirsher 
811adfc5217SJeff Kirsher /**
812adfc5217SJeff Kirsher  * bnx2x_set_one_mac_e1x - fill a single MAC rule ramrod data
813adfc5217SJeff Kirsher  *
814adfc5217SJeff Kirsher  * @bp:		device handle
815adfc5217SJeff Kirsher  * @o:		bnx2x_vlan_mac_obj
816adfc5217SJeff Kirsher  * @elem:	bnx2x_exeq_elem
817adfc5217SJeff Kirsher  * @rule_idx:	rule_idx
818adfc5217SJeff Kirsher  * @cam_offset: cam_offset
819adfc5217SJeff Kirsher  */
820adfc5217SJeff Kirsher static void bnx2x_set_one_mac_e1x(struct bnx2x *bp,
821adfc5217SJeff Kirsher 				  struct bnx2x_vlan_mac_obj *o,
822adfc5217SJeff Kirsher 				  struct bnx2x_exeq_elem *elem, int rule_idx,
823adfc5217SJeff Kirsher 				  int cam_offset)
824adfc5217SJeff Kirsher {
825adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
826adfc5217SJeff Kirsher 	struct mac_configuration_cmd *config =
827adfc5217SJeff Kirsher 		(struct mac_configuration_cmd *)(raw->rdata);
828adfc5217SJeff Kirsher 	/*
829adfc5217SJeff Kirsher 	 * 57710 and 57711 do not support MOVE command,
830adfc5217SJeff Kirsher 	 * so it's either ADD or DEL
831adfc5217SJeff Kirsher 	 */
832adfc5217SJeff Kirsher 	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
833adfc5217SJeff Kirsher 		true : false;
834adfc5217SJeff Kirsher 
835adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer */
836adfc5217SJeff Kirsher 	memset(config, 0, sizeof(*config));
837adfc5217SJeff Kirsher 
838adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_MAC_PENDING,
839adfc5217SJeff Kirsher 				     cam_offset, add,
840adfc5217SJeff Kirsher 				     elem->cmd_data.vlan_mac.u.mac.mac, 0,
841adfc5217SJeff Kirsher 				     ETH_VLAN_FILTER_ANY_VLAN, config);
842adfc5217SJeff Kirsher }
843adfc5217SJeff Kirsher 
844adfc5217SJeff Kirsher static void bnx2x_set_one_vlan_e2(struct bnx2x *bp,
845adfc5217SJeff Kirsher 				  struct bnx2x_vlan_mac_obj *o,
846adfc5217SJeff Kirsher 				  struct bnx2x_exeq_elem *elem, int rule_idx,
847adfc5217SJeff Kirsher 				  int cam_offset)
848adfc5217SJeff Kirsher {
849adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
850adfc5217SJeff Kirsher 	struct eth_classify_rules_ramrod_data *data =
851adfc5217SJeff Kirsher 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
852adfc5217SJeff Kirsher 	int rule_cnt = rule_idx + 1;
853adfc5217SJeff Kirsher 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
854adfc5217SJeff Kirsher 	int cmd = elem->cmd_data.vlan_mac.cmd;
855adfc5217SJeff Kirsher 	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
856adfc5217SJeff Kirsher 	u16 vlan = elem->cmd_data.vlan_mac.u.vlan.vlan;
857adfc5217SJeff Kirsher 
858adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer for the first rule */
859adfc5217SJeff Kirsher 	if (rule_idx == 0)
860adfc5217SJeff Kirsher 		memset(data, 0, sizeof(*data));
861adfc5217SJeff Kirsher 
862adfc5217SJeff Kirsher 	/* Set a rule header */
863adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_VLAN,
864adfc5217SJeff Kirsher 				      &rule_entry->vlan.header);
865adfc5217SJeff Kirsher 
866adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "About to %s VLAN %d\n", (add ? "add" : "delete"),
867adfc5217SJeff Kirsher 			 vlan);
868adfc5217SJeff Kirsher 
869adfc5217SJeff Kirsher 	/* Set a VLAN itself */
870adfc5217SJeff Kirsher 	rule_entry->vlan.vlan = cpu_to_le16(vlan);
871adfc5217SJeff Kirsher 
872adfc5217SJeff Kirsher 	/* MOVE: Add a rule that will add this MAC to the target Queue */
873adfc5217SJeff Kirsher 	if (cmd == BNX2X_VLAN_MAC_MOVE) {
874adfc5217SJeff Kirsher 		rule_entry++;
875adfc5217SJeff Kirsher 		rule_cnt++;
876adfc5217SJeff Kirsher 
877adfc5217SJeff Kirsher 		/* Setup ramrod data */
878adfc5217SJeff Kirsher 		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
879adfc5217SJeff Kirsher 					elem->cmd_data.vlan_mac.target_obj,
880adfc5217SJeff Kirsher 					      true, CLASSIFY_RULE_OPCODE_VLAN,
881adfc5217SJeff Kirsher 					      &rule_entry->vlan.header);
882adfc5217SJeff Kirsher 
883adfc5217SJeff Kirsher 		/* Set a VLAN itself */
884adfc5217SJeff Kirsher 		rule_entry->vlan.vlan = cpu_to_le16(vlan);
885adfc5217SJeff Kirsher 	}
886adfc5217SJeff Kirsher 
887adfc5217SJeff Kirsher 	/* Set the ramrod data header */
888adfc5217SJeff Kirsher 	/* TODO: take this to the higher level in order to prevent multiple
889adfc5217SJeff Kirsher 		 writing */
890adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
891adfc5217SJeff Kirsher 					rule_cnt);
892adfc5217SJeff Kirsher }
893adfc5217SJeff Kirsher 
894adfc5217SJeff Kirsher static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
895adfc5217SJeff Kirsher 				      struct bnx2x_vlan_mac_obj *o,
896adfc5217SJeff Kirsher 				      struct bnx2x_exeq_elem *elem,
897adfc5217SJeff Kirsher 				      int rule_idx, int cam_offset)
898adfc5217SJeff Kirsher {
899adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
900adfc5217SJeff Kirsher 	struct eth_classify_rules_ramrod_data *data =
901adfc5217SJeff Kirsher 		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
902adfc5217SJeff Kirsher 	int rule_cnt = rule_idx + 1;
903adfc5217SJeff Kirsher 	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
904adfc5217SJeff Kirsher 	int cmd = elem->cmd_data.vlan_mac.cmd;
905adfc5217SJeff Kirsher 	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
906adfc5217SJeff Kirsher 	u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
907adfc5217SJeff Kirsher 	u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
908adfc5217SJeff Kirsher 
909adfc5217SJeff Kirsher 
910adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer for the first rule */
911adfc5217SJeff Kirsher 	if (rule_idx == 0)
912adfc5217SJeff Kirsher 		memset(data, 0, sizeof(*data));
913adfc5217SJeff Kirsher 
914adfc5217SJeff Kirsher 	/* Set a rule header */
915adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
916adfc5217SJeff Kirsher 				      &rule_entry->pair.header);
917adfc5217SJeff Kirsher 
918adfc5217SJeff Kirsher 	/* Set VLAN and MAC themselvs */
919adfc5217SJeff Kirsher 	rule_entry->pair.vlan = cpu_to_le16(vlan);
920adfc5217SJeff Kirsher 	bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
921adfc5217SJeff Kirsher 			      &rule_entry->pair.mac_mid,
922adfc5217SJeff Kirsher 			      &rule_entry->pair.mac_lsb, mac);
923adfc5217SJeff Kirsher 
924adfc5217SJeff Kirsher 	/* MOVE: Add a rule that will add this MAC to the target Queue */
925adfc5217SJeff Kirsher 	if (cmd == BNX2X_VLAN_MAC_MOVE) {
926adfc5217SJeff Kirsher 		rule_entry++;
927adfc5217SJeff Kirsher 		rule_cnt++;
928adfc5217SJeff Kirsher 
929adfc5217SJeff Kirsher 		/* Setup ramrod data */
930adfc5217SJeff Kirsher 		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
931adfc5217SJeff Kirsher 					elem->cmd_data.vlan_mac.target_obj,
932adfc5217SJeff Kirsher 					      true, CLASSIFY_RULE_OPCODE_PAIR,
933adfc5217SJeff Kirsher 					      &rule_entry->pair.header);
934adfc5217SJeff Kirsher 
935adfc5217SJeff Kirsher 		/* Set a VLAN itself */
936adfc5217SJeff Kirsher 		rule_entry->pair.vlan = cpu_to_le16(vlan);
937adfc5217SJeff Kirsher 		bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
938adfc5217SJeff Kirsher 				      &rule_entry->pair.mac_mid,
939adfc5217SJeff Kirsher 				      &rule_entry->pair.mac_lsb, mac);
940adfc5217SJeff Kirsher 	}
941adfc5217SJeff Kirsher 
942adfc5217SJeff Kirsher 	/* Set the ramrod data header */
943adfc5217SJeff Kirsher 	/* TODO: take this to the higher level in order to prevent multiple
944adfc5217SJeff Kirsher 		 writing */
945adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
946adfc5217SJeff Kirsher 					rule_cnt);
947adfc5217SJeff Kirsher }
948adfc5217SJeff Kirsher 
949adfc5217SJeff Kirsher /**
950adfc5217SJeff Kirsher  * bnx2x_set_one_vlan_mac_e1h -
951adfc5217SJeff Kirsher  *
952adfc5217SJeff Kirsher  * @bp:		device handle
953adfc5217SJeff Kirsher  * @o:		bnx2x_vlan_mac_obj
954adfc5217SJeff Kirsher  * @elem:	bnx2x_exeq_elem
955adfc5217SJeff Kirsher  * @rule_idx:	rule_idx
956adfc5217SJeff Kirsher  * @cam_offset:	cam_offset
957adfc5217SJeff Kirsher  */
958adfc5217SJeff Kirsher static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
959adfc5217SJeff Kirsher 				       struct bnx2x_vlan_mac_obj *o,
960adfc5217SJeff Kirsher 				       struct bnx2x_exeq_elem *elem,
961adfc5217SJeff Kirsher 				       int rule_idx, int cam_offset)
962adfc5217SJeff Kirsher {
963adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
964adfc5217SJeff Kirsher 	struct mac_configuration_cmd *config =
965adfc5217SJeff Kirsher 		(struct mac_configuration_cmd *)(raw->rdata);
966adfc5217SJeff Kirsher 	/*
967adfc5217SJeff Kirsher 	 * 57710 and 57711 do not support MOVE command,
968adfc5217SJeff Kirsher 	 * so it's either ADD or DEL
969adfc5217SJeff Kirsher 	 */
970adfc5217SJeff Kirsher 	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
971adfc5217SJeff Kirsher 		true : false;
972adfc5217SJeff Kirsher 
973adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer */
974adfc5217SJeff Kirsher 	memset(config, 0, sizeof(*config));
975adfc5217SJeff Kirsher 
976adfc5217SJeff Kirsher 	bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING,
977adfc5217SJeff Kirsher 				     cam_offset, add,
978adfc5217SJeff Kirsher 				     elem->cmd_data.vlan_mac.u.vlan_mac.mac,
979adfc5217SJeff Kirsher 				     elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
980adfc5217SJeff Kirsher 				     ETH_VLAN_FILTER_CLASSIFY, config);
981adfc5217SJeff Kirsher }
982adfc5217SJeff Kirsher 
983adfc5217SJeff Kirsher #define list_next_entry(pos, member) \
984adfc5217SJeff Kirsher 	list_entry((pos)->member.next, typeof(*(pos)), member)
985adfc5217SJeff Kirsher 
986adfc5217SJeff Kirsher /**
987adfc5217SJeff Kirsher  * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
988adfc5217SJeff Kirsher  *
989adfc5217SJeff Kirsher  * @bp:		device handle
990adfc5217SJeff Kirsher  * @p:		command parameters
991adfc5217SJeff Kirsher  * @ppos:	pointer to the cooky
992adfc5217SJeff Kirsher  *
993adfc5217SJeff Kirsher  * reconfigure next MAC/VLAN/VLAN-MAC element from the
994adfc5217SJeff Kirsher  * previously configured elements list.
995adfc5217SJeff Kirsher  *
996adfc5217SJeff Kirsher  * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is	taken
997adfc5217SJeff Kirsher  * into an account
998adfc5217SJeff Kirsher  *
999adfc5217SJeff Kirsher  * pointer to the cooky  - that should be given back in the next call to make
1000adfc5217SJeff Kirsher  * function handle the next element. If *ppos is set to NULL it will restart the
1001adfc5217SJeff Kirsher  * iterator. If returned *ppos == NULL this means that the last element has been
1002adfc5217SJeff Kirsher  * handled.
1003adfc5217SJeff Kirsher  *
1004adfc5217SJeff Kirsher  */
1005adfc5217SJeff Kirsher static int bnx2x_vlan_mac_restore(struct bnx2x *bp,
1006adfc5217SJeff Kirsher 			   struct bnx2x_vlan_mac_ramrod_params *p,
1007adfc5217SJeff Kirsher 			   struct bnx2x_vlan_mac_registry_elem **ppos)
1008adfc5217SJeff Kirsher {
1009adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
1010adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
1011adfc5217SJeff Kirsher 
1012adfc5217SJeff Kirsher 	/* If list is empty - there is nothing to do here */
1013adfc5217SJeff Kirsher 	if (list_empty(&o->head)) {
1014adfc5217SJeff Kirsher 		*ppos = NULL;
1015adfc5217SJeff Kirsher 		return 0;
1016adfc5217SJeff Kirsher 	}
1017adfc5217SJeff Kirsher 
1018adfc5217SJeff Kirsher 	/* make a step... */
1019adfc5217SJeff Kirsher 	if (*ppos == NULL)
1020adfc5217SJeff Kirsher 		*ppos = list_first_entry(&o->head,
1021adfc5217SJeff Kirsher 					 struct bnx2x_vlan_mac_registry_elem,
1022adfc5217SJeff Kirsher 					 link);
1023adfc5217SJeff Kirsher 	else
1024adfc5217SJeff Kirsher 		*ppos = list_next_entry(*ppos, link);
1025adfc5217SJeff Kirsher 
1026adfc5217SJeff Kirsher 	pos = *ppos;
1027adfc5217SJeff Kirsher 
1028adfc5217SJeff Kirsher 	/* If it's the last step - return NULL */
1029adfc5217SJeff Kirsher 	if (list_is_last(&pos->link, &o->head))
1030adfc5217SJeff Kirsher 		*ppos = NULL;
1031adfc5217SJeff Kirsher 
1032adfc5217SJeff Kirsher 	/* Prepare a 'user_req' */
1033adfc5217SJeff Kirsher 	memcpy(&p->user_req.u, &pos->u, sizeof(pos->u));
1034adfc5217SJeff Kirsher 
1035adfc5217SJeff Kirsher 	/* Set the command */
1036adfc5217SJeff Kirsher 	p->user_req.cmd = BNX2X_VLAN_MAC_ADD;
1037adfc5217SJeff Kirsher 
1038adfc5217SJeff Kirsher 	/* Set vlan_mac_flags */
1039adfc5217SJeff Kirsher 	p->user_req.vlan_mac_flags = pos->vlan_mac_flags;
1040adfc5217SJeff Kirsher 
1041adfc5217SJeff Kirsher 	/* Set a restore bit */
1042adfc5217SJeff Kirsher 	__set_bit(RAMROD_RESTORE, &p->ramrod_flags);
1043adfc5217SJeff Kirsher 
1044adfc5217SJeff Kirsher 	return bnx2x_config_vlan_mac(bp, p);
1045adfc5217SJeff Kirsher }
1046adfc5217SJeff Kirsher 
1047adfc5217SJeff Kirsher /*
1048adfc5217SJeff Kirsher  * bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a
1049adfc5217SJeff Kirsher  * pointer to an element with a specific criteria and NULL if such an element
1050adfc5217SJeff Kirsher  * hasn't been found.
1051adfc5217SJeff Kirsher  */
1052adfc5217SJeff Kirsher static struct bnx2x_exeq_elem *bnx2x_exeq_get_mac(
1053adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *o,
1054adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem)
1055adfc5217SJeff Kirsher {
1056adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *pos;
1057adfc5217SJeff Kirsher 	struct bnx2x_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac;
1058adfc5217SJeff Kirsher 
1059adfc5217SJeff Kirsher 	/* Check pending for execution commands */
1060adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->exe_queue, link)
1061adfc5217SJeff Kirsher 		if (!memcmp(&pos->cmd_data.vlan_mac.u.mac, data,
1062adfc5217SJeff Kirsher 			      sizeof(*data)) &&
1063adfc5217SJeff Kirsher 		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
1064adfc5217SJeff Kirsher 			return pos;
1065adfc5217SJeff Kirsher 
1066adfc5217SJeff Kirsher 	return NULL;
1067adfc5217SJeff Kirsher }
1068adfc5217SJeff Kirsher 
1069adfc5217SJeff Kirsher static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan(
1070adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *o,
1071adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem)
1072adfc5217SJeff Kirsher {
1073adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *pos;
1074adfc5217SJeff Kirsher 	struct bnx2x_vlan_ramrod_data *data = &elem->cmd_data.vlan_mac.u.vlan;
1075adfc5217SJeff Kirsher 
1076adfc5217SJeff Kirsher 	/* Check pending for execution commands */
1077adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->exe_queue, link)
1078adfc5217SJeff Kirsher 		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan, data,
1079adfc5217SJeff Kirsher 			      sizeof(*data)) &&
1080adfc5217SJeff Kirsher 		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
1081adfc5217SJeff Kirsher 			return pos;
1082adfc5217SJeff Kirsher 
1083adfc5217SJeff Kirsher 	return NULL;
1084adfc5217SJeff Kirsher }
1085adfc5217SJeff Kirsher 
1086adfc5217SJeff Kirsher static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac(
1087adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *o,
1088adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem)
1089adfc5217SJeff Kirsher {
1090adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *pos;
1091adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_ramrod_data *data =
1092adfc5217SJeff Kirsher 		&elem->cmd_data.vlan_mac.u.vlan_mac;
1093adfc5217SJeff Kirsher 
1094adfc5217SJeff Kirsher 	/* Check pending for execution commands */
1095adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->exe_queue, link)
1096adfc5217SJeff Kirsher 		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
1097adfc5217SJeff Kirsher 			      sizeof(*data)) &&
1098adfc5217SJeff Kirsher 		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
1099adfc5217SJeff Kirsher 			return pos;
1100adfc5217SJeff Kirsher 
1101adfc5217SJeff Kirsher 	return NULL;
1102adfc5217SJeff Kirsher }
1103adfc5217SJeff Kirsher 
1104adfc5217SJeff Kirsher /**
1105adfc5217SJeff Kirsher  * bnx2x_validate_vlan_mac_add - check if an ADD command can be executed
1106adfc5217SJeff Kirsher  *
1107adfc5217SJeff Kirsher  * @bp:		device handle
1108adfc5217SJeff Kirsher  * @qo:		bnx2x_qable_obj
1109adfc5217SJeff Kirsher  * @elem:	bnx2x_exeq_elem
1110adfc5217SJeff Kirsher  *
1111adfc5217SJeff Kirsher  * Checks that the requested configuration can be added. If yes and if
1112adfc5217SJeff Kirsher  * requested, consume CAM credit.
1113adfc5217SJeff Kirsher  *
1114adfc5217SJeff Kirsher  * The 'validate' is run after the 'optimize'.
1115adfc5217SJeff Kirsher  *
1116adfc5217SJeff Kirsher  */
1117adfc5217SJeff Kirsher static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp,
1118adfc5217SJeff Kirsher 					      union bnx2x_qable_obj *qo,
1119adfc5217SJeff Kirsher 					      struct bnx2x_exeq_elem *elem)
1120adfc5217SJeff Kirsher {
1121adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
1122adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
1123adfc5217SJeff Kirsher 	int rc;
1124adfc5217SJeff Kirsher 
1125adfc5217SJeff Kirsher 	/* Check the registry */
1126adfc5217SJeff Kirsher 	rc = o->check_add(o, &elem->cmd_data.vlan_mac.u);
1127adfc5217SJeff Kirsher 	if (rc) {
1128adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "ADD command is not allowed considering "
1129adfc5217SJeff Kirsher 				 "current registry state\n");
1130adfc5217SJeff Kirsher 		return rc;
1131adfc5217SJeff Kirsher 	}
1132adfc5217SJeff Kirsher 
1133adfc5217SJeff Kirsher 	/*
1134adfc5217SJeff Kirsher 	 * Check if there is a pending ADD command for this
1135adfc5217SJeff Kirsher 	 * MAC/VLAN/VLAN-MAC. Return an error if there is.
1136adfc5217SJeff Kirsher 	 */
1137adfc5217SJeff Kirsher 	if (exeq->get(exeq, elem)) {
1138adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "There is a pending ADD command already\n");
1139adfc5217SJeff Kirsher 		return -EEXIST;
1140adfc5217SJeff Kirsher 	}
1141adfc5217SJeff Kirsher 
1142adfc5217SJeff Kirsher 	/*
1143adfc5217SJeff Kirsher 	 * TODO: Check the pending MOVE from other objects where this
1144adfc5217SJeff Kirsher 	 * object is a destination object.
1145adfc5217SJeff Kirsher 	 */
1146adfc5217SJeff Kirsher 
1147adfc5217SJeff Kirsher 	/* Consume the credit if not requested not to */
1148adfc5217SJeff Kirsher 	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
1149adfc5217SJeff Kirsher 		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
1150adfc5217SJeff Kirsher 	    o->get_credit(o)))
1151adfc5217SJeff Kirsher 		return -EINVAL;
1152adfc5217SJeff Kirsher 
1153adfc5217SJeff Kirsher 	return 0;
1154adfc5217SJeff Kirsher }
1155adfc5217SJeff Kirsher 
1156adfc5217SJeff Kirsher /**
1157adfc5217SJeff Kirsher  * bnx2x_validate_vlan_mac_del - check if the DEL command can be executed
1158adfc5217SJeff Kirsher  *
1159adfc5217SJeff Kirsher  * @bp:		device handle
1160adfc5217SJeff Kirsher  * @qo:		quable object to check
1161adfc5217SJeff Kirsher  * @elem:	element that needs to be deleted
1162adfc5217SJeff Kirsher  *
1163adfc5217SJeff Kirsher  * Checks that the requested configuration can be deleted. If yes and if
1164adfc5217SJeff Kirsher  * requested, returns a CAM credit.
1165adfc5217SJeff Kirsher  *
1166adfc5217SJeff Kirsher  * The 'validate' is run after the 'optimize'.
1167adfc5217SJeff Kirsher  */
1168adfc5217SJeff Kirsher static inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp,
1169adfc5217SJeff Kirsher 					      union bnx2x_qable_obj *qo,
1170adfc5217SJeff Kirsher 					      struct bnx2x_exeq_elem *elem)
1171adfc5217SJeff Kirsher {
1172adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
1173adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos;
1174adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
1175adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem query_elem;
1176adfc5217SJeff Kirsher 
1177adfc5217SJeff Kirsher 	/* If this classification can not be deleted (doesn't exist)
1178adfc5217SJeff Kirsher 	 * - return a BNX2X_EXIST.
1179adfc5217SJeff Kirsher 	 */
1180adfc5217SJeff Kirsher 	pos = o->check_del(o, &elem->cmd_data.vlan_mac.u);
1181adfc5217SJeff Kirsher 	if (!pos) {
1182adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "DEL command is not allowed considering "
1183adfc5217SJeff Kirsher 				 "current registry state\n");
1184adfc5217SJeff Kirsher 		return -EEXIST;
1185adfc5217SJeff Kirsher 	}
1186adfc5217SJeff Kirsher 
1187adfc5217SJeff Kirsher 	/*
1188adfc5217SJeff Kirsher 	 * Check if there are pending DEL or MOVE commands for this
1189adfc5217SJeff Kirsher 	 * MAC/VLAN/VLAN-MAC. Return an error if so.
1190adfc5217SJeff Kirsher 	 */
1191adfc5217SJeff Kirsher 	memcpy(&query_elem, elem, sizeof(query_elem));
1192adfc5217SJeff Kirsher 
1193adfc5217SJeff Kirsher 	/* Check for MOVE commands */
1194adfc5217SJeff Kirsher 	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_MOVE;
1195adfc5217SJeff Kirsher 	if (exeq->get(exeq, &query_elem)) {
1196adfc5217SJeff Kirsher 		BNX2X_ERR("There is a pending MOVE command already\n");
1197adfc5217SJeff Kirsher 		return -EINVAL;
1198adfc5217SJeff Kirsher 	}
1199adfc5217SJeff Kirsher 
1200adfc5217SJeff Kirsher 	/* Check for DEL commands */
1201adfc5217SJeff Kirsher 	if (exeq->get(exeq, elem)) {
1202adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "There is a pending DEL command already\n");
1203adfc5217SJeff Kirsher 		return -EEXIST;
1204adfc5217SJeff Kirsher 	}
1205adfc5217SJeff Kirsher 
1206adfc5217SJeff Kirsher 	/* Return the credit to the credit pool if not requested not to */
1207adfc5217SJeff Kirsher 	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
1208adfc5217SJeff Kirsher 		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
1209adfc5217SJeff Kirsher 	    o->put_credit(o))) {
1210adfc5217SJeff Kirsher 		BNX2X_ERR("Failed to return a credit\n");
1211adfc5217SJeff Kirsher 		return -EINVAL;
1212adfc5217SJeff Kirsher 	}
1213adfc5217SJeff Kirsher 
1214adfc5217SJeff Kirsher 	return 0;
1215adfc5217SJeff Kirsher }
1216adfc5217SJeff Kirsher 
1217adfc5217SJeff Kirsher /**
1218adfc5217SJeff Kirsher  * bnx2x_validate_vlan_mac_move - check if the MOVE command can be executed
1219adfc5217SJeff Kirsher  *
1220adfc5217SJeff Kirsher  * @bp:		device handle
1221adfc5217SJeff Kirsher  * @qo:		quable object to check (source)
1222adfc5217SJeff Kirsher  * @elem:	element that needs to be moved
1223adfc5217SJeff Kirsher  *
1224adfc5217SJeff Kirsher  * Checks that the requested configuration can be moved. If yes and if
1225adfc5217SJeff Kirsher  * requested, returns a CAM credit.
1226adfc5217SJeff Kirsher  *
1227adfc5217SJeff Kirsher  * The 'validate' is run after the 'optimize'.
1228adfc5217SJeff Kirsher  */
1229adfc5217SJeff Kirsher static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp,
1230adfc5217SJeff Kirsher 					       union bnx2x_qable_obj *qo,
1231adfc5217SJeff Kirsher 					       struct bnx2x_exeq_elem *elem)
1232adfc5217SJeff Kirsher {
1233adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *src_o = &qo->vlan_mac;
1234adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj;
1235adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem query_elem;
1236adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue;
1237adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue;
1238adfc5217SJeff Kirsher 
1239adfc5217SJeff Kirsher 	/*
1240adfc5217SJeff Kirsher 	 * Check if we can perform this operation based on the current registry
1241adfc5217SJeff Kirsher 	 * state.
1242adfc5217SJeff Kirsher 	 */
1243adfc5217SJeff Kirsher 	if (!src_o->check_move(src_o, dest_o, &elem->cmd_data.vlan_mac.u)) {
1244adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "MOVE command is not allowed considering "
1245adfc5217SJeff Kirsher 				 "current registry state\n");
1246adfc5217SJeff Kirsher 		return -EINVAL;
1247adfc5217SJeff Kirsher 	}
1248adfc5217SJeff Kirsher 
1249adfc5217SJeff Kirsher 	/*
1250adfc5217SJeff Kirsher 	 * Check if there is an already pending DEL or MOVE command for the
1251adfc5217SJeff Kirsher 	 * source object or ADD command for a destination object. Return an
1252adfc5217SJeff Kirsher 	 * error if so.
1253adfc5217SJeff Kirsher 	 */
1254adfc5217SJeff Kirsher 	memcpy(&query_elem, elem, sizeof(query_elem));
1255adfc5217SJeff Kirsher 
1256adfc5217SJeff Kirsher 	/* Check DEL on source */
1257adfc5217SJeff Kirsher 	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
1258adfc5217SJeff Kirsher 	if (src_exeq->get(src_exeq, &query_elem)) {
1259adfc5217SJeff Kirsher 		BNX2X_ERR("There is a pending DEL command on the source "
1260adfc5217SJeff Kirsher 			  "queue already\n");
1261adfc5217SJeff Kirsher 		return -EINVAL;
1262adfc5217SJeff Kirsher 	}
1263adfc5217SJeff Kirsher 
1264adfc5217SJeff Kirsher 	/* Check MOVE on source */
1265adfc5217SJeff Kirsher 	if (src_exeq->get(src_exeq, elem)) {
1266adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "There is a pending MOVE command already\n");
1267adfc5217SJeff Kirsher 		return -EEXIST;
1268adfc5217SJeff Kirsher 	}
1269adfc5217SJeff Kirsher 
1270adfc5217SJeff Kirsher 	/* Check ADD on destination */
1271adfc5217SJeff Kirsher 	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
1272adfc5217SJeff Kirsher 	if (dest_exeq->get(dest_exeq, &query_elem)) {
1273adfc5217SJeff Kirsher 		BNX2X_ERR("There is a pending ADD command on the "
1274adfc5217SJeff Kirsher 			  "destination queue already\n");
1275adfc5217SJeff Kirsher 		return -EINVAL;
1276adfc5217SJeff Kirsher 	}
1277adfc5217SJeff Kirsher 
1278adfc5217SJeff Kirsher 	/* Consume the credit if not requested not to */
1279adfc5217SJeff Kirsher 	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
1280adfc5217SJeff Kirsher 		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
1281adfc5217SJeff Kirsher 	    dest_o->get_credit(dest_o)))
1282adfc5217SJeff Kirsher 		return -EINVAL;
1283adfc5217SJeff Kirsher 
1284adfc5217SJeff Kirsher 	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
1285adfc5217SJeff Kirsher 		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
1286adfc5217SJeff Kirsher 	    src_o->put_credit(src_o))) {
1287adfc5217SJeff Kirsher 		/* return the credit taken from dest... */
1288adfc5217SJeff Kirsher 		dest_o->put_credit(dest_o);
1289adfc5217SJeff Kirsher 		return -EINVAL;
1290adfc5217SJeff Kirsher 	}
1291adfc5217SJeff Kirsher 
1292adfc5217SJeff Kirsher 	return 0;
1293adfc5217SJeff Kirsher }
1294adfc5217SJeff Kirsher 
1295adfc5217SJeff Kirsher static int bnx2x_validate_vlan_mac(struct bnx2x *bp,
1296adfc5217SJeff Kirsher 				   union bnx2x_qable_obj *qo,
1297adfc5217SJeff Kirsher 				   struct bnx2x_exeq_elem *elem)
1298adfc5217SJeff Kirsher {
1299adfc5217SJeff Kirsher 	switch (elem->cmd_data.vlan_mac.cmd) {
1300adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_ADD:
1301adfc5217SJeff Kirsher 		return bnx2x_validate_vlan_mac_add(bp, qo, elem);
1302adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_DEL:
1303adfc5217SJeff Kirsher 		return bnx2x_validate_vlan_mac_del(bp, qo, elem);
1304adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_MOVE:
1305adfc5217SJeff Kirsher 		return bnx2x_validate_vlan_mac_move(bp, qo, elem);
1306adfc5217SJeff Kirsher 	default:
1307adfc5217SJeff Kirsher 		return -EINVAL;
1308adfc5217SJeff Kirsher 	}
1309adfc5217SJeff Kirsher }
1310adfc5217SJeff Kirsher 
1311adfc5217SJeff Kirsher /**
1312adfc5217SJeff Kirsher  * bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
1313adfc5217SJeff Kirsher  *
1314adfc5217SJeff Kirsher  * @bp:		device handle
1315adfc5217SJeff Kirsher  * @o:		bnx2x_vlan_mac_obj
1316adfc5217SJeff Kirsher  *
1317adfc5217SJeff Kirsher  */
1318adfc5217SJeff Kirsher static int bnx2x_wait_vlan_mac(struct bnx2x *bp,
1319adfc5217SJeff Kirsher 			       struct bnx2x_vlan_mac_obj *o)
1320adfc5217SJeff Kirsher {
1321adfc5217SJeff Kirsher 	int cnt = 5000, rc;
1322adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
1323adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
1324adfc5217SJeff Kirsher 
1325adfc5217SJeff Kirsher 	while (cnt--) {
1326adfc5217SJeff Kirsher 		/* Wait for the current command to complete */
1327adfc5217SJeff Kirsher 		rc = raw->wait_comp(bp, raw);
1328adfc5217SJeff Kirsher 		if (rc)
1329adfc5217SJeff Kirsher 			return rc;
1330adfc5217SJeff Kirsher 
1331adfc5217SJeff Kirsher 		/* Wait until there are no pending commands */
1332adfc5217SJeff Kirsher 		if (!bnx2x_exe_queue_empty(exeq))
1333adfc5217SJeff Kirsher 			usleep_range(1000, 1000);
1334adfc5217SJeff Kirsher 		else
1335adfc5217SJeff Kirsher 			return 0;
1336adfc5217SJeff Kirsher 	}
1337adfc5217SJeff Kirsher 
1338adfc5217SJeff Kirsher 	return -EBUSY;
1339adfc5217SJeff Kirsher }
1340adfc5217SJeff Kirsher 
1341adfc5217SJeff Kirsher /**
1342adfc5217SJeff Kirsher  * bnx2x_complete_vlan_mac - complete one VLAN-MAC ramrod
1343adfc5217SJeff Kirsher  *
1344adfc5217SJeff Kirsher  * @bp:		device handle
1345adfc5217SJeff Kirsher  * @o:		bnx2x_vlan_mac_obj
1346adfc5217SJeff Kirsher  * @cqe:
1347adfc5217SJeff Kirsher  * @cont:	if true schedule next execution chunk
1348adfc5217SJeff Kirsher  *
1349adfc5217SJeff Kirsher  */
1350adfc5217SJeff Kirsher static int bnx2x_complete_vlan_mac(struct bnx2x *bp,
1351adfc5217SJeff Kirsher 				   struct bnx2x_vlan_mac_obj *o,
1352adfc5217SJeff Kirsher 				   union event_ring_elem *cqe,
1353adfc5217SJeff Kirsher 				   unsigned long *ramrod_flags)
1354adfc5217SJeff Kirsher {
1355adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
1356adfc5217SJeff Kirsher 	int rc;
1357adfc5217SJeff Kirsher 
1358adfc5217SJeff Kirsher 	/* Reset pending list */
1359adfc5217SJeff Kirsher 	bnx2x_exe_queue_reset_pending(bp, &o->exe_queue);
1360adfc5217SJeff Kirsher 
1361adfc5217SJeff Kirsher 	/* Clear pending */
1362adfc5217SJeff Kirsher 	r->clear_pending(r);
1363adfc5217SJeff Kirsher 
1364adfc5217SJeff Kirsher 	/* If ramrod failed this is most likely a SW bug */
1365adfc5217SJeff Kirsher 	if (cqe->message.error)
1366adfc5217SJeff Kirsher 		return -EINVAL;
1367adfc5217SJeff Kirsher 
1368adfc5217SJeff Kirsher 	/* Run the next bulk of pending commands if requeted */
1369adfc5217SJeff Kirsher 	if (test_bit(RAMROD_CONT, ramrod_flags)) {
1370adfc5217SJeff Kirsher 		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
1371adfc5217SJeff Kirsher 		if (rc < 0)
1372adfc5217SJeff Kirsher 			return rc;
1373adfc5217SJeff Kirsher 	}
1374adfc5217SJeff Kirsher 
1375adfc5217SJeff Kirsher 	/* If there is more work to do return PENDING */
1376adfc5217SJeff Kirsher 	if (!bnx2x_exe_queue_empty(&o->exe_queue))
1377adfc5217SJeff Kirsher 		return 1;
1378adfc5217SJeff Kirsher 
1379adfc5217SJeff Kirsher 	return 0;
1380adfc5217SJeff Kirsher }
1381adfc5217SJeff Kirsher 
1382adfc5217SJeff Kirsher /**
1383adfc5217SJeff Kirsher  * bnx2x_optimize_vlan_mac - optimize ADD and DEL commands.
1384adfc5217SJeff Kirsher  *
1385adfc5217SJeff Kirsher  * @bp:		device handle
1386adfc5217SJeff Kirsher  * @o:		bnx2x_qable_obj
1387adfc5217SJeff Kirsher  * @elem:	bnx2x_exeq_elem
1388adfc5217SJeff Kirsher  */
1389adfc5217SJeff Kirsher static int bnx2x_optimize_vlan_mac(struct bnx2x *bp,
1390adfc5217SJeff Kirsher 				   union bnx2x_qable_obj *qo,
1391adfc5217SJeff Kirsher 				   struct bnx2x_exeq_elem *elem)
1392adfc5217SJeff Kirsher {
1393adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem query, *pos;
1394adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
1395adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
1396adfc5217SJeff Kirsher 
1397adfc5217SJeff Kirsher 	memcpy(&query, elem, sizeof(query));
1398adfc5217SJeff Kirsher 
1399adfc5217SJeff Kirsher 	switch (elem->cmd_data.vlan_mac.cmd) {
1400adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_ADD:
1401adfc5217SJeff Kirsher 		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
1402adfc5217SJeff Kirsher 		break;
1403adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_DEL:
1404adfc5217SJeff Kirsher 		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
1405adfc5217SJeff Kirsher 		break;
1406adfc5217SJeff Kirsher 	default:
1407adfc5217SJeff Kirsher 		/* Don't handle anything other than ADD or DEL */
1408adfc5217SJeff Kirsher 		return 0;
1409adfc5217SJeff Kirsher 	}
1410adfc5217SJeff Kirsher 
1411adfc5217SJeff Kirsher 	/* If we found the appropriate element - delete it */
1412adfc5217SJeff Kirsher 	pos = exeq->get(exeq, &query);
1413adfc5217SJeff Kirsher 	if (pos) {
1414adfc5217SJeff Kirsher 
1415adfc5217SJeff Kirsher 		/* Return the credit of the optimized command */
1416adfc5217SJeff Kirsher 		if (!test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
1417adfc5217SJeff Kirsher 			      &pos->cmd_data.vlan_mac.vlan_mac_flags)) {
1418adfc5217SJeff Kirsher 			if ((query.cmd_data.vlan_mac.cmd ==
1419adfc5217SJeff Kirsher 			     BNX2X_VLAN_MAC_ADD) && !o->put_credit(o)) {
1420adfc5217SJeff Kirsher 				BNX2X_ERR("Failed to return the credit for the "
1421adfc5217SJeff Kirsher 					  "optimized ADD command\n");
1422adfc5217SJeff Kirsher 				return -EINVAL;
1423adfc5217SJeff Kirsher 			} else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */
1424adfc5217SJeff Kirsher 				BNX2X_ERR("Failed to recover the credit from "
1425adfc5217SJeff Kirsher 					  "the optimized DEL command\n");
1426adfc5217SJeff Kirsher 				return -EINVAL;
1427adfc5217SJeff Kirsher 			}
1428adfc5217SJeff Kirsher 		}
1429adfc5217SJeff Kirsher 
1430adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Optimizing %s command\n",
1431adfc5217SJeff Kirsher 			   (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
1432adfc5217SJeff Kirsher 			   "ADD" : "DEL");
1433adfc5217SJeff Kirsher 
1434adfc5217SJeff Kirsher 		list_del(&pos->link);
1435adfc5217SJeff Kirsher 		bnx2x_exe_queue_free_elem(bp, pos);
1436adfc5217SJeff Kirsher 		return 1;
1437adfc5217SJeff Kirsher 	}
1438adfc5217SJeff Kirsher 
1439adfc5217SJeff Kirsher 	return 0;
1440adfc5217SJeff Kirsher }
1441adfc5217SJeff Kirsher 
1442adfc5217SJeff Kirsher /**
1443adfc5217SJeff Kirsher  * bnx2x_vlan_mac_get_registry_elem - prepare a registry element
1444adfc5217SJeff Kirsher  *
1445adfc5217SJeff Kirsher  * @bp:	  device handle
1446adfc5217SJeff Kirsher  * @o:
1447adfc5217SJeff Kirsher  * @elem:
1448adfc5217SJeff Kirsher  * @restore:
1449adfc5217SJeff Kirsher  * @re:
1450adfc5217SJeff Kirsher  *
1451adfc5217SJeff Kirsher  * prepare a registry element according to the current command request.
1452adfc5217SJeff Kirsher  */
1453adfc5217SJeff Kirsher static inline int bnx2x_vlan_mac_get_registry_elem(
1454adfc5217SJeff Kirsher 	struct bnx2x *bp,
1455adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o,
1456adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem,
1457adfc5217SJeff Kirsher 	bool restore,
1458adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem **re)
1459adfc5217SJeff Kirsher {
1460adfc5217SJeff Kirsher 	int cmd = elem->cmd_data.vlan_mac.cmd;
1461adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *reg_elem;
1462adfc5217SJeff Kirsher 
1463adfc5217SJeff Kirsher 	/* Allocate a new registry element if needed. */
1464adfc5217SJeff Kirsher 	if (!restore &&
1465adfc5217SJeff Kirsher 	    ((cmd == BNX2X_VLAN_MAC_ADD) || (cmd == BNX2X_VLAN_MAC_MOVE))) {
1466adfc5217SJeff Kirsher 		reg_elem = kzalloc(sizeof(*reg_elem), GFP_ATOMIC);
1467adfc5217SJeff Kirsher 		if (!reg_elem)
1468adfc5217SJeff Kirsher 			return -ENOMEM;
1469adfc5217SJeff Kirsher 
1470adfc5217SJeff Kirsher 		/* Get a new CAM offset */
1471adfc5217SJeff Kirsher 		if (!o->get_cam_offset(o, &reg_elem->cam_offset)) {
1472adfc5217SJeff Kirsher 			/*
1473adfc5217SJeff Kirsher 			 * This shell never happen, because we have checked the
1474adfc5217SJeff Kirsher 			 * CAM availiability in the 'validate'.
1475adfc5217SJeff Kirsher 			 */
1476adfc5217SJeff Kirsher 			WARN_ON(1);
1477adfc5217SJeff Kirsher 			kfree(reg_elem);
1478adfc5217SJeff Kirsher 			return -EINVAL;
1479adfc5217SJeff Kirsher 		}
1480adfc5217SJeff Kirsher 
1481adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Got cam offset %d\n", reg_elem->cam_offset);
1482adfc5217SJeff Kirsher 
1483adfc5217SJeff Kirsher 		/* Set a VLAN-MAC data */
1484adfc5217SJeff Kirsher 		memcpy(&reg_elem->u, &elem->cmd_data.vlan_mac.u,
1485adfc5217SJeff Kirsher 			  sizeof(reg_elem->u));
1486adfc5217SJeff Kirsher 
1487adfc5217SJeff Kirsher 		/* Copy the flags (needed for DEL and RESTORE flows) */
1488adfc5217SJeff Kirsher 		reg_elem->vlan_mac_flags =
1489adfc5217SJeff Kirsher 			elem->cmd_data.vlan_mac.vlan_mac_flags;
1490adfc5217SJeff Kirsher 	} else /* DEL, RESTORE */
1491adfc5217SJeff Kirsher 		reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
1492adfc5217SJeff Kirsher 
1493adfc5217SJeff Kirsher 	*re = reg_elem;
1494adfc5217SJeff Kirsher 	return 0;
1495adfc5217SJeff Kirsher }
1496adfc5217SJeff Kirsher 
1497adfc5217SJeff Kirsher /**
1498adfc5217SJeff Kirsher  * bnx2x_execute_vlan_mac - execute vlan mac command
1499adfc5217SJeff Kirsher  *
1500adfc5217SJeff Kirsher  * @bp:			device handle
1501adfc5217SJeff Kirsher  * @qo:
1502adfc5217SJeff Kirsher  * @exe_chunk:
1503adfc5217SJeff Kirsher  * @ramrod_flags:
1504adfc5217SJeff Kirsher  *
1505adfc5217SJeff Kirsher  * go and send a ramrod!
1506adfc5217SJeff Kirsher  */
1507adfc5217SJeff Kirsher static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
1508adfc5217SJeff Kirsher 				  union bnx2x_qable_obj *qo,
1509adfc5217SJeff Kirsher 				  struct list_head *exe_chunk,
1510adfc5217SJeff Kirsher 				  unsigned long *ramrod_flags)
1511adfc5217SJeff Kirsher {
1512adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem;
1513adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj;
1514adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
1515adfc5217SJeff Kirsher 	int rc, idx = 0;
1516adfc5217SJeff Kirsher 	bool restore = test_bit(RAMROD_RESTORE, ramrod_flags);
1517adfc5217SJeff Kirsher 	bool drv_only = test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags);
1518adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *reg_elem;
1519adfc5217SJeff Kirsher 	int cmd;
1520adfc5217SJeff Kirsher 
1521adfc5217SJeff Kirsher 	/*
1522adfc5217SJeff Kirsher 	 * If DRIVER_ONLY execution is requested, cleanup a registry
1523adfc5217SJeff Kirsher 	 * and exit. Otherwise send a ramrod to FW.
1524adfc5217SJeff Kirsher 	 */
1525adfc5217SJeff Kirsher 	if (!drv_only) {
1526adfc5217SJeff Kirsher 		WARN_ON(r->check_pending(r));
1527adfc5217SJeff Kirsher 
1528adfc5217SJeff Kirsher 		/* Set pending */
1529adfc5217SJeff Kirsher 		r->set_pending(r);
1530adfc5217SJeff Kirsher 
1531adfc5217SJeff Kirsher 		/* Fill tha ramrod data */
1532adfc5217SJeff Kirsher 		list_for_each_entry(elem, exe_chunk, link) {
1533adfc5217SJeff Kirsher 			cmd = elem->cmd_data.vlan_mac.cmd;
1534adfc5217SJeff Kirsher 			/*
1535adfc5217SJeff Kirsher 			 * We will add to the target object in MOVE command, so
1536adfc5217SJeff Kirsher 			 * change the object for a CAM search.
1537adfc5217SJeff Kirsher 			 */
1538adfc5217SJeff Kirsher 			if (cmd == BNX2X_VLAN_MAC_MOVE)
1539adfc5217SJeff Kirsher 				cam_obj = elem->cmd_data.vlan_mac.target_obj;
1540adfc5217SJeff Kirsher 			else
1541adfc5217SJeff Kirsher 				cam_obj = o;
1542adfc5217SJeff Kirsher 
1543adfc5217SJeff Kirsher 			rc = bnx2x_vlan_mac_get_registry_elem(bp, cam_obj,
1544adfc5217SJeff Kirsher 							      elem, restore,
1545adfc5217SJeff Kirsher 							      &reg_elem);
1546adfc5217SJeff Kirsher 			if (rc)
1547adfc5217SJeff Kirsher 				goto error_exit;
1548adfc5217SJeff Kirsher 
1549adfc5217SJeff Kirsher 			WARN_ON(!reg_elem);
1550adfc5217SJeff Kirsher 
1551adfc5217SJeff Kirsher 			/* Push a new entry into the registry */
1552adfc5217SJeff Kirsher 			if (!restore &&
1553adfc5217SJeff Kirsher 			    ((cmd == BNX2X_VLAN_MAC_ADD) ||
1554adfc5217SJeff Kirsher 			    (cmd == BNX2X_VLAN_MAC_MOVE)))
1555adfc5217SJeff Kirsher 				list_add(&reg_elem->link, &cam_obj->head);
1556adfc5217SJeff Kirsher 
1557adfc5217SJeff Kirsher 			/* Configure a single command in a ramrod data buffer */
1558adfc5217SJeff Kirsher 			o->set_one_rule(bp, o, elem, idx,
1559adfc5217SJeff Kirsher 					reg_elem->cam_offset);
1560adfc5217SJeff Kirsher 
1561adfc5217SJeff Kirsher 			/* MOVE command consumes 2 entries in the ramrod data */
1562adfc5217SJeff Kirsher 			if (cmd == BNX2X_VLAN_MAC_MOVE)
1563adfc5217SJeff Kirsher 				idx += 2;
1564adfc5217SJeff Kirsher 			else
1565adfc5217SJeff Kirsher 				idx++;
1566adfc5217SJeff Kirsher 		}
1567adfc5217SJeff Kirsher 
1568adfc5217SJeff Kirsher 		/*
1569adfc5217SJeff Kirsher 		 *  No need for an explicit memory barrier here as long we would
1570adfc5217SJeff Kirsher 		 *  need to ensure the ordering of writing to the SPQ element
1571adfc5217SJeff Kirsher 		 *  and updating of the SPQ producer which involves a memory
1572adfc5217SJeff Kirsher 		 *  read and we will have to put a full memory barrier there
1573adfc5217SJeff Kirsher 		 *  (inside bnx2x_sp_post()).
1574adfc5217SJeff Kirsher 		 */
1575adfc5217SJeff Kirsher 
1576adfc5217SJeff Kirsher 		rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid,
1577adfc5217SJeff Kirsher 				   U64_HI(r->rdata_mapping),
1578adfc5217SJeff Kirsher 				   U64_LO(r->rdata_mapping),
1579adfc5217SJeff Kirsher 				   ETH_CONNECTION_TYPE);
1580adfc5217SJeff Kirsher 		if (rc)
1581adfc5217SJeff Kirsher 			goto error_exit;
1582adfc5217SJeff Kirsher 	}
1583adfc5217SJeff Kirsher 
1584adfc5217SJeff Kirsher 	/* Now, when we are done with the ramrod - clean up the registry */
1585adfc5217SJeff Kirsher 	list_for_each_entry(elem, exe_chunk, link) {
1586adfc5217SJeff Kirsher 		cmd = elem->cmd_data.vlan_mac.cmd;
1587adfc5217SJeff Kirsher 		if ((cmd == BNX2X_VLAN_MAC_DEL) ||
1588adfc5217SJeff Kirsher 		    (cmd == BNX2X_VLAN_MAC_MOVE)) {
1589adfc5217SJeff Kirsher 			reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
1590adfc5217SJeff Kirsher 
1591adfc5217SJeff Kirsher 			WARN_ON(!reg_elem);
1592adfc5217SJeff Kirsher 
1593adfc5217SJeff Kirsher 			o->put_cam_offset(o, reg_elem->cam_offset);
1594adfc5217SJeff Kirsher 			list_del(&reg_elem->link);
1595adfc5217SJeff Kirsher 			kfree(reg_elem);
1596adfc5217SJeff Kirsher 		}
1597adfc5217SJeff Kirsher 	}
1598adfc5217SJeff Kirsher 
1599adfc5217SJeff Kirsher 	if (!drv_only)
1600adfc5217SJeff Kirsher 		return 1;
1601adfc5217SJeff Kirsher 	else
1602adfc5217SJeff Kirsher 		return 0;
1603adfc5217SJeff Kirsher 
1604adfc5217SJeff Kirsher error_exit:
1605adfc5217SJeff Kirsher 	r->clear_pending(r);
1606adfc5217SJeff Kirsher 
1607adfc5217SJeff Kirsher 	/* Cleanup a registry in case of a failure */
1608adfc5217SJeff Kirsher 	list_for_each_entry(elem, exe_chunk, link) {
1609adfc5217SJeff Kirsher 		cmd = elem->cmd_data.vlan_mac.cmd;
1610adfc5217SJeff Kirsher 
1611adfc5217SJeff Kirsher 		if (cmd == BNX2X_VLAN_MAC_MOVE)
1612adfc5217SJeff Kirsher 			cam_obj = elem->cmd_data.vlan_mac.target_obj;
1613adfc5217SJeff Kirsher 		else
1614adfc5217SJeff Kirsher 			cam_obj = o;
1615adfc5217SJeff Kirsher 
1616adfc5217SJeff Kirsher 		/* Delete all newly added above entries */
1617adfc5217SJeff Kirsher 		if (!restore &&
1618adfc5217SJeff Kirsher 		    ((cmd == BNX2X_VLAN_MAC_ADD) ||
1619adfc5217SJeff Kirsher 		    (cmd == BNX2X_VLAN_MAC_MOVE))) {
1620adfc5217SJeff Kirsher 			reg_elem = o->check_del(cam_obj,
1621adfc5217SJeff Kirsher 						&elem->cmd_data.vlan_mac.u);
1622adfc5217SJeff Kirsher 			if (reg_elem) {
1623adfc5217SJeff Kirsher 				list_del(&reg_elem->link);
1624adfc5217SJeff Kirsher 				kfree(reg_elem);
1625adfc5217SJeff Kirsher 			}
1626adfc5217SJeff Kirsher 		}
1627adfc5217SJeff Kirsher 	}
1628adfc5217SJeff Kirsher 
1629adfc5217SJeff Kirsher 	return rc;
1630adfc5217SJeff Kirsher }
1631adfc5217SJeff Kirsher 
1632adfc5217SJeff Kirsher static inline int bnx2x_vlan_mac_push_new_cmd(
1633adfc5217SJeff Kirsher 	struct bnx2x *bp,
1634adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_ramrod_params *p)
1635adfc5217SJeff Kirsher {
1636adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *elem;
1637adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
1638adfc5217SJeff Kirsher 	bool restore = test_bit(RAMROD_RESTORE, &p->ramrod_flags);
1639adfc5217SJeff Kirsher 
1640adfc5217SJeff Kirsher 	/* Allocate the execution queue element */
1641adfc5217SJeff Kirsher 	elem = bnx2x_exe_queue_alloc_elem(bp);
1642adfc5217SJeff Kirsher 	if (!elem)
1643adfc5217SJeff Kirsher 		return -ENOMEM;
1644adfc5217SJeff Kirsher 
1645adfc5217SJeff Kirsher 	/* Set the command 'length' */
1646adfc5217SJeff Kirsher 	switch (p->user_req.cmd) {
1647adfc5217SJeff Kirsher 	case BNX2X_VLAN_MAC_MOVE:
1648adfc5217SJeff Kirsher 		elem->cmd_len = 2;
1649adfc5217SJeff Kirsher 		break;
1650adfc5217SJeff Kirsher 	default:
1651adfc5217SJeff Kirsher 		elem->cmd_len = 1;
1652adfc5217SJeff Kirsher 	}
1653adfc5217SJeff Kirsher 
1654adfc5217SJeff Kirsher 	/* Fill the object specific info */
1655adfc5217SJeff Kirsher 	memcpy(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req));
1656adfc5217SJeff Kirsher 
1657adfc5217SJeff Kirsher 	/* Try to add a new command to the pending list */
1658adfc5217SJeff Kirsher 	return bnx2x_exe_queue_add(bp, &o->exe_queue, elem, restore);
1659adfc5217SJeff Kirsher }
1660adfc5217SJeff Kirsher 
1661adfc5217SJeff Kirsher /**
1662adfc5217SJeff Kirsher  * bnx2x_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules.
1663adfc5217SJeff Kirsher  *
1664adfc5217SJeff Kirsher  * @bp:	  device handle
1665adfc5217SJeff Kirsher  * @p:
1666adfc5217SJeff Kirsher  *
1667adfc5217SJeff Kirsher  */
1668adfc5217SJeff Kirsher int bnx2x_config_vlan_mac(
1669adfc5217SJeff Kirsher 	struct bnx2x *bp,
1670adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_ramrod_params *p)
1671adfc5217SJeff Kirsher {
1672adfc5217SJeff Kirsher 	int rc = 0;
1673adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
1674adfc5217SJeff Kirsher 	unsigned long *ramrod_flags = &p->ramrod_flags;
1675adfc5217SJeff Kirsher 	bool cont = test_bit(RAMROD_CONT, ramrod_flags);
1676adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
1677adfc5217SJeff Kirsher 
1678adfc5217SJeff Kirsher 	/*
1679adfc5217SJeff Kirsher 	 * Add new elements to the execution list for commands that require it.
1680adfc5217SJeff Kirsher 	 */
1681adfc5217SJeff Kirsher 	if (!cont) {
1682adfc5217SJeff Kirsher 		rc = bnx2x_vlan_mac_push_new_cmd(bp, p);
1683adfc5217SJeff Kirsher 		if (rc)
1684adfc5217SJeff Kirsher 			return rc;
1685adfc5217SJeff Kirsher 	}
1686adfc5217SJeff Kirsher 
1687adfc5217SJeff Kirsher 	/*
1688adfc5217SJeff Kirsher 	 * If nothing will be executed further in this iteration we want to
1689adfc5217SJeff Kirsher 	 * return PENDING if there are pending commands
1690adfc5217SJeff Kirsher 	 */
1691adfc5217SJeff Kirsher 	if (!bnx2x_exe_queue_empty(&o->exe_queue))
1692adfc5217SJeff Kirsher 		rc = 1;
1693adfc5217SJeff Kirsher 
1694adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags))  {
1695adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: "
1696adfc5217SJeff Kirsher 				 "clearing a pending bit.\n");
1697adfc5217SJeff Kirsher 		raw->clear_pending(raw);
1698adfc5217SJeff Kirsher 	}
1699adfc5217SJeff Kirsher 
1700adfc5217SJeff Kirsher 	/* Execute commands if required */
1701adfc5217SJeff Kirsher 	if (cont || test_bit(RAMROD_EXEC, ramrod_flags) ||
1702adfc5217SJeff Kirsher 	    test_bit(RAMROD_COMP_WAIT, ramrod_flags)) {
1703adfc5217SJeff Kirsher 		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
1704adfc5217SJeff Kirsher 		if (rc < 0)
1705adfc5217SJeff Kirsher 			return rc;
1706adfc5217SJeff Kirsher 	}
1707adfc5217SJeff Kirsher 
1708adfc5217SJeff Kirsher 	/*
1709adfc5217SJeff Kirsher 	 * RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
1710adfc5217SJeff Kirsher 	 * then user want to wait until the last command is done.
1711adfc5217SJeff Kirsher 	 */
1712adfc5217SJeff Kirsher 	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
1713adfc5217SJeff Kirsher 		/*
1714adfc5217SJeff Kirsher 		 * Wait maximum for the current exe_queue length iterations plus
1715adfc5217SJeff Kirsher 		 * one (for the current pending command).
1716adfc5217SJeff Kirsher 		 */
1717adfc5217SJeff Kirsher 		int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1;
1718adfc5217SJeff Kirsher 
1719adfc5217SJeff Kirsher 		while (!bnx2x_exe_queue_empty(&o->exe_queue) &&
1720adfc5217SJeff Kirsher 		       max_iterations--) {
1721adfc5217SJeff Kirsher 
1722adfc5217SJeff Kirsher 			/* Wait for the current command to complete */
1723adfc5217SJeff Kirsher 			rc = raw->wait_comp(bp, raw);
1724adfc5217SJeff Kirsher 			if (rc)
1725adfc5217SJeff Kirsher 				return rc;
1726adfc5217SJeff Kirsher 
1727adfc5217SJeff Kirsher 			/* Make a next step */
1728adfc5217SJeff Kirsher 			rc = bnx2x_exe_queue_step(bp, &o->exe_queue,
1729adfc5217SJeff Kirsher 						  ramrod_flags);
1730adfc5217SJeff Kirsher 			if (rc < 0)
1731adfc5217SJeff Kirsher 				return rc;
1732adfc5217SJeff Kirsher 		}
1733adfc5217SJeff Kirsher 
1734adfc5217SJeff Kirsher 		return 0;
1735adfc5217SJeff Kirsher 	}
1736adfc5217SJeff Kirsher 
1737adfc5217SJeff Kirsher 	return rc;
1738adfc5217SJeff Kirsher }
1739adfc5217SJeff Kirsher 
1740adfc5217SJeff Kirsher 
1741adfc5217SJeff Kirsher 
1742adfc5217SJeff Kirsher /**
1743adfc5217SJeff Kirsher  * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec
1744adfc5217SJeff Kirsher  *
1745adfc5217SJeff Kirsher  * @bp:			device handle
1746adfc5217SJeff Kirsher  * @o:
1747adfc5217SJeff Kirsher  * @vlan_mac_flags:
1748adfc5217SJeff Kirsher  * @ramrod_flags:	execution flags to be used for this deletion
1749adfc5217SJeff Kirsher  *
1750adfc5217SJeff Kirsher  * if the last operation has completed successfully and there are no
1751adfc5217SJeff Kirsher  * moreelements left, positive value if the last operation has completed
1752adfc5217SJeff Kirsher  * successfully and there are more previously configured elements, negative
1753adfc5217SJeff Kirsher  * value is current operation has failed.
1754adfc5217SJeff Kirsher  */
1755adfc5217SJeff Kirsher static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
1756adfc5217SJeff Kirsher 				  struct bnx2x_vlan_mac_obj *o,
1757adfc5217SJeff Kirsher 				  unsigned long *vlan_mac_flags,
1758adfc5217SJeff Kirsher 				  unsigned long *ramrod_flags)
1759adfc5217SJeff Kirsher {
1760adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_registry_elem *pos = NULL;
1761adfc5217SJeff Kirsher 	int rc = 0;
1762adfc5217SJeff Kirsher 	struct bnx2x_vlan_mac_ramrod_params p;
1763adfc5217SJeff Kirsher 	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
1764adfc5217SJeff Kirsher 	struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
1765adfc5217SJeff Kirsher 
1766adfc5217SJeff Kirsher 	/* Clear pending commands first */
1767adfc5217SJeff Kirsher 
1768adfc5217SJeff Kirsher 	spin_lock_bh(&exeq->lock);
1769adfc5217SJeff Kirsher 
1770adfc5217SJeff Kirsher 	list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
1771adfc5217SJeff Kirsher 		if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
1772adfc5217SJeff Kirsher 		    *vlan_mac_flags)
1773adfc5217SJeff Kirsher 			list_del(&exeq_pos->link);
1774adfc5217SJeff Kirsher 	}
1775adfc5217SJeff Kirsher 
1776adfc5217SJeff Kirsher 	spin_unlock_bh(&exeq->lock);
1777adfc5217SJeff Kirsher 
1778adfc5217SJeff Kirsher 	/* Prepare a command request */
1779adfc5217SJeff Kirsher 	memset(&p, 0, sizeof(p));
1780adfc5217SJeff Kirsher 	p.vlan_mac_obj = o;
1781adfc5217SJeff Kirsher 	p.ramrod_flags = *ramrod_flags;
1782adfc5217SJeff Kirsher 	p.user_req.cmd = BNX2X_VLAN_MAC_DEL;
1783adfc5217SJeff Kirsher 
1784adfc5217SJeff Kirsher 	/*
1785adfc5217SJeff Kirsher 	 * Add all but the last VLAN-MAC to the execution queue without actually
1786adfc5217SJeff Kirsher 	 * execution anything.
1787adfc5217SJeff Kirsher 	 */
1788adfc5217SJeff Kirsher 	__clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags);
1789adfc5217SJeff Kirsher 	__clear_bit(RAMROD_EXEC, &p.ramrod_flags);
1790adfc5217SJeff Kirsher 	__clear_bit(RAMROD_CONT, &p.ramrod_flags);
1791adfc5217SJeff Kirsher 
1792adfc5217SJeff Kirsher 	list_for_each_entry(pos, &o->head, link) {
1793adfc5217SJeff Kirsher 		if (pos->vlan_mac_flags == *vlan_mac_flags) {
1794adfc5217SJeff Kirsher 			p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
1795adfc5217SJeff Kirsher 			memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
1796adfc5217SJeff Kirsher 			rc = bnx2x_config_vlan_mac(bp, &p);
1797adfc5217SJeff Kirsher 			if (rc < 0) {
1798adfc5217SJeff Kirsher 				BNX2X_ERR("Failed to add a new DEL command\n");
1799adfc5217SJeff Kirsher 				return rc;
1800adfc5217SJeff Kirsher 			}
1801adfc5217SJeff Kirsher 		}
1802adfc5217SJeff Kirsher 	}
1803adfc5217SJeff Kirsher 
1804adfc5217SJeff Kirsher 	p.ramrod_flags = *ramrod_flags;
1805adfc5217SJeff Kirsher 	__set_bit(RAMROD_CONT, &p.ramrod_flags);
1806adfc5217SJeff Kirsher 
1807adfc5217SJeff Kirsher 	return bnx2x_config_vlan_mac(bp, &p);
1808adfc5217SJeff Kirsher }
1809adfc5217SJeff Kirsher 
1810adfc5217SJeff Kirsher static inline void bnx2x_init_raw_obj(struct bnx2x_raw_obj *raw, u8 cl_id,
1811adfc5217SJeff Kirsher 	u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping, int state,
1812adfc5217SJeff Kirsher 	unsigned long *pstate, bnx2x_obj_type type)
1813adfc5217SJeff Kirsher {
1814adfc5217SJeff Kirsher 	raw->func_id = func_id;
1815adfc5217SJeff Kirsher 	raw->cid = cid;
1816adfc5217SJeff Kirsher 	raw->cl_id = cl_id;
1817adfc5217SJeff Kirsher 	raw->rdata = rdata;
1818adfc5217SJeff Kirsher 	raw->rdata_mapping = rdata_mapping;
1819adfc5217SJeff Kirsher 	raw->state = state;
1820adfc5217SJeff Kirsher 	raw->pstate = pstate;
1821adfc5217SJeff Kirsher 	raw->obj_type = type;
1822adfc5217SJeff Kirsher 	raw->check_pending = bnx2x_raw_check_pending;
1823adfc5217SJeff Kirsher 	raw->clear_pending = bnx2x_raw_clear_pending;
1824adfc5217SJeff Kirsher 	raw->set_pending = bnx2x_raw_set_pending;
1825adfc5217SJeff Kirsher 	raw->wait_comp = bnx2x_raw_wait;
1826adfc5217SJeff Kirsher }
1827adfc5217SJeff Kirsher 
1828adfc5217SJeff Kirsher static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o,
1829adfc5217SJeff Kirsher 	u8 cl_id, u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping,
1830adfc5217SJeff Kirsher 	int state, unsigned long *pstate, bnx2x_obj_type type,
1831adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *macs_pool,
1832adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *vlans_pool)
1833adfc5217SJeff Kirsher {
1834adfc5217SJeff Kirsher 	INIT_LIST_HEAD(&o->head);
1835adfc5217SJeff Kirsher 
1836adfc5217SJeff Kirsher 	o->macs_pool = macs_pool;
1837adfc5217SJeff Kirsher 	o->vlans_pool = vlans_pool;
1838adfc5217SJeff Kirsher 
1839adfc5217SJeff Kirsher 	o->delete_all = bnx2x_vlan_mac_del_all;
1840adfc5217SJeff Kirsher 	o->restore = bnx2x_vlan_mac_restore;
1841adfc5217SJeff Kirsher 	o->complete = bnx2x_complete_vlan_mac;
1842adfc5217SJeff Kirsher 	o->wait = bnx2x_wait_vlan_mac;
1843adfc5217SJeff Kirsher 
1844adfc5217SJeff Kirsher 	bnx2x_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping,
1845adfc5217SJeff Kirsher 			   state, pstate, type);
1846adfc5217SJeff Kirsher }
1847adfc5217SJeff Kirsher 
1848adfc5217SJeff Kirsher 
1849adfc5217SJeff Kirsher void bnx2x_init_mac_obj(struct bnx2x *bp,
1850adfc5217SJeff Kirsher 			struct bnx2x_vlan_mac_obj *mac_obj,
1851adfc5217SJeff Kirsher 			u8 cl_id, u32 cid, u8 func_id, void *rdata,
1852adfc5217SJeff Kirsher 			dma_addr_t rdata_mapping, int state,
1853adfc5217SJeff Kirsher 			unsigned long *pstate, bnx2x_obj_type type,
1854adfc5217SJeff Kirsher 			struct bnx2x_credit_pool_obj *macs_pool)
1855adfc5217SJeff Kirsher {
1856adfc5217SJeff Kirsher 	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)mac_obj;
1857adfc5217SJeff Kirsher 
1858adfc5217SJeff Kirsher 	bnx2x_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata,
1859adfc5217SJeff Kirsher 				   rdata_mapping, state, pstate, type,
1860adfc5217SJeff Kirsher 				   macs_pool, NULL);
1861adfc5217SJeff Kirsher 
1862adfc5217SJeff Kirsher 	/* CAM credit pool handling */
1863adfc5217SJeff Kirsher 	mac_obj->get_credit = bnx2x_get_credit_mac;
1864adfc5217SJeff Kirsher 	mac_obj->put_credit = bnx2x_put_credit_mac;
1865adfc5217SJeff Kirsher 	mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
1866adfc5217SJeff Kirsher 	mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
1867adfc5217SJeff Kirsher 
1868adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp)) {
1869adfc5217SJeff Kirsher 		mac_obj->set_one_rule      = bnx2x_set_one_mac_e1x;
1870adfc5217SJeff Kirsher 		mac_obj->check_del         = bnx2x_check_mac_del;
1871adfc5217SJeff Kirsher 		mac_obj->check_add         = bnx2x_check_mac_add;
1872adfc5217SJeff Kirsher 		mac_obj->check_move        = bnx2x_check_move_always_err;
1873adfc5217SJeff Kirsher 		mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
1874adfc5217SJeff Kirsher 
1875adfc5217SJeff Kirsher 		/* Exe Queue */
1876adfc5217SJeff Kirsher 		bnx2x_exe_queue_init(bp,
1877adfc5217SJeff Kirsher 				     &mac_obj->exe_queue, 1, qable_obj,
1878adfc5217SJeff Kirsher 				     bnx2x_validate_vlan_mac,
1879adfc5217SJeff Kirsher 				     bnx2x_optimize_vlan_mac,
1880adfc5217SJeff Kirsher 				     bnx2x_execute_vlan_mac,
1881adfc5217SJeff Kirsher 				     bnx2x_exeq_get_mac);
1882adfc5217SJeff Kirsher 	} else {
1883adfc5217SJeff Kirsher 		mac_obj->set_one_rule      = bnx2x_set_one_mac_e2;
1884adfc5217SJeff Kirsher 		mac_obj->check_del         = bnx2x_check_mac_del;
1885adfc5217SJeff Kirsher 		mac_obj->check_add         = bnx2x_check_mac_add;
1886adfc5217SJeff Kirsher 		mac_obj->check_move        = bnx2x_check_move;
1887adfc5217SJeff Kirsher 		mac_obj->ramrod_cmd        =
1888adfc5217SJeff Kirsher 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
1889adfc5217SJeff Kirsher 
1890adfc5217SJeff Kirsher 		/* Exe Queue */
1891adfc5217SJeff Kirsher 		bnx2x_exe_queue_init(bp,
1892adfc5217SJeff Kirsher 				     &mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
1893adfc5217SJeff Kirsher 				     qable_obj, bnx2x_validate_vlan_mac,
1894adfc5217SJeff Kirsher 				     bnx2x_optimize_vlan_mac,
1895adfc5217SJeff Kirsher 				     bnx2x_execute_vlan_mac,
1896adfc5217SJeff Kirsher 				     bnx2x_exeq_get_mac);
1897adfc5217SJeff Kirsher 	}
1898adfc5217SJeff Kirsher }
1899adfc5217SJeff Kirsher 
1900adfc5217SJeff Kirsher void bnx2x_init_vlan_obj(struct bnx2x *bp,
1901adfc5217SJeff Kirsher 			 struct bnx2x_vlan_mac_obj *vlan_obj,
1902adfc5217SJeff Kirsher 			 u8 cl_id, u32 cid, u8 func_id, void *rdata,
1903adfc5217SJeff Kirsher 			 dma_addr_t rdata_mapping, int state,
1904adfc5217SJeff Kirsher 			 unsigned long *pstate, bnx2x_obj_type type,
1905adfc5217SJeff Kirsher 			 struct bnx2x_credit_pool_obj *vlans_pool)
1906adfc5217SJeff Kirsher {
1907adfc5217SJeff Kirsher 	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)vlan_obj;
1908adfc5217SJeff Kirsher 
1909adfc5217SJeff Kirsher 	bnx2x_init_vlan_mac_common(vlan_obj, cl_id, cid, func_id, rdata,
1910adfc5217SJeff Kirsher 				   rdata_mapping, state, pstate, type, NULL,
1911adfc5217SJeff Kirsher 				   vlans_pool);
1912adfc5217SJeff Kirsher 
1913adfc5217SJeff Kirsher 	vlan_obj->get_credit = bnx2x_get_credit_vlan;
1914adfc5217SJeff Kirsher 	vlan_obj->put_credit = bnx2x_put_credit_vlan;
1915adfc5217SJeff Kirsher 	vlan_obj->get_cam_offset = bnx2x_get_cam_offset_vlan;
1916adfc5217SJeff Kirsher 	vlan_obj->put_cam_offset = bnx2x_put_cam_offset_vlan;
1917adfc5217SJeff Kirsher 
1918adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp)) {
1919adfc5217SJeff Kirsher 		BNX2X_ERR("Do not support chips others than E2 and newer\n");
1920adfc5217SJeff Kirsher 		BUG();
1921adfc5217SJeff Kirsher 	} else {
1922adfc5217SJeff Kirsher 		vlan_obj->set_one_rule      = bnx2x_set_one_vlan_e2;
1923adfc5217SJeff Kirsher 		vlan_obj->check_del         = bnx2x_check_vlan_del;
1924adfc5217SJeff Kirsher 		vlan_obj->check_add         = bnx2x_check_vlan_add;
1925adfc5217SJeff Kirsher 		vlan_obj->check_move        = bnx2x_check_move;
1926adfc5217SJeff Kirsher 		vlan_obj->ramrod_cmd        =
1927adfc5217SJeff Kirsher 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
1928adfc5217SJeff Kirsher 
1929adfc5217SJeff Kirsher 		/* Exe Queue */
1930adfc5217SJeff Kirsher 		bnx2x_exe_queue_init(bp,
1931adfc5217SJeff Kirsher 				     &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
1932adfc5217SJeff Kirsher 				     qable_obj, bnx2x_validate_vlan_mac,
1933adfc5217SJeff Kirsher 				     bnx2x_optimize_vlan_mac,
1934adfc5217SJeff Kirsher 				     bnx2x_execute_vlan_mac,
1935adfc5217SJeff Kirsher 				     bnx2x_exeq_get_vlan);
1936adfc5217SJeff Kirsher 	}
1937adfc5217SJeff Kirsher }
1938adfc5217SJeff Kirsher 
1939adfc5217SJeff Kirsher void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
1940adfc5217SJeff Kirsher 			     struct bnx2x_vlan_mac_obj *vlan_mac_obj,
1941adfc5217SJeff Kirsher 			     u8 cl_id, u32 cid, u8 func_id, void *rdata,
1942adfc5217SJeff Kirsher 			     dma_addr_t rdata_mapping, int state,
1943adfc5217SJeff Kirsher 			     unsigned long *pstate, bnx2x_obj_type type,
1944adfc5217SJeff Kirsher 			     struct bnx2x_credit_pool_obj *macs_pool,
1945adfc5217SJeff Kirsher 			     struct bnx2x_credit_pool_obj *vlans_pool)
1946adfc5217SJeff Kirsher {
1947adfc5217SJeff Kirsher 	union bnx2x_qable_obj *qable_obj =
1948adfc5217SJeff Kirsher 		(union bnx2x_qable_obj *)vlan_mac_obj;
1949adfc5217SJeff Kirsher 
1950adfc5217SJeff Kirsher 	bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
1951adfc5217SJeff Kirsher 				   rdata_mapping, state, pstate, type,
1952adfc5217SJeff Kirsher 				   macs_pool, vlans_pool);
1953adfc5217SJeff Kirsher 
1954adfc5217SJeff Kirsher 	/* CAM pool handling */
1955adfc5217SJeff Kirsher 	vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac;
1956adfc5217SJeff Kirsher 	vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac;
1957adfc5217SJeff Kirsher 	/*
1958adfc5217SJeff Kirsher 	 * CAM offset is relevant for 57710 and 57711 chips only which have a
1959adfc5217SJeff Kirsher 	 * single CAM for both MACs and VLAN-MAC pairs. So the offset
1960adfc5217SJeff Kirsher 	 * will be taken from MACs' pool object only.
1961adfc5217SJeff Kirsher 	 */
1962adfc5217SJeff Kirsher 	vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
1963adfc5217SJeff Kirsher 	vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
1964adfc5217SJeff Kirsher 
1965adfc5217SJeff Kirsher 	if (CHIP_IS_E1(bp)) {
1966adfc5217SJeff Kirsher 		BNX2X_ERR("Do not support chips others than E2\n");
1967adfc5217SJeff Kirsher 		BUG();
1968adfc5217SJeff Kirsher 	} else if (CHIP_IS_E1H(bp)) {
1969adfc5217SJeff Kirsher 		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e1h;
1970adfc5217SJeff Kirsher 		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
1971adfc5217SJeff Kirsher 		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
1972adfc5217SJeff Kirsher 		vlan_mac_obj->check_move        = bnx2x_check_move_always_err;
1973adfc5217SJeff Kirsher 		vlan_mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
1974adfc5217SJeff Kirsher 
1975adfc5217SJeff Kirsher 		/* Exe Queue */
1976adfc5217SJeff Kirsher 		bnx2x_exe_queue_init(bp,
1977adfc5217SJeff Kirsher 				     &vlan_mac_obj->exe_queue, 1, qable_obj,
1978adfc5217SJeff Kirsher 				     bnx2x_validate_vlan_mac,
1979adfc5217SJeff Kirsher 				     bnx2x_optimize_vlan_mac,
1980adfc5217SJeff Kirsher 				     bnx2x_execute_vlan_mac,
1981adfc5217SJeff Kirsher 				     bnx2x_exeq_get_vlan_mac);
1982adfc5217SJeff Kirsher 	} else {
1983adfc5217SJeff Kirsher 		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e2;
1984adfc5217SJeff Kirsher 		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
1985adfc5217SJeff Kirsher 		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
1986adfc5217SJeff Kirsher 		vlan_mac_obj->check_move        = bnx2x_check_move;
1987adfc5217SJeff Kirsher 		vlan_mac_obj->ramrod_cmd        =
1988adfc5217SJeff Kirsher 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
1989adfc5217SJeff Kirsher 
1990adfc5217SJeff Kirsher 		/* Exe Queue */
1991adfc5217SJeff Kirsher 		bnx2x_exe_queue_init(bp,
1992adfc5217SJeff Kirsher 				     &vlan_mac_obj->exe_queue,
1993adfc5217SJeff Kirsher 				     CLASSIFY_RULES_COUNT,
1994adfc5217SJeff Kirsher 				     qable_obj, bnx2x_validate_vlan_mac,
1995adfc5217SJeff Kirsher 				     bnx2x_optimize_vlan_mac,
1996adfc5217SJeff Kirsher 				     bnx2x_execute_vlan_mac,
1997adfc5217SJeff Kirsher 				     bnx2x_exeq_get_vlan_mac);
1998adfc5217SJeff Kirsher 	}
1999adfc5217SJeff Kirsher 
2000adfc5217SJeff Kirsher }
2001adfc5217SJeff Kirsher 
2002adfc5217SJeff Kirsher /* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
2003adfc5217SJeff Kirsher static inline void __storm_memset_mac_filters(struct bnx2x *bp,
2004adfc5217SJeff Kirsher 			struct tstorm_eth_mac_filter_config *mac_filters,
2005adfc5217SJeff Kirsher 			u16 pf_id)
2006adfc5217SJeff Kirsher {
2007adfc5217SJeff Kirsher 	size_t size = sizeof(struct tstorm_eth_mac_filter_config);
2008adfc5217SJeff Kirsher 
2009adfc5217SJeff Kirsher 	u32 addr = BAR_TSTRORM_INTMEM +
2010adfc5217SJeff Kirsher 			TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id);
2011adfc5217SJeff Kirsher 
2012adfc5217SJeff Kirsher 	__storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
2013adfc5217SJeff Kirsher }
2014adfc5217SJeff Kirsher 
2015adfc5217SJeff Kirsher static int bnx2x_set_rx_mode_e1x(struct bnx2x *bp,
2016adfc5217SJeff Kirsher 				 struct bnx2x_rx_mode_ramrod_params *p)
2017adfc5217SJeff Kirsher {
2018adfc5217SJeff Kirsher 	/* update the bp MAC filter structure  */
2019adfc5217SJeff Kirsher 	u32 mask = (1 << p->cl_id);
2020adfc5217SJeff Kirsher 
2021adfc5217SJeff Kirsher 	struct tstorm_eth_mac_filter_config *mac_filters =
2022adfc5217SJeff Kirsher 		(struct tstorm_eth_mac_filter_config *)p->rdata;
2023adfc5217SJeff Kirsher 
2024adfc5217SJeff Kirsher 	/* initial seeting is drop-all */
2025adfc5217SJeff Kirsher 	u8 drop_all_ucast = 1, drop_all_mcast = 1;
2026adfc5217SJeff Kirsher 	u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
2027adfc5217SJeff Kirsher 	u8 unmatched_unicast = 0;
2028adfc5217SJeff Kirsher 
2029adfc5217SJeff Kirsher     /* In e1x there we only take into account rx acceot flag since tx switching
2030adfc5217SJeff Kirsher      * isn't enabled. */
2031adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags))
2032adfc5217SJeff Kirsher 		/* accept matched ucast */
2033adfc5217SJeff Kirsher 		drop_all_ucast = 0;
2034adfc5217SJeff Kirsher 
2035adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_MULTICAST, &p->rx_accept_flags))
2036adfc5217SJeff Kirsher 		/* accept matched mcast */
2037adfc5217SJeff Kirsher 		drop_all_mcast = 0;
2038adfc5217SJeff Kirsher 
2039adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) {
2040adfc5217SJeff Kirsher 		/* accept all mcast */
2041adfc5217SJeff Kirsher 		drop_all_ucast = 0;
2042adfc5217SJeff Kirsher 		accp_all_ucast = 1;
2043adfc5217SJeff Kirsher 	}
2044adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) {
2045adfc5217SJeff Kirsher 		/* accept all mcast */
2046adfc5217SJeff Kirsher 		drop_all_mcast = 0;
2047adfc5217SJeff Kirsher 		accp_all_mcast = 1;
2048adfc5217SJeff Kirsher 	}
2049adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_BROADCAST, &p->rx_accept_flags))
2050adfc5217SJeff Kirsher 		/* accept (all) bcast */
2051adfc5217SJeff Kirsher 		accp_all_bcast = 1;
2052adfc5217SJeff Kirsher 	if (test_bit(BNX2X_ACCEPT_UNMATCHED, &p->rx_accept_flags))
2053adfc5217SJeff Kirsher 		/* accept unmatched unicasts */
2054adfc5217SJeff Kirsher 		unmatched_unicast = 1;
2055adfc5217SJeff Kirsher 
2056adfc5217SJeff Kirsher 	mac_filters->ucast_drop_all = drop_all_ucast ?
2057adfc5217SJeff Kirsher 		mac_filters->ucast_drop_all | mask :
2058adfc5217SJeff Kirsher 		mac_filters->ucast_drop_all & ~mask;
2059adfc5217SJeff Kirsher 
2060adfc5217SJeff Kirsher 	mac_filters->mcast_drop_all = drop_all_mcast ?
2061adfc5217SJeff Kirsher 		mac_filters->mcast_drop_all | mask :
2062adfc5217SJeff Kirsher 		mac_filters->mcast_drop_all & ~mask;
2063adfc5217SJeff Kirsher 
2064adfc5217SJeff Kirsher 	mac_filters->ucast_accept_all = accp_all_ucast ?
2065adfc5217SJeff Kirsher 		mac_filters->ucast_accept_all | mask :
2066adfc5217SJeff Kirsher 		mac_filters->ucast_accept_all & ~mask;
2067adfc5217SJeff Kirsher 
2068adfc5217SJeff Kirsher 	mac_filters->mcast_accept_all = accp_all_mcast ?
2069adfc5217SJeff Kirsher 		mac_filters->mcast_accept_all | mask :
2070adfc5217SJeff Kirsher 		mac_filters->mcast_accept_all & ~mask;
2071adfc5217SJeff Kirsher 
2072adfc5217SJeff Kirsher 	mac_filters->bcast_accept_all = accp_all_bcast ?
2073adfc5217SJeff Kirsher 		mac_filters->bcast_accept_all | mask :
2074adfc5217SJeff Kirsher 		mac_filters->bcast_accept_all & ~mask;
2075adfc5217SJeff Kirsher 
2076adfc5217SJeff Kirsher 	mac_filters->unmatched_unicast = unmatched_unicast ?
2077adfc5217SJeff Kirsher 		mac_filters->unmatched_unicast | mask :
2078adfc5217SJeff Kirsher 		mac_filters->unmatched_unicast & ~mask;
2079adfc5217SJeff Kirsher 
2080adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "drop_ucast 0x%x\ndrop_mcast 0x%x\n accp_ucast 0x%x\n"
2081adfc5217SJeff Kirsher 			 "accp_mcast 0x%x\naccp_bcast 0x%x\n",
2082adfc5217SJeff Kirsher 			 mac_filters->ucast_drop_all,
2083adfc5217SJeff Kirsher 			 mac_filters->mcast_drop_all,
2084adfc5217SJeff Kirsher 			 mac_filters->ucast_accept_all,
2085adfc5217SJeff Kirsher 			 mac_filters->mcast_accept_all,
2086adfc5217SJeff Kirsher 			 mac_filters->bcast_accept_all);
2087adfc5217SJeff Kirsher 
2088adfc5217SJeff Kirsher 	/* write the MAC filter structure*/
2089adfc5217SJeff Kirsher 	__storm_memset_mac_filters(bp, mac_filters, p->func_id);
2090adfc5217SJeff Kirsher 
2091adfc5217SJeff Kirsher 	/* The operation is completed */
2092adfc5217SJeff Kirsher 	clear_bit(p->state, p->pstate);
2093adfc5217SJeff Kirsher 	smp_mb__after_clear_bit();
2094adfc5217SJeff Kirsher 
2095adfc5217SJeff Kirsher 	return 0;
2096adfc5217SJeff Kirsher }
2097adfc5217SJeff Kirsher 
2098adfc5217SJeff Kirsher /* Setup ramrod data */
2099adfc5217SJeff Kirsher static inline void bnx2x_rx_mode_set_rdata_hdr_e2(u32 cid,
2100adfc5217SJeff Kirsher 				struct eth_classify_header *hdr,
2101adfc5217SJeff Kirsher 				u8 rule_cnt)
2102adfc5217SJeff Kirsher {
2103adfc5217SJeff Kirsher 	hdr->echo = cid;
2104adfc5217SJeff Kirsher 	hdr->rule_cnt = rule_cnt;
2105adfc5217SJeff Kirsher }
2106adfc5217SJeff Kirsher 
2107adfc5217SJeff Kirsher static inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp,
2108adfc5217SJeff Kirsher 				unsigned long accept_flags,
2109adfc5217SJeff Kirsher 				struct eth_filter_rules_cmd *cmd,
2110adfc5217SJeff Kirsher 				bool clear_accept_all)
2111adfc5217SJeff Kirsher {
2112adfc5217SJeff Kirsher 	u16 state;
2113adfc5217SJeff Kirsher 
2114adfc5217SJeff Kirsher 	/* start with 'drop-all' */
2115adfc5217SJeff Kirsher 	state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL |
2116adfc5217SJeff Kirsher 		ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
2117adfc5217SJeff Kirsher 
2118adfc5217SJeff Kirsher 	if (accept_flags) {
2119adfc5217SJeff Kirsher 		if (test_bit(BNX2X_ACCEPT_UNICAST, &accept_flags))
2120adfc5217SJeff Kirsher 			state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
2121adfc5217SJeff Kirsher 
2122adfc5217SJeff Kirsher 		if (test_bit(BNX2X_ACCEPT_MULTICAST, &accept_flags))
2123adfc5217SJeff Kirsher 			state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
2124adfc5217SJeff Kirsher 
2125adfc5217SJeff Kirsher 		if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &accept_flags)) {
2126adfc5217SJeff Kirsher 			state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
2127adfc5217SJeff Kirsher 			state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
2128adfc5217SJeff Kirsher 		}
2129adfc5217SJeff Kirsher 
2130adfc5217SJeff Kirsher 		if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags)) {
2131adfc5217SJeff Kirsher 			state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
2132adfc5217SJeff Kirsher 			state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
2133adfc5217SJeff Kirsher 		}
2134adfc5217SJeff Kirsher 		if (test_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags))
2135adfc5217SJeff Kirsher 			state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
2136adfc5217SJeff Kirsher 
2137adfc5217SJeff Kirsher 		if (test_bit(BNX2X_ACCEPT_UNMATCHED, &accept_flags)) {
2138adfc5217SJeff Kirsher 			state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
2139adfc5217SJeff Kirsher 			state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
2140adfc5217SJeff Kirsher 		}
2141adfc5217SJeff Kirsher 		if (test_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags))
2142adfc5217SJeff Kirsher 			state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN;
2143adfc5217SJeff Kirsher 	}
2144adfc5217SJeff Kirsher 
2145adfc5217SJeff Kirsher 	/* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */
2146adfc5217SJeff Kirsher 	if (clear_accept_all) {
2147adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
2148adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
2149adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
2150adfc5217SJeff Kirsher 		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
2151adfc5217SJeff Kirsher 	}
2152adfc5217SJeff Kirsher 
2153adfc5217SJeff Kirsher 	cmd->state = cpu_to_le16(state);
2154adfc5217SJeff Kirsher 
2155adfc5217SJeff Kirsher }
2156adfc5217SJeff Kirsher 
2157adfc5217SJeff Kirsher static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
2158adfc5217SJeff Kirsher 				struct bnx2x_rx_mode_ramrod_params *p)
2159adfc5217SJeff Kirsher {
2160adfc5217SJeff Kirsher 	struct eth_filter_rules_ramrod_data *data = p->rdata;
2161adfc5217SJeff Kirsher 	int rc;
2162adfc5217SJeff Kirsher 	u8 rule_idx = 0;
2163adfc5217SJeff Kirsher 
2164adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer */
2165adfc5217SJeff Kirsher 	memset(data, 0, sizeof(*data));
2166adfc5217SJeff Kirsher 
2167adfc5217SJeff Kirsher 	/* Setup ramrod data */
2168adfc5217SJeff Kirsher 
2169adfc5217SJeff Kirsher 	/* Tx (internal switching) */
2170adfc5217SJeff Kirsher 	if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
2171adfc5217SJeff Kirsher 		data->rules[rule_idx].client_id = p->cl_id;
2172adfc5217SJeff Kirsher 		data->rules[rule_idx].func_id = p->func_id;
2173adfc5217SJeff Kirsher 
2174adfc5217SJeff Kirsher 		data->rules[rule_idx].cmd_general_data =
2175adfc5217SJeff Kirsher 			ETH_FILTER_RULES_CMD_TX_CMD;
2176adfc5217SJeff Kirsher 
2177adfc5217SJeff Kirsher 		bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
2178adfc5217SJeff Kirsher 			&(data->rules[rule_idx++]), false);
2179adfc5217SJeff Kirsher 	}
2180adfc5217SJeff Kirsher 
2181adfc5217SJeff Kirsher 	/* Rx */
2182adfc5217SJeff Kirsher 	if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
2183adfc5217SJeff Kirsher 		data->rules[rule_idx].client_id = p->cl_id;
2184adfc5217SJeff Kirsher 		data->rules[rule_idx].func_id = p->func_id;
2185adfc5217SJeff Kirsher 
2186adfc5217SJeff Kirsher 		data->rules[rule_idx].cmd_general_data =
2187adfc5217SJeff Kirsher 			ETH_FILTER_RULES_CMD_RX_CMD;
2188adfc5217SJeff Kirsher 
2189adfc5217SJeff Kirsher 		bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
2190adfc5217SJeff Kirsher 			&(data->rules[rule_idx++]), false);
2191adfc5217SJeff Kirsher 	}
2192adfc5217SJeff Kirsher 
2193adfc5217SJeff Kirsher 
2194adfc5217SJeff Kirsher 	/*
2195adfc5217SJeff Kirsher 	 * If FCoE Queue configuration has been requested configure the Rx and
2196adfc5217SJeff Kirsher 	 * internal switching modes for this queue in separate rules.
2197adfc5217SJeff Kirsher 	 *
2198adfc5217SJeff Kirsher 	 * FCoE queue shell never be set to ACCEPT_ALL packets of any sort:
2199adfc5217SJeff Kirsher 	 * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED.
2200adfc5217SJeff Kirsher 	 */
2201adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) {
2202adfc5217SJeff Kirsher 		/*  Tx (internal switching) */
2203adfc5217SJeff Kirsher 		if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
2204adfc5217SJeff Kirsher 			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
2205adfc5217SJeff Kirsher 			data->rules[rule_idx].func_id = p->func_id;
2206adfc5217SJeff Kirsher 
2207adfc5217SJeff Kirsher 			data->rules[rule_idx].cmd_general_data =
2208adfc5217SJeff Kirsher 						ETH_FILTER_RULES_CMD_TX_CMD;
2209adfc5217SJeff Kirsher 
2210adfc5217SJeff Kirsher 			bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
2211adfc5217SJeff Kirsher 						     &(data->rules[rule_idx++]),
2212adfc5217SJeff Kirsher 						       true);
2213adfc5217SJeff Kirsher 		}
2214adfc5217SJeff Kirsher 
2215adfc5217SJeff Kirsher 		/* Rx */
2216adfc5217SJeff Kirsher 		if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
2217adfc5217SJeff Kirsher 			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
2218adfc5217SJeff Kirsher 			data->rules[rule_idx].func_id = p->func_id;
2219adfc5217SJeff Kirsher 
2220adfc5217SJeff Kirsher 			data->rules[rule_idx].cmd_general_data =
2221adfc5217SJeff Kirsher 						ETH_FILTER_RULES_CMD_RX_CMD;
2222adfc5217SJeff Kirsher 
2223adfc5217SJeff Kirsher 			bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
2224adfc5217SJeff Kirsher 						     &(data->rules[rule_idx++]),
2225adfc5217SJeff Kirsher 						       true);
2226adfc5217SJeff Kirsher 		}
2227adfc5217SJeff Kirsher 	}
2228adfc5217SJeff Kirsher 
2229adfc5217SJeff Kirsher 	/*
2230adfc5217SJeff Kirsher 	 * Set the ramrod header (most importantly - number of rules to
2231adfc5217SJeff Kirsher 	 * configure).
2232adfc5217SJeff Kirsher 	 */
2233adfc5217SJeff Kirsher 	bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx);
2234adfc5217SJeff Kirsher 
2235adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "About to configure %d rules, rx_accept_flags 0x%lx, "
2236adfc5217SJeff Kirsher 			 "tx_accept_flags 0x%lx\n",
2237adfc5217SJeff Kirsher 			 data->header.rule_cnt, p->rx_accept_flags,
2238adfc5217SJeff Kirsher 			 p->tx_accept_flags);
2239adfc5217SJeff Kirsher 
2240adfc5217SJeff Kirsher 	/*
2241adfc5217SJeff Kirsher 	 *  No need for an explicit memory barrier here as long we would
2242adfc5217SJeff Kirsher 	 *  need to ensure the ordering of writing to the SPQ element
2243adfc5217SJeff Kirsher 	 *  and updating of the SPQ producer which involves a memory
2244adfc5217SJeff Kirsher 	 *  read and we will have to put a full memory barrier there
2245adfc5217SJeff Kirsher 	 *  (inside bnx2x_sp_post()).
2246adfc5217SJeff Kirsher 	 */
2247adfc5217SJeff Kirsher 
2248adfc5217SJeff Kirsher 	/* Send a ramrod */
2249adfc5217SJeff Kirsher 	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid,
2250adfc5217SJeff Kirsher 			   U64_HI(p->rdata_mapping),
2251adfc5217SJeff Kirsher 			   U64_LO(p->rdata_mapping),
2252adfc5217SJeff Kirsher 			   ETH_CONNECTION_TYPE);
2253adfc5217SJeff Kirsher 	if (rc)
2254adfc5217SJeff Kirsher 		return rc;
2255adfc5217SJeff Kirsher 
2256adfc5217SJeff Kirsher 	/* Ramrod completion is pending */
2257adfc5217SJeff Kirsher 	return 1;
2258adfc5217SJeff Kirsher }
2259adfc5217SJeff Kirsher 
2260adfc5217SJeff Kirsher static int bnx2x_wait_rx_mode_comp_e2(struct bnx2x *bp,
2261adfc5217SJeff Kirsher 				      struct bnx2x_rx_mode_ramrod_params *p)
2262adfc5217SJeff Kirsher {
2263adfc5217SJeff Kirsher 	return bnx2x_state_wait(bp, p->state, p->pstate);
2264adfc5217SJeff Kirsher }
2265adfc5217SJeff Kirsher 
2266adfc5217SJeff Kirsher static int bnx2x_empty_rx_mode_wait(struct bnx2x *bp,
2267adfc5217SJeff Kirsher 				    struct bnx2x_rx_mode_ramrod_params *p)
2268adfc5217SJeff Kirsher {
2269adfc5217SJeff Kirsher 	/* Do nothing */
2270adfc5217SJeff Kirsher 	return 0;
2271adfc5217SJeff Kirsher }
2272adfc5217SJeff Kirsher 
2273adfc5217SJeff Kirsher int bnx2x_config_rx_mode(struct bnx2x *bp,
2274adfc5217SJeff Kirsher 			 struct bnx2x_rx_mode_ramrod_params *p)
2275adfc5217SJeff Kirsher {
2276adfc5217SJeff Kirsher 	int rc;
2277adfc5217SJeff Kirsher 
2278adfc5217SJeff Kirsher 	/* Configure the new classification in the chip */
2279adfc5217SJeff Kirsher 	rc = p->rx_mode_obj->config_rx_mode(bp, p);
2280adfc5217SJeff Kirsher 	if (rc < 0)
2281adfc5217SJeff Kirsher 		return rc;
2282adfc5217SJeff Kirsher 
2283adfc5217SJeff Kirsher 	/* Wait for a ramrod completion if was requested */
2284adfc5217SJeff Kirsher 	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
2285adfc5217SJeff Kirsher 		rc = p->rx_mode_obj->wait_comp(bp, p);
2286adfc5217SJeff Kirsher 		if (rc)
2287adfc5217SJeff Kirsher 			return rc;
2288adfc5217SJeff Kirsher 	}
2289adfc5217SJeff Kirsher 
2290adfc5217SJeff Kirsher 	return rc;
2291adfc5217SJeff Kirsher }
2292adfc5217SJeff Kirsher 
2293adfc5217SJeff Kirsher void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
2294adfc5217SJeff Kirsher 			    struct bnx2x_rx_mode_obj *o)
2295adfc5217SJeff Kirsher {
2296adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp)) {
2297adfc5217SJeff Kirsher 		o->wait_comp      = bnx2x_empty_rx_mode_wait;
2298adfc5217SJeff Kirsher 		o->config_rx_mode = bnx2x_set_rx_mode_e1x;
2299adfc5217SJeff Kirsher 	} else {
2300adfc5217SJeff Kirsher 		o->wait_comp      = bnx2x_wait_rx_mode_comp_e2;
2301adfc5217SJeff Kirsher 		o->config_rx_mode = bnx2x_set_rx_mode_e2;
2302adfc5217SJeff Kirsher 	}
2303adfc5217SJeff Kirsher }
2304adfc5217SJeff Kirsher 
2305adfc5217SJeff Kirsher /********************* Multicast verbs: SET, CLEAR ****************************/
2306adfc5217SJeff Kirsher static inline u8 bnx2x_mcast_bin_from_mac(u8 *mac)
2307adfc5217SJeff Kirsher {
2308adfc5217SJeff Kirsher 	return (crc32c_le(0, mac, ETH_ALEN) >> 24) & 0xff;
2309adfc5217SJeff Kirsher }
2310adfc5217SJeff Kirsher 
2311adfc5217SJeff Kirsher struct bnx2x_mcast_mac_elem {
2312adfc5217SJeff Kirsher 	struct list_head link;
2313adfc5217SJeff Kirsher 	u8 mac[ETH_ALEN];
2314adfc5217SJeff Kirsher 	u8 pad[2]; /* For a natural alignment of the following buffer */
2315adfc5217SJeff Kirsher };
2316adfc5217SJeff Kirsher 
2317adfc5217SJeff Kirsher struct bnx2x_pending_mcast_cmd {
2318adfc5217SJeff Kirsher 	struct list_head link;
2319adfc5217SJeff Kirsher 	int type; /* BNX2X_MCAST_CMD_X */
2320adfc5217SJeff Kirsher 	union {
2321adfc5217SJeff Kirsher 		struct list_head macs_head;
2322adfc5217SJeff Kirsher 		u32 macs_num; /* Needed for DEL command */
2323adfc5217SJeff Kirsher 		int next_bin; /* Needed for RESTORE flow with aprox match */
2324adfc5217SJeff Kirsher 	} data;
2325adfc5217SJeff Kirsher 
2326adfc5217SJeff Kirsher 	bool done; /* set to true, when the command has been handled,
2327adfc5217SJeff Kirsher 		    * practically used in 57712 handling only, where one pending
2328adfc5217SJeff Kirsher 		    * command may be handled in a few operations. As long as for
2329adfc5217SJeff Kirsher 		    * other chips every operation handling is completed in a
2330adfc5217SJeff Kirsher 		    * single ramrod, there is no need to utilize this field.
2331adfc5217SJeff Kirsher 		    */
2332adfc5217SJeff Kirsher };
2333adfc5217SJeff Kirsher 
2334adfc5217SJeff Kirsher static int bnx2x_mcast_wait(struct bnx2x *bp,
2335adfc5217SJeff Kirsher 			    struct bnx2x_mcast_obj *o)
2336adfc5217SJeff Kirsher {
2337adfc5217SJeff Kirsher 	if (bnx2x_state_wait(bp, o->sched_state, o->raw.pstate) ||
2338adfc5217SJeff Kirsher 			o->raw.wait_comp(bp, &o->raw))
2339adfc5217SJeff Kirsher 		return -EBUSY;
2340adfc5217SJeff Kirsher 
2341adfc5217SJeff Kirsher 	return 0;
2342adfc5217SJeff Kirsher }
2343adfc5217SJeff Kirsher 
2344adfc5217SJeff Kirsher static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
2345adfc5217SJeff Kirsher 				   struct bnx2x_mcast_obj *o,
2346adfc5217SJeff Kirsher 				   struct bnx2x_mcast_ramrod_params *p,
2347adfc5217SJeff Kirsher 				   int cmd)
2348adfc5217SJeff Kirsher {
2349adfc5217SJeff Kirsher 	int total_sz;
2350adfc5217SJeff Kirsher 	struct bnx2x_pending_mcast_cmd *new_cmd;
2351adfc5217SJeff Kirsher 	struct bnx2x_mcast_mac_elem *cur_mac = NULL;
2352adfc5217SJeff Kirsher 	struct bnx2x_mcast_list_elem *pos;
2353adfc5217SJeff Kirsher 	int macs_list_len = ((cmd == BNX2X_MCAST_CMD_ADD) ?
2354adfc5217SJeff Kirsher 			     p->mcast_list_len : 0);
2355adfc5217SJeff Kirsher 
2356adfc5217SJeff Kirsher 	/* If the command is empty ("handle pending commands only"), break */
2357adfc5217SJeff Kirsher 	if (!p->mcast_list_len)
2358adfc5217SJeff Kirsher 		return 0;
2359adfc5217SJeff Kirsher 
2360adfc5217SJeff Kirsher 	total_sz = sizeof(*new_cmd) +
2361adfc5217SJeff Kirsher 		macs_list_len * sizeof(struct bnx2x_mcast_mac_elem);
2362adfc5217SJeff Kirsher 
2363adfc5217SJeff Kirsher 	/* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
2364adfc5217SJeff Kirsher 	new_cmd = kzalloc(total_sz, GFP_ATOMIC);
2365adfc5217SJeff Kirsher 
2366adfc5217SJeff Kirsher 	if (!new_cmd)
2367adfc5217SJeff Kirsher 		return -ENOMEM;
2368adfc5217SJeff Kirsher 
2369adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "About to enqueue a new %d command. "
2370adfc5217SJeff Kirsher 			 "macs_list_len=%d\n", cmd, macs_list_len);
2371adfc5217SJeff Kirsher 
2372adfc5217SJeff Kirsher 	INIT_LIST_HEAD(&new_cmd->data.macs_head);
2373adfc5217SJeff Kirsher 
2374adfc5217SJeff Kirsher 	new_cmd->type = cmd;
2375adfc5217SJeff Kirsher 	new_cmd->done = false;
2376adfc5217SJeff Kirsher 
2377adfc5217SJeff Kirsher 	switch (cmd) {
2378adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
2379adfc5217SJeff Kirsher 		cur_mac = (struct bnx2x_mcast_mac_elem *)
2380adfc5217SJeff Kirsher 			  ((u8 *)new_cmd + sizeof(*new_cmd));
2381adfc5217SJeff Kirsher 
2382adfc5217SJeff Kirsher 		/* Push the MACs of the current command into the pendig command
2383adfc5217SJeff Kirsher 		 * MACs list: FIFO
2384adfc5217SJeff Kirsher 		 */
2385adfc5217SJeff Kirsher 		list_for_each_entry(pos, &p->mcast_list, link) {
2386adfc5217SJeff Kirsher 			memcpy(cur_mac->mac, pos->mac, ETH_ALEN);
2387adfc5217SJeff Kirsher 			list_add_tail(&cur_mac->link, &new_cmd->data.macs_head);
2388adfc5217SJeff Kirsher 			cur_mac++;
2389adfc5217SJeff Kirsher 		}
2390adfc5217SJeff Kirsher 
2391adfc5217SJeff Kirsher 		break;
2392adfc5217SJeff Kirsher 
2393adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
2394adfc5217SJeff Kirsher 		new_cmd->data.macs_num = p->mcast_list_len;
2395adfc5217SJeff Kirsher 		break;
2396adfc5217SJeff Kirsher 
2397adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
2398adfc5217SJeff Kirsher 		new_cmd->data.next_bin = 0;
2399adfc5217SJeff Kirsher 		break;
2400adfc5217SJeff Kirsher 
2401adfc5217SJeff Kirsher 	default:
2402adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
2403adfc5217SJeff Kirsher 		return -EINVAL;
2404adfc5217SJeff Kirsher 	}
2405adfc5217SJeff Kirsher 
2406adfc5217SJeff Kirsher 	/* Push the new pending command to the tail of the pending list: FIFO */
2407adfc5217SJeff Kirsher 	list_add_tail(&new_cmd->link, &o->pending_cmds_head);
2408adfc5217SJeff Kirsher 
2409adfc5217SJeff Kirsher 	o->set_sched(o);
2410adfc5217SJeff Kirsher 
2411adfc5217SJeff Kirsher 	return 1;
2412adfc5217SJeff Kirsher }
2413adfc5217SJeff Kirsher 
2414adfc5217SJeff Kirsher /**
2415adfc5217SJeff Kirsher  * bnx2x_mcast_get_next_bin - get the next set bin (index)
2416adfc5217SJeff Kirsher  *
2417adfc5217SJeff Kirsher  * @o:
2418adfc5217SJeff Kirsher  * @last:	index to start looking from (including)
2419adfc5217SJeff Kirsher  *
2420adfc5217SJeff Kirsher  * returns the next found (set) bin or a negative value if none is found.
2421adfc5217SJeff Kirsher  */
2422adfc5217SJeff Kirsher static inline int bnx2x_mcast_get_next_bin(struct bnx2x_mcast_obj *o, int last)
2423adfc5217SJeff Kirsher {
2424adfc5217SJeff Kirsher 	int i, j, inner_start = last % BIT_VEC64_ELEM_SZ;
2425adfc5217SJeff Kirsher 
2426adfc5217SJeff Kirsher 	for (i = last / BIT_VEC64_ELEM_SZ; i < BNX2X_MCAST_VEC_SZ; i++) {
2427adfc5217SJeff Kirsher 		if (o->registry.aprox_match.vec[i])
2428adfc5217SJeff Kirsher 			for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) {
2429adfc5217SJeff Kirsher 				int cur_bit = j + BIT_VEC64_ELEM_SZ * i;
2430adfc5217SJeff Kirsher 				if (BIT_VEC64_TEST_BIT(o->registry.aprox_match.
2431adfc5217SJeff Kirsher 						       vec, cur_bit)) {
2432adfc5217SJeff Kirsher 					return cur_bit;
2433adfc5217SJeff Kirsher 				}
2434adfc5217SJeff Kirsher 			}
2435adfc5217SJeff Kirsher 		inner_start = 0;
2436adfc5217SJeff Kirsher 	}
2437adfc5217SJeff Kirsher 
2438adfc5217SJeff Kirsher 	/* None found */
2439adfc5217SJeff Kirsher 	return -1;
2440adfc5217SJeff Kirsher }
2441adfc5217SJeff Kirsher 
2442adfc5217SJeff Kirsher /**
2443adfc5217SJeff Kirsher  * bnx2x_mcast_clear_first_bin - find the first set bin and clear it
2444adfc5217SJeff Kirsher  *
2445adfc5217SJeff Kirsher  * @o:
2446adfc5217SJeff Kirsher  *
2447adfc5217SJeff Kirsher  * returns the index of the found bin or -1 if none is found
2448adfc5217SJeff Kirsher  */
2449adfc5217SJeff Kirsher static inline int bnx2x_mcast_clear_first_bin(struct bnx2x_mcast_obj *o)
2450adfc5217SJeff Kirsher {
2451adfc5217SJeff Kirsher 	int cur_bit = bnx2x_mcast_get_next_bin(o, 0);
2452adfc5217SJeff Kirsher 
2453adfc5217SJeff Kirsher 	if (cur_bit >= 0)
2454adfc5217SJeff Kirsher 		BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit);
2455adfc5217SJeff Kirsher 
2456adfc5217SJeff Kirsher 	return cur_bit;
2457adfc5217SJeff Kirsher }
2458adfc5217SJeff Kirsher 
2459adfc5217SJeff Kirsher static inline u8 bnx2x_mcast_get_rx_tx_flag(struct bnx2x_mcast_obj *o)
2460adfc5217SJeff Kirsher {
2461adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
2462adfc5217SJeff Kirsher 	u8 rx_tx_flag = 0;
2463adfc5217SJeff Kirsher 
2464adfc5217SJeff Kirsher 	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
2465adfc5217SJeff Kirsher 	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
2466adfc5217SJeff Kirsher 		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD;
2467adfc5217SJeff Kirsher 
2468adfc5217SJeff Kirsher 	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
2469adfc5217SJeff Kirsher 	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
2470adfc5217SJeff Kirsher 		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD;
2471adfc5217SJeff Kirsher 
2472adfc5217SJeff Kirsher 	return rx_tx_flag;
2473adfc5217SJeff Kirsher }
2474adfc5217SJeff Kirsher 
2475adfc5217SJeff Kirsher static void bnx2x_mcast_set_one_rule_e2(struct bnx2x *bp,
2476adfc5217SJeff Kirsher 					struct bnx2x_mcast_obj *o, int idx,
2477adfc5217SJeff Kirsher 					union bnx2x_mcast_config_data *cfg_data,
2478adfc5217SJeff Kirsher 					int cmd)
2479adfc5217SJeff Kirsher {
2480adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
2481adfc5217SJeff Kirsher 	struct eth_multicast_rules_ramrod_data *data =
2482adfc5217SJeff Kirsher 		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
2483adfc5217SJeff Kirsher 	u8 func_id = r->func_id;
2484adfc5217SJeff Kirsher 	u8 rx_tx_add_flag = bnx2x_mcast_get_rx_tx_flag(o);
2485adfc5217SJeff Kirsher 	int bin;
2486adfc5217SJeff Kirsher 
2487adfc5217SJeff Kirsher 	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE))
2488adfc5217SJeff Kirsher 		rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD;
2489adfc5217SJeff Kirsher 
2490adfc5217SJeff Kirsher 	data->rules[idx].cmd_general_data |= rx_tx_add_flag;
2491adfc5217SJeff Kirsher 
2492adfc5217SJeff Kirsher 	/* Get a bin and update a bins' vector */
2493adfc5217SJeff Kirsher 	switch (cmd) {
2494adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
2495adfc5217SJeff Kirsher 		bin = bnx2x_mcast_bin_from_mac(cfg_data->mac);
2496adfc5217SJeff Kirsher 		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
2497adfc5217SJeff Kirsher 		break;
2498adfc5217SJeff Kirsher 
2499adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
2500adfc5217SJeff Kirsher 		/* If there were no more bins to clear
2501adfc5217SJeff Kirsher 		 * (bnx2x_mcast_clear_first_bin() returns -1) then we would
2502adfc5217SJeff Kirsher 		 * clear any (0xff) bin.
2503adfc5217SJeff Kirsher 		 * See bnx2x_mcast_validate_e2() for explanation when it may
2504adfc5217SJeff Kirsher 		 * happen.
2505adfc5217SJeff Kirsher 		 */
2506adfc5217SJeff Kirsher 		bin = bnx2x_mcast_clear_first_bin(o);
2507adfc5217SJeff Kirsher 		break;
2508adfc5217SJeff Kirsher 
2509adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
2510adfc5217SJeff Kirsher 		bin = cfg_data->bin;
2511adfc5217SJeff Kirsher 		break;
2512adfc5217SJeff Kirsher 
2513adfc5217SJeff Kirsher 	default:
2514adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
2515adfc5217SJeff Kirsher 		return;
2516adfc5217SJeff Kirsher 	}
2517adfc5217SJeff Kirsher 
2518adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "%s bin %d\n",
2519adfc5217SJeff Kirsher 			 ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ?
2520adfc5217SJeff Kirsher 			 "Setting"  : "Clearing"), bin);
2521adfc5217SJeff Kirsher 
2522adfc5217SJeff Kirsher 	data->rules[idx].bin_id    = (u8)bin;
2523adfc5217SJeff Kirsher 	data->rules[idx].func_id   = func_id;
2524adfc5217SJeff Kirsher 	data->rules[idx].engine_id = o->engine_id;
2525adfc5217SJeff Kirsher }
2526adfc5217SJeff Kirsher 
2527adfc5217SJeff Kirsher /**
2528adfc5217SJeff Kirsher  * bnx2x_mcast_handle_restore_cmd_e2 - restore configuration from the registry
2529adfc5217SJeff Kirsher  *
2530adfc5217SJeff Kirsher  * @bp:		device handle
2531adfc5217SJeff Kirsher  * @o:
2532adfc5217SJeff Kirsher  * @start_bin:	index in the registry to start from (including)
2533adfc5217SJeff Kirsher  * @rdata_idx:	index in the ramrod data to start from
2534adfc5217SJeff Kirsher  *
2535adfc5217SJeff Kirsher  * returns last handled bin index or -1 if all bins have been handled
2536adfc5217SJeff Kirsher  */
2537adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_restore_cmd_e2(
2538adfc5217SJeff Kirsher 	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_bin,
2539adfc5217SJeff Kirsher 	int *rdata_idx)
2540adfc5217SJeff Kirsher {
2541adfc5217SJeff Kirsher 	int cur_bin, cnt = *rdata_idx;
2542adfc5217SJeff Kirsher 	union bnx2x_mcast_config_data cfg_data = {0};
2543adfc5217SJeff Kirsher 
2544adfc5217SJeff Kirsher 	/* go through the registry and configure the bins from it */
2545adfc5217SJeff Kirsher 	for (cur_bin = bnx2x_mcast_get_next_bin(o, start_bin); cur_bin >= 0;
2546adfc5217SJeff Kirsher 	    cur_bin = bnx2x_mcast_get_next_bin(o, cur_bin + 1)) {
2547adfc5217SJeff Kirsher 
2548adfc5217SJeff Kirsher 		cfg_data.bin = (u8)cur_bin;
2549adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, &cfg_data,
2550adfc5217SJeff Kirsher 				BNX2X_MCAST_CMD_RESTORE);
2551adfc5217SJeff Kirsher 
2552adfc5217SJeff Kirsher 		cnt++;
2553adfc5217SJeff Kirsher 
2554adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "About to configure a bin %d\n", cur_bin);
2555adfc5217SJeff Kirsher 
2556adfc5217SJeff Kirsher 		/* Break if we reached the maximum number
2557adfc5217SJeff Kirsher 		 * of rules.
2558adfc5217SJeff Kirsher 		 */
2559adfc5217SJeff Kirsher 		if (cnt >= o->max_cmd_len)
2560adfc5217SJeff Kirsher 			break;
2561adfc5217SJeff Kirsher 	}
2562adfc5217SJeff Kirsher 
2563adfc5217SJeff Kirsher 	*rdata_idx = cnt;
2564adfc5217SJeff Kirsher 
2565adfc5217SJeff Kirsher 	return cur_bin;
2566adfc5217SJeff Kirsher }
2567adfc5217SJeff Kirsher 
2568adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp,
2569adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
2570adfc5217SJeff Kirsher 	int *line_idx)
2571adfc5217SJeff Kirsher {
2572adfc5217SJeff Kirsher 	struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
2573adfc5217SJeff Kirsher 	int cnt = *line_idx;
2574adfc5217SJeff Kirsher 	union bnx2x_mcast_config_data cfg_data = {0};
2575adfc5217SJeff Kirsher 
2576adfc5217SJeff Kirsher 	list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head,
2577adfc5217SJeff Kirsher 				 link) {
2578adfc5217SJeff Kirsher 
2579adfc5217SJeff Kirsher 		cfg_data.mac = &pmac_pos->mac[0];
2580adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
2581adfc5217SJeff Kirsher 
2582adfc5217SJeff Kirsher 		cnt++;
2583adfc5217SJeff Kirsher 
25840f9dad10SJoe Perches 		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
25850f9dad10SJoe Perches 				 pmac_pos->mac);
2586adfc5217SJeff Kirsher 
2587adfc5217SJeff Kirsher 		list_del(&pmac_pos->link);
2588adfc5217SJeff Kirsher 
2589adfc5217SJeff Kirsher 		/* Break if we reached the maximum number
2590adfc5217SJeff Kirsher 		 * of rules.
2591adfc5217SJeff Kirsher 		 */
2592adfc5217SJeff Kirsher 		if (cnt >= o->max_cmd_len)
2593adfc5217SJeff Kirsher 			break;
2594adfc5217SJeff Kirsher 	}
2595adfc5217SJeff Kirsher 
2596adfc5217SJeff Kirsher 	*line_idx = cnt;
2597adfc5217SJeff Kirsher 
2598adfc5217SJeff Kirsher 	/* if no more MACs to configure - we are done */
2599adfc5217SJeff Kirsher 	if (list_empty(&cmd_pos->data.macs_head))
2600adfc5217SJeff Kirsher 		cmd_pos->done = true;
2601adfc5217SJeff Kirsher }
2602adfc5217SJeff Kirsher 
2603adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp,
2604adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
2605adfc5217SJeff Kirsher 	int *line_idx)
2606adfc5217SJeff Kirsher {
2607adfc5217SJeff Kirsher 	int cnt = *line_idx;
2608adfc5217SJeff Kirsher 
2609adfc5217SJeff Kirsher 	while (cmd_pos->data.macs_num) {
2610adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, NULL, cmd_pos->type);
2611adfc5217SJeff Kirsher 
2612adfc5217SJeff Kirsher 		cnt++;
2613adfc5217SJeff Kirsher 
2614adfc5217SJeff Kirsher 		cmd_pos->data.macs_num--;
2615adfc5217SJeff Kirsher 
2616adfc5217SJeff Kirsher 		  DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n",
2617adfc5217SJeff Kirsher 				   cmd_pos->data.macs_num, cnt);
2618adfc5217SJeff Kirsher 
2619adfc5217SJeff Kirsher 		/* Break if we reached the maximum
2620adfc5217SJeff Kirsher 		 * number of rules.
2621adfc5217SJeff Kirsher 		 */
2622adfc5217SJeff Kirsher 		if (cnt >= o->max_cmd_len)
2623adfc5217SJeff Kirsher 			break;
2624adfc5217SJeff Kirsher 	}
2625adfc5217SJeff Kirsher 
2626adfc5217SJeff Kirsher 	*line_idx = cnt;
2627adfc5217SJeff Kirsher 
2628adfc5217SJeff Kirsher 	/* If we cleared all bins - we are done */
2629adfc5217SJeff Kirsher 	if (!cmd_pos->data.macs_num)
2630adfc5217SJeff Kirsher 		cmd_pos->done = true;
2631adfc5217SJeff Kirsher }
2632adfc5217SJeff Kirsher 
2633adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_pending_restore_e2(struct bnx2x *bp,
2634adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
2635adfc5217SJeff Kirsher 	int *line_idx)
2636adfc5217SJeff Kirsher {
2637adfc5217SJeff Kirsher 	cmd_pos->data.next_bin = o->hdl_restore(bp, o, cmd_pos->data.next_bin,
2638adfc5217SJeff Kirsher 						line_idx);
2639adfc5217SJeff Kirsher 
2640adfc5217SJeff Kirsher 	if (cmd_pos->data.next_bin < 0)
2641adfc5217SJeff Kirsher 		/* If o->set_restore returned -1 we are done */
2642adfc5217SJeff Kirsher 		cmd_pos->done = true;
2643adfc5217SJeff Kirsher 	else
2644adfc5217SJeff Kirsher 		/* Start from the next bin next time */
2645adfc5217SJeff Kirsher 		cmd_pos->data.next_bin++;
2646adfc5217SJeff Kirsher }
2647adfc5217SJeff Kirsher 
2648adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x *bp,
2649adfc5217SJeff Kirsher 				struct bnx2x_mcast_ramrod_params *p)
2650adfc5217SJeff Kirsher {
2651adfc5217SJeff Kirsher 	struct bnx2x_pending_mcast_cmd *cmd_pos, *cmd_pos_n;
2652adfc5217SJeff Kirsher 	int cnt = 0;
2653adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
2654adfc5217SJeff Kirsher 
2655adfc5217SJeff Kirsher 	list_for_each_entry_safe(cmd_pos, cmd_pos_n, &o->pending_cmds_head,
2656adfc5217SJeff Kirsher 				 link) {
2657adfc5217SJeff Kirsher 		switch (cmd_pos->type) {
2658adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_ADD:
2659adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_pending_add_e2(bp, o, cmd_pos, &cnt);
2660adfc5217SJeff Kirsher 			break;
2661adfc5217SJeff Kirsher 
2662adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_DEL:
2663adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_pending_del_e2(bp, o, cmd_pos, &cnt);
2664adfc5217SJeff Kirsher 			break;
2665adfc5217SJeff Kirsher 
2666adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_RESTORE:
2667adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_pending_restore_e2(bp, o, cmd_pos,
2668adfc5217SJeff Kirsher 							   &cnt);
2669adfc5217SJeff Kirsher 			break;
2670adfc5217SJeff Kirsher 
2671adfc5217SJeff Kirsher 		default:
2672adfc5217SJeff Kirsher 			BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
2673adfc5217SJeff Kirsher 			return -EINVAL;
2674adfc5217SJeff Kirsher 		}
2675adfc5217SJeff Kirsher 
2676adfc5217SJeff Kirsher 		/* If the command has been completed - remove it from the list
2677adfc5217SJeff Kirsher 		 * and free the memory
2678adfc5217SJeff Kirsher 		 */
2679adfc5217SJeff Kirsher 		if (cmd_pos->done) {
2680adfc5217SJeff Kirsher 			list_del(&cmd_pos->link);
2681adfc5217SJeff Kirsher 			kfree(cmd_pos);
2682adfc5217SJeff Kirsher 		}
2683adfc5217SJeff Kirsher 
2684adfc5217SJeff Kirsher 		/* Break if we reached the maximum number of rules */
2685adfc5217SJeff Kirsher 		if (cnt >= o->max_cmd_len)
2686adfc5217SJeff Kirsher 			break;
2687adfc5217SJeff Kirsher 	}
2688adfc5217SJeff Kirsher 
2689adfc5217SJeff Kirsher 	return cnt;
2690adfc5217SJeff Kirsher }
2691adfc5217SJeff Kirsher 
2692adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_add(struct bnx2x *bp,
2693adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
2694adfc5217SJeff Kirsher 	int *line_idx)
2695adfc5217SJeff Kirsher {
2696adfc5217SJeff Kirsher 	struct bnx2x_mcast_list_elem *mlist_pos;
2697adfc5217SJeff Kirsher 	union bnx2x_mcast_config_data cfg_data = {0};
2698adfc5217SJeff Kirsher 	int cnt = *line_idx;
2699adfc5217SJeff Kirsher 
2700adfc5217SJeff Kirsher 	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
2701adfc5217SJeff Kirsher 		cfg_data.mac = mlist_pos->mac;
2702adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, &cfg_data, BNX2X_MCAST_CMD_ADD);
2703adfc5217SJeff Kirsher 
2704adfc5217SJeff Kirsher 		cnt++;
2705adfc5217SJeff Kirsher 
27060f9dad10SJoe Perches 		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
27070f9dad10SJoe Perches 				 mlist_pos->mac);
2708adfc5217SJeff Kirsher 	}
2709adfc5217SJeff Kirsher 
2710adfc5217SJeff Kirsher 	*line_idx = cnt;
2711adfc5217SJeff Kirsher }
2712adfc5217SJeff Kirsher 
2713adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_del(struct bnx2x *bp,
2714adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
2715adfc5217SJeff Kirsher 	int *line_idx)
2716adfc5217SJeff Kirsher {
2717adfc5217SJeff Kirsher 	int cnt = *line_idx, i;
2718adfc5217SJeff Kirsher 
2719adfc5217SJeff Kirsher 	for (i = 0; i < p->mcast_list_len; i++) {
2720adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, cnt, NULL, BNX2X_MCAST_CMD_DEL);
2721adfc5217SJeff Kirsher 
2722adfc5217SJeff Kirsher 		cnt++;
2723adfc5217SJeff Kirsher 
2724adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Deleting MAC. %d left\n",
2725adfc5217SJeff Kirsher 				 p->mcast_list_len - i - 1);
2726adfc5217SJeff Kirsher 	}
2727adfc5217SJeff Kirsher 
2728adfc5217SJeff Kirsher 	*line_idx = cnt;
2729adfc5217SJeff Kirsher }
2730adfc5217SJeff Kirsher 
2731adfc5217SJeff Kirsher /**
2732adfc5217SJeff Kirsher  * bnx2x_mcast_handle_current_cmd -
2733adfc5217SJeff Kirsher  *
2734adfc5217SJeff Kirsher  * @bp:		device handle
2735adfc5217SJeff Kirsher  * @p:
2736adfc5217SJeff Kirsher  * @cmd:
2737adfc5217SJeff Kirsher  * @start_cnt:	first line in the ramrod data that may be used
2738adfc5217SJeff Kirsher  *
2739adfc5217SJeff Kirsher  * This function is called iff there is enough place for the current command in
2740adfc5217SJeff Kirsher  * the ramrod data.
2741adfc5217SJeff Kirsher  * Returns number of lines filled in the ramrod data in total.
2742adfc5217SJeff Kirsher  */
2743adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_current_cmd(struct bnx2x *bp,
2744adfc5217SJeff Kirsher 			struct bnx2x_mcast_ramrod_params *p, int cmd,
2745adfc5217SJeff Kirsher 			int start_cnt)
2746adfc5217SJeff Kirsher {
2747adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
2748adfc5217SJeff Kirsher 	int cnt = start_cnt;
2749adfc5217SJeff Kirsher 
2750adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
2751adfc5217SJeff Kirsher 
2752adfc5217SJeff Kirsher 	switch (cmd) {
2753adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
2754adfc5217SJeff Kirsher 		bnx2x_mcast_hdl_add(bp, o, p, &cnt);
2755adfc5217SJeff Kirsher 		break;
2756adfc5217SJeff Kirsher 
2757adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
2758adfc5217SJeff Kirsher 		bnx2x_mcast_hdl_del(bp, o, p, &cnt);
2759adfc5217SJeff Kirsher 		break;
2760adfc5217SJeff Kirsher 
2761adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
2762adfc5217SJeff Kirsher 		o->hdl_restore(bp, o, 0, &cnt);
2763adfc5217SJeff Kirsher 		break;
2764adfc5217SJeff Kirsher 
2765adfc5217SJeff Kirsher 	default:
2766adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
2767adfc5217SJeff Kirsher 		return -EINVAL;
2768adfc5217SJeff Kirsher 	}
2769adfc5217SJeff Kirsher 
2770adfc5217SJeff Kirsher 	/* The current command has been handled */
2771adfc5217SJeff Kirsher 	p->mcast_list_len = 0;
2772adfc5217SJeff Kirsher 
2773adfc5217SJeff Kirsher 	return cnt;
2774adfc5217SJeff Kirsher }
2775adfc5217SJeff Kirsher 
2776adfc5217SJeff Kirsher static int bnx2x_mcast_validate_e2(struct bnx2x *bp,
2777adfc5217SJeff Kirsher 				   struct bnx2x_mcast_ramrod_params *p,
2778adfc5217SJeff Kirsher 				   int cmd)
2779adfc5217SJeff Kirsher {
2780adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
2781adfc5217SJeff Kirsher 	int reg_sz = o->get_registry_size(o);
2782adfc5217SJeff Kirsher 
2783adfc5217SJeff Kirsher 	switch (cmd) {
2784adfc5217SJeff Kirsher 	/* DEL command deletes all currently configured MACs */
2785adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
2786adfc5217SJeff Kirsher 		o->set_registry_size(o, 0);
2787adfc5217SJeff Kirsher 		/* Don't break */
2788adfc5217SJeff Kirsher 
2789adfc5217SJeff Kirsher 	/* RESTORE command will restore the entire multicast configuration */
2790adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
2791adfc5217SJeff Kirsher 		/* Here we set the approximate amount of work to do, which in
2792adfc5217SJeff Kirsher 		 * fact may be only less as some MACs in postponed ADD
2793adfc5217SJeff Kirsher 		 * command(s) scheduled before this command may fall into
2794adfc5217SJeff Kirsher 		 * the same bin and the actual number of bins set in the
2795adfc5217SJeff Kirsher 		 * registry would be less than we estimated here. See
2796adfc5217SJeff Kirsher 		 * bnx2x_mcast_set_one_rule_e2() for further details.
2797adfc5217SJeff Kirsher 		 */
2798adfc5217SJeff Kirsher 		p->mcast_list_len = reg_sz;
2799adfc5217SJeff Kirsher 		break;
2800adfc5217SJeff Kirsher 
2801adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
2802adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_CONT:
2803adfc5217SJeff Kirsher 		/* Here we assume that all new MACs will fall into new bins.
2804adfc5217SJeff Kirsher 		 * However we will correct the real registry size after we
2805adfc5217SJeff Kirsher 		 * handle all pending commands.
2806adfc5217SJeff Kirsher 		 */
2807adfc5217SJeff Kirsher 		o->set_registry_size(o, reg_sz + p->mcast_list_len);
2808adfc5217SJeff Kirsher 		break;
2809adfc5217SJeff Kirsher 
2810adfc5217SJeff Kirsher 	default:
2811adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
2812adfc5217SJeff Kirsher 		return -EINVAL;
2813adfc5217SJeff Kirsher 
2814adfc5217SJeff Kirsher 	}
2815adfc5217SJeff Kirsher 
2816adfc5217SJeff Kirsher 	/* Increase the total number of MACs pending to be configured */
2817adfc5217SJeff Kirsher 	o->total_pending_num += p->mcast_list_len;
2818adfc5217SJeff Kirsher 
2819adfc5217SJeff Kirsher 	return 0;
2820adfc5217SJeff Kirsher }
2821adfc5217SJeff Kirsher 
2822adfc5217SJeff Kirsher static void bnx2x_mcast_revert_e2(struct bnx2x *bp,
2823adfc5217SJeff Kirsher 				      struct bnx2x_mcast_ramrod_params *p,
2824adfc5217SJeff Kirsher 				      int old_num_bins)
2825adfc5217SJeff Kirsher {
2826adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
2827adfc5217SJeff Kirsher 
2828adfc5217SJeff Kirsher 	o->set_registry_size(o, old_num_bins);
2829adfc5217SJeff Kirsher 	o->total_pending_num -= p->mcast_list_len;
2830adfc5217SJeff Kirsher }
2831adfc5217SJeff Kirsher 
2832adfc5217SJeff Kirsher /**
2833adfc5217SJeff Kirsher  * bnx2x_mcast_set_rdata_hdr_e2 - sets a header values
2834adfc5217SJeff Kirsher  *
2835adfc5217SJeff Kirsher  * @bp:		device handle
2836adfc5217SJeff Kirsher  * @p:
2837adfc5217SJeff Kirsher  * @len:	number of rules to handle
2838adfc5217SJeff Kirsher  */
2839adfc5217SJeff Kirsher static inline void bnx2x_mcast_set_rdata_hdr_e2(struct bnx2x *bp,
2840adfc5217SJeff Kirsher 					struct bnx2x_mcast_ramrod_params *p,
2841adfc5217SJeff Kirsher 					u8 len)
2842adfc5217SJeff Kirsher {
2843adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
2844adfc5217SJeff Kirsher 	struct eth_multicast_rules_ramrod_data *data =
2845adfc5217SJeff Kirsher 		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
2846adfc5217SJeff Kirsher 
2847adfc5217SJeff Kirsher 	data->header.echo = ((r->cid & BNX2X_SWCID_MASK) |
2848adfc5217SJeff Kirsher 			  (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
2849adfc5217SJeff Kirsher 	data->header.rule_cnt = len;
2850adfc5217SJeff Kirsher }
2851adfc5217SJeff Kirsher 
2852adfc5217SJeff Kirsher /**
2853adfc5217SJeff Kirsher  * bnx2x_mcast_refresh_registry_e2 - recalculate the actual number of set bins
2854adfc5217SJeff Kirsher  *
2855adfc5217SJeff Kirsher  * @bp:		device handle
2856adfc5217SJeff Kirsher  * @o:
2857adfc5217SJeff Kirsher  *
2858adfc5217SJeff Kirsher  * Recalculate the actual number of set bins in the registry using Brian
2859adfc5217SJeff Kirsher  * Kernighan's algorithm: it's execution complexity is as a number of set bins.
2860adfc5217SJeff Kirsher  *
2861adfc5217SJeff Kirsher  * returns 0 for the compliance with bnx2x_mcast_refresh_registry_e1().
2862adfc5217SJeff Kirsher  */
2863adfc5217SJeff Kirsher static inline int bnx2x_mcast_refresh_registry_e2(struct bnx2x *bp,
2864adfc5217SJeff Kirsher 						  struct bnx2x_mcast_obj *o)
2865adfc5217SJeff Kirsher {
2866adfc5217SJeff Kirsher 	int i, cnt = 0;
2867adfc5217SJeff Kirsher 	u64 elem;
2868adfc5217SJeff Kirsher 
2869adfc5217SJeff Kirsher 	for (i = 0; i < BNX2X_MCAST_VEC_SZ; i++) {
2870adfc5217SJeff Kirsher 		elem = o->registry.aprox_match.vec[i];
2871adfc5217SJeff Kirsher 		for (; elem; cnt++)
2872adfc5217SJeff Kirsher 			elem &= elem - 1;
2873adfc5217SJeff Kirsher 	}
2874adfc5217SJeff Kirsher 
2875adfc5217SJeff Kirsher 	o->set_registry_size(o, cnt);
2876adfc5217SJeff Kirsher 
2877adfc5217SJeff Kirsher 	return 0;
2878adfc5217SJeff Kirsher }
2879adfc5217SJeff Kirsher 
2880adfc5217SJeff Kirsher static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
2881adfc5217SJeff Kirsher 				struct bnx2x_mcast_ramrod_params *p,
2882adfc5217SJeff Kirsher 				int cmd)
2883adfc5217SJeff Kirsher {
2884adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &p->mcast_obj->raw;
2885adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
2886adfc5217SJeff Kirsher 	struct eth_multicast_rules_ramrod_data *data =
2887adfc5217SJeff Kirsher 		(struct eth_multicast_rules_ramrod_data *)(raw->rdata);
2888adfc5217SJeff Kirsher 	int cnt = 0, rc;
2889adfc5217SJeff Kirsher 
2890adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer */
2891adfc5217SJeff Kirsher 	memset(data, 0, sizeof(*data));
2892adfc5217SJeff Kirsher 
2893adfc5217SJeff Kirsher 	cnt = bnx2x_mcast_handle_pending_cmds_e2(bp, p);
2894adfc5217SJeff Kirsher 
2895adfc5217SJeff Kirsher 	/* If there are no more pending commands - clear SCHEDULED state */
2896adfc5217SJeff Kirsher 	if (list_empty(&o->pending_cmds_head))
2897adfc5217SJeff Kirsher 		o->clear_sched(o);
2898adfc5217SJeff Kirsher 
2899adfc5217SJeff Kirsher 	/* The below may be true iff there was enough room in ramrod
2900adfc5217SJeff Kirsher 	 * data for all pending commands and for the current
2901adfc5217SJeff Kirsher 	 * command. Otherwise the current command would have been added
2902adfc5217SJeff Kirsher 	 * to the pending commands and p->mcast_list_len would have been
2903adfc5217SJeff Kirsher 	 * zeroed.
2904adfc5217SJeff Kirsher 	 */
2905adfc5217SJeff Kirsher 	if (p->mcast_list_len > 0)
2906adfc5217SJeff Kirsher 		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, cnt);
2907adfc5217SJeff Kirsher 
2908adfc5217SJeff Kirsher 	/* We've pulled out some MACs - update the total number of
2909adfc5217SJeff Kirsher 	 * outstanding.
2910adfc5217SJeff Kirsher 	 */
2911adfc5217SJeff Kirsher 	o->total_pending_num -= cnt;
2912adfc5217SJeff Kirsher 
2913adfc5217SJeff Kirsher 	/* send a ramrod */
2914adfc5217SJeff Kirsher 	WARN_ON(o->total_pending_num < 0);
2915adfc5217SJeff Kirsher 	WARN_ON(cnt > o->max_cmd_len);
2916adfc5217SJeff Kirsher 
2917adfc5217SJeff Kirsher 	bnx2x_mcast_set_rdata_hdr_e2(bp, p, (u8)cnt);
2918adfc5217SJeff Kirsher 
2919adfc5217SJeff Kirsher 	/* Update a registry size if there are no more pending operations.
2920adfc5217SJeff Kirsher 	 *
2921adfc5217SJeff Kirsher 	 * We don't want to change the value of the registry size if there are
2922adfc5217SJeff Kirsher 	 * pending operations because we want it to always be equal to the
2923adfc5217SJeff Kirsher 	 * exact or the approximate number (see bnx2x_mcast_validate_e2()) of
2924adfc5217SJeff Kirsher 	 * set bins after the last requested operation in order to properly
2925adfc5217SJeff Kirsher 	 * evaluate the size of the next DEL/RESTORE operation.
2926adfc5217SJeff Kirsher 	 *
2927adfc5217SJeff Kirsher 	 * Note that we update the registry itself during command(s) handling
2928adfc5217SJeff Kirsher 	 * - see bnx2x_mcast_set_one_rule_e2(). That's because for 57712 we
2929adfc5217SJeff Kirsher 	 * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but
2930adfc5217SJeff Kirsher 	 * with a limited amount of update commands (per MAC/bin) and we don't
2931adfc5217SJeff Kirsher 	 * know in this scope what the actual state of bins configuration is
2932adfc5217SJeff Kirsher 	 * going to be after this ramrod.
2933adfc5217SJeff Kirsher 	 */
2934adfc5217SJeff Kirsher 	if (!o->total_pending_num)
2935adfc5217SJeff Kirsher 		bnx2x_mcast_refresh_registry_e2(bp, o);
2936adfc5217SJeff Kirsher 
2937adfc5217SJeff Kirsher 	/*
2938adfc5217SJeff Kirsher 	 * If CLEAR_ONLY was requested - don't send a ramrod and clear
2939adfc5217SJeff Kirsher 	 * RAMROD_PENDING status immediately.
2940adfc5217SJeff Kirsher 	 */
2941adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
2942adfc5217SJeff Kirsher 		raw->clear_pending(raw);
2943adfc5217SJeff Kirsher 		return 0;
2944adfc5217SJeff Kirsher 	} else {
2945adfc5217SJeff Kirsher 		/*
2946adfc5217SJeff Kirsher 		 *  No need for an explicit memory barrier here as long we would
2947adfc5217SJeff Kirsher 		 *  need to ensure the ordering of writing to the SPQ element
2948adfc5217SJeff Kirsher 		 *  and updating of the SPQ producer which involves a memory
2949adfc5217SJeff Kirsher 		 *  read and we will have to put a full memory barrier there
2950adfc5217SJeff Kirsher 		 *  (inside bnx2x_sp_post()).
2951adfc5217SJeff Kirsher 		 */
2952adfc5217SJeff Kirsher 
2953adfc5217SJeff Kirsher 		/* Send a ramrod */
2954adfc5217SJeff Kirsher 		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES,
2955adfc5217SJeff Kirsher 				   raw->cid, U64_HI(raw->rdata_mapping),
2956adfc5217SJeff Kirsher 				   U64_LO(raw->rdata_mapping),
2957adfc5217SJeff Kirsher 				   ETH_CONNECTION_TYPE);
2958adfc5217SJeff Kirsher 		if (rc)
2959adfc5217SJeff Kirsher 			return rc;
2960adfc5217SJeff Kirsher 
2961adfc5217SJeff Kirsher 		/* Ramrod completion is pending */
2962adfc5217SJeff Kirsher 		return 1;
2963adfc5217SJeff Kirsher 	}
2964adfc5217SJeff Kirsher }
2965adfc5217SJeff Kirsher 
2966adfc5217SJeff Kirsher static int bnx2x_mcast_validate_e1h(struct bnx2x *bp,
2967adfc5217SJeff Kirsher 				    struct bnx2x_mcast_ramrod_params *p,
2968adfc5217SJeff Kirsher 				    int cmd)
2969adfc5217SJeff Kirsher {
2970adfc5217SJeff Kirsher 	/* Mark, that there is a work to do */
2971adfc5217SJeff Kirsher 	if ((cmd == BNX2X_MCAST_CMD_DEL) || (cmd == BNX2X_MCAST_CMD_RESTORE))
2972adfc5217SJeff Kirsher 		p->mcast_list_len = 1;
2973adfc5217SJeff Kirsher 
2974adfc5217SJeff Kirsher 	return 0;
2975adfc5217SJeff Kirsher }
2976adfc5217SJeff Kirsher 
2977adfc5217SJeff Kirsher static void bnx2x_mcast_revert_e1h(struct bnx2x *bp,
2978adfc5217SJeff Kirsher 				       struct bnx2x_mcast_ramrod_params *p,
2979adfc5217SJeff Kirsher 				       int old_num_bins)
2980adfc5217SJeff Kirsher {
2981adfc5217SJeff Kirsher 	/* Do nothing */
2982adfc5217SJeff Kirsher }
2983adfc5217SJeff Kirsher 
2984adfc5217SJeff Kirsher #define BNX2X_57711_SET_MC_FILTER(filter, bit) \
2985adfc5217SJeff Kirsher do { \
2986adfc5217SJeff Kirsher 	(filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \
2987adfc5217SJeff Kirsher } while (0)
2988adfc5217SJeff Kirsher 
2989adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp,
2990adfc5217SJeff Kirsher 					   struct bnx2x_mcast_obj *o,
2991adfc5217SJeff Kirsher 					   struct bnx2x_mcast_ramrod_params *p,
2992adfc5217SJeff Kirsher 					   u32 *mc_filter)
2993adfc5217SJeff Kirsher {
2994adfc5217SJeff Kirsher 	struct bnx2x_mcast_list_elem *mlist_pos;
2995adfc5217SJeff Kirsher 	int bit;
2996adfc5217SJeff Kirsher 
2997adfc5217SJeff Kirsher 	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
2998adfc5217SJeff Kirsher 		bit = bnx2x_mcast_bin_from_mac(mlist_pos->mac);
2999adfc5217SJeff Kirsher 		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
3000adfc5217SJeff Kirsher 
30010f9dad10SJoe Perches 		DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC, bin %d\n",
30020f9dad10SJoe Perches 				 mlist_pos->mac, bit);
3003adfc5217SJeff Kirsher 
3004adfc5217SJeff Kirsher 		/* bookkeeping... */
3005adfc5217SJeff Kirsher 		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
3006adfc5217SJeff Kirsher 				  bit);
3007adfc5217SJeff Kirsher 	}
3008adfc5217SJeff Kirsher }
3009adfc5217SJeff Kirsher 
3010adfc5217SJeff Kirsher static inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp,
3011adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
3012adfc5217SJeff Kirsher 	u32 *mc_filter)
3013adfc5217SJeff Kirsher {
3014adfc5217SJeff Kirsher 	int bit;
3015adfc5217SJeff Kirsher 
3016adfc5217SJeff Kirsher 	for (bit = bnx2x_mcast_get_next_bin(o, 0);
3017adfc5217SJeff Kirsher 	     bit >= 0;
3018adfc5217SJeff Kirsher 	     bit = bnx2x_mcast_get_next_bin(o, bit + 1)) {
3019adfc5217SJeff Kirsher 		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
3020adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "About to set bin %d\n", bit);
3021adfc5217SJeff Kirsher 	}
3022adfc5217SJeff Kirsher }
3023adfc5217SJeff Kirsher 
3024adfc5217SJeff Kirsher /* On 57711 we write the multicast MACs' aproximate match
3025adfc5217SJeff Kirsher  * table by directly into the TSTORM's internal RAM. So we don't
3026adfc5217SJeff Kirsher  * really need to handle any tricks to make it work.
3027adfc5217SJeff Kirsher  */
3028adfc5217SJeff Kirsher static int bnx2x_mcast_setup_e1h(struct bnx2x *bp,
3029adfc5217SJeff Kirsher 				 struct bnx2x_mcast_ramrod_params *p,
3030adfc5217SJeff Kirsher 				 int cmd)
3031adfc5217SJeff Kirsher {
3032adfc5217SJeff Kirsher 	int i;
3033adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3034adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
3035adfc5217SJeff Kirsher 
3036adfc5217SJeff Kirsher 	/* If CLEAR_ONLY has been requested - clear the registry
3037adfc5217SJeff Kirsher 	 * and clear a pending bit.
3038adfc5217SJeff Kirsher 	 */
3039adfc5217SJeff Kirsher 	if (!test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
3040adfc5217SJeff Kirsher 		u32 mc_filter[MC_HASH_SIZE] = {0};
3041adfc5217SJeff Kirsher 
3042adfc5217SJeff Kirsher 		/* Set the multicast filter bits before writing it into
3043adfc5217SJeff Kirsher 		 * the internal memory.
3044adfc5217SJeff Kirsher 		 */
3045adfc5217SJeff Kirsher 		switch (cmd) {
3046adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_ADD:
3047adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_add_e1h(bp, o, p, mc_filter);
3048adfc5217SJeff Kirsher 			break;
3049adfc5217SJeff Kirsher 
3050adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_DEL:
305194f05b0fSJoe Perches 			DP(BNX2X_MSG_SP,
305294f05b0fSJoe Perches 			   "Invalidating multicast MACs configuration\n");
3053adfc5217SJeff Kirsher 
3054adfc5217SJeff Kirsher 			/* clear the registry */
3055adfc5217SJeff Kirsher 			memset(o->registry.aprox_match.vec, 0,
3056adfc5217SJeff Kirsher 			       sizeof(o->registry.aprox_match.vec));
3057adfc5217SJeff Kirsher 			break;
3058adfc5217SJeff Kirsher 
3059adfc5217SJeff Kirsher 		case BNX2X_MCAST_CMD_RESTORE:
3060adfc5217SJeff Kirsher 			bnx2x_mcast_hdl_restore_e1h(bp, o, p, mc_filter);
3061adfc5217SJeff Kirsher 			break;
3062adfc5217SJeff Kirsher 
3063adfc5217SJeff Kirsher 		default:
3064adfc5217SJeff Kirsher 			BNX2X_ERR("Unknown command: %d\n", cmd);
3065adfc5217SJeff Kirsher 			return -EINVAL;
3066adfc5217SJeff Kirsher 		}
3067adfc5217SJeff Kirsher 
3068adfc5217SJeff Kirsher 		/* Set the mcast filter in the internal memory */
3069adfc5217SJeff Kirsher 		for (i = 0; i < MC_HASH_SIZE; i++)
3070adfc5217SJeff Kirsher 			REG_WR(bp, MC_HASH_OFFSET(bp, i), mc_filter[i]);
3071adfc5217SJeff Kirsher 	} else
3072adfc5217SJeff Kirsher 		/* clear the registry */
3073adfc5217SJeff Kirsher 		memset(o->registry.aprox_match.vec, 0,
3074adfc5217SJeff Kirsher 		       sizeof(o->registry.aprox_match.vec));
3075adfc5217SJeff Kirsher 
3076adfc5217SJeff Kirsher 	/* We are done */
3077adfc5217SJeff Kirsher 	r->clear_pending(r);
3078adfc5217SJeff Kirsher 
3079adfc5217SJeff Kirsher 	return 0;
3080adfc5217SJeff Kirsher }
3081adfc5217SJeff Kirsher 
3082adfc5217SJeff Kirsher static int bnx2x_mcast_validate_e1(struct bnx2x *bp,
3083adfc5217SJeff Kirsher 				   struct bnx2x_mcast_ramrod_params *p,
3084adfc5217SJeff Kirsher 				   int cmd)
3085adfc5217SJeff Kirsher {
3086adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3087adfc5217SJeff Kirsher 	int reg_sz = o->get_registry_size(o);
3088adfc5217SJeff Kirsher 
3089adfc5217SJeff Kirsher 	switch (cmd) {
3090adfc5217SJeff Kirsher 	/* DEL command deletes all currently configured MACs */
3091adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
3092adfc5217SJeff Kirsher 		o->set_registry_size(o, 0);
3093adfc5217SJeff Kirsher 		/* Don't break */
3094adfc5217SJeff Kirsher 
3095adfc5217SJeff Kirsher 	/* RESTORE command will restore the entire multicast configuration */
3096adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
3097adfc5217SJeff Kirsher 		p->mcast_list_len = reg_sz;
3098adfc5217SJeff Kirsher 		  DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n",
3099adfc5217SJeff Kirsher 				   cmd, p->mcast_list_len);
3100adfc5217SJeff Kirsher 		break;
3101adfc5217SJeff Kirsher 
3102adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
3103adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_CONT:
3104adfc5217SJeff Kirsher 		/* Multicast MACs on 57710 are configured as unicast MACs and
3105adfc5217SJeff Kirsher 		 * there is only a limited number of CAM entries for that
3106adfc5217SJeff Kirsher 		 * matter.
3107adfc5217SJeff Kirsher 		 */
3108adfc5217SJeff Kirsher 		if (p->mcast_list_len > o->max_cmd_len) {
3109adfc5217SJeff Kirsher 			BNX2X_ERR("Can't configure more than %d multicast MACs"
3110adfc5217SJeff Kirsher 				   "on 57710\n", o->max_cmd_len);
3111adfc5217SJeff Kirsher 			return -EINVAL;
3112adfc5217SJeff Kirsher 		}
3113adfc5217SJeff Kirsher 		/* Every configured MAC should be cleared if DEL command is
3114adfc5217SJeff Kirsher 		 * called. Only the last ADD command is relevant as long as
3115adfc5217SJeff Kirsher 		 * every ADD commands overrides the previous configuration.
3116adfc5217SJeff Kirsher 		 */
3117adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
3118adfc5217SJeff Kirsher 		if (p->mcast_list_len > 0)
3119adfc5217SJeff Kirsher 			o->set_registry_size(o, p->mcast_list_len);
3120adfc5217SJeff Kirsher 
3121adfc5217SJeff Kirsher 		break;
3122adfc5217SJeff Kirsher 
3123adfc5217SJeff Kirsher 	default:
3124adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd);
3125adfc5217SJeff Kirsher 		return -EINVAL;
3126adfc5217SJeff Kirsher 
3127adfc5217SJeff Kirsher 	}
3128adfc5217SJeff Kirsher 
3129adfc5217SJeff Kirsher 	/* We want to ensure that commands are executed one by one for 57710.
3130adfc5217SJeff Kirsher 	 * Therefore each none-empty command will consume o->max_cmd_len.
3131adfc5217SJeff Kirsher 	 */
3132adfc5217SJeff Kirsher 	if (p->mcast_list_len)
3133adfc5217SJeff Kirsher 		o->total_pending_num += o->max_cmd_len;
3134adfc5217SJeff Kirsher 
3135adfc5217SJeff Kirsher 	return 0;
3136adfc5217SJeff Kirsher }
3137adfc5217SJeff Kirsher 
3138adfc5217SJeff Kirsher static void bnx2x_mcast_revert_e1(struct bnx2x *bp,
3139adfc5217SJeff Kirsher 				      struct bnx2x_mcast_ramrod_params *p,
3140adfc5217SJeff Kirsher 				      int old_num_macs)
3141adfc5217SJeff Kirsher {
3142adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3143adfc5217SJeff Kirsher 
3144adfc5217SJeff Kirsher 	o->set_registry_size(o, old_num_macs);
3145adfc5217SJeff Kirsher 
3146adfc5217SJeff Kirsher 	/* If current command hasn't been handled yet and we are
3147adfc5217SJeff Kirsher 	 * here means that it's meant to be dropped and we have to
3148adfc5217SJeff Kirsher 	 * update the number of outstandling MACs accordingly.
3149adfc5217SJeff Kirsher 	 */
3150adfc5217SJeff Kirsher 	if (p->mcast_list_len)
3151adfc5217SJeff Kirsher 		o->total_pending_num -= o->max_cmd_len;
3152adfc5217SJeff Kirsher }
3153adfc5217SJeff Kirsher 
3154adfc5217SJeff Kirsher static void bnx2x_mcast_set_one_rule_e1(struct bnx2x *bp,
3155adfc5217SJeff Kirsher 					struct bnx2x_mcast_obj *o, int idx,
3156adfc5217SJeff Kirsher 					union bnx2x_mcast_config_data *cfg_data,
3157adfc5217SJeff Kirsher 					int cmd)
3158adfc5217SJeff Kirsher {
3159adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
3160adfc5217SJeff Kirsher 	struct mac_configuration_cmd *data =
3161adfc5217SJeff Kirsher 		(struct mac_configuration_cmd *)(r->rdata);
3162adfc5217SJeff Kirsher 
3163adfc5217SJeff Kirsher 	/* copy mac */
3164adfc5217SJeff Kirsher 	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE)) {
3165adfc5217SJeff Kirsher 		bnx2x_set_fw_mac_addr(&data->config_table[idx].msb_mac_addr,
3166adfc5217SJeff Kirsher 				      &data->config_table[idx].middle_mac_addr,
3167adfc5217SJeff Kirsher 				      &data->config_table[idx].lsb_mac_addr,
3168adfc5217SJeff Kirsher 				      cfg_data->mac);
3169adfc5217SJeff Kirsher 
3170adfc5217SJeff Kirsher 		data->config_table[idx].vlan_id = 0;
3171adfc5217SJeff Kirsher 		data->config_table[idx].pf_id = r->func_id;
3172adfc5217SJeff Kirsher 		data->config_table[idx].clients_bit_vector =
3173adfc5217SJeff Kirsher 			cpu_to_le32(1 << r->cl_id);
3174adfc5217SJeff Kirsher 
3175adfc5217SJeff Kirsher 		SET_FLAG(data->config_table[idx].flags,
3176adfc5217SJeff Kirsher 			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
3177adfc5217SJeff Kirsher 			 T_ETH_MAC_COMMAND_SET);
3178adfc5217SJeff Kirsher 	}
3179adfc5217SJeff Kirsher }
3180adfc5217SJeff Kirsher 
3181adfc5217SJeff Kirsher /**
3182adfc5217SJeff Kirsher  * bnx2x_mcast_set_rdata_hdr_e1  - set header values in mac_configuration_cmd
3183adfc5217SJeff Kirsher  *
3184adfc5217SJeff Kirsher  * @bp:		device handle
3185adfc5217SJeff Kirsher  * @p:
3186adfc5217SJeff Kirsher  * @len:	number of rules to handle
3187adfc5217SJeff Kirsher  */
3188adfc5217SJeff Kirsher static inline void bnx2x_mcast_set_rdata_hdr_e1(struct bnx2x *bp,
3189adfc5217SJeff Kirsher 					struct bnx2x_mcast_ramrod_params *p,
3190adfc5217SJeff Kirsher 					u8 len)
3191adfc5217SJeff Kirsher {
3192adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
3193adfc5217SJeff Kirsher 	struct mac_configuration_cmd *data =
3194adfc5217SJeff Kirsher 		(struct mac_configuration_cmd *)(r->rdata);
3195adfc5217SJeff Kirsher 
3196adfc5217SJeff Kirsher 	u8 offset = (CHIP_REV_IS_SLOW(bp) ?
3197adfc5217SJeff Kirsher 		     BNX2X_MAX_EMUL_MULTI*(1 + r->func_id) :
3198adfc5217SJeff Kirsher 		     BNX2X_MAX_MULTICAST*(1 + r->func_id));
3199adfc5217SJeff Kirsher 
3200adfc5217SJeff Kirsher 	data->hdr.offset = offset;
3201adfc5217SJeff Kirsher 	data->hdr.client_id = 0xff;
3202adfc5217SJeff Kirsher 	data->hdr.echo = ((r->cid & BNX2X_SWCID_MASK) |
3203adfc5217SJeff Kirsher 			  (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
3204adfc5217SJeff Kirsher 	data->hdr.length = len;
3205adfc5217SJeff Kirsher }
3206adfc5217SJeff Kirsher 
3207adfc5217SJeff Kirsher /**
3208adfc5217SJeff Kirsher  * bnx2x_mcast_handle_restore_cmd_e1 - restore command for 57710
3209adfc5217SJeff Kirsher  *
3210adfc5217SJeff Kirsher  * @bp:		device handle
3211adfc5217SJeff Kirsher  * @o:
3212adfc5217SJeff Kirsher  * @start_idx:	index in the registry to start from
3213adfc5217SJeff Kirsher  * @rdata_idx:	index in the ramrod data to start from
3214adfc5217SJeff Kirsher  *
3215adfc5217SJeff Kirsher  * restore command for 57710 is like all other commands - always a stand alone
3216adfc5217SJeff Kirsher  * command - start_idx and rdata_idx will always be 0. This function will always
3217adfc5217SJeff Kirsher  * succeed.
3218adfc5217SJeff Kirsher  * returns -1 to comply with 57712 variant.
3219adfc5217SJeff Kirsher  */
3220adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_restore_cmd_e1(
3221adfc5217SJeff Kirsher 	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_idx,
3222adfc5217SJeff Kirsher 	int *rdata_idx)
3223adfc5217SJeff Kirsher {
3224adfc5217SJeff Kirsher 	struct bnx2x_mcast_mac_elem *elem;
3225adfc5217SJeff Kirsher 	int i = 0;
3226adfc5217SJeff Kirsher 	union bnx2x_mcast_config_data cfg_data = {0};
3227adfc5217SJeff Kirsher 
3228adfc5217SJeff Kirsher 	/* go through the registry and configure the MACs from it. */
3229adfc5217SJeff Kirsher 	list_for_each_entry(elem, &o->registry.exact_match.macs, link) {
3230adfc5217SJeff Kirsher 		cfg_data.mac = &elem->mac[0];
3231adfc5217SJeff Kirsher 		o->set_one_rule(bp, o, i, &cfg_data, BNX2X_MCAST_CMD_RESTORE);
3232adfc5217SJeff Kirsher 
3233adfc5217SJeff Kirsher 		i++;
3234adfc5217SJeff Kirsher 
32350f9dad10SJoe Perches 		  DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
32360f9dad10SJoe Perches 				   cfg_data.mac);
3237adfc5217SJeff Kirsher 	}
3238adfc5217SJeff Kirsher 
3239adfc5217SJeff Kirsher 	*rdata_idx = i;
3240adfc5217SJeff Kirsher 
3241adfc5217SJeff Kirsher 	return -1;
3242adfc5217SJeff Kirsher }
3243adfc5217SJeff Kirsher 
3244adfc5217SJeff Kirsher 
3245adfc5217SJeff Kirsher static inline int bnx2x_mcast_handle_pending_cmds_e1(
3246adfc5217SJeff Kirsher 	struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p)
3247adfc5217SJeff Kirsher {
3248adfc5217SJeff Kirsher 	struct bnx2x_pending_mcast_cmd *cmd_pos;
3249adfc5217SJeff Kirsher 	struct bnx2x_mcast_mac_elem *pmac_pos;
3250adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3251adfc5217SJeff Kirsher 	union bnx2x_mcast_config_data cfg_data = {0};
3252adfc5217SJeff Kirsher 	int cnt = 0;
3253adfc5217SJeff Kirsher 
3254adfc5217SJeff Kirsher 
3255adfc5217SJeff Kirsher 	/* If nothing to be done - return */
3256adfc5217SJeff Kirsher 	if (list_empty(&o->pending_cmds_head))
3257adfc5217SJeff Kirsher 		return 0;
3258adfc5217SJeff Kirsher 
3259adfc5217SJeff Kirsher 	/* Handle the first command */
3260adfc5217SJeff Kirsher 	cmd_pos = list_first_entry(&o->pending_cmds_head,
3261adfc5217SJeff Kirsher 				   struct bnx2x_pending_mcast_cmd, link);
3262adfc5217SJeff Kirsher 
3263adfc5217SJeff Kirsher 	switch (cmd_pos->type) {
3264adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_ADD:
3265adfc5217SJeff Kirsher 		list_for_each_entry(pmac_pos, &cmd_pos->data.macs_head, link) {
3266adfc5217SJeff Kirsher 			cfg_data.mac = &pmac_pos->mac[0];
3267adfc5217SJeff Kirsher 			o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
3268adfc5217SJeff Kirsher 
3269adfc5217SJeff Kirsher 			cnt++;
3270adfc5217SJeff Kirsher 
32710f9dad10SJoe Perches 			DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
32720f9dad10SJoe Perches 					 pmac_pos->mac);
3273adfc5217SJeff Kirsher 		}
3274adfc5217SJeff Kirsher 		break;
3275adfc5217SJeff Kirsher 
3276adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_DEL:
3277adfc5217SJeff Kirsher 		cnt = cmd_pos->data.macs_num;
3278adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "About to delete %d multicast MACs\n", cnt);
3279adfc5217SJeff Kirsher 		break;
3280adfc5217SJeff Kirsher 
3281adfc5217SJeff Kirsher 	case BNX2X_MCAST_CMD_RESTORE:
3282adfc5217SJeff Kirsher 		o->hdl_restore(bp, o, 0, &cnt);
3283adfc5217SJeff Kirsher 		break;
3284adfc5217SJeff Kirsher 
3285adfc5217SJeff Kirsher 	default:
3286adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
3287adfc5217SJeff Kirsher 		return -EINVAL;
3288adfc5217SJeff Kirsher 	}
3289adfc5217SJeff Kirsher 
3290adfc5217SJeff Kirsher 	list_del(&cmd_pos->link);
3291adfc5217SJeff Kirsher 	kfree(cmd_pos);
3292adfc5217SJeff Kirsher 
3293adfc5217SJeff Kirsher 	return cnt;
3294adfc5217SJeff Kirsher }
3295adfc5217SJeff Kirsher 
3296adfc5217SJeff Kirsher /**
3297adfc5217SJeff Kirsher  * bnx2x_get_fw_mac_addr - revert the bnx2x_set_fw_mac_addr().
3298adfc5217SJeff Kirsher  *
3299adfc5217SJeff Kirsher  * @fw_hi:
3300adfc5217SJeff Kirsher  * @fw_mid:
3301adfc5217SJeff Kirsher  * @fw_lo:
3302adfc5217SJeff Kirsher  * @mac:
3303adfc5217SJeff Kirsher  */
3304adfc5217SJeff Kirsher static inline void bnx2x_get_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid,
3305adfc5217SJeff Kirsher 					 __le16 *fw_lo, u8 *mac)
3306adfc5217SJeff Kirsher {
3307adfc5217SJeff Kirsher 	mac[1] = ((u8 *)fw_hi)[0];
3308adfc5217SJeff Kirsher 	mac[0] = ((u8 *)fw_hi)[1];
3309adfc5217SJeff Kirsher 	mac[3] = ((u8 *)fw_mid)[0];
3310adfc5217SJeff Kirsher 	mac[2] = ((u8 *)fw_mid)[1];
3311adfc5217SJeff Kirsher 	mac[5] = ((u8 *)fw_lo)[0];
3312adfc5217SJeff Kirsher 	mac[4] = ((u8 *)fw_lo)[1];
3313adfc5217SJeff Kirsher }
3314adfc5217SJeff Kirsher 
3315adfc5217SJeff Kirsher /**
3316adfc5217SJeff Kirsher  * bnx2x_mcast_refresh_registry_e1 -
3317adfc5217SJeff Kirsher  *
3318adfc5217SJeff Kirsher  * @bp:		device handle
3319adfc5217SJeff Kirsher  * @cnt:
3320adfc5217SJeff Kirsher  *
3321adfc5217SJeff Kirsher  * Check the ramrod data first entry flag to see if it's a DELETE or ADD command
3322adfc5217SJeff Kirsher  * and update the registry correspondingly: if ADD - allocate a memory and add
3323adfc5217SJeff Kirsher  * the entries to the registry (list), if DELETE - clear the registry and free
3324adfc5217SJeff Kirsher  * the memory.
3325adfc5217SJeff Kirsher  */
3326adfc5217SJeff Kirsher static inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp,
3327adfc5217SJeff Kirsher 						  struct bnx2x_mcast_obj *o)
3328adfc5217SJeff Kirsher {
3329adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
3330adfc5217SJeff Kirsher 	struct bnx2x_mcast_mac_elem *elem;
3331adfc5217SJeff Kirsher 	struct mac_configuration_cmd *data =
3332adfc5217SJeff Kirsher 			(struct mac_configuration_cmd *)(raw->rdata);
3333adfc5217SJeff Kirsher 
3334adfc5217SJeff Kirsher 	/* If first entry contains a SET bit - the command was ADD,
3335adfc5217SJeff Kirsher 	 * otherwise - DEL_ALL
3336adfc5217SJeff Kirsher 	 */
3337adfc5217SJeff Kirsher 	if (GET_FLAG(data->config_table[0].flags,
3338adfc5217SJeff Kirsher 			MAC_CONFIGURATION_ENTRY_ACTION_TYPE)) {
3339adfc5217SJeff Kirsher 		int i, len = data->hdr.length;
3340adfc5217SJeff Kirsher 
3341adfc5217SJeff Kirsher 		/* Break if it was a RESTORE command */
3342adfc5217SJeff Kirsher 		if (!list_empty(&o->registry.exact_match.macs))
3343adfc5217SJeff Kirsher 			return 0;
3344adfc5217SJeff Kirsher 
3345adfc5217SJeff Kirsher 		elem = kzalloc(sizeof(*elem)*len, GFP_ATOMIC);
3346adfc5217SJeff Kirsher 		if (!elem) {
3347adfc5217SJeff Kirsher 			BNX2X_ERR("Failed to allocate registry memory\n");
3348adfc5217SJeff Kirsher 			return -ENOMEM;
3349adfc5217SJeff Kirsher 		}
3350adfc5217SJeff Kirsher 
3351adfc5217SJeff Kirsher 		for (i = 0; i < len; i++, elem++) {
3352adfc5217SJeff Kirsher 			bnx2x_get_fw_mac_addr(
3353adfc5217SJeff Kirsher 				&data->config_table[i].msb_mac_addr,
3354adfc5217SJeff Kirsher 				&data->config_table[i].middle_mac_addr,
3355adfc5217SJeff Kirsher 				&data->config_table[i].lsb_mac_addr,
3356adfc5217SJeff Kirsher 				elem->mac);
33570f9dad10SJoe Perches 			DP(BNX2X_MSG_SP, "Adding registry entry for [%pM]\n",
33580f9dad10SJoe Perches 					 elem->mac);
3359adfc5217SJeff Kirsher 			list_add_tail(&elem->link,
3360adfc5217SJeff Kirsher 				      &o->registry.exact_match.macs);
3361adfc5217SJeff Kirsher 		}
3362adfc5217SJeff Kirsher 	} else {
3363adfc5217SJeff Kirsher 		elem = list_first_entry(&o->registry.exact_match.macs,
3364adfc5217SJeff Kirsher 					struct bnx2x_mcast_mac_elem, link);
3365adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Deleting a registry\n");
3366adfc5217SJeff Kirsher 		kfree(elem);
3367adfc5217SJeff Kirsher 		INIT_LIST_HEAD(&o->registry.exact_match.macs);
3368adfc5217SJeff Kirsher 	}
3369adfc5217SJeff Kirsher 
3370adfc5217SJeff Kirsher 	return 0;
3371adfc5217SJeff Kirsher }
3372adfc5217SJeff Kirsher 
3373adfc5217SJeff Kirsher static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
3374adfc5217SJeff Kirsher 				struct bnx2x_mcast_ramrod_params *p,
3375adfc5217SJeff Kirsher 				int cmd)
3376adfc5217SJeff Kirsher {
3377adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3378adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *raw = &o->raw;
3379adfc5217SJeff Kirsher 	struct mac_configuration_cmd *data =
3380adfc5217SJeff Kirsher 		(struct mac_configuration_cmd *)(raw->rdata);
3381adfc5217SJeff Kirsher 	int cnt = 0, i, rc;
3382adfc5217SJeff Kirsher 
3383adfc5217SJeff Kirsher 	/* Reset the ramrod data buffer */
3384adfc5217SJeff Kirsher 	memset(data, 0, sizeof(*data));
3385adfc5217SJeff Kirsher 
3386adfc5217SJeff Kirsher 	/* First set all entries as invalid */
3387adfc5217SJeff Kirsher 	for (i = 0; i < o->max_cmd_len ; i++)
3388adfc5217SJeff Kirsher 		SET_FLAG(data->config_table[i].flags,
3389adfc5217SJeff Kirsher 			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
3390adfc5217SJeff Kirsher 			 T_ETH_MAC_COMMAND_INVALIDATE);
3391adfc5217SJeff Kirsher 
3392adfc5217SJeff Kirsher 	/* Handle pending commands first */
3393adfc5217SJeff Kirsher 	cnt = bnx2x_mcast_handle_pending_cmds_e1(bp, p);
3394adfc5217SJeff Kirsher 
3395adfc5217SJeff Kirsher 	/* If there are no more pending commands - clear SCHEDULED state */
3396adfc5217SJeff Kirsher 	if (list_empty(&o->pending_cmds_head))
3397adfc5217SJeff Kirsher 		o->clear_sched(o);
3398adfc5217SJeff Kirsher 
3399adfc5217SJeff Kirsher 	/* The below may be true iff there were no pending commands */
3400adfc5217SJeff Kirsher 	if (!cnt)
3401adfc5217SJeff Kirsher 		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, 0);
3402adfc5217SJeff Kirsher 
3403adfc5217SJeff Kirsher 	/* For 57710 every command has o->max_cmd_len length to ensure that
3404adfc5217SJeff Kirsher 	 * commands are done one at a time.
3405adfc5217SJeff Kirsher 	 */
3406adfc5217SJeff Kirsher 	o->total_pending_num -= o->max_cmd_len;
3407adfc5217SJeff Kirsher 
3408adfc5217SJeff Kirsher 	/* send a ramrod */
3409adfc5217SJeff Kirsher 
3410adfc5217SJeff Kirsher 	WARN_ON(cnt > o->max_cmd_len);
3411adfc5217SJeff Kirsher 
3412adfc5217SJeff Kirsher 	/* Set ramrod header (in particular, a number of entries to update) */
3413adfc5217SJeff Kirsher 	bnx2x_mcast_set_rdata_hdr_e1(bp, p, (u8)cnt);
3414adfc5217SJeff Kirsher 
3415adfc5217SJeff Kirsher 	/* update a registry: we need the registry contents to be always up
3416adfc5217SJeff Kirsher 	 * to date in order to be able to execute a RESTORE opcode. Here
3417adfc5217SJeff Kirsher 	 * we use the fact that for 57710 we sent one command at a time
3418adfc5217SJeff Kirsher 	 * hence we may take the registry update out of the command handling
3419adfc5217SJeff Kirsher 	 * and do it in a simpler way here.
3420adfc5217SJeff Kirsher 	 */
3421adfc5217SJeff Kirsher 	rc = bnx2x_mcast_refresh_registry_e1(bp, o);
3422adfc5217SJeff Kirsher 	if (rc)
3423adfc5217SJeff Kirsher 		return rc;
3424adfc5217SJeff Kirsher 
3425adfc5217SJeff Kirsher 	/*
3426adfc5217SJeff Kirsher 	 * If CLEAR_ONLY was requested - don't send a ramrod and clear
3427adfc5217SJeff Kirsher 	 * RAMROD_PENDING status immediately.
3428adfc5217SJeff Kirsher 	 */
3429adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
3430adfc5217SJeff Kirsher 		raw->clear_pending(raw);
3431adfc5217SJeff Kirsher 		return 0;
3432adfc5217SJeff Kirsher 	} else {
3433adfc5217SJeff Kirsher 		/*
3434adfc5217SJeff Kirsher 		 *  No need for an explicit memory barrier here as long we would
3435adfc5217SJeff Kirsher 		 *  need to ensure the ordering of writing to the SPQ element
3436adfc5217SJeff Kirsher 		 *  and updating of the SPQ producer which involves a memory
3437adfc5217SJeff Kirsher 		 *  read and we will have to put a full memory barrier there
3438adfc5217SJeff Kirsher 		 *  (inside bnx2x_sp_post()).
3439adfc5217SJeff Kirsher 		 */
3440adfc5217SJeff Kirsher 
3441adfc5217SJeff Kirsher 		/* Send a ramrod */
3442adfc5217SJeff Kirsher 		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid,
3443adfc5217SJeff Kirsher 				   U64_HI(raw->rdata_mapping),
3444adfc5217SJeff Kirsher 				   U64_LO(raw->rdata_mapping),
3445adfc5217SJeff Kirsher 				   ETH_CONNECTION_TYPE);
3446adfc5217SJeff Kirsher 		if (rc)
3447adfc5217SJeff Kirsher 			return rc;
3448adfc5217SJeff Kirsher 
3449adfc5217SJeff Kirsher 		/* Ramrod completion is pending */
3450adfc5217SJeff Kirsher 		return 1;
3451adfc5217SJeff Kirsher 	}
3452adfc5217SJeff Kirsher 
3453adfc5217SJeff Kirsher }
3454adfc5217SJeff Kirsher 
3455adfc5217SJeff Kirsher static int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o)
3456adfc5217SJeff Kirsher {
3457adfc5217SJeff Kirsher 	return o->registry.exact_match.num_macs_set;
3458adfc5217SJeff Kirsher }
3459adfc5217SJeff Kirsher 
3460adfc5217SJeff Kirsher static int bnx2x_mcast_get_registry_size_aprox(struct bnx2x_mcast_obj *o)
3461adfc5217SJeff Kirsher {
3462adfc5217SJeff Kirsher 	return o->registry.aprox_match.num_bins_set;
3463adfc5217SJeff Kirsher }
3464adfc5217SJeff Kirsher 
3465adfc5217SJeff Kirsher static void bnx2x_mcast_set_registry_size_exact(struct bnx2x_mcast_obj *o,
3466adfc5217SJeff Kirsher 						int n)
3467adfc5217SJeff Kirsher {
3468adfc5217SJeff Kirsher 	o->registry.exact_match.num_macs_set = n;
3469adfc5217SJeff Kirsher }
3470adfc5217SJeff Kirsher 
3471adfc5217SJeff Kirsher static void bnx2x_mcast_set_registry_size_aprox(struct bnx2x_mcast_obj *o,
3472adfc5217SJeff Kirsher 						int n)
3473adfc5217SJeff Kirsher {
3474adfc5217SJeff Kirsher 	o->registry.aprox_match.num_bins_set = n;
3475adfc5217SJeff Kirsher }
3476adfc5217SJeff Kirsher 
3477adfc5217SJeff Kirsher int bnx2x_config_mcast(struct bnx2x *bp,
3478adfc5217SJeff Kirsher 		       struct bnx2x_mcast_ramrod_params *p,
3479adfc5217SJeff Kirsher 		       int cmd)
3480adfc5217SJeff Kirsher {
3481adfc5217SJeff Kirsher 	struct bnx2x_mcast_obj *o = p->mcast_obj;
3482adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
3483adfc5217SJeff Kirsher 	int rc = 0, old_reg_size;
3484adfc5217SJeff Kirsher 
3485adfc5217SJeff Kirsher 	/* This is needed to recover number of currently configured mcast macs
3486adfc5217SJeff Kirsher 	 * in case of failure.
3487adfc5217SJeff Kirsher 	 */
3488adfc5217SJeff Kirsher 	old_reg_size = o->get_registry_size(o);
3489adfc5217SJeff Kirsher 
3490adfc5217SJeff Kirsher 	/* Do some calculations and checks */
3491adfc5217SJeff Kirsher 	rc = o->validate(bp, p, cmd);
3492adfc5217SJeff Kirsher 	if (rc)
3493adfc5217SJeff Kirsher 		return rc;
3494adfc5217SJeff Kirsher 
3495adfc5217SJeff Kirsher 	/* Return if there is no work to do */
3496adfc5217SJeff Kirsher 	if ((!p->mcast_list_len) && (!o->check_sched(o)))
3497adfc5217SJeff Kirsher 		return 0;
3498adfc5217SJeff Kirsher 
3499adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "o->total_pending_num=%d p->mcast_list_len=%d "
3500adfc5217SJeff Kirsher 			 "o->max_cmd_len=%d\n", o->total_pending_num,
3501adfc5217SJeff Kirsher 			 p->mcast_list_len, o->max_cmd_len);
3502adfc5217SJeff Kirsher 
3503adfc5217SJeff Kirsher 	/* Enqueue the current command to the pending list if we can't complete
3504adfc5217SJeff Kirsher 	 * it in the current iteration
3505adfc5217SJeff Kirsher 	 */
3506adfc5217SJeff Kirsher 	if (r->check_pending(r) ||
3507adfc5217SJeff Kirsher 	    ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) {
3508adfc5217SJeff Kirsher 		rc = o->enqueue_cmd(bp, p->mcast_obj, p, cmd);
3509adfc5217SJeff Kirsher 		if (rc < 0)
3510adfc5217SJeff Kirsher 			goto error_exit1;
3511adfc5217SJeff Kirsher 
3512adfc5217SJeff Kirsher 		/* As long as the current command is in a command list we
3513adfc5217SJeff Kirsher 		 * don't need to handle it separately.
3514adfc5217SJeff Kirsher 		 */
3515adfc5217SJeff Kirsher 		p->mcast_list_len = 0;
3516adfc5217SJeff Kirsher 	}
3517adfc5217SJeff Kirsher 
3518adfc5217SJeff Kirsher 	if (!r->check_pending(r)) {
3519adfc5217SJeff Kirsher 
3520adfc5217SJeff Kirsher 		/* Set 'pending' state */
3521adfc5217SJeff Kirsher 		r->set_pending(r);
3522adfc5217SJeff Kirsher 
3523adfc5217SJeff Kirsher 		/* Configure the new classification in the chip */
3524adfc5217SJeff Kirsher 		rc = o->config_mcast(bp, p, cmd);
3525adfc5217SJeff Kirsher 		if (rc < 0)
3526adfc5217SJeff Kirsher 			goto error_exit2;
3527adfc5217SJeff Kirsher 
3528adfc5217SJeff Kirsher 		/* Wait for a ramrod completion if was requested */
3529adfc5217SJeff Kirsher 		if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
3530adfc5217SJeff Kirsher 			rc = o->wait_comp(bp, o);
3531adfc5217SJeff Kirsher 	}
3532adfc5217SJeff Kirsher 
3533adfc5217SJeff Kirsher 	return rc;
3534adfc5217SJeff Kirsher 
3535adfc5217SJeff Kirsher error_exit2:
3536adfc5217SJeff Kirsher 	r->clear_pending(r);
3537adfc5217SJeff Kirsher 
3538adfc5217SJeff Kirsher error_exit1:
3539adfc5217SJeff Kirsher 	o->revert(bp, p, old_reg_size);
3540adfc5217SJeff Kirsher 
3541adfc5217SJeff Kirsher 	return rc;
3542adfc5217SJeff Kirsher }
3543adfc5217SJeff Kirsher 
3544adfc5217SJeff Kirsher static void bnx2x_mcast_clear_sched(struct bnx2x_mcast_obj *o)
3545adfc5217SJeff Kirsher {
3546adfc5217SJeff Kirsher 	smp_mb__before_clear_bit();
3547adfc5217SJeff Kirsher 	clear_bit(o->sched_state, o->raw.pstate);
3548adfc5217SJeff Kirsher 	smp_mb__after_clear_bit();
3549adfc5217SJeff Kirsher }
3550adfc5217SJeff Kirsher 
3551adfc5217SJeff Kirsher static void bnx2x_mcast_set_sched(struct bnx2x_mcast_obj *o)
3552adfc5217SJeff Kirsher {
3553adfc5217SJeff Kirsher 	smp_mb__before_clear_bit();
3554adfc5217SJeff Kirsher 	set_bit(o->sched_state, o->raw.pstate);
3555adfc5217SJeff Kirsher 	smp_mb__after_clear_bit();
3556adfc5217SJeff Kirsher }
3557adfc5217SJeff Kirsher 
3558adfc5217SJeff Kirsher static bool bnx2x_mcast_check_sched(struct bnx2x_mcast_obj *o)
3559adfc5217SJeff Kirsher {
3560adfc5217SJeff Kirsher 	return !!test_bit(o->sched_state, o->raw.pstate);
3561adfc5217SJeff Kirsher }
3562adfc5217SJeff Kirsher 
3563adfc5217SJeff Kirsher static bool bnx2x_mcast_check_pending(struct bnx2x_mcast_obj *o)
3564adfc5217SJeff Kirsher {
3565adfc5217SJeff Kirsher 	return o->raw.check_pending(&o->raw) || o->check_sched(o);
3566adfc5217SJeff Kirsher }
3567adfc5217SJeff Kirsher 
3568adfc5217SJeff Kirsher void bnx2x_init_mcast_obj(struct bnx2x *bp,
3569adfc5217SJeff Kirsher 			  struct bnx2x_mcast_obj *mcast_obj,
3570adfc5217SJeff Kirsher 			  u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
3571adfc5217SJeff Kirsher 			  u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
3572adfc5217SJeff Kirsher 			  int state, unsigned long *pstate, bnx2x_obj_type type)
3573adfc5217SJeff Kirsher {
3574adfc5217SJeff Kirsher 	memset(mcast_obj, 0, sizeof(*mcast_obj));
3575adfc5217SJeff Kirsher 
3576adfc5217SJeff Kirsher 	bnx2x_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id,
3577adfc5217SJeff Kirsher 			   rdata, rdata_mapping, state, pstate, type);
3578adfc5217SJeff Kirsher 
3579adfc5217SJeff Kirsher 	mcast_obj->engine_id = engine_id;
3580adfc5217SJeff Kirsher 
3581adfc5217SJeff Kirsher 	INIT_LIST_HEAD(&mcast_obj->pending_cmds_head);
3582adfc5217SJeff Kirsher 
3583adfc5217SJeff Kirsher 	mcast_obj->sched_state = BNX2X_FILTER_MCAST_SCHED;
3584adfc5217SJeff Kirsher 	mcast_obj->check_sched = bnx2x_mcast_check_sched;
3585adfc5217SJeff Kirsher 	mcast_obj->set_sched = bnx2x_mcast_set_sched;
3586adfc5217SJeff Kirsher 	mcast_obj->clear_sched = bnx2x_mcast_clear_sched;
3587adfc5217SJeff Kirsher 
3588adfc5217SJeff Kirsher 	if (CHIP_IS_E1(bp)) {
3589adfc5217SJeff Kirsher 		mcast_obj->config_mcast      = bnx2x_mcast_setup_e1;
3590adfc5217SJeff Kirsher 		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
3591adfc5217SJeff Kirsher 		mcast_obj->hdl_restore       =
3592adfc5217SJeff Kirsher 			bnx2x_mcast_handle_restore_cmd_e1;
3593adfc5217SJeff Kirsher 		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
3594adfc5217SJeff Kirsher 
3595adfc5217SJeff Kirsher 		if (CHIP_REV_IS_SLOW(bp))
3596adfc5217SJeff Kirsher 			mcast_obj->max_cmd_len = BNX2X_MAX_EMUL_MULTI;
3597adfc5217SJeff Kirsher 		else
3598adfc5217SJeff Kirsher 			mcast_obj->max_cmd_len = BNX2X_MAX_MULTICAST;
3599adfc5217SJeff Kirsher 
3600adfc5217SJeff Kirsher 		mcast_obj->wait_comp         = bnx2x_mcast_wait;
3601adfc5217SJeff Kirsher 		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e1;
3602adfc5217SJeff Kirsher 		mcast_obj->validate          = bnx2x_mcast_validate_e1;
3603adfc5217SJeff Kirsher 		mcast_obj->revert            = bnx2x_mcast_revert_e1;
3604adfc5217SJeff Kirsher 		mcast_obj->get_registry_size =
3605adfc5217SJeff Kirsher 			bnx2x_mcast_get_registry_size_exact;
3606adfc5217SJeff Kirsher 		mcast_obj->set_registry_size =
3607adfc5217SJeff Kirsher 			bnx2x_mcast_set_registry_size_exact;
3608adfc5217SJeff Kirsher 
3609adfc5217SJeff Kirsher 		/* 57710 is the only chip that uses the exact match for mcast
3610adfc5217SJeff Kirsher 		 * at the moment.
3611adfc5217SJeff Kirsher 		 */
3612adfc5217SJeff Kirsher 		INIT_LIST_HEAD(&mcast_obj->registry.exact_match.macs);
3613adfc5217SJeff Kirsher 
3614adfc5217SJeff Kirsher 	} else if (CHIP_IS_E1H(bp)) {
3615adfc5217SJeff Kirsher 		mcast_obj->config_mcast  = bnx2x_mcast_setup_e1h;
3616adfc5217SJeff Kirsher 		mcast_obj->enqueue_cmd   = NULL;
3617adfc5217SJeff Kirsher 		mcast_obj->hdl_restore   = NULL;
3618adfc5217SJeff Kirsher 		mcast_obj->check_pending = bnx2x_mcast_check_pending;
3619adfc5217SJeff Kirsher 
3620adfc5217SJeff Kirsher 		/* 57711 doesn't send a ramrod, so it has unlimited credit
3621adfc5217SJeff Kirsher 		 * for one command.
3622adfc5217SJeff Kirsher 		 */
3623adfc5217SJeff Kirsher 		mcast_obj->max_cmd_len       = -1;
3624adfc5217SJeff Kirsher 		mcast_obj->wait_comp         = bnx2x_mcast_wait;
3625adfc5217SJeff Kirsher 		mcast_obj->set_one_rule      = NULL;
3626adfc5217SJeff Kirsher 		mcast_obj->validate          = bnx2x_mcast_validate_e1h;
3627adfc5217SJeff Kirsher 		mcast_obj->revert            = bnx2x_mcast_revert_e1h;
3628adfc5217SJeff Kirsher 		mcast_obj->get_registry_size =
3629adfc5217SJeff Kirsher 			bnx2x_mcast_get_registry_size_aprox;
3630adfc5217SJeff Kirsher 		mcast_obj->set_registry_size =
3631adfc5217SJeff Kirsher 			bnx2x_mcast_set_registry_size_aprox;
3632adfc5217SJeff Kirsher 	} else {
3633adfc5217SJeff Kirsher 		mcast_obj->config_mcast      = bnx2x_mcast_setup_e2;
3634adfc5217SJeff Kirsher 		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
3635adfc5217SJeff Kirsher 		mcast_obj->hdl_restore       =
3636adfc5217SJeff Kirsher 			bnx2x_mcast_handle_restore_cmd_e2;
3637adfc5217SJeff Kirsher 		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
3638adfc5217SJeff Kirsher 		/* TODO: There should be a proper HSI define for this number!!!
3639adfc5217SJeff Kirsher 		 */
3640adfc5217SJeff Kirsher 		mcast_obj->max_cmd_len       = 16;
3641adfc5217SJeff Kirsher 		mcast_obj->wait_comp         = bnx2x_mcast_wait;
3642adfc5217SJeff Kirsher 		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e2;
3643adfc5217SJeff Kirsher 		mcast_obj->validate          = bnx2x_mcast_validate_e2;
3644adfc5217SJeff Kirsher 		mcast_obj->revert            = bnx2x_mcast_revert_e2;
3645adfc5217SJeff Kirsher 		mcast_obj->get_registry_size =
3646adfc5217SJeff Kirsher 			bnx2x_mcast_get_registry_size_aprox;
3647adfc5217SJeff Kirsher 		mcast_obj->set_registry_size =
3648adfc5217SJeff Kirsher 			bnx2x_mcast_set_registry_size_aprox;
3649adfc5217SJeff Kirsher 	}
3650adfc5217SJeff Kirsher }
3651adfc5217SJeff Kirsher 
3652adfc5217SJeff Kirsher /*************************** Credit handling **********************************/
3653adfc5217SJeff Kirsher 
3654adfc5217SJeff Kirsher /**
3655adfc5217SJeff Kirsher  * atomic_add_ifless - add if the result is less than a given value.
3656adfc5217SJeff Kirsher  *
3657adfc5217SJeff Kirsher  * @v:	pointer of type atomic_t
3658adfc5217SJeff Kirsher  * @a:	the amount to add to v...
3659adfc5217SJeff Kirsher  * @u:	...if (v + a) is less than u.
3660adfc5217SJeff Kirsher  *
3661adfc5217SJeff Kirsher  * returns true if (v + a) was less than u, and false otherwise.
3662adfc5217SJeff Kirsher  *
3663adfc5217SJeff Kirsher  */
3664adfc5217SJeff Kirsher static inline bool __atomic_add_ifless(atomic_t *v, int a, int u)
3665adfc5217SJeff Kirsher {
3666adfc5217SJeff Kirsher 	int c, old;
3667adfc5217SJeff Kirsher 
3668adfc5217SJeff Kirsher 	c = atomic_read(v);
3669adfc5217SJeff Kirsher 	for (;;) {
3670adfc5217SJeff Kirsher 		if (unlikely(c + a >= u))
3671adfc5217SJeff Kirsher 			return false;
3672adfc5217SJeff Kirsher 
3673adfc5217SJeff Kirsher 		old = atomic_cmpxchg((v), c, c + a);
3674adfc5217SJeff Kirsher 		if (likely(old == c))
3675adfc5217SJeff Kirsher 			break;
3676adfc5217SJeff Kirsher 		c = old;
3677adfc5217SJeff Kirsher 	}
3678adfc5217SJeff Kirsher 
3679adfc5217SJeff Kirsher 	return true;
3680adfc5217SJeff Kirsher }
3681adfc5217SJeff Kirsher 
3682adfc5217SJeff Kirsher /**
3683adfc5217SJeff Kirsher  * atomic_dec_ifmoe - dec if the result is more or equal than a given value.
3684adfc5217SJeff Kirsher  *
3685adfc5217SJeff Kirsher  * @v:	pointer of type atomic_t
3686adfc5217SJeff Kirsher  * @a:	the amount to dec from v...
3687adfc5217SJeff Kirsher  * @u:	...if (v - a) is more or equal than u.
3688adfc5217SJeff Kirsher  *
3689adfc5217SJeff Kirsher  * returns true if (v - a) was more or equal than u, and false
3690adfc5217SJeff Kirsher  * otherwise.
3691adfc5217SJeff Kirsher  */
3692adfc5217SJeff Kirsher static inline bool __atomic_dec_ifmoe(atomic_t *v, int a, int u)
3693adfc5217SJeff Kirsher {
3694adfc5217SJeff Kirsher 	int c, old;
3695adfc5217SJeff Kirsher 
3696adfc5217SJeff Kirsher 	c = atomic_read(v);
3697adfc5217SJeff Kirsher 	for (;;) {
3698adfc5217SJeff Kirsher 		if (unlikely(c - a < u))
3699adfc5217SJeff Kirsher 			return false;
3700adfc5217SJeff Kirsher 
3701adfc5217SJeff Kirsher 		old = atomic_cmpxchg((v), c, c - a);
3702adfc5217SJeff Kirsher 		if (likely(old == c))
3703adfc5217SJeff Kirsher 			break;
3704adfc5217SJeff Kirsher 		c = old;
3705adfc5217SJeff Kirsher 	}
3706adfc5217SJeff Kirsher 
3707adfc5217SJeff Kirsher 	return true;
3708adfc5217SJeff Kirsher }
3709adfc5217SJeff Kirsher 
3710adfc5217SJeff Kirsher static bool bnx2x_credit_pool_get(struct bnx2x_credit_pool_obj *o, int cnt)
3711adfc5217SJeff Kirsher {
3712adfc5217SJeff Kirsher 	bool rc;
3713adfc5217SJeff Kirsher 
3714adfc5217SJeff Kirsher 	smp_mb();
3715adfc5217SJeff Kirsher 	rc = __atomic_dec_ifmoe(&o->credit, cnt, 0);
3716adfc5217SJeff Kirsher 	smp_mb();
3717adfc5217SJeff Kirsher 
3718adfc5217SJeff Kirsher 	return rc;
3719adfc5217SJeff Kirsher }
3720adfc5217SJeff Kirsher 
3721adfc5217SJeff Kirsher static bool bnx2x_credit_pool_put(struct bnx2x_credit_pool_obj *o, int cnt)
3722adfc5217SJeff Kirsher {
3723adfc5217SJeff Kirsher 	bool rc;
3724adfc5217SJeff Kirsher 
3725adfc5217SJeff Kirsher 	smp_mb();
3726adfc5217SJeff Kirsher 
3727adfc5217SJeff Kirsher 	/* Don't let to refill if credit + cnt > pool_sz */
3728adfc5217SJeff Kirsher 	rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1);
3729adfc5217SJeff Kirsher 
3730adfc5217SJeff Kirsher 	smp_mb();
3731adfc5217SJeff Kirsher 
3732adfc5217SJeff Kirsher 	return rc;
3733adfc5217SJeff Kirsher }
3734adfc5217SJeff Kirsher 
3735adfc5217SJeff Kirsher static int bnx2x_credit_pool_check(struct bnx2x_credit_pool_obj *o)
3736adfc5217SJeff Kirsher {
3737adfc5217SJeff Kirsher 	int cur_credit;
3738adfc5217SJeff Kirsher 
3739adfc5217SJeff Kirsher 	smp_mb();
3740adfc5217SJeff Kirsher 	cur_credit = atomic_read(&o->credit);
3741adfc5217SJeff Kirsher 
3742adfc5217SJeff Kirsher 	return cur_credit;
3743adfc5217SJeff Kirsher }
3744adfc5217SJeff Kirsher 
3745adfc5217SJeff Kirsher static bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o,
3746adfc5217SJeff Kirsher 					  int cnt)
3747adfc5217SJeff Kirsher {
3748adfc5217SJeff Kirsher 	return true;
3749adfc5217SJeff Kirsher }
3750adfc5217SJeff Kirsher 
3751adfc5217SJeff Kirsher 
3752adfc5217SJeff Kirsher static bool bnx2x_credit_pool_get_entry(
3753adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *o,
3754adfc5217SJeff Kirsher 	int *offset)
3755adfc5217SJeff Kirsher {
3756adfc5217SJeff Kirsher 	int idx, vec, i;
3757adfc5217SJeff Kirsher 
3758adfc5217SJeff Kirsher 	*offset = -1;
3759adfc5217SJeff Kirsher 
3760adfc5217SJeff Kirsher 	/* Find "internal cam-offset" then add to base for this object... */
3761adfc5217SJeff Kirsher 	for (vec = 0; vec < BNX2X_POOL_VEC_SIZE; vec++) {
3762adfc5217SJeff Kirsher 
3763adfc5217SJeff Kirsher 		/* Skip the current vector if there are no free entries in it */
3764adfc5217SJeff Kirsher 		if (!o->pool_mirror[vec])
3765adfc5217SJeff Kirsher 			continue;
3766adfc5217SJeff Kirsher 
3767adfc5217SJeff Kirsher 		/* If we've got here we are going to find a free entry */
3768adfc5217SJeff Kirsher 		for (idx = vec * BNX2X_POOL_VEC_SIZE, i = 0;
3769adfc5217SJeff Kirsher 		      i < BIT_VEC64_ELEM_SZ; idx++, i++)
3770adfc5217SJeff Kirsher 
3771adfc5217SJeff Kirsher 			if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
3772adfc5217SJeff Kirsher 				/* Got one!! */
3773adfc5217SJeff Kirsher 				BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx);
3774adfc5217SJeff Kirsher 				*offset = o->base_pool_offset + idx;
3775adfc5217SJeff Kirsher 				return true;
3776adfc5217SJeff Kirsher 			}
3777adfc5217SJeff Kirsher 	}
3778adfc5217SJeff Kirsher 
3779adfc5217SJeff Kirsher 	return false;
3780adfc5217SJeff Kirsher }
3781adfc5217SJeff Kirsher 
3782adfc5217SJeff Kirsher static bool bnx2x_credit_pool_put_entry(
3783adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *o,
3784adfc5217SJeff Kirsher 	int offset)
3785adfc5217SJeff Kirsher {
3786adfc5217SJeff Kirsher 	if (offset < o->base_pool_offset)
3787adfc5217SJeff Kirsher 		return false;
3788adfc5217SJeff Kirsher 
3789adfc5217SJeff Kirsher 	offset -= o->base_pool_offset;
3790adfc5217SJeff Kirsher 
3791adfc5217SJeff Kirsher 	if (offset >= o->pool_sz)
3792adfc5217SJeff Kirsher 		return false;
3793adfc5217SJeff Kirsher 
3794adfc5217SJeff Kirsher 	/* Return the entry to the pool */
3795adfc5217SJeff Kirsher 	BIT_VEC64_SET_BIT(o->pool_mirror, offset);
3796adfc5217SJeff Kirsher 
3797adfc5217SJeff Kirsher 	return true;
3798adfc5217SJeff Kirsher }
3799adfc5217SJeff Kirsher 
3800adfc5217SJeff Kirsher static bool bnx2x_credit_pool_put_entry_always_true(
3801adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *o,
3802adfc5217SJeff Kirsher 	int offset)
3803adfc5217SJeff Kirsher {
3804adfc5217SJeff Kirsher 	return true;
3805adfc5217SJeff Kirsher }
3806adfc5217SJeff Kirsher 
3807adfc5217SJeff Kirsher static bool bnx2x_credit_pool_get_entry_always_true(
3808adfc5217SJeff Kirsher 	struct bnx2x_credit_pool_obj *o,
3809adfc5217SJeff Kirsher 	int *offset)
3810adfc5217SJeff Kirsher {
3811adfc5217SJeff Kirsher 	*offset = -1;
3812adfc5217SJeff Kirsher 	return true;
3813adfc5217SJeff Kirsher }
3814adfc5217SJeff Kirsher /**
3815adfc5217SJeff Kirsher  * bnx2x_init_credit_pool - initialize credit pool internals.
3816adfc5217SJeff Kirsher  *
3817adfc5217SJeff Kirsher  * @p:
3818adfc5217SJeff Kirsher  * @base:	Base entry in the CAM to use.
3819adfc5217SJeff Kirsher  * @credit:	pool size.
3820adfc5217SJeff Kirsher  *
3821adfc5217SJeff Kirsher  * If base is negative no CAM entries handling will be performed.
3822adfc5217SJeff Kirsher  * If credit is negative pool operations will always succeed (unlimited pool).
3823adfc5217SJeff Kirsher  *
3824adfc5217SJeff Kirsher  */
3825adfc5217SJeff Kirsher static inline void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
3826adfc5217SJeff Kirsher 					  int base, int credit)
3827adfc5217SJeff Kirsher {
3828adfc5217SJeff Kirsher 	/* Zero the object first */
3829adfc5217SJeff Kirsher 	memset(p, 0, sizeof(*p));
3830adfc5217SJeff Kirsher 
3831adfc5217SJeff Kirsher 	/* Set the table to all 1s */
3832adfc5217SJeff Kirsher 	memset(&p->pool_mirror, 0xff, sizeof(p->pool_mirror));
3833adfc5217SJeff Kirsher 
3834adfc5217SJeff Kirsher 	/* Init a pool as full */
3835adfc5217SJeff Kirsher 	atomic_set(&p->credit, credit);
3836adfc5217SJeff Kirsher 
3837adfc5217SJeff Kirsher 	/* The total poll size */
3838adfc5217SJeff Kirsher 	p->pool_sz = credit;
3839adfc5217SJeff Kirsher 
3840adfc5217SJeff Kirsher 	p->base_pool_offset = base;
3841adfc5217SJeff Kirsher 
3842adfc5217SJeff Kirsher 	/* Commit the change */
3843adfc5217SJeff Kirsher 	smp_mb();
3844adfc5217SJeff Kirsher 
3845adfc5217SJeff Kirsher 	p->check = bnx2x_credit_pool_check;
3846adfc5217SJeff Kirsher 
3847adfc5217SJeff Kirsher 	/* if pool credit is negative - disable the checks */
3848adfc5217SJeff Kirsher 	if (credit >= 0) {
3849adfc5217SJeff Kirsher 		p->put      = bnx2x_credit_pool_put;
3850adfc5217SJeff Kirsher 		p->get      = bnx2x_credit_pool_get;
3851adfc5217SJeff Kirsher 		p->put_entry = bnx2x_credit_pool_put_entry;
3852adfc5217SJeff Kirsher 		p->get_entry = bnx2x_credit_pool_get_entry;
3853adfc5217SJeff Kirsher 	} else {
3854adfc5217SJeff Kirsher 		p->put      = bnx2x_credit_pool_always_true;
3855adfc5217SJeff Kirsher 		p->get      = bnx2x_credit_pool_always_true;
3856adfc5217SJeff Kirsher 		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
3857adfc5217SJeff Kirsher 		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
3858adfc5217SJeff Kirsher 	}
3859adfc5217SJeff Kirsher 
3860adfc5217SJeff Kirsher 	/* If base is negative - disable entries handling */
3861adfc5217SJeff Kirsher 	if (base < 0) {
3862adfc5217SJeff Kirsher 		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
3863adfc5217SJeff Kirsher 		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
3864adfc5217SJeff Kirsher 	}
3865adfc5217SJeff Kirsher }
3866adfc5217SJeff Kirsher 
3867adfc5217SJeff Kirsher void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
3868adfc5217SJeff Kirsher 				struct bnx2x_credit_pool_obj *p, u8 func_id,
3869adfc5217SJeff Kirsher 				u8 func_num)
3870adfc5217SJeff Kirsher {
3871adfc5217SJeff Kirsher /* TODO: this will be defined in consts as well... */
3872adfc5217SJeff Kirsher #define BNX2X_CAM_SIZE_EMUL 5
3873adfc5217SJeff Kirsher 
3874adfc5217SJeff Kirsher 	int cam_sz;
3875adfc5217SJeff Kirsher 
3876adfc5217SJeff Kirsher 	if (CHIP_IS_E1(bp)) {
3877adfc5217SJeff Kirsher 		/* In E1, Multicast is saved in cam... */
3878adfc5217SJeff Kirsher 		if (!CHIP_REV_IS_SLOW(bp))
3879adfc5217SJeff Kirsher 			cam_sz = (MAX_MAC_CREDIT_E1 / 2) - BNX2X_MAX_MULTICAST;
3880adfc5217SJeff Kirsher 		else
3881adfc5217SJeff Kirsher 			cam_sz = BNX2X_CAM_SIZE_EMUL - BNX2X_MAX_EMUL_MULTI;
3882adfc5217SJeff Kirsher 
3883adfc5217SJeff Kirsher 		bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
3884adfc5217SJeff Kirsher 
3885adfc5217SJeff Kirsher 	} else if (CHIP_IS_E1H(bp)) {
3886adfc5217SJeff Kirsher 		/* CAM credit is equaly divided between all active functions
3887adfc5217SJeff Kirsher 		 * on the PORT!.
3888adfc5217SJeff Kirsher 		 */
3889adfc5217SJeff Kirsher 		if ((func_num > 0)) {
3890adfc5217SJeff Kirsher 			if (!CHIP_REV_IS_SLOW(bp))
3891adfc5217SJeff Kirsher 				cam_sz = (MAX_MAC_CREDIT_E1H / (2*func_num));
3892adfc5217SJeff Kirsher 			else
3893adfc5217SJeff Kirsher 				cam_sz = BNX2X_CAM_SIZE_EMUL;
3894adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
3895adfc5217SJeff Kirsher 		} else {
3896adfc5217SJeff Kirsher 			/* this should never happen! Block MAC operations. */
3897adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, 0, 0);
3898adfc5217SJeff Kirsher 		}
3899adfc5217SJeff Kirsher 
3900adfc5217SJeff Kirsher 	} else {
3901adfc5217SJeff Kirsher 
3902adfc5217SJeff Kirsher 		/*
3903adfc5217SJeff Kirsher 		 * CAM credit is equaly divided between all active functions
3904adfc5217SJeff Kirsher 		 * on the PATH.
3905adfc5217SJeff Kirsher 		 */
3906adfc5217SJeff Kirsher 		if ((func_num > 0)) {
3907adfc5217SJeff Kirsher 			if (!CHIP_REV_IS_SLOW(bp))
3908adfc5217SJeff Kirsher 				cam_sz = (MAX_MAC_CREDIT_E2 / func_num);
3909adfc5217SJeff Kirsher 			else
3910adfc5217SJeff Kirsher 				cam_sz = BNX2X_CAM_SIZE_EMUL;
3911adfc5217SJeff Kirsher 
3912adfc5217SJeff Kirsher 			/*
3913adfc5217SJeff Kirsher 			 * No need for CAM entries handling for 57712 and
3914adfc5217SJeff Kirsher 			 * newer.
3915adfc5217SJeff Kirsher 			 */
3916adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, -1, cam_sz);
3917adfc5217SJeff Kirsher 		} else {
3918adfc5217SJeff Kirsher 			/* this should never happen! Block MAC operations. */
3919adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, 0, 0);
3920adfc5217SJeff Kirsher 		}
3921adfc5217SJeff Kirsher 
3922adfc5217SJeff Kirsher 	}
3923adfc5217SJeff Kirsher }
3924adfc5217SJeff Kirsher 
3925adfc5217SJeff Kirsher void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
3926adfc5217SJeff Kirsher 				 struct bnx2x_credit_pool_obj *p,
3927adfc5217SJeff Kirsher 				 u8 func_id,
3928adfc5217SJeff Kirsher 				 u8 func_num)
3929adfc5217SJeff Kirsher {
3930adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp)) {
3931adfc5217SJeff Kirsher 		/*
3932adfc5217SJeff Kirsher 		 * There is no VLAN credit in HW on 57710 and 57711 only
3933adfc5217SJeff Kirsher 		 * MAC / MAC-VLAN can be set
3934adfc5217SJeff Kirsher 		 */
3935adfc5217SJeff Kirsher 		bnx2x_init_credit_pool(p, 0, -1);
3936adfc5217SJeff Kirsher 	} else {
3937adfc5217SJeff Kirsher 		/*
3938adfc5217SJeff Kirsher 		 * CAM credit is equaly divided between all active functions
3939adfc5217SJeff Kirsher 		 * on the PATH.
3940adfc5217SJeff Kirsher 		 */
3941adfc5217SJeff Kirsher 		if (func_num > 0) {
3942adfc5217SJeff Kirsher 			int credit = MAX_VLAN_CREDIT_E2 / func_num;
3943adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, func_id * credit, credit);
3944adfc5217SJeff Kirsher 		} else
3945adfc5217SJeff Kirsher 			/* this should never happen! Block VLAN operations. */
3946adfc5217SJeff Kirsher 			bnx2x_init_credit_pool(p, 0, 0);
3947adfc5217SJeff Kirsher 	}
3948adfc5217SJeff Kirsher }
3949adfc5217SJeff Kirsher 
3950adfc5217SJeff Kirsher /****************** RSS Configuration ******************/
3951adfc5217SJeff Kirsher /**
3952adfc5217SJeff Kirsher  * bnx2x_debug_print_ind_table - prints the indirection table configuration.
3953adfc5217SJeff Kirsher  *
3954adfc5217SJeff Kirsher  * @bp:		driver hanlde
3955adfc5217SJeff Kirsher  * @p:		pointer to rss configuration
3956adfc5217SJeff Kirsher  *
3957adfc5217SJeff Kirsher  * Prints it when NETIF_MSG_IFUP debug level is configured.
3958adfc5217SJeff Kirsher  */
3959adfc5217SJeff Kirsher static inline void bnx2x_debug_print_ind_table(struct bnx2x *bp,
3960adfc5217SJeff Kirsher 					struct bnx2x_config_rss_params *p)
3961adfc5217SJeff Kirsher {
3962adfc5217SJeff Kirsher 	int i;
3963adfc5217SJeff Kirsher 
3964adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Setting indirection table to:\n");
3965adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "0x0000: ");
3966adfc5217SJeff Kirsher 	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
3967adfc5217SJeff Kirsher 		DP_CONT(BNX2X_MSG_SP, "0x%02x ", p->ind_table[i]);
3968adfc5217SJeff Kirsher 
3969adfc5217SJeff Kirsher 		/* Print 4 bytes in a line */
3970adfc5217SJeff Kirsher 		if ((i + 1 < T_ETH_INDIRECTION_TABLE_SIZE) &&
3971adfc5217SJeff Kirsher 		    (((i + 1) & 0x3) == 0)) {
3972adfc5217SJeff Kirsher 			DP_CONT(BNX2X_MSG_SP, "\n");
3973adfc5217SJeff Kirsher 			DP(BNX2X_MSG_SP, "0x%04x: ", i + 1);
3974adfc5217SJeff Kirsher 		}
3975adfc5217SJeff Kirsher 	}
3976adfc5217SJeff Kirsher 
3977adfc5217SJeff Kirsher 	DP_CONT(BNX2X_MSG_SP, "\n");
3978adfc5217SJeff Kirsher }
3979adfc5217SJeff Kirsher 
3980adfc5217SJeff Kirsher /**
3981adfc5217SJeff Kirsher  * bnx2x_setup_rss - configure RSS
3982adfc5217SJeff Kirsher  *
3983adfc5217SJeff Kirsher  * @bp:		device handle
3984adfc5217SJeff Kirsher  * @p:		rss configuration
3985adfc5217SJeff Kirsher  *
3986adfc5217SJeff Kirsher  * sends on UPDATE ramrod for that matter.
3987adfc5217SJeff Kirsher  */
3988adfc5217SJeff Kirsher static int bnx2x_setup_rss(struct bnx2x *bp,
3989adfc5217SJeff Kirsher 			   struct bnx2x_config_rss_params *p)
3990adfc5217SJeff Kirsher {
3991adfc5217SJeff Kirsher 	struct bnx2x_rss_config_obj *o = p->rss_obj;
3992adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
3993adfc5217SJeff Kirsher 	struct eth_rss_update_ramrod_data *data =
3994adfc5217SJeff Kirsher 		(struct eth_rss_update_ramrod_data *)(r->rdata);
3995adfc5217SJeff Kirsher 	u8 rss_mode = 0;
3996adfc5217SJeff Kirsher 	int rc;
3997adfc5217SJeff Kirsher 
3998adfc5217SJeff Kirsher 	memset(data, 0, sizeof(*data));
3999adfc5217SJeff Kirsher 
4000adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Configuring RSS\n");
4001adfc5217SJeff Kirsher 
4002adfc5217SJeff Kirsher 	/* Set an echo field */
4003adfc5217SJeff Kirsher 	data->echo = (r->cid & BNX2X_SWCID_MASK) |
4004adfc5217SJeff Kirsher 		     (r->state << BNX2X_SWCID_SHIFT);
4005adfc5217SJeff Kirsher 
4006adfc5217SJeff Kirsher 	/* RSS mode */
4007adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_MODE_DISABLED, &p->rss_flags))
4008adfc5217SJeff Kirsher 		rss_mode = ETH_RSS_MODE_DISABLED;
4009adfc5217SJeff Kirsher 	else if (test_bit(BNX2X_RSS_MODE_REGULAR, &p->rss_flags))
4010adfc5217SJeff Kirsher 		rss_mode = ETH_RSS_MODE_REGULAR;
4011adfc5217SJeff Kirsher 	else if (test_bit(BNX2X_RSS_MODE_VLAN_PRI, &p->rss_flags))
4012adfc5217SJeff Kirsher 		rss_mode = ETH_RSS_MODE_VLAN_PRI;
4013adfc5217SJeff Kirsher 	else if (test_bit(BNX2X_RSS_MODE_E1HOV_PRI, &p->rss_flags))
4014adfc5217SJeff Kirsher 		rss_mode = ETH_RSS_MODE_E1HOV_PRI;
4015adfc5217SJeff Kirsher 	else if (test_bit(BNX2X_RSS_MODE_IP_DSCP, &p->rss_flags))
4016adfc5217SJeff Kirsher 		rss_mode = ETH_RSS_MODE_IP_DSCP;
4017adfc5217SJeff Kirsher 
4018adfc5217SJeff Kirsher 	data->rss_mode = rss_mode;
4019adfc5217SJeff Kirsher 
4020adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "rss_mode=%d\n", rss_mode);
4021adfc5217SJeff Kirsher 
4022adfc5217SJeff Kirsher 	/* RSS capabilities */
4023adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_IPV4, &p->rss_flags))
4024adfc5217SJeff Kirsher 		data->capabilities |=
4025adfc5217SJeff Kirsher 			ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY;
4026adfc5217SJeff Kirsher 
4027adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_IPV4_TCP, &p->rss_flags))
4028adfc5217SJeff Kirsher 		data->capabilities |=
4029adfc5217SJeff Kirsher 			ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
4030adfc5217SJeff Kirsher 
4031adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags))
4032adfc5217SJeff Kirsher 		data->capabilities |=
4033adfc5217SJeff Kirsher 			ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
4034adfc5217SJeff Kirsher 
4035adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_IPV6_TCP, &p->rss_flags))
4036adfc5217SJeff Kirsher 		data->capabilities |=
4037adfc5217SJeff Kirsher 			ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
4038adfc5217SJeff Kirsher 
4039adfc5217SJeff Kirsher 	/* Hashing mask */
4040adfc5217SJeff Kirsher 	data->rss_result_mask = p->rss_result_mask;
4041adfc5217SJeff Kirsher 
4042adfc5217SJeff Kirsher 	/* RSS engine ID */
4043adfc5217SJeff Kirsher 	data->rss_engine_id = o->engine_id;
4044adfc5217SJeff Kirsher 
4045adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "rss_engine_id=%d\n", data->rss_engine_id);
4046adfc5217SJeff Kirsher 
4047adfc5217SJeff Kirsher 	/* Indirection table */
4048adfc5217SJeff Kirsher 	memcpy(data->indirection_table, p->ind_table,
4049adfc5217SJeff Kirsher 		  T_ETH_INDIRECTION_TABLE_SIZE);
4050adfc5217SJeff Kirsher 
4051adfc5217SJeff Kirsher 	/* Remember the last configuration */
4052adfc5217SJeff Kirsher 	memcpy(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
4053adfc5217SJeff Kirsher 
4054adfc5217SJeff Kirsher 	/* Print the indirection table */
4055adfc5217SJeff Kirsher 	if (netif_msg_ifup(bp))
4056adfc5217SJeff Kirsher 		bnx2x_debug_print_ind_table(bp, p);
4057adfc5217SJeff Kirsher 
4058adfc5217SJeff Kirsher 	/* RSS keys */
4059adfc5217SJeff Kirsher 	if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
4060adfc5217SJeff Kirsher 		memcpy(&data->rss_key[0], &p->rss_key[0],
4061adfc5217SJeff Kirsher 		       sizeof(data->rss_key));
4062adfc5217SJeff Kirsher 		data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
4063adfc5217SJeff Kirsher 	}
4064adfc5217SJeff Kirsher 
4065adfc5217SJeff Kirsher 	/*
4066adfc5217SJeff Kirsher 	 *  No need for an explicit memory barrier here as long we would
4067adfc5217SJeff Kirsher 	 *  need to ensure the ordering of writing to the SPQ element
4068adfc5217SJeff Kirsher 	 *  and updating of the SPQ producer which involves a memory
4069adfc5217SJeff Kirsher 	 *  read and we will have to put a full memory barrier there
4070adfc5217SJeff Kirsher 	 *  (inside bnx2x_sp_post()).
4071adfc5217SJeff Kirsher 	 */
4072adfc5217SJeff Kirsher 
4073adfc5217SJeff Kirsher 	/* Send a ramrod */
4074adfc5217SJeff Kirsher 	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid,
4075adfc5217SJeff Kirsher 			   U64_HI(r->rdata_mapping),
4076adfc5217SJeff Kirsher 			   U64_LO(r->rdata_mapping),
4077adfc5217SJeff Kirsher 			   ETH_CONNECTION_TYPE);
4078adfc5217SJeff Kirsher 
4079adfc5217SJeff Kirsher 	if (rc < 0)
4080adfc5217SJeff Kirsher 		return rc;
4081adfc5217SJeff Kirsher 
4082adfc5217SJeff Kirsher 	return 1;
4083adfc5217SJeff Kirsher }
4084adfc5217SJeff Kirsher 
4085adfc5217SJeff Kirsher void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
4086adfc5217SJeff Kirsher 			     u8 *ind_table)
4087adfc5217SJeff Kirsher {
4088adfc5217SJeff Kirsher 	memcpy(ind_table, rss_obj->ind_table, sizeof(rss_obj->ind_table));
4089adfc5217SJeff Kirsher }
4090adfc5217SJeff Kirsher 
4091adfc5217SJeff Kirsher int bnx2x_config_rss(struct bnx2x *bp,
4092adfc5217SJeff Kirsher 		     struct bnx2x_config_rss_params *p)
4093adfc5217SJeff Kirsher {
4094adfc5217SJeff Kirsher 	int rc;
4095adfc5217SJeff Kirsher 	struct bnx2x_rss_config_obj *o = p->rss_obj;
4096adfc5217SJeff Kirsher 	struct bnx2x_raw_obj *r = &o->raw;
4097adfc5217SJeff Kirsher 
4098adfc5217SJeff Kirsher 	/* Do nothing if only driver cleanup was requested */
4099adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
4100adfc5217SJeff Kirsher 		return 0;
4101adfc5217SJeff Kirsher 
4102adfc5217SJeff Kirsher 	r->set_pending(r);
4103adfc5217SJeff Kirsher 
4104adfc5217SJeff Kirsher 	rc = o->config_rss(bp, p);
4105adfc5217SJeff Kirsher 	if (rc < 0) {
4106adfc5217SJeff Kirsher 		r->clear_pending(r);
4107adfc5217SJeff Kirsher 		return rc;
4108adfc5217SJeff Kirsher 	}
4109adfc5217SJeff Kirsher 
4110adfc5217SJeff Kirsher 	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
4111adfc5217SJeff Kirsher 		rc = r->wait_comp(bp, r);
4112adfc5217SJeff Kirsher 
4113adfc5217SJeff Kirsher 	return rc;
4114adfc5217SJeff Kirsher }
4115adfc5217SJeff Kirsher 
4116adfc5217SJeff Kirsher 
4117adfc5217SJeff Kirsher void bnx2x_init_rss_config_obj(struct bnx2x *bp,
4118adfc5217SJeff Kirsher 			       struct bnx2x_rss_config_obj *rss_obj,
4119adfc5217SJeff Kirsher 			       u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
4120adfc5217SJeff Kirsher 			       void *rdata, dma_addr_t rdata_mapping,
4121adfc5217SJeff Kirsher 			       int state, unsigned long *pstate,
4122adfc5217SJeff Kirsher 			       bnx2x_obj_type type)
4123adfc5217SJeff Kirsher {
4124adfc5217SJeff Kirsher 	bnx2x_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata,
4125adfc5217SJeff Kirsher 			   rdata_mapping, state, pstate, type);
4126adfc5217SJeff Kirsher 
4127adfc5217SJeff Kirsher 	rss_obj->engine_id  = engine_id;
4128adfc5217SJeff Kirsher 	rss_obj->config_rss = bnx2x_setup_rss;
4129adfc5217SJeff Kirsher }
4130adfc5217SJeff Kirsher 
4131adfc5217SJeff Kirsher /********************** Queue state object ***********************************/
4132adfc5217SJeff Kirsher 
4133adfc5217SJeff Kirsher /**
4134adfc5217SJeff Kirsher  * bnx2x_queue_state_change - perform Queue state change transition
4135adfc5217SJeff Kirsher  *
4136adfc5217SJeff Kirsher  * @bp:		device handle
4137adfc5217SJeff Kirsher  * @params:	parameters to perform the transition
4138adfc5217SJeff Kirsher  *
4139adfc5217SJeff Kirsher  * returns 0 in case of successfully completed transition, negative error
4140adfc5217SJeff Kirsher  * code in case of failure, positive (EBUSY) value if there is a completion
4141adfc5217SJeff Kirsher  * to that is still pending (possible only if RAMROD_COMP_WAIT is
4142adfc5217SJeff Kirsher  * not set in params->ramrod_flags for asynchronous commands).
4143adfc5217SJeff Kirsher  *
4144adfc5217SJeff Kirsher  */
4145adfc5217SJeff Kirsher int bnx2x_queue_state_change(struct bnx2x *bp,
4146adfc5217SJeff Kirsher 			     struct bnx2x_queue_state_params *params)
4147adfc5217SJeff Kirsher {
4148adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4149adfc5217SJeff Kirsher 	int rc, pending_bit;
4150adfc5217SJeff Kirsher 	unsigned long *pending = &o->pending;
4151adfc5217SJeff Kirsher 
4152adfc5217SJeff Kirsher 	/* Check that the requested transition is legal */
4153adfc5217SJeff Kirsher 	if (o->check_transition(bp, o, params))
4154adfc5217SJeff Kirsher 		return -EINVAL;
4155adfc5217SJeff Kirsher 
4156adfc5217SJeff Kirsher 	/* Set "pending" bit */
4157adfc5217SJeff Kirsher 	pending_bit = o->set_pending(o, params);
4158adfc5217SJeff Kirsher 
4159adfc5217SJeff Kirsher 	/* Don't send a command if only driver cleanup was requested */
4160adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags))
4161adfc5217SJeff Kirsher 		o->complete_cmd(bp, o, pending_bit);
4162adfc5217SJeff Kirsher 	else {
4163adfc5217SJeff Kirsher 		/* Send a ramrod */
4164adfc5217SJeff Kirsher 		rc = o->send_cmd(bp, params);
4165adfc5217SJeff Kirsher 		if (rc) {
4166adfc5217SJeff Kirsher 			o->next_state = BNX2X_Q_STATE_MAX;
4167adfc5217SJeff Kirsher 			clear_bit(pending_bit, pending);
4168adfc5217SJeff Kirsher 			smp_mb__after_clear_bit();
4169adfc5217SJeff Kirsher 			return rc;
4170adfc5217SJeff Kirsher 		}
4171adfc5217SJeff Kirsher 
4172adfc5217SJeff Kirsher 		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
4173adfc5217SJeff Kirsher 			rc = o->wait_comp(bp, o, pending_bit);
4174adfc5217SJeff Kirsher 			if (rc)
4175adfc5217SJeff Kirsher 				return rc;
4176adfc5217SJeff Kirsher 
4177adfc5217SJeff Kirsher 			return 0;
4178adfc5217SJeff Kirsher 		}
4179adfc5217SJeff Kirsher 	}
4180adfc5217SJeff Kirsher 
4181adfc5217SJeff Kirsher 	return !!test_bit(pending_bit, pending);
4182adfc5217SJeff Kirsher }
4183adfc5217SJeff Kirsher 
4184adfc5217SJeff Kirsher 
4185adfc5217SJeff Kirsher static int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj,
4186adfc5217SJeff Kirsher 				   struct bnx2x_queue_state_params *params)
4187adfc5217SJeff Kirsher {
4188adfc5217SJeff Kirsher 	enum bnx2x_queue_cmd cmd = params->cmd, bit;
4189adfc5217SJeff Kirsher 
4190adfc5217SJeff Kirsher 	/* ACTIVATE and DEACTIVATE commands are implemented on top of
4191adfc5217SJeff Kirsher 	 * UPDATE command.
4192adfc5217SJeff Kirsher 	 */
4193adfc5217SJeff Kirsher 	if ((cmd == BNX2X_Q_CMD_ACTIVATE) ||
4194adfc5217SJeff Kirsher 	    (cmd == BNX2X_Q_CMD_DEACTIVATE))
4195adfc5217SJeff Kirsher 		bit = BNX2X_Q_CMD_UPDATE;
4196adfc5217SJeff Kirsher 	else
4197adfc5217SJeff Kirsher 		bit = cmd;
4198adfc5217SJeff Kirsher 
4199adfc5217SJeff Kirsher 	set_bit(bit, &obj->pending);
4200adfc5217SJeff Kirsher 	return bit;
4201adfc5217SJeff Kirsher }
4202adfc5217SJeff Kirsher 
4203adfc5217SJeff Kirsher static int bnx2x_queue_wait_comp(struct bnx2x *bp,
4204adfc5217SJeff Kirsher 				 struct bnx2x_queue_sp_obj *o,
4205adfc5217SJeff Kirsher 				 enum bnx2x_queue_cmd cmd)
4206adfc5217SJeff Kirsher {
4207adfc5217SJeff Kirsher 	return bnx2x_state_wait(bp, cmd, &o->pending);
4208adfc5217SJeff Kirsher }
4209adfc5217SJeff Kirsher 
4210adfc5217SJeff Kirsher /**
4211adfc5217SJeff Kirsher  * bnx2x_queue_comp_cmd - complete the state change command.
4212adfc5217SJeff Kirsher  *
4213adfc5217SJeff Kirsher  * @bp:		device handle
4214adfc5217SJeff Kirsher  * @o:
4215adfc5217SJeff Kirsher  * @cmd:
4216adfc5217SJeff Kirsher  *
4217adfc5217SJeff Kirsher  * Checks that the arrived completion is expected.
4218adfc5217SJeff Kirsher  */
4219adfc5217SJeff Kirsher static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
4220adfc5217SJeff Kirsher 				struct bnx2x_queue_sp_obj *o,
4221adfc5217SJeff Kirsher 				enum bnx2x_queue_cmd cmd)
4222adfc5217SJeff Kirsher {
4223adfc5217SJeff Kirsher 	unsigned long cur_pending = o->pending;
4224adfc5217SJeff Kirsher 
4225adfc5217SJeff Kirsher 	if (!test_and_clear_bit(cmd, &cur_pending)) {
4226adfc5217SJeff Kirsher 		BNX2X_ERR("Bad MC reply %d for queue %d in state %d "
4227adfc5217SJeff Kirsher 			  "pending 0x%lx, next_state %d\n", cmd,
4228adfc5217SJeff Kirsher 			  o->cids[BNX2X_PRIMARY_CID_INDEX],
4229adfc5217SJeff Kirsher 			  o->state, cur_pending, o->next_state);
4230adfc5217SJeff Kirsher 		return -EINVAL;
4231adfc5217SJeff Kirsher 	}
4232adfc5217SJeff Kirsher 
4233adfc5217SJeff Kirsher 	if (o->next_tx_only >= o->max_cos)
4234adfc5217SJeff Kirsher 		/* >= becuase tx only must always be smaller than cos since the
4235adfc5217SJeff Kirsher 		 * primary connection suports COS 0
4236adfc5217SJeff Kirsher 		 */
4237adfc5217SJeff Kirsher 		BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
4238adfc5217SJeff Kirsher 			   o->next_tx_only, o->max_cos);
4239adfc5217SJeff Kirsher 
4240adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Completing command %d for queue %d, "
4241adfc5217SJeff Kirsher 			 "setting state to %d\n", cmd,
4242adfc5217SJeff Kirsher 			 o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state);
4243adfc5217SJeff Kirsher 
4244adfc5217SJeff Kirsher 	if (o->next_tx_only)  /* print num tx-only if any exist */
424594f05b0fSJoe Perches 		DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d\n",
4246adfc5217SJeff Kirsher 			   o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only);
4247adfc5217SJeff Kirsher 
4248adfc5217SJeff Kirsher 	o->state = o->next_state;
4249adfc5217SJeff Kirsher 	o->num_tx_only = o->next_tx_only;
4250adfc5217SJeff Kirsher 	o->next_state = BNX2X_Q_STATE_MAX;
4251adfc5217SJeff Kirsher 
4252adfc5217SJeff Kirsher 	/* It's important that o->state and o->next_state are
4253adfc5217SJeff Kirsher 	 * updated before o->pending.
4254adfc5217SJeff Kirsher 	 */
4255adfc5217SJeff Kirsher 	wmb();
4256adfc5217SJeff Kirsher 
4257adfc5217SJeff Kirsher 	clear_bit(cmd, &o->pending);
4258adfc5217SJeff Kirsher 	smp_mb__after_clear_bit();
4259adfc5217SJeff Kirsher 
4260adfc5217SJeff Kirsher 	return 0;
4261adfc5217SJeff Kirsher }
4262adfc5217SJeff Kirsher 
4263adfc5217SJeff Kirsher static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp,
4264adfc5217SJeff Kirsher 				struct bnx2x_queue_state_params *cmd_params,
4265adfc5217SJeff Kirsher 				struct client_init_ramrod_data *data)
4266adfc5217SJeff Kirsher {
4267adfc5217SJeff Kirsher 	struct bnx2x_queue_setup_params *params = &cmd_params->params.setup;
4268adfc5217SJeff Kirsher 
4269adfc5217SJeff Kirsher 	/* Rx data */
4270adfc5217SJeff Kirsher 
4271adfc5217SJeff Kirsher 	/* IPv6 TPA supported for E2 and above only */
4272adfc5217SJeff Kirsher 	data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, &params->flags) *
4273adfc5217SJeff Kirsher 				CLIENT_INIT_RX_DATA_TPA_EN_IPV6;
4274adfc5217SJeff Kirsher }
4275adfc5217SJeff Kirsher 
4276adfc5217SJeff Kirsher static void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
4277adfc5217SJeff Kirsher 				struct bnx2x_queue_sp_obj *o,
4278adfc5217SJeff Kirsher 				struct bnx2x_general_setup_params *params,
4279adfc5217SJeff Kirsher 				struct client_init_general_data *gen_data,
4280adfc5217SJeff Kirsher 				unsigned long *flags)
4281adfc5217SJeff Kirsher {
4282adfc5217SJeff Kirsher 	gen_data->client_id = o->cl_id;
4283adfc5217SJeff Kirsher 
4284adfc5217SJeff Kirsher 	if (test_bit(BNX2X_Q_FLG_STATS, flags)) {
4285adfc5217SJeff Kirsher 		gen_data->statistics_counter_id =
4286adfc5217SJeff Kirsher 					params->stat_id;
4287adfc5217SJeff Kirsher 		gen_data->statistics_en_flg = 1;
4288adfc5217SJeff Kirsher 		gen_data->statistics_zero_flg =
4289adfc5217SJeff Kirsher 			test_bit(BNX2X_Q_FLG_ZERO_STATS, flags);
4290adfc5217SJeff Kirsher 	} else
4291adfc5217SJeff Kirsher 		gen_data->statistics_counter_id =
4292adfc5217SJeff Kirsher 					DISABLE_STATISTIC_COUNTER_ID_VALUE;
4293adfc5217SJeff Kirsher 
4294adfc5217SJeff Kirsher 	gen_data->is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, flags);
4295adfc5217SJeff Kirsher 	gen_data->activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, flags);
4296adfc5217SJeff Kirsher 	gen_data->sp_client_id = params->spcl_id;
4297adfc5217SJeff Kirsher 	gen_data->mtu = cpu_to_le16(params->mtu);
4298adfc5217SJeff Kirsher 	gen_data->func_id = o->func_id;
4299adfc5217SJeff Kirsher 
4300adfc5217SJeff Kirsher 
4301adfc5217SJeff Kirsher 	gen_data->cos = params->cos;
4302adfc5217SJeff Kirsher 
4303adfc5217SJeff Kirsher 	gen_data->traffic_type =
4304adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_FCOE, flags) ?
4305adfc5217SJeff Kirsher 		LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
4306adfc5217SJeff Kirsher 
430794f05b0fSJoe Perches 	DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d\n",
4308adfc5217SJeff Kirsher 	   gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
4309adfc5217SJeff Kirsher }
4310adfc5217SJeff Kirsher 
4311adfc5217SJeff Kirsher static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o,
4312adfc5217SJeff Kirsher 				struct bnx2x_txq_setup_params *params,
4313adfc5217SJeff Kirsher 				struct client_init_tx_data *tx_data,
4314adfc5217SJeff Kirsher 				unsigned long *flags)
4315adfc5217SJeff Kirsher {
4316adfc5217SJeff Kirsher 	tx_data->enforce_security_flg =
4317adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_TX_SEC, flags);
4318adfc5217SJeff Kirsher 	tx_data->default_vlan =
4319adfc5217SJeff Kirsher 		cpu_to_le16(params->default_vlan);
4320adfc5217SJeff Kirsher 	tx_data->default_vlan_flg =
4321adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_DEF_VLAN, flags);
4322adfc5217SJeff Kirsher 	tx_data->tx_switching_flg =
4323adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_TX_SWITCH, flags);
4324adfc5217SJeff Kirsher 	tx_data->anti_spoofing_flg =
4325adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags);
4326adfc5217SJeff Kirsher 	tx_data->tx_status_block_id = params->fw_sb_id;
4327adfc5217SJeff Kirsher 	tx_data->tx_sb_index_number = params->sb_cq_index;
4328adfc5217SJeff Kirsher 	tx_data->tss_leading_client_id = params->tss_leading_cl_id;
4329adfc5217SJeff Kirsher 
4330adfc5217SJeff Kirsher 	tx_data->tx_bd_page_base.lo =
4331adfc5217SJeff Kirsher 		cpu_to_le32(U64_LO(params->dscr_map));
4332adfc5217SJeff Kirsher 	tx_data->tx_bd_page_base.hi =
4333adfc5217SJeff Kirsher 		cpu_to_le32(U64_HI(params->dscr_map));
4334adfc5217SJeff Kirsher 
4335adfc5217SJeff Kirsher 	/* Don't configure any Tx switching mode during queue SETUP */
4336adfc5217SJeff Kirsher 	tx_data->state = 0;
4337adfc5217SJeff Kirsher }
4338adfc5217SJeff Kirsher 
4339adfc5217SJeff Kirsher static void bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj *o,
4340adfc5217SJeff Kirsher 				struct rxq_pause_params *params,
4341adfc5217SJeff Kirsher 				struct client_init_rx_data *rx_data)
4342adfc5217SJeff Kirsher {
4343adfc5217SJeff Kirsher 	/* flow control data */
4344adfc5217SJeff Kirsher 	rx_data->cqe_pause_thr_low = cpu_to_le16(params->rcq_th_lo);
4345adfc5217SJeff Kirsher 	rx_data->cqe_pause_thr_high = cpu_to_le16(params->rcq_th_hi);
4346adfc5217SJeff Kirsher 	rx_data->bd_pause_thr_low = cpu_to_le16(params->bd_th_lo);
4347adfc5217SJeff Kirsher 	rx_data->bd_pause_thr_high = cpu_to_le16(params->bd_th_hi);
4348adfc5217SJeff Kirsher 	rx_data->sge_pause_thr_low = cpu_to_le16(params->sge_th_lo);
4349adfc5217SJeff Kirsher 	rx_data->sge_pause_thr_high = cpu_to_le16(params->sge_th_hi);
4350adfc5217SJeff Kirsher 	rx_data->rx_cos_mask = cpu_to_le16(params->pri_map);
4351adfc5217SJeff Kirsher }
4352adfc5217SJeff Kirsher 
4353adfc5217SJeff Kirsher static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o,
4354adfc5217SJeff Kirsher 				struct bnx2x_rxq_setup_params *params,
4355adfc5217SJeff Kirsher 				struct client_init_rx_data *rx_data,
4356adfc5217SJeff Kirsher 				unsigned long *flags)
4357adfc5217SJeff Kirsher {
4358adfc5217SJeff Kirsher 		/* Rx data */
4359adfc5217SJeff Kirsher 	rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) *
4360adfc5217SJeff Kirsher 				CLIENT_INIT_RX_DATA_TPA_EN_IPV4;
4361adfc5217SJeff Kirsher 	rx_data->vmqueue_mode_en_flg = 0;
4362adfc5217SJeff Kirsher 
4363adfc5217SJeff Kirsher 	rx_data->cache_line_alignment_log_size =
4364adfc5217SJeff Kirsher 		params->cache_line_log;
4365adfc5217SJeff Kirsher 	rx_data->enable_dynamic_hc =
4366adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_DHC, flags);
4367adfc5217SJeff Kirsher 	rx_data->max_sges_for_packet = params->max_sges_pkt;
4368adfc5217SJeff Kirsher 	rx_data->client_qzone_id = params->cl_qzone_id;
4369adfc5217SJeff Kirsher 	rx_data->max_agg_size = cpu_to_le16(params->tpa_agg_sz);
4370adfc5217SJeff Kirsher 
4371adfc5217SJeff Kirsher 	/* Always start in DROP_ALL mode */
4372adfc5217SJeff Kirsher 	rx_data->state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL |
4373adfc5217SJeff Kirsher 				     CLIENT_INIT_RX_DATA_MCAST_DROP_ALL);
4374adfc5217SJeff Kirsher 
4375adfc5217SJeff Kirsher 	/* We don't set drop flags */
4376adfc5217SJeff Kirsher 	rx_data->drop_ip_cs_err_flg = 0;
4377adfc5217SJeff Kirsher 	rx_data->drop_tcp_cs_err_flg = 0;
4378adfc5217SJeff Kirsher 	rx_data->drop_ttl0_flg = 0;
4379adfc5217SJeff Kirsher 	rx_data->drop_udp_cs_err_flg = 0;
4380adfc5217SJeff Kirsher 	rx_data->inner_vlan_removal_enable_flg =
4381adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_VLAN, flags);
4382adfc5217SJeff Kirsher 	rx_data->outer_vlan_removal_enable_flg =
4383adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_OV, flags);
4384adfc5217SJeff Kirsher 	rx_data->status_block_id = params->fw_sb_id;
4385adfc5217SJeff Kirsher 	rx_data->rx_sb_index_number = params->sb_cq_index;
4386adfc5217SJeff Kirsher 	rx_data->max_tpa_queues = params->max_tpa_queues;
4387adfc5217SJeff Kirsher 	rx_data->max_bytes_on_bd = cpu_to_le16(params->buf_sz);
4388adfc5217SJeff Kirsher 	rx_data->sge_buff_size = cpu_to_le16(params->sge_buf_sz);
4389adfc5217SJeff Kirsher 	rx_data->bd_page_base.lo =
4390adfc5217SJeff Kirsher 		cpu_to_le32(U64_LO(params->dscr_map));
4391adfc5217SJeff Kirsher 	rx_data->bd_page_base.hi =
4392adfc5217SJeff Kirsher 		cpu_to_le32(U64_HI(params->dscr_map));
4393adfc5217SJeff Kirsher 	rx_data->sge_page_base.lo =
4394adfc5217SJeff Kirsher 		cpu_to_le32(U64_LO(params->sge_map));
4395adfc5217SJeff Kirsher 	rx_data->sge_page_base.hi =
4396adfc5217SJeff Kirsher 		cpu_to_le32(U64_HI(params->sge_map));
4397adfc5217SJeff Kirsher 	rx_data->cqe_page_base.lo =
4398adfc5217SJeff Kirsher 		cpu_to_le32(U64_LO(params->rcq_map));
4399adfc5217SJeff Kirsher 	rx_data->cqe_page_base.hi =
4400adfc5217SJeff Kirsher 		cpu_to_le32(U64_HI(params->rcq_map));
4401adfc5217SJeff Kirsher 	rx_data->is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, flags);
4402adfc5217SJeff Kirsher 
4403adfc5217SJeff Kirsher 	if (test_bit(BNX2X_Q_FLG_MCAST, flags)) {
4404adfc5217SJeff Kirsher 		rx_data->approx_mcast_engine_id = o->func_id;
4405adfc5217SJeff Kirsher 		rx_data->is_approx_mcast = 1;
4406adfc5217SJeff Kirsher 	}
4407adfc5217SJeff Kirsher 
4408adfc5217SJeff Kirsher 	rx_data->rss_engine_id = params->rss_engine_id;
4409adfc5217SJeff Kirsher 
4410adfc5217SJeff Kirsher 	/* silent vlan removal */
4411adfc5217SJeff Kirsher 	rx_data->silent_vlan_removal_flg =
4412adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, flags);
4413adfc5217SJeff Kirsher 	rx_data->silent_vlan_value =
4414adfc5217SJeff Kirsher 		cpu_to_le16(params->silent_removal_value);
4415adfc5217SJeff Kirsher 	rx_data->silent_vlan_mask =
4416adfc5217SJeff Kirsher 		cpu_to_le16(params->silent_removal_mask);
4417adfc5217SJeff Kirsher 
4418adfc5217SJeff Kirsher }
4419adfc5217SJeff Kirsher 
4420adfc5217SJeff Kirsher /* initialize the general, tx and rx parts of a queue object */
4421adfc5217SJeff Kirsher static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp,
4422adfc5217SJeff Kirsher 				struct bnx2x_queue_state_params *cmd_params,
4423adfc5217SJeff Kirsher 				struct client_init_ramrod_data *data)
4424adfc5217SJeff Kirsher {
4425adfc5217SJeff Kirsher 	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
4426adfc5217SJeff Kirsher 				       &cmd_params->params.setup.gen_params,
4427adfc5217SJeff Kirsher 				       &data->general,
4428adfc5217SJeff Kirsher 				       &cmd_params->params.setup.flags);
4429adfc5217SJeff Kirsher 
4430adfc5217SJeff Kirsher 	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
4431adfc5217SJeff Kirsher 				  &cmd_params->params.setup.txq_params,
4432adfc5217SJeff Kirsher 				  &data->tx,
4433adfc5217SJeff Kirsher 				  &cmd_params->params.setup.flags);
4434adfc5217SJeff Kirsher 
4435adfc5217SJeff Kirsher 	bnx2x_q_fill_init_rx_data(cmd_params->q_obj,
4436adfc5217SJeff Kirsher 				  &cmd_params->params.setup.rxq_params,
4437adfc5217SJeff Kirsher 				  &data->rx,
4438adfc5217SJeff Kirsher 				  &cmd_params->params.setup.flags);
4439adfc5217SJeff Kirsher 
4440adfc5217SJeff Kirsher 	bnx2x_q_fill_init_pause_data(cmd_params->q_obj,
4441adfc5217SJeff Kirsher 				     &cmd_params->params.setup.pause_params,
4442adfc5217SJeff Kirsher 				     &data->rx);
4443adfc5217SJeff Kirsher }
4444adfc5217SJeff Kirsher 
4445adfc5217SJeff Kirsher /* initialize the general and tx parts of a tx-only queue object */
4446adfc5217SJeff Kirsher static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp,
4447adfc5217SJeff Kirsher 				struct bnx2x_queue_state_params *cmd_params,
4448adfc5217SJeff Kirsher 				struct tx_queue_init_ramrod_data *data)
4449adfc5217SJeff Kirsher {
4450adfc5217SJeff Kirsher 	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
4451adfc5217SJeff Kirsher 				       &cmd_params->params.tx_only.gen_params,
4452adfc5217SJeff Kirsher 				       &data->general,
4453adfc5217SJeff Kirsher 				       &cmd_params->params.tx_only.flags);
4454adfc5217SJeff Kirsher 
4455adfc5217SJeff Kirsher 	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
4456adfc5217SJeff Kirsher 				  &cmd_params->params.tx_only.txq_params,
4457adfc5217SJeff Kirsher 				  &data->tx,
4458adfc5217SJeff Kirsher 				  &cmd_params->params.tx_only.flags);
4459adfc5217SJeff Kirsher 
446094f05b0fSJoe Perches 	DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x\n",cmd_params->q_obj->cids[0],
4461adfc5217SJeff Kirsher 	   data->tx.tx_bd_page_base.lo, data->tx.tx_bd_page_base.hi);
4462adfc5217SJeff Kirsher }
4463adfc5217SJeff Kirsher 
4464adfc5217SJeff Kirsher /**
4465adfc5217SJeff Kirsher  * bnx2x_q_init - init HW/FW queue
4466adfc5217SJeff Kirsher  *
4467adfc5217SJeff Kirsher  * @bp:		device handle
4468adfc5217SJeff Kirsher  * @params:
4469adfc5217SJeff Kirsher  *
4470adfc5217SJeff Kirsher  * HW/FW initial Queue configuration:
4471adfc5217SJeff Kirsher  *      - HC: Rx and Tx
4472adfc5217SJeff Kirsher  *      - CDU context validation
4473adfc5217SJeff Kirsher  *
4474adfc5217SJeff Kirsher  */
4475adfc5217SJeff Kirsher static inline int bnx2x_q_init(struct bnx2x *bp,
4476adfc5217SJeff Kirsher 			       struct bnx2x_queue_state_params *params)
4477adfc5217SJeff Kirsher {
4478adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4479adfc5217SJeff Kirsher 	struct bnx2x_queue_init_params *init = &params->params.init;
4480adfc5217SJeff Kirsher 	u16 hc_usec;
4481adfc5217SJeff Kirsher 	u8 cos;
4482adfc5217SJeff Kirsher 
4483adfc5217SJeff Kirsher 	/* Tx HC configuration */
4484adfc5217SJeff Kirsher 	if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) &&
4485adfc5217SJeff Kirsher 	    test_bit(BNX2X_Q_FLG_HC, &init->tx.flags)) {
4486adfc5217SJeff Kirsher 		hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0;
4487adfc5217SJeff Kirsher 
4488adfc5217SJeff Kirsher 		bnx2x_update_coalesce_sb_index(bp, init->tx.fw_sb_id,
4489adfc5217SJeff Kirsher 			init->tx.sb_cq_index,
4490adfc5217SJeff Kirsher 			!test_bit(BNX2X_Q_FLG_HC_EN, &init->tx.flags),
4491adfc5217SJeff Kirsher 			hc_usec);
4492adfc5217SJeff Kirsher 	}
4493adfc5217SJeff Kirsher 
4494adfc5217SJeff Kirsher 	/* Rx HC configuration */
4495adfc5217SJeff Kirsher 	if (test_bit(BNX2X_Q_TYPE_HAS_RX, &o->type) &&
4496adfc5217SJeff Kirsher 	    test_bit(BNX2X_Q_FLG_HC, &init->rx.flags)) {
4497adfc5217SJeff Kirsher 		hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0;
4498adfc5217SJeff Kirsher 
4499adfc5217SJeff Kirsher 		bnx2x_update_coalesce_sb_index(bp, init->rx.fw_sb_id,
4500adfc5217SJeff Kirsher 			init->rx.sb_cq_index,
4501adfc5217SJeff Kirsher 			!test_bit(BNX2X_Q_FLG_HC_EN, &init->rx.flags),
4502adfc5217SJeff Kirsher 			hc_usec);
4503adfc5217SJeff Kirsher 	}
4504adfc5217SJeff Kirsher 
4505adfc5217SJeff Kirsher 	/* Set CDU context validation values */
4506adfc5217SJeff Kirsher 	for (cos = 0; cos < o->max_cos; cos++) {
450794f05b0fSJoe Perches 		DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d\n",
4508adfc5217SJeff Kirsher 				 o->cids[cos], cos);
450994f05b0fSJoe Perches 		DP(BNX2X_MSG_SP, "context pointer %p\n", init->cxts[cos]);
4510adfc5217SJeff Kirsher 		bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]);
4511adfc5217SJeff Kirsher 	}
4512adfc5217SJeff Kirsher 
4513adfc5217SJeff Kirsher 	/* As no ramrod is sent, complete the command immediately  */
4514adfc5217SJeff Kirsher 	o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT);
4515adfc5217SJeff Kirsher 
4516adfc5217SJeff Kirsher 	mmiowb();
4517adfc5217SJeff Kirsher 	smp_mb();
4518adfc5217SJeff Kirsher 
4519adfc5217SJeff Kirsher 	return 0;
4520adfc5217SJeff Kirsher }
4521adfc5217SJeff Kirsher 
4522adfc5217SJeff Kirsher static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
4523adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
4524adfc5217SJeff Kirsher {
4525adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4526adfc5217SJeff Kirsher 	struct client_init_ramrod_data *rdata =
4527adfc5217SJeff Kirsher 		(struct client_init_ramrod_data *)o->rdata;
4528adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
4529adfc5217SJeff Kirsher 	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
4530adfc5217SJeff Kirsher 
4531adfc5217SJeff Kirsher 	/* Clear the ramrod data */
4532adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
4533adfc5217SJeff Kirsher 
4534adfc5217SJeff Kirsher 	/* Fill the ramrod data */
4535adfc5217SJeff Kirsher 	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
4536adfc5217SJeff Kirsher 
4537adfc5217SJeff Kirsher 	/*
4538adfc5217SJeff Kirsher 	 *  No need for an explicit memory barrier here as long we would
4539adfc5217SJeff Kirsher 	 *  need to ensure the ordering of writing to the SPQ element
4540adfc5217SJeff Kirsher 	 *  and updating of the SPQ producer which involves a memory
4541adfc5217SJeff Kirsher 	 *  read and we will have to put a full memory barrier there
4542adfc5217SJeff Kirsher 	 *  (inside bnx2x_sp_post()).
4543adfc5217SJeff Kirsher 	 */
4544adfc5217SJeff Kirsher 
4545adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
4546adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
4547adfc5217SJeff Kirsher 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
4548adfc5217SJeff Kirsher }
4549adfc5217SJeff Kirsher 
4550adfc5217SJeff Kirsher static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
4551adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
4552adfc5217SJeff Kirsher {
4553adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4554adfc5217SJeff Kirsher 	struct client_init_ramrod_data *rdata =
4555adfc5217SJeff Kirsher 		(struct client_init_ramrod_data *)o->rdata;
4556adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
4557adfc5217SJeff Kirsher 	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
4558adfc5217SJeff Kirsher 
4559adfc5217SJeff Kirsher 	/* Clear the ramrod data */
4560adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
4561adfc5217SJeff Kirsher 
4562adfc5217SJeff Kirsher 	/* Fill the ramrod data */
4563adfc5217SJeff Kirsher 	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
4564adfc5217SJeff Kirsher 	bnx2x_q_fill_setup_data_e2(bp, params, rdata);
4565adfc5217SJeff Kirsher 
4566adfc5217SJeff Kirsher 	/*
4567adfc5217SJeff Kirsher 	 *  No need for an explicit memory barrier here as long we would
4568adfc5217SJeff Kirsher 	 *  need to ensure the ordering of writing to the SPQ element
4569adfc5217SJeff Kirsher 	 *  and updating of the SPQ producer which involves a memory
4570adfc5217SJeff Kirsher 	 *  read and we will have to put a full memory barrier there
4571adfc5217SJeff Kirsher 	 *  (inside bnx2x_sp_post()).
4572adfc5217SJeff Kirsher 	 */
4573adfc5217SJeff Kirsher 
4574adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
4575adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
4576adfc5217SJeff Kirsher 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
4577adfc5217SJeff Kirsher }
4578adfc5217SJeff Kirsher 
4579adfc5217SJeff Kirsher static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
4580adfc5217SJeff Kirsher 				  struct bnx2x_queue_state_params *params)
4581adfc5217SJeff Kirsher {
4582adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4583adfc5217SJeff Kirsher 	struct tx_queue_init_ramrod_data *rdata =
4584adfc5217SJeff Kirsher 		(struct tx_queue_init_ramrod_data *)o->rdata;
4585adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
4586adfc5217SJeff Kirsher 	int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP;
4587adfc5217SJeff Kirsher 	struct bnx2x_queue_setup_tx_only_params *tx_only_params =
4588adfc5217SJeff Kirsher 		&params->params.tx_only;
4589adfc5217SJeff Kirsher 	u8 cid_index = tx_only_params->cid_index;
4590adfc5217SJeff Kirsher 
4591adfc5217SJeff Kirsher 
4592adfc5217SJeff Kirsher 	if (cid_index >= o->max_cos) {
4593adfc5217SJeff Kirsher 		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
4594adfc5217SJeff Kirsher 			  o->cl_id, cid_index);
4595adfc5217SJeff Kirsher 		return -EINVAL;
4596adfc5217SJeff Kirsher 	}
4597adfc5217SJeff Kirsher 
459894f05b0fSJoe Perches 	DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d\n",
4599adfc5217SJeff Kirsher 			 tx_only_params->gen_params.cos,
4600adfc5217SJeff Kirsher 			 tx_only_params->gen_params.spcl_id);
4601adfc5217SJeff Kirsher 
4602adfc5217SJeff Kirsher 	/* Clear the ramrod data */
4603adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
4604adfc5217SJeff Kirsher 
4605adfc5217SJeff Kirsher 	/* Fill the ramrod data */
4606adfc5217SJeff Kirsher 	bnx2x_q_fill_setup_tx_only(bp, params, rdata);
4607adfc5217SJeff Kirsher 
4608adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d,"
460994f05b0fSJoe Perches 			 "sp-client id %d, cos %d\n",
4610adfc5217SJeff Kirsher 			 o->cids[cid_index],
4611adfc5217SJeff Kirsher 			 rdata->general.client_id,
4612adfc5217SJeff Kirsher 			 rdata->general.sp_client_id, rdata->general.cos);
4613adfc5217SJeff Kirsher 
4614adfc5217SJeff Kirsher 	/*
4615adfc5217SJeff Kirsher 	 *  No need for an explicit memory barrier here as long we would
4616adfc5217SJeff Kirsher 	 *  need to ensure the ordering of writing to the SPQ element
4617adfc5217SJeff Kirsher 	 *  and updating of the SPQ producer which involves a memory
4618adfc5217SJeff Kirsher 	 *  read and we will have to put a full memory barrier there
4619adfc5217SJeff Kirsher 	 *  (inside bnx2x_sp_post()).
4620adfc5217SJeff Kirsher 	 */
4621adfc5217SJeff Kirsher 
4622adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, ramrod, o->cids[cid_index],
4623adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
4624adfc5217SJeff Kirsher 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
4625adfc5217SJeff Kirsher }
4626adfc5217SJeff Kirsher 
4627adfc5217SJeff Kirsher static void bnx2x_q_fill_update_data(struct bnx2x *bp,
4628adfc5217SJeff Kirsher 				     struct bnx2x_queue_sp_obj *obj,
4629adfc5217SJeff Kirsher 				     struct bnx2x_queue_update_params *params,
4630adfc5217SJeff Kirsher 				     struct client_update_ramrod_data *data)
4631adfc5217SJeff Kirsher {
4632adfc5217SJeff Kirsher 	/* Client ID of the client to update */
4633adfc5217SJeff Kirsher 	data->client_id = obj->cl_id;
4634adfc5217SJeff Kirsher 
4635adfc5217SJeff Kirsher 	/* Function ID of the client to update */
4636adfc5217SJeff Kirsher 	data->func_id = obj->func_id;
4637adfc5217SJeff Kirsher 
4638adfc5217SJeff Kirsher 	/* Default VLAN value */
4639adfc5217SJeff Kirsher 	data->default_vlan = cpu_to_le16(params->def_vlan);
4640adfc5217SJeff Kirsher 
4641adfc5217SJeff Kirsher 	/* Inner VLAN stripping */
4642adfc5217SJeff Kirsher 	data->inner_vlan_removal_enable_flg =
4643adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM, &params->update_flags);
4644adfc5217SJeff Kirsher 	data->inner_vlan_removal_change_flg =
4645adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
4646adfc5217SJeff Kirsher 			 &params->update_flags);
4647adfc5217SJeff Kirsher 
4648adfc5217SJeff Kirsher 	/* Outer VLAN sripping */
4649adfc5217SJeff Kirsher 	data->outer_vlan_removal_enable_flg =
4650adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, &params->update_flags);
4651adfc5217SJeff Kirsher 	data->outer_vlan_removal_change_flg =
4652adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
4653adfc5217SJeff Kirsher 			 &params->update_flags);
4654adfc5217SJeff Kirsher 
4655adfc5217SJeff Kirsher 	/* Drop packets that have source MAC that doesn't belong to this
4656adfc5217SJeff Kirsher 	 * Queue.
4657adfc5217SJeff Kirsher 	 */
4658adfc5217SJeff Kirsher 	data->anti_spoofing_enable_flg =
4659adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF, &params->update_flags);
4660adfc5217SJeff Kirsher 	data->anti_spoofing_change_flg =
4661adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG, &params->update_flags);
4662adfc5217SJeff Kirsher 
4663adfc5217SJeff Kirsher 	/* Activate/Deactivate */
4664adfc5217SJeff Kirsher 	data->activate_flg =
4665adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_ACTIVATE, &params->update_flags);
4666adfc5217SJeff Kirsher 	data->activate_change_flg =
4667adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &params->update_flags);
4668adfc5217SJeff Kirsher 
4669adfc5217SJeff Kirsher 	/* Enable default VLAN */
4670adfc5217SJeff Kirsher 	data->default_vlan_enable_flg =
4671adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, &params->update_flags);
4672adfc5217SJeff Kirsher 	data->default_vlan_change_flg =
4673adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
4674adfc5217SJeff Kirsher 			 &params->update_flags);
4675adfc5217SJeff Kirsher 
4676adfc5217SJeff Kirsher 	/* silent vlan removal */
4677adfc5217SJeff Kirsher 	data->silent_vlan_change_flg =
4678adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
4679adfc5217SJeff Kirsher 			 &params->update_flags);
4680adfc5217SJeff Kirsher 	data->silent_vlan_removal_flg =
4681adfc5217SJeff Kirsher 		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, &params->update_flags);
4682adfc5217SJeff Kirsher 	data->silent_vlan_value = cpu_to_le16(params->silent_removal_value);
4683adfc5217SJeff Kirsher 	data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask);
4684adfc5217SJeff Kirsher }
4685adfc5217SJeff Kirsher 
4686adfc5217SJeff Kirsher static inline int bnx2x_q_send_update(struct bnx2x *bp,
4687adfc5217SJeff Kirsher 				      struct bnx2x_queue_state_params *params)
4688adfc5217SJeff Kirsher {
4689adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4690adfc5217SJeff Kirsher 	struct client_update_ramrod_data *rdata =
4691adfc5217SJeff Kirsher 		(struct client_update_ramrod_data *)o->rdata;
4692adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
4693adfc5217SJeff Kirsher 	struct bnx2x_queue_update_params *update_params =
4694adfc5217SJeff Kirsher 		&params->params.update;
4695adfc5217SJeff Kirsher 	u8 cid_index = update_params->cid_index;
4696adfc5217SJeff Kirsher 
4697adfc5217SJeff Kirsher 	if (cid_index >= o->max_cos) {
4698adfc5217SJeff Kirsher 		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
4699adfc5217SJeff Kirsher 			  o->cl_id, cid_index);
4700adfc5217SJeff Kirsher 		return -EINVAL;
4701adfc5217SJeff Kirsher 	}
4702adfc5217SJeff Kirsher 
4703adfc5217SJeff Kirsher 
4704adfc5217SJeff Kirsher 	/* Clear the ramrod data */
4705adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
4706adfc5217SJeff Kirsher 
4707adfc5217SJeff Kirsher 	/* Fill the ramrod data */
4708adfc5217SJeff Kirsher 	bnx2x_q_fill_update_data(bp, o, update_params, rdata);
4709adfc5217SJeff Kirsher 
4710adfc5217SJeff Kirsher 	/*
4711adfc5217SJeff Kirsher 	 *  No need for an explicit memory barrier here as long we would
4712adfc5217SJeff Kirsher 	 *  need to ensure the ordering of writing to the SPQ element
4713adfc5217SJeff Kirsher 	 *  and updating of the SPQ producer which involves a memory
4714adfc5217SJeff Kirsher 	 *  read and we will have to put a full memory barrier there
4715adfc5217SJeff Kirsher 	 *  (inside bnx2x_sp_post()).
4716adfc5217SJeff Kirsher 	 */
4717adfc5217SJeff Kirsher 
4718adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
4719adfc5217SJeff Kirsher 			     o->cids[cid_index], U64_HI(data_mapping),
4720adfc5217SJeff Kirsher 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
4721adfc5217SJeff Kirsher }
4722adfc5217SJeff Kirsher 
4723adfc5217SJeff Kirsher /**
4724adfc5217SJeff Kirsher  * bnx2x_q_send_deactivate - send DEACTIVATE command
4725adfc5217SJeff Kirsher  *
4726adfc5217SJeff Kirsher  * @bp:		device handle
4727adfc5217SJeff Kirsher  * @params:
4728adfc5217SJeff Kirsher  *
4729adfc5217SJeff Kirsher  * implemented using the UPDATE command.
4730adfc5217SJeff Kirsher  */
4731adfc5217SJeff Kirsher static inline int bnx2x_q_send_deactivate(struct bnx2x *bp,
4732adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
4733adfc5217SJeff Kirsher {
4734adfc5217SJeff Kirsher 	struct bnx2x_queue_update_params *update = &params->params.update;
4735adfc5217SJeff Kirsher 
4736adfc5217SJeff Kirsher 	memset(update, 0, sizeof(*update));
4737adfc5217SJeff Kirsher 
4738adfc5217SJeff Kirsher 	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
4739adfc5217SJeff Kirsher 
4740adfc5217SJeff Kirsher 	return bnx2x_q_send_update(bp, params);
4741adfc5217SJeff Kirsher }
4742adfc5217SJeff Kirsher 
4743adfc5217SJeff Kirsher /**
4744adfc5217SJeff Kirsher  * bnx2x_q_send_activate - send ACTIVATE command
4745adfc5217SJeff Kirsher  *
4746adfc5217SJeff Kirsher  * @bp:		device handle
4747adfc5217SJeff Kirsher  * @params:
4748adfc5217SJeff Kirsher  *
4749adfc5217SJeff Kirsher  * implemented using the UPDATE command.
4750adfc5217SJeff Kirsher  */
4751adfc5217SJeff Kirsher static inline int bnx2x_q_send_activate(struct bnx2x *bp,
4752adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
4753adfc5217SJeff Kirsher {
4754adfc5217SJeff Kirsher 	struct bnx2x_queue_update_params *update = &params->params.update;
4755adfc5217SJeff Kirsher 
4756adfc5217SJeff Kirsher 	memset(update, 0, sizeof(*update));
4757adfc5217SJeff Kirsher 
4758adfc5217SJeff Kirsher 	__set_bit(BNX2X_Q_UPDATE_ACTIVATE, &update->update_flags);
4759adfc5217SJeff Kirsher 	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
4760adfc5217SJeff Kirsher 
4761adfc5217SJeff Kirsher 	return bnx2x_q_send_update(bp, params);
4762adfc5217SJeff Kirsher }
4763adfc5217SJeff Kirsher 
4764adfc5217SJeff Kirsher static inline int bnx2x_q_send_update_tpa(struct bnx2x *bp,
4765adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
4766adfc5217SJeff Kirsher {
4767adfc5217SJeff Kirsher 	/* TODO: Not implemented yet. */
4768adfc5217SJeff Kirsher 	return -1;
4769adfc5217SJeff Kirsher }
4770adfc5217SJeff Kirsher 
4771adfc5217SJeff Kirsher static inline int bnx2x_q_send_halt(struct bnx2x *bp,
4772adfc5217SJeff Kirsher 				    struct bnx2x_queue_state_params *params)
4773adfc5217SJeff Kirsher {
4774adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4775adfc5217SJeff Kirsher 
4776adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT,
4777adfc5217SJeff Kirsher 			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, o->cl_id,
4778adfc5217SJeff Kirsher 			     ETH_CONNECTION_TYPE);
4779adfc5217SJeff Kirsher }
4780adfc5217SJeff Kirsher 
4781adfc5217SJeff Kirsher static inline int bnx2x_q_send_cfc_del(struct bnx2x *bp,
4782adfc5217SJeff Kirsher 				       struct bnx2x_queue_state_params *params)
4783adfc5217SJeff Kirsher {
4784adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4785adfc5217SJeff Kirsher 	u8 cid_idx = params->params.cfc_del.cid_index;
4786adfc5217SJeff Kirsher 
4787adfc5217SJeff Kirsher 	if (cid_idx >= o->max_cos) {
4788adfc5217SJeff Kirsher 		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
4789adfc5217SJeff Kirsher 			  o->cl_id, cid_idx);
4790adfc5217SJeff Kirsher 		return -EINVAL;
4791adfc5217SJeff Kirsher 	}
4792adfc5217SJeff Kirsher 
4793adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL,
4794adfc5217SJeff Kirsher 			     o->cids[cid_idx], 0, 0, NONE_CONNECTION_TYPE);
4795adfc5217SJeff Kirsher }
4796adfc5217SJeff Kirsher 
4797adfc5217SJeff Kirsher static inline int bnx2x_q_send_terminate(struct bnx2x *bp,
4798adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
4799adfc5217SJeff Kirsher {
4800adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4801adfc5217SJeff Kirsher 	u8 cid_index = params->params.terminate.cid_index;
4802adfc5217SJeff Kirsher 
4803adfc5217SJeff Kirsher 	if (cid_index >= o->max_cos) {
4804adfc5217SJeff Kirsher 		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
4805adfc5217SJeff Kirsher 			  o->cl_id, cid_index);
4806adfc5217SJeff Kirsher 		return -EINVAL;
4807adfc5217SJeff Kirsher 	}
4808adfc5217SJeff Kirsher 
4809adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE,
4810adfc5217SJeff Kirsher 			     o->cids[cid_index], 0, 0, ETH_CONNECTION_TYPE);
4811adfc5217SJeff Kirsher }
4812adfc5217SJeff Kirsher 
4813adfc5217SJeff Kirsher static inline int bnx2x_q_send_empty(struct bnx2x *bp,
4814adfc5217SJeff Kirsher 				     struct bnx2x_queue_state_params *params)
4815adfc5217SJeff Kirsher {
4816adfc5217SJeff Kirsher 	struct bnx2x_queue_sp_obj *o = params->q_obj;
4817adfc5217SJeff Kirsher 
4818adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY,
4819adfc5217SJeff Kirsher 			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, 0,
4820adfc5217SJeff Kirsher 			     ETH_CONNECTION_TYPE);
4821adfc5217SJeff Kirsher }
4822adfc5217SJeff Kirsher 
4823adfc5217SJeff Kirsher static inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp,
4824adfc5217SJeff Kirsher 					struct bnx2x_queue_state_params *params)
4825adfc5217SJeff Kirsher {
4826adfc5217SJeff Kirsher 	switch (params->cmd) {
4827adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_INIT:
4828adfc5217SJeff Kirsher 		return bnx2x_q_init(bp, params);
4829adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP_TX_ONLY:
4830adfc5217SJeff Kirsher 		return bnx2x_q_send_setup_tx_only(bp, params);
4831adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_DEACTIVATE:
4832adfc5217SJeff Kirsher 		return bnx2x_q_send_deactivate(bp, params);
4833adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_ACTIVATE:
4834adfc5217SJeff Kirsher 		return bnx2x_q_send_activate(bp, params);
4835adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE:
4836adfc5217SJeff Kirsher 		return bnx2x_q_send_update(bp, params);
4837adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE_TPA:
4838adfc5217SJeff Kirsher 		return bnx2x_q_send_update_tpa(bp, params);
4839adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_HALT:
4840adfc5217SJeff Kirsher 		return bnx2x_q_send_halt(bp, params);
4841adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_CFC_DEL:
4842adfc5217SJeff Kirsher 		return bnx2x_q_send_cfc_del(bp, params);
4843adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_TERMINATE:
4844adfc5217SJeff Kirsher 		return bnx2x_q_send_terminate(bp, params);
4845adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_EMPTY:
4846adfc5217SJeff Kirsher 		return bnx2x_q_send_empty(bp, params);
4847adfc5217SJeff Kirsher 	default:
4848adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", params->cmd);
4849adfc5217SJeff Kirsher 		return -EINVAL;
4850adfc5217SJeff Kirsher 	}
4851adfc5217SJeff Kirsher }
4852adfc5217SJeff Kirsher 
4853adfc5217SJeff Kirsher static int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp,
4854adfc5217SJeff Kirsher 				    struct bnx2x_queue_state_params *params)
4855adfc5217SJeff Kirsher {
4856adfc5217SJeff Kirsher 	switch (params->cmd) {
4857adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP:
4858adfc5217SJeff Kirsher 		return bnx2x_q_send_setup_e1x(bp, params);
4859adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_INIT:
4860adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP_TX_ONLY:
4861adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_DEACTIVATE:
4862adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_ACTIVATE:
4863adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE:
4864adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE_TPA:
4865adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_HALT:
4866adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_CFC_DEL:
4867adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_TERMINATE:
4868adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_EMPTY:
4869adfc5217SJeff Kirsher 		return bnx2x_queue_send_cmd_cmn(bp, params);
4870adfc5217SJeff Kirsher 	default:
4871adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", params->cmd);
4872adfc5217SJeff Kirsher 		return -EINVAL;
4873adfc5217SJeff Kirsher 	}
4874adfc5217SJeff Kirsher }
4875adfc5217SJeff Kirsher 
4876adfc5217SJeff Kirsher static int bnx2x_queue_send_cmd_e2(struct bnx2x *bp,
4877adfc5217SJeff Kirsher 				   struct bnx2x_queue_state_params *params)
4878adfc5217SJeff Kirsher {
4879adfc5217SJeff Kirsher 	switch (params->cmd) {
4880adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP:
4881adfc5217SJeff Kirsher 		return bnx2x_q_send_setup_e2(bp, params);
4882adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_INIT:
4883adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_SETUP_TX_ONLY:
4884adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_DEACTIVATE:
4885adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_ACTIVATE:
4886adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE:
4887adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_UPDATE_TPA:
4888adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_HALT:
4889adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_CFC_DEL:
4890adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_TERMINATE:
4891adfc5217SJeff Kirsher 	case BNX2X_Q_CMD_EMPTY:
4892adfc5217SJeff Kirsher 		return bnx2x_queue_send_cmd_cmn(bp, params);
4893adfc5217SJeff Kirsher 	default:
4894adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", params->cmd);
4895adfc5217SJeff Kirsher 		return -EINVAL;
4896adfc5217SJeff Kirsher 	}
4897adfc5217SJeff Kirsher }
4898adfc5217SJeff Kirsher 
4899adfc5217SJeff Kirsher /**
4900adfc5217SJeff Kirsher  * bnx2x_queue_chk_transition - check state machine of a regular Queue
4901adfc5217SJeff Kirsher  *
4902adfc5217SJeff Kirsher  * @bp:		device handle
4903adfc5217SJeff Kirsher  * @o:
4904adfc5217SJeff Kirsher  * @params:
4905adfc5217SJeff Kirsher  *
4906adfc5217SJeff Kirsher  * (not Forwarding)
4907adfc5217SJeff Kirsher  * It both checks if the requested command is legal in a current
4908adfc5217SJeff Kirsher  * state and, if it's legal, sets a `next_state' in the object
4909adfc5217SJeff Kirsher  * that will be used in the completion flow to set the `state'
4910adfc5217SJeff Kirsher  * of the object.
4911adfc5217SJeff Kirsher  *
4912adfc5217SJeff Kirsher  * returns 0 if a requested command is a legal transition,
4913adfc5217SJeff Kirsher  *         -EINVAL otherwise.
4914adfc5217SJeff Kirsher  */
4915adfc5217SJeff Kirsher static int bnx2x_queue_chk_transition(struct bnx2x *bp,
4916adfc5217SJeff Kirsher 				      struct bnx2x_queue_sp_obj *o,
4917adfc5217SJeff Kirsher 				      struct bnx2x_queue_state_params *params)
4918adfc5217SJeff Kirsher {
4919adfc5217SJeff Kirsher 	enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX;
4920adfc5217SJeff Kirsher 	enum bnx2x_queue_cmd cmd = params->cmd;
4921adfc5217SJeff Kirsher 	struct bnx2x_queue_update_params *update_params =
4922adfc5217SJeff Kirsher 		 &params->params.update;
4923adfc5217SJeff Kirsher 	u8 next_tx_only = o->num_tx_only;
4924adfc5217SJeff Kirsher 
4925adfc5217SJeff Kirsher 	/*
4926adfc5217SJeff Kirsher 	 * Forget all pending for completion commands if a driver only state
4927adfc5217SJeff Kirsher 	 * transition has been requested.
4928adfc5217SJeff Kirsher 	 */
4929adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
4930adfc5217SJeff Kirsher 		o->pending = 0;
4931adfc5217SJeff Kirsher 		o->next_state = BNX2X_Q_STATE_MAX;
4932adfc5217SJeff Kirsher 	}
4933adfc5217SJeff Kirsher 
4934adfc5217SJeff Kirsher 	/*
4935adfc5217SJeff Kirsher 	 * Don't allow a next state transition if we are in the middle of
4936adfc5217SJeff Kirsher 	 * the previous one.
4937adfc5217SJeff Kirsher 	 */
4938adfc5217SJeff Kirsher 	if (o->pending)
4939adfc5217SJeff Kirsher 		return -EBUSY;
4940adfc5217SJeff Kirsher 
4941adfc5217SJeff Kirsher 	switch (state) {
4942adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_RESET:
4943adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_INIT)
4944adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_INITIALIZED;
4945adfc5217SJeff Kirsher 
4946adfc5217SJeff Kirsher 		break;
4947adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_INITIALIZED:
4948adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_SETUP) {
4949adfc5217SJeff Kirsher 			if (test_bit(BNX2X_Q_FLG_ACTIVE,
4950adfc5217SJeff Kirsher 				     &params->params.setup.flags))
4951adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_ACTIVE;
4952adfc5217SJeff Kirsher 			else
4953adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_INACTIVE;
4954adfc5217SJeff Kirsher 		}
4955adfc5217SJeff Kirsher 
4956adfc5217SJeff Kirsher 		break;
4957adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_ACTIVE:
4958adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_DEACTIVATE)
4959adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_INACTIVE;
4960adfc5217SJeff Kirsher 
4961adfc5217SJeff Kirsher 		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
4962adfc5217SJeff Kirsher 			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
4963adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_ACTIVE;
4964adfc5217SJeff Kirsher 
4965adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
4966adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_MULTI_COS;
4967adfc5217SJeff Kirsher 			next_tx_only = 1;
4968adfc5217SJeff Kirsher 		}
4969adfc5217SJeff Kirsher 
4970adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_HALT)
4971adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_STOPPED;
4972adfc5217SJeff Kirsher 
4973adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_UPDATE) {
4974adfc5217SJeff Kirsher 			/* If "active" state change is requested, update the
4975adfc5217SJeff Kirsher 			 *  state accordingly.
4976adfc5217SJeff Kirsher 			 */
4977adfc5217SJeff Kirsher 			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
4978adfc5217SJeff Kirsher 				     &update_params->update_flags) &&
4979adfc5217SJeff Kirsher 			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
4980adfc5217SJeff Kirsher 				      &update_params->update_flags))
4981adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_INACTIVE;
4982adfc5217SJeff Kirsher 			else
4983adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_ACTIVE;
4984adfc5217SJeff Kirsher 		}
4985adfc5217SJeff Kirsher 
4986adfc5217SJeff Kirsher 		break;
4987adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_MULTI_COS:
4988adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_TERMINATE)
4989adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_MCOS_TERMINATED;
4990adfc5217SJeff Kirsher 
4991adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
4992adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_MULTI_COS;
4993adfc5217SJeff Kirsher 			next_tx_only = o->num_tx_only + 1;
4994adfc5217SJeff Kirsher 		}
4995adfc5217SJeff Kirsher 
4996adfc5217SJeff Kirsher 		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
4997adfc5217SJeff Kirsher 			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
4998adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_MULTI_COS;
4999adfc5217SJeff Kirsher 
5000adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_UPDATE) {
5001adfc5217SJeff Kirsher 			/* If "active" state change is requested, update the
5002adfc5217SJeff Kirsher 			 *  state accordingly.
5003adfc5217SJeff Kirsher 			 */
5004adfc5217SJeff Kirsher 			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
5005adfc5217SJeff Kirsher 				     &update_params->update_flags) &&
5006adfc5217SJeff Kirsher 			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
5007adfc5217SJeff Kirsher 				      &update_params->update_flags))
5008adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_INACTIVE;
5009adfc5217SJeff Kirsher 			else
5010adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_MULTI_COS;
5011adfc5217SJeff Kirsher 		}
5012adfc5217SJeff Kirsher 
5013adfc5217SJeff Kirsher 		break;
5014adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_MCOS_TERMINATED:
5015adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_CFC_DEL) {
5016adfc5217SJeff Kirsher 			next_tx_only = o->num_tx_only - 1;
5017adfc5217SJeff Kirsher 			if (next_tx_only == 0)
5018adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_ACTIVE;
5019adfc5217SJeff Kirsher 			else
5020adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_MULTI_COS;
5021adfc5217SJeff Kirsher 		}
5022adfc5217SJeff Kirsher 
5023adfc5217SJeff Kirsher 		break;
5024adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_INACTIVE:
5025adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_ACTIVATE)
5026adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_ACTIVE;
5027adfc5217SJeff Kirsher 
5028adfc5217SJeff Kirsher 		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
5029adfc5217SJeff Kirsher 			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
5030adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_INACTIVE;
5031adfc5217SJeff Kirsher 
5032adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_HALT)
5033adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_STOPPED;
5034adfc5217SJeff Kirsher 
5035adfc5217SJeff Kirsher 		else if (cmd == BNX2X_Q_CMD_UPDATE) {
5036adfc5217SJeff Kirsher 			/* If "active" state change is requested, update the
5037adfc5217SJeff Kirsher 			 * state accordingly.
5038adfc5217SJeff Kirsher 			 */
5039adfc5217SJeff Kirsher 			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
5040adfc5217SJeff Kirsher 				     &update_params->update_flags) &&
5041adfc5217SJeff Kirsher 			    test_bit(BNX2X_Q_UPDATE_ACTIVATE,
5042adfc5217SJeff Kirsher 				     &update_params->update_flags)){
5043adfc5217SJeff Kirsher 				if (o->num_tx_only == 0)
5044adfc5217SJeff Kirsher 					next_state = BNX2X_Q_STATE_ACTIVE;
5045adfc5217SJeff Kirsher 				else /* tx only queues exist for this queue */
5046adfc5217SJeff Kirsher 					next_state = BNX2X_Q_STATE_MULTI_COS;
5047adfc5217SJeff Kirsher 			} else
5048adfc5217SJeff Kirsher 				next_state = BNX2X_Q_STATE_INACTIVE;
5049adfc5217SJeff Kirsher 		}
5050adfc5217SJeff Kirsher 
5051adfc5217SJeff Kirsher 		break;
5052adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_STOPPED:
5053adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_TERMINATE)
5054adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_TERMINATED;
5055adfc5217SJeff Kirsher 
5056adfc5217SJeff Kirsher 		break;
5057adfc5217SJeff Kirsher 	case BNX2X_Q_STATE_TERMINATED:
5058adfc5217SJeff Kirsher 		if (cmd == BNX2X_Q_CMD_CFC_DEL)
5059adfc5217SJeff Kirsher 			next_state = BNX2X_Q_STATE_RESET;
5060adfc5217SJeff Kirsher 
5061adfc5217SJeff Kirsher 		break;
5062adfc5217SJeff Kirsher 	default:
5063adfc5217SJeff Kirsher 		BNX2X_ERR("Illegal state: %d\n", state);
5064adfc5217SJeff Kirsher 	}
5065adfc5217SJeff Kirsher 
5066adfc5217SJeff Kirsher 	/* Transition is assured */
5067adfc5217SJeff Kirsher 	if (next_state != BNX2X_Q_STATE_MAX) {
5068adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n",
5069adfc5217SJeff Kirsher 				 state, cmd, next_state);
5070adfc5217SJeff Kirsher 		o->next_state = next_state;
5071adfc5217SJeff Kirsher 		o->next_tx_only = next_tx_only;
5072adfc5217SJeff Kirsher 		return 0;
5073adfc5217SJeff Kirsher 	}
5074adfc5217SJeff Kirsher 
5075adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Bad state transition request: %d %d\n", state, cmd);
5076adfc5217SJeff Kirsher 
5077adfc5217SJeff Kirsher 	return -EINVAL;
5078adfc5217SJeff Kirsher }
5079adfc5217SJeff Kirsher 
5080adfc5217SJeff Kirsher void bnx2x_init_queue_obj(struct bnx2x *bp,
5081adfc5217SJeff Kirsher 			  struct bnx2x_queue_sp_obj *obj,
5082adfc5217SJeff Kirsher 			  u8 cl_id, u32 *cids, u8 cid_cnt, u8 func_id,
5083adfc5217SJeff Kirsher 			  void *rdata,
5084adfc5217SJeff Kirsher 			  dma_addr_t rdata_mapping, unsigned long type)
5085adfc5217SJeff Kirsher {
5086adfc5217SJeff Kirsher 	memset(obj, 0, sizeof(*obj));
5087adfc5217SJeff Kirsher 
5088adfc5217SJeff Kirsher 	/* We support only BNX2X_MULTI_TX_COS Tx CoS at the moment */
5089adfc5217SJeff Kirsher 	BUG_ON(BNX2X_MULTI_TX_COS < cid_cnt);
5090adfc5217SJeff Kirsher 
5091adfc5217SJeff Kirsher 	memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt);
5092adfc5217SJeff Kirsher 	obj->max_cos = cid_cnt;
5093adfc5217SJeff Kirsher 	obj->cl_id = cl_id;
5094adfc5217SJeff Kirsher 	obj->func_id = func_id;
5095adfc5217SJeff Kirsher 	obj->rdata = rdata;
5096adfc5217SJeff Kirsher 	obj->rdata_mapping = rdata_mapping;
5097adfc5217SJeff Kirsher 	obj->type = type;
5098adfc5217SJeff Kirsher 	obj->next_state = BNX2X_Q_STATE_MAX;
5099adfc5217SJeff Kirsher 
5100adfc5217SJeff Kirsher 	if (CHIP_IS_E1x(bp))
5101adfc5217SJeff Kirsher 		obj->send_cmd = bnx2x_queue_send_cmd_e1x;
5102adfc5217SJeff Kirsher 	else
5103adfc5217SJeff Kirsher 		obj->send_cmd = bnx2x_queue_send_cmd_e2;
5104adfc5217SJeff Kirsher 
5105adfc5217SJeff Kirsher 	obj->check_transition = bnx2x_queue_chk_transition;
5106adfc5217SJeff Kirsher 
5107adfc5217SJeff Kirsher 	obj->complete_cmd = bnx2x_queue_comp_cmd;
5108adfc5217SJeff Kirsher 	obj->wait_comp = bnx2x_queue_wait_comp;
5109adfc5217SJeff Kirsher 	obj->set_pending = bnx2x_queue_set_pending;
5110adfc5217SJeff Kirsher }
5111adfc5217SJeff Kirsher 
5112adfc5217SJeff Kirsher void bnx2x_queue_set_cos_cid(struct bnx2x *bp,
5113adfc5217SJeff Kirsher 			     struct bnx2x_queue_sp_obj *obj,
5114adfc5217SJeff Kirsher 			     u32 cid, u8 index)
5115adfc5217SJeff Kirsher {
5116adfc5217SJeff Kirsher 	obj->cids[index] = cid;
5117adfc5217SJeff Kirsher }
5118adfc5217SJeff Kirsher 
5119adfc5217SJeff Kirsher /********************** Function state object *********************************/
5120adfc5217SJeff Kirsher enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
5121adfc5217SJeff Kirsher 					   struct bnx2x_func_sp_obj *o)
5122adfc5217SJeff Kirsher {
5123adfc5217SJeff Kirsher 	/* in the middle of transaction - return INVALID state */
5124adfc5217SJeff Kirsher 	if (o->pending)
5125adfc5217SJeff Kirsher 		return BNX2X_F_STATE_MAX;
5126adfc5217SJeff Kirsher 
5127adfc5217SJeff Kirsher 	/*
5128adfc5217SJeff Kirsher 	 * unsure the order of reading of o->pending and o->state
5129adfc5217SJeff Kirsher 	 * o->pending should be read first
5130adfc5217SJeff Kirsher 	 */
5131adfc5217SJeff Kirsher 	rmb();
5132adfc5217SJeff Kirsher 
5133adfc5217SJeff Kirsher 	return o->state;
5134adfc5217SJeff Kirsher }
5135adfc5217SJeff Kirsher 
5136adfc5217SJeff Kirsher static int bnx2x_func_wait_comp(struct bnx2x *bp,
5137adfc5217SJeff Kirsher 				struct bnx2x_func_sp_obj *o,
5138adfc5217SJeff Kirsher 				enum bnx2x_func_cmd cmd)
5139adfc5217SJeff Kirsher {
5140adfc5217SJeff Kirsher 	return bnx2x_state_wait(bp, cmd, &o->pending);
5141adfc5217SJeff Kirsher }
5142adfc5217SJeff Kirsher 
5143adfc5217SJeff Kirsher /**
5144adfc5217SJeff Kirsher  * bnx2x_func_state_change_comp - complete the state machine transition
5145adfc5217SJeff Kirsher  *
5146adfc5217SJeff Kirsher  * @bp:		device handle
5147adfc5217SJeff Kirsher  * @o:
5148adfc5217SJeff Kirsher  * @cmd:
5149adfc5217SJeff Kirsher  *
5150adfc5217SJeff Kirsher  * Called on state change transition. Completes the state
5151adfc5217SJeff Kirsher  * machine transition only - no HW interaction.
5152adfc5217SJeff Kirsher  */
5153adfc5217SJeff Kirsher static inline int bnx2x_func_state_change_comp(struct bnx2x *bp,
5154adfc5217SJeff Kirsher 					       struct bnx2x_func_sp_obj *o,
5155adfc5217SJeff Kirsher 					       enum bnx2x_func_cmd cmd)
5156adfc5217SJeff Kirsher {
5157adfc5217SJeff Kirsher 	unsigned long cur_pending = o->pending;
5158adfc5217SJeff Kirsher 
5159adfc5217SJeff Kirsher 	if (!test_and_clear_bit(cmd, &cur_pending)) {
5160adfc5217SJeff Kirsher 		BNX2X_ERR("Bad MC reply %d for func %d in state %d "
5161adfc5217SJeff Kirsher 			  "pending 0x%lx, next_state %d\n", cmd, BP_FUNC(bp),
5162adfc5217SJeff Kirsher 			  o->state, cur_pending, o->next_state);
5163adfc5217SJeff Kirsher 		return -EINVAL;
5164adfc5217SJeff Kirsher 	}
5165adfc5217SJeff Kirsher 
516694f05b0fSJoe Perches 	DP(BNX2X_MSG_SP,
516794f05b0fSJoe Perches 	   "Completing command %d for func %d, setting state to %d\n",
516894f05b0fSJoe Perches 	   cmd, BP_FUNC(bp), o->next_state);
5169adfc5217SJeff Kirsher 
5170adfc5217SJeff Kirsher 	o->state = o->next_state;
5171adfc5217SJeff Kirsher 	o->next_state = BNX2X_F_STATE_MAX;
5172adfc5217SJeff Kirsher 
5173adfc5217SJeff Kirsher 	/* It's important that o->state and o->next_state are
5174adfc5217SJeff Kirsher 	 * updated before o->pending.
5175adfc5217SJeff Kirsher 	 */
5176adfc5217SJeff Kirsher 	wmb();
5177adfc5217SJeff Kirsher 
5178adfc5217SJeff Kirsher 	clear_bit(cmd, &o->pending);
5179adfc5217SJeff Kirsher 	smp_mb__after_clear_bit();
5180adfc5217SJeff Kirsher 
5181adfc5217SJeff Kirsher 	return 0;
5182adfc5217SJeff Kirsher }
5183adfc5217SJeff Kirsher 
5184adfc5217SJeff Kirsher /**
5185adfc5217SJeff Kirsher  * bnx2x_func_comp_cmd - complete the state change command
5186adfc5217SJeff Kirsher  *
5187adfc5217SJeff Kirsher  * @bp:		device handle
5188adfc5217SJeff Kirsher  * @o:
5189adfc5217SJeff Kirsher  * @cmd:
5190adfc5217SJeff Kirsher  *
5191adfc5217SJeff Kirsher  * Checks that the arrived completion is expected.
5192adfc5217SJeff Kirsher  */
5193adfc5217SJeff Kirsher static int bnx2x_func_comp_cmd(struct bnx2x *bp,
5194adfc5217SJeff Kirsher 			       struct bnx2x_func_sp_obj *o,
5195adfc5217SJeff Kirsher 			       enum bnx2x_func_cmd cmd)
5196adfc5217SJeff Kirsher {
5197adfc5217SJeff Kirsher 	/* Complete the state machine part first, check if it's a
5198adfc5217SJeff Kirsher 	 * legal completion.
5199adfc5217SJeff Kirsher 	 */
5200adfc5217SJeff Kirsher 	int rc = bnx2x_func_state_change_comp(bp, o, cmd);
5201adfc5217SJeff Kirsher 	return rc;
5202adfc5217SJeff Kirsher }
5203adfc5217SJeff Kirsher 
5204adfc5217SJeff Kirsher /**
5205adfc5217SJeff Kirsher  * bnx2x_func_chk_transition - perform function state machine transition
5206adfc5217SJeff Kirsher  *
5207adfc5217SJeff Kirsher  * @bp:		device handle
5208adfc5217SJeff Kirsher  * @o:
5209adfc5217SJeff Kirsher  * @params:
5210adfc5217SJeff Kirsher  *
5211adfc5217SJeff Kirsher  * It both checks if the requested command is legal in a current
5212adfc5217SJeff Kirsher  * state and, if it's legal, sets a `next_state' in the object
5213adfc5217SJeff Kirsher  * that will be used in the completion flow to set the `state'
5214adfc5217SJeff Kirsher  * of the object.
5215adfc5217SJeff Kirsher  *
5216adfc5217SJeff Kirsher  * returns 0 if a requested command is a legal transition,
5217adfc5217SJeff Kirsher  *         -EINVAL otherwise.
5218adfc5217SJeff Kirsher  */
5219adfc5217SJeff Kirsher static int bnx2x_func_chk_transition(struct bnx2x *bp,
5220adfc5217SJeff Kirsher 				     struct bnx2x_func_sp_obj *o,
5221adfc5217SJeff Kirsher 				     struct bnx2x_func_state_params *params)
5222adfc5217SJeff Kirsher {
5223adfc5217SJeff Kirsher 	enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
5224adfc5217SJeff Kirsher 	enum bnx2x_func_cmd cmd = params->cmd;
5225adfc5217SJeff Kirsher 
5226adfc5217SJeff Kirsher 	/*
5227adfc5217SJeff Kirsher 	 * Forget all pending for completion commands if a driver only state
5228adfc5217SJeff Kirsher 	 * transition has been requested.
5229adfc5217SJeff Kirsher 	 */
5230adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
5231adfc5217SJeff Kirsher 		o->pending = 0;
5232adfc5217SJeff Kirsher 		o->next_state = BNX2X_F_STATE_MAX;
5233adfc5217SJeff Kirsher 	}
5234adfc5217SJeff Kirsher 
5235adfc5217SJeff Kirsher 	/*
5236adfc5217SJeff Kirsher 	 * Don't allow a next state transition if we are in the middle of
5237adfc5217SJeff Kirsher 	 * the previous one.
5238adfc5217SJeff Kirsher 	 */
5239adfc5217SJeff Kirsher 	if (o->pending)
5240adfc5217SJeff Kirsher 		return -EBUSY;
5241adfc5217SJeff Kirsher 
5242adfc5217SJeff Kirsher 	switch (state) {
5243adfc5217SJeff Kirsher 	case BNX2X_F_STATE_RESET:
5244adfc5217SJeff Kirsher 		if (cmd == BNX2X_F_CMD_HW_INIT)
5245adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_INITIALIZED;
5246adfc5217SJeff Kirsher 
5247adfc5217SJeff Kirsher 		break;
5248adfc5217SJeff Kirsher 	case BNX2X_F_STATE_INITIALIZED:
5249adfc5217SJeff Kirsher 		if (cmd == BNX2X_F_CMD_START)
5250adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_STARTED;
5251adfc5217SJeff Kirsher 
5252adfc5217SJeff Kirsher 		else if (cmd == BNX2X_F_CMD_HW_RESET)
5253adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_RESET;
5254adfc5217SJeff Kirsher 
5255adfc5217SJeff Kirsher 		break;
5256adfc5217SJeff Kirsher 	case BNX2X_F_STATE_STARTED:
5257adfc5217SJeff Kirsher 		if (cmd == BNX2X_F_CMD_STOP)
5258adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_INITIALIZED;
5259adfc5217SJeff Kirsher 		else if (cmd == BNX2X_F_CMD_TX_STOP)
5260adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_TX_STOPPED;
5261adfc5217SJeff Kirsher 
5262adfc5217SJeff Kirsher 		break;
5263adfc5217SJeff Kirsher 	case BNX2X_F_STATE_TX_STOPPED:
5264adfc5217SJeff Kirsher 		if (cmd == BNX2X_F_CMD_TX_START)
5265adfc5217SJeff Kirsher 			next_state = BNX2X_F_STATE_STARTED;
5266adfc5217SJeff Kirsher 
5267adfc5217SJeff Kirsher 		break;
5268adfc5217SJeff Kirsher 	default:
5269adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown state: %d\n", state);
5270adfc5217SJeff Kirsher 	}
5271adfc5217SJeff Kirsher 
5272adfc5217SJeff Kirsher 	/* Transition is assured */
5273adfc5217SJeff Kirsher 	if (next_state != BNX2X_F_STATE_MAX) {
5274adfc5217SJeff Kirsher 		DP(BNX2X_MSG_SP, "Good function state transition: %d(%d)->%d\n",
5275adfc5217SJeff Kirsher 				 state, cmd, next_state);
5276adfc5217SJeff Kirsher 		o->next_state = next_state;
5277adfc5217SJeff Kirsher 		return 0;
5278adfc5217SJeff Kirsher 	}
5279adfc5217SJeff Kirsher 
5280adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "Bad function state transition request: %d %d\n",
5281adfc5217SJeff Kirsher 			 state, cmd);
5282adfc5217SJeff Kirsher 
5283adfc5217SJeff Kirsher 	return -EINVAL;
5284adfc5217SJeff Kirsher }
5285adfc5217SJeff Kirsher 
5286adfc5217SJeff Kirsher /**
5287adfc5217SJeff Kirsher  * bnx2x_func_init_func - performs HW init at function stage
5288adfc5217SJeff Kirsher  *
5289adfc5217SJeff Kirsher  * @bp:		device handle
5290adfc5217SJeff Kirsher  * @drv:
5291adfc5217SJeff Kirsher  *
5292adfc5217SJeff Kirsher  * Init HW when the current phase is
5293adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only
5294adfc5217SJeff Kirsher  * HW blocks.
5295adfc5217SJeff Kirsher  */
5296adfc5217SJeff Kirsher static inline int bnx2x_func_init_func(struct bnx2x *bp,
5297adfc5217SJeff Kirsher 				       const struct bnx2x_func_sp_drv_ops *drv)
5298adfc5217SJeff Kirsher {
5299adfc5217SJeff Kirsher 	return drv->init_hw_func(bp);
5300adfc5217SJeff Kirsher }
5301adfc5217SJeff Kirsher 
5302adfc5217SJeff Kirsher /**
5303adfc5217SJeff Kirsher  * bnx2x_func_init_port - performs HW init at port stage
5304adfc5217SJeff Kirsher  *
5305adfc5217SJeff Kirsher  * @bp:		device handle
5306adfc5217SJeff Kirsher  * @drv:
5307adfc5217SJeff Kirsher  *
5308adfc5217SJeff Kirsher  * Init HW when the current phase is
5309adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and
5310adfc5217SJeff Kirsher  * FUNCTION-only HW blocks.
5311adfc5217SJeff Kirsher  *
5312adfc5217SJeff Kirsher  */
5313adfc5217SJeff Kirsher static inline int bnx2x_func_init_port(struct bnx2x *bp,
5314adfc5217SJeff Kirsher 				       const struct bnx2x_func_sp_drv_ops *drv)
5315adfc5217SJeff Kirsher {
5316adfc5217SJeff Kirsher 	int rc = drv->init_hw_port(bp);
5317adfc5217SJeff Kirsher 	if (rc)
5318adfc5217SJeff Kirsher 		return rc;
5319adfc5217SJeff Kirsher 
5320adfc5217SJeff Kirsher 	return bnx2x_func_init_func(bp, drv);
5321adfc5217SJeff Kirsher }
5322adfc5217SJeff Kirsher 
5323adfc5217SJeff Kirsher /**
5324adfc5217SJeff Kirsher  * bnx2x_func_init_cmn_chip - performs HW init at chip-common stage
5325adfc5217SJeff Kirsher  *
5326adfc5217SJeff Kirsher  * @bp:		device handle
5327adfc5217SJeff Kirsher  * @drv:
5328adfc5217SJeff Kirsher  *
5329adfc5217SJeff Kirsher  * Init HW when the current phase is
5330adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP,
5331adfc5217SJeff Kirsher  * PORT-only and FUNCTION-only HW blocks.
5332adfc5217SJeff Kirsher  */
5333adfc5217SJeff Kirsher static inline int bnx2x_func_init_cmn_chip(struct bnx2x *bp,
5334adfc5217SJeff Kirsher 					const struct bnx2x_func_sp_drv_ops *drv)
5335adfc5217SJeff Kirsher {
5336adfc5217SJeff Kirsher 	int rc = drv->init_hw_cmn_chip(bp);
5337adfc5217SJeff Kirsher 	if (rc)
5338adfc5217SJeff Kirsher 		return rc;
5339adfc5217SJeff Kirsher 
5340adfc5217SJeff Kirsher 	return bnx2x_func_init_port(bp, drv);
5341adfc5217SJeff Kirsher }
5342adfc5217SJeff Kirsher 
5343adfc5217SJeff Kirsher /**
5344adfc5217SJeff Kirsher  * bnx2x_func_init_cmn - performs HW init at common stage
5345adfc5217SJeff Kirsher  *
5346adfc5217SJeff Kirsher  * @bp:		device handle
5347adfc5217SJeff Kirsher  * @drv:
5348adfc5217SJeff Kirsher  *
5349adfc5217SJeff Kirsher  * Init HW when the current phase is
5350adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON,
5351adfc5217SJeff Kirsher  * PORT-only and FUNCTION-only HW blocks.
5352adfc5217SJeff Kirsher  */
5353adfc5217SJeff Kirsher static inline int bnx2x_func_init_cmn(struct bnx2x *bp,
5354adfc5217SJeff Kirsher 				      const struct bnx2x_func_sp_drv_ops *drv)
5355adfc5217SJeff Kirsher {
5356adfc5217SJeff Kirsher 	int rc = drv->init_hw_cmn(bp);
5357adfc5217SJeff Kirsher 	if (rc)
5358adfc5217SJeff Kirsher 		return rc;
5359adfc5217SJeff Kirsher 
5360adfc5217SJeff Kirsher 	return bnx2x_func_init_port(bp, drv);
5361adfc5217SJeff Kirsher }
5362adfc5217SJeff Kirsher 
5363adfc5217SJeff Kirsher static int bnx2x_func_hw_init(struct bnx2x *bp,
5364adfc5217SJeff Kirsher 			      struct bnx2x_func_state_params *params)
5365adfc5217SJeff Kirsher {
5366adfc5217SJeff Kirsher 	u32 load_code = params->params.hw_init.load_phase;
5367adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
5368adfc5217SJeff Kirsher 	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
5369adfc5217SJeff Kirsher 	int rc = 0;
5370adfc5217SJeff Kirsher 
5371adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "function %d  load_code %x\n",
5372adfc5217SJeff Kirsher 			 BP_ABS_FUNC(bp), load_code);
5373adfc5217SJeff Kirsher 
5374adfc5217SJeff Kirsher 	/* Prepare buffers for unzipping the FW */
5375adfc5217SJeff Kirsher 	rc = drv->gunzip_init(bp);
5376adfc5217SJeff Kirsher 	if (rc)
5377adfc5217SJeff Kirsher 		return rc;
5378adfc5217SJeff Kirsher 
5379adfc5217SJeff Kirsher 	/* Prepare FW */
5380adfc5217SJeff Kirsher 	rc = drv->init_fw(bp);
5381adfc5217SJeff Kirsher 	if (rc) {
5382adfc5217SJeff Kirsher 		BNX2X_ERR("Error loading firmware\n");
5383eb2afd4aSDmitry Kravkov 		goto init_err;
5384adfc5217SJeff Kirsher 	}
5385adfc5217SJeff Kirsher 
5386adfc5217SJeff Kirsher 	/* Handle the beginning of COMMON_XXX pases separatelly... */
5387adfc5217SJeff Kirsher 	switch (load_code) {
5388adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
5389adfc5217SJeff Kirsher 		rc = bnx2x_func_init_cmn_chip(bp, drv);
5390adfc5217SJeff Kirsher 		if (rc)
5391eb2afd4aSDmitry Kravkov 			goto init_err;
5392adfc5217SJeff Kirsher 
5393adfc5217SJeff Kirsher 		break;
5394adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_LOAD_COMMON:
5395adfc5217SJeff Kirsher 		rc = bnx2x_func_init_cmn(bp, drv);
5396adfc5217SJeff Kirsher 		if (rc)
5397eb2afd4aSDmitry Kravkov 			goto init_err;
5398adfc5217SJeff Kirsher 
5399adfc5217SJeff Kirsher 		break;
5400adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_LOAD_PORT:
5401adfc5217SJeff Kirsher 		rc = bnx2x_func_init_port(bp, drv);
5402adfc5217SJeff Kirsher 		if (rc)
5403eb2afd4aSDmitry Kravkov 			goto init_err;
5404adfc5217SJeff Kirsher 
5405adfc5217SJeff Kirsher 		break;
5406adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
5407adfc5217SJeff Kirsher 		rc = bnx2x_func_init_func(bp, drv);
5408adfc5217SJeff Kirsher 		if (rc)
5409eb2afd4aSDmitry Kravkov 			goto init_err;
5410adfc5217SJeff Kirsher 
5411adfc5217SJeff Kirsher 		break;
5412adfc5217SJeff Kirsher 	default:
5413adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
5414adfc5217SJeff Kirsher 		rc = -EINVAL;
5415adfc5217SJeff Kirsher 	}
5416adfc5217SJeff Kirsher 
5417eb2afd4aSDmitry Kravkov init_err:
5418adfc5217SJeff Kirsher 	drv->gunzip_end(bp);
5419adfc5217SJeff Kirsher 
5420adfc5217SJeff Kirsher 	/* In case of success, complete the comand immediatelly: no ramrods
5421adfc5217SJeff Kirsher 	 * have been sent.
5422adfc5217SJeff Kirsher 	 */
5423adfc5217SJeff Kirsher 	if (!rc)
5424adfc5217SJeff Kirsher 		o->complete_cmd(bp, o, BNX2X_F_CMD_HW_INIT);
5425adfc5217SJeff Kirsher 
5426adfc5217SJeff Kirsher 	return rc;
5427adfc5217SJeff Kirsher }
5428adfc5217SJeff Kirsher 
5429adfc5217SJeff Kirsher /**
5430adfc5217SJeff Kirsher  * bnx2x_func_reset_func - reset HW at function stage
5431adfc5217SJeff Kirsher  *
5432adfc5217SJeff Kirsher  * @bp:		device handle
5433adfc5217SJeff Kirsher  * @drv:
5434adfc5217SJeff Kirsher  *
5435adfc5217SJeff Kirsher  * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only
5436adfc5217SJeff Kirsher  * FUNCTION-only HW blocks.
5437adfc5217SJeff Kirsher  */
5438adfc5217SJeff Kirsher static inline void bnx2x_func_reset_func(struct bnx2x *bp,
5439adfc5217SJeff Kirsher 					const struct bnx2x_func_sp_drv_ops *drv)
5440adfc5217SJeff Kirsher {
5441adfc5217SJeff Kirsher 	drv->reset_hw_func(bp);
5442adfc5217SJeff Kirsher }
5443adfc5217SJeff Kirsher 
5444adfc5217SJeff Kirsher /**
5445adfc5217SJeff Kirsher  * bnx2x_func_reset_port - reser HW at port stage
5446adfc5217SJeff Kirsher  *
5447adfc5217SJeff Kirsher  * @bp:		device handle
5448adfc5217SJeff Kirsher  * @drv:
5449adfc5217SJeff Kirsher  *
5450adfc5217SJeff Kirsher  * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset
5451adfc5217SJeff Kirsher  * FUNCTION-only and PORT-only HW blocks.
5452adfc5217SJeff Kirsher  *
5453adfc5217SJeff Kirsher  *                 !!!IMPORTANT!!!
5454adfc5217SJeff Kirsher  *
5455adfc5217SJeff Kirsher  * It's important to call reset_port before reset_func() as the last thing
5456adfc5217SJeff Kirsher  * reset_func does is pf_disable() thus disabling PGLUE_B, which
5457adfc5217SJeff Kirsher  * makes impossible any DMAE transactions.
5458adfc5217SJeff Kirsher  */
5459adfc5217SJeff Kirsher static inline void bnx2x_func_reset_port(struct bnx2x *bp,
5460adfc5217SJeff Kirsher 					const struct bnx2x_func_sp_drv_ops *drv)
5461adfc5217SJeff Kirsher {
5462adfc5217SJeff Kirsher 	drv->reset_hw_port(bp);
5463adfc5217SJeff Kirsher 	bnx2x_func_reset_func(bp, drv);
5464adfc5217SJeff Kirsher }
5465adfc5217SJeff Kirsher 
5466adfc5217SJeff Kirsher /**
5467adfc5217SJeff Kirsher  * bnx2x_func_reset_cmn - reser HW at common stage
5468adfc5217SJeff Kirsher  *
5469adfc5217SJeff Kirsher  * @bp:		device handle
5470adfc5217SJeff Kirsher  * @drv:
5471adfc5217SJeff Kirsher  *
5472adfc5217SJeff Kirsher  * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and
5473adfc5217SJeff Kirsher  * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON,
5474adfc5217SJeff Kirsher  * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks.
5475adfc5217SJeff Kirsher  */
5476adfc5217SJeff Kirsher static inline void bnx2x_func_reset_cmn(struct bnx2x *bp,
5477adfc5217SJeff Kirsher 					const struct bnx2x_func_sp_drv_ops *drv)
5478adfc5217SJeff Kirsher {
5479adfc5217SJeff Kirsher 	bnx2x_func_reset_port(bp, drv);
5480adfc5217SJeff Kirsher 	drv->reset_hw_cmn(bp);
5481adfc5217SJeff Kirsher }
5482adfc5217SJeff Kirsher 
5483adfc5217SJeff Kirsher 
5484adfc5217SJeff Kirsher static inline int bnx2x_func_hw_reset(struct bnx2x *bp,
5485adfc5217SJeff Kirsher 				      struct bnx2x_func_state_params *params)
5486adfc5217SJeff Kirsher {
5487adfc5217SJeff Kirsher 	u32 reset_phase = params->params.hw_reset.reset_phase;
5488adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
5489adfc5217SJeff Kirsher 	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
5490adfc5217SJeff Kirsher 
5491adfc5217SJeff Kirsher 	DP(BNX2X_MSG_SP, "function %d  reset_phase %x\n", BP_ABS_FUNC(bp),
5492adfc5217SJeff Kirsher 			 reset_phase);
5493adfc5217SJeff Kirsher 
5494adfc5217SJeff Kirsher 	switch (reset_phase) {
5495adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_UNLOAD_COMMON:
5496adfc5217SJeff Kirsher 		bnx2x_func_reset_cmn(bp, drv);
5497adfc5217SJeff Kirsher 		break;
5498adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_UNLOAD_PORT:
5499adfc5217SJeff Kirsher 		bnx2x_func_reset_port(bp, drv);
5500adfc5217SJeff Kirsher 		break;
5501adfc5217SJeff Kirsher 	case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
5502adfc5217SJeff Kirsher 		bnx2x_func_reset_func(bp, drv);
5503adfc5217SJeff Kirsher 		break;
5504adfc5217SJeff Kirsher 	default:
5505adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown reset_phase (0x%x) from MCP\n",
5506adfc5217SJeff Kirsher 			   reset_phase);
5507adfc5217SJeff Kirsher 		break;
5508adfc5217SJeff Kirsher 	}
5509adfc5217SJeff Kirsher 
5510adfc5217SJeff Kirsher 	/* Complete the comand immediatelly: no ramrods have been sent. */
5511adfc5217SJeff Kirsher 	o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET);
5512adfc5217SJeff Kirsher 
5513adfc5217SJeff Kirsher 	return 0;
5514adfc5217SJeff Kirsher }
5515adfc5217SJeff Kirsher 
5516adfc5217SJeff Kirsher static inline int bnx2x_func_send_start(struct bnx2x *bp,
5517adfc5217SJeff Kirsher 					struct bnx2x_func_state_params *params)
5518adfc5217SJeff Kirsher {
5519adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
5520adfc5217SJeff Kirsher 	struct function_start_data *rdata =
5521adfc5217SJeff Kirsher 		(struct function_start_data *)o->rdata;
5522adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
5523adfc5217SJeff Kirsher 	struct bnx2x_func_start_params *start_params = &params->params.start;
5524adfc5217SJeff Kirsher 
5525adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
5526adfc5217SJeff Kirsher 
5527adfc5217SJeff Kirsher 	/* Fill the ramrod data with provided parameters */
5528adfc5217SJeff Kirsher 	rdata->function_mode = cpu_to_le16(start_params->mf_mode);
5529adfc5217SJeff Kirsher 	rdata->sd_vlan_tag   = start_params->sd_vlan_tag;
5530adfc5217SJeff Kirsher 	rdata->path_id       = BP_PATH(bp);
5531adfc5217SJeff Kirsher 	rdata->network_cos_mode = start_params->network_cos_mode;
5532adfc5217SJeff Kirsher 
5533adfc5217SJeff Kirsher 	/*
5534adfc5217SJeff Kirsher 	 *  No need for an explicit memory barrier here as long we would
5535adfc5217SJeff Kirsher 	 *  need to ensure the ordering of writing to the SPQ element
5536adfc5217SJeff Kirsher 	 *  and updating of the SPQ producer which involves a memory
5537adfc5217SJeff Kirsher 	 *  read and we will have to put a full memory barrier there
5538adfc5217SJeff Kirsher 	 *  (inside bnx2x_sp_post()).
5539adfc5217SJeff Kirsher 	 */
5540adfc5217SJeff Kirsher 
5541adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0,
5542adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
5543adfc5217SJeff Kirsher 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
5544adfc5217SJeff Kirsher }
5545adfc5217SJeff Kirsher 
5546adfc5217SJeff Kirsher static inline int bnx2x_func_send_stop(struct bnx2x *bp,
5547adfc5217SJeff Kirsher 				       struct bnx2x_func_state_params *params)
5548adfc5217SJeff Kirsher {
5549adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0,
5550adfc5217SJeff Kirsher 			     NONE_CONNECTION_TYPE);
5551adfc5217SJeff Kirsher }
5552adfc5217SJeff Kirsher 
5553adfc5217SJeff Kirsher static inline int bnx2x_func_send_tx_stop(struct bnx2x *bp,
5554adfc5217SJeff Kirsher 				       struct bnx2x_func_state_params *params)
5555adfc5217SJeff Kirsher {
5556adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0,
5557adfc5217SJeff Kirsher 			     NONE_CONNECTION_TYPE);
5558adfc5217SJeff Kirsher }
5559adfc5217SJeff Kirsher static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
5560adfc5217SJeff Kirsher 				       struct bnx2x_func_state_params *params)
5561adfc5217SJeff Kirsher {
5562adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
5563adfc5217SJeff Kirsher 	struct flow_control_configuration *rdata =
5564adfc5217SJeff Kirsher 		(struct flow_control_configuration *)o->rdata;
5565adfc5217SJeff Kirsher 	dma_addr_t data_mapping = o->rdata_mapping;
5566adfc5217SJeff Kirsher 	struct bnx2x_func_tx_start_params *tx_start_params =
5567adfc5217SJeff Kirsher 		&params->params.tx_start;
5568adfc5217SJeff Kirsher 	int i;
5569adfc5217SJeff Kirsher 
5570adfc5217SJeff Kirsher 	memset(rdata, 0, sizeof(*rdata));
5571adfc5217SJeff Kirsher 
5572adfc5217SJeff Kirsher 	rdata->dcb_enabled = tx_start_params->dcb_enabled;
5573adfc5217SJeff Kirsher 	rdata->dcb_version = tx_start_params->dcb_version;
5574adfc5217SJeff Kirsher 	rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en;
5575adfc5217SJeff Kirsher 
5576adfc5217SJeff Kirsher 	for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++)
5577adfc5217SJeff Kirsher 		rdata->traffic_type_to_priority_cos[i] =
5578adfc5217SJeff Kirsher 			tx_start_params->traffic_type_to_priority_cos[i];
5579adfc5217SJeff Kirsher 
5580adfc5217SJeff Kirsher 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
5581adfc5217SJeff Kirsher 			     U64_HI(data_mapping),
5582adfc5217SJeff Kirsher 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
5583adfc5217SJeff Kirsher }
5584adfc5217SJeff Kirsher 
5585adfc5217SJeff Kirsher static int bnx2x_func_send_cmd(struct bnx2x *bp,
5586adfc5217SJeff Kirsher 			       struct bnx2x_func_state_params *params)
5587adfc5217SJeff Kirsher {
5588adfc5217SJeff Kirsher 	switch (params->cmd) {
5589adfc5217SJeff Kirsher 	case BNX2X_F_CMD_HW_INIT:
5590adfc5217SJeff Kirsher 		return bnx2x_func_hw_init(bp, params);
5591adfc5217SJeff Kirsher 	case BNX2X_F_CMD_START:
5592adfc5217SJeff Kirsher 		return bnx2x_func_send_start(bp, params);
5593adfc5217SJeff Kirsher 	case BNX2X_F_CMD_STOP:
5594adfc5217SJeff Kirsher 		return bnx2x_func_send_stop(bp, params);
5595adfc5217SJeff Kirsher 	case BNX2X_F_CMD_HW_RESET:
5596adfc5217SJeff Kirsher 		return bnx2x_func_hw_reset(bp, params);
5597adfc5217SJeff Kirsher 	case BNX2X_F_CMD_TX_STOP:
5598adfc5217SJeff Kirsher 		return bnx2x_func_send_tx_stop(bp, params);
5599adfc5217SJeff Kirsher 	case BNX2X_F_CMD_TX_START:
5600adfc5217SJeff Kirsher 		return bnx2x_func_send_tx_start(bp, params);
5601adfc5217SJeff Kirsher 	default:
5602adfc5217SJeff Kirsher 		BNX2X_ERR("Unknown command: %d\n", params->cmd);
5603adfc5217SJeff Kirsher 		return -EINVAL;
5604adfc5217SJeff Kirsher 	}
5605adfc5217SJeff Kirsher }
5606adfc5217SJeff Kirsher 
5607adfc5217SJeff Kirsher void bnx2x_init_func_obj(struct bnx2x *bp,
5608adfc5217SJeff Kirsher 			 struct bnx2x_func_sp_obj *obj,
5609adfc5217SJeff Kirsher 			 void *rdata, dma_addr_t rdata_mapping,
5610adfc5217SJeff Kirsher 			 struct bnx2x_func_sp_drv_ops *drv_iface)
5611adfc5217SJeff Kirsher {
5612adfc5217SJeff Kirsher 	memset(obj, 0, sizeof(*obj));
5613adfc5217SJeff Kirsher 
5614adfc5217SJeff Kirsher 	mutex_init(&obj->one_pending_mutex);
5615adfc5217SJeff Kirsher 
5616adfc5217SJeff Kirsher 	obj->rdata = rdata;
5617adfc5217SJeff Kirsher 	obj->rdata_mapping = rdata_mapping;
5618adfc5217SJeff Kirsher 
5619adfc5217SJeff Kirsher 	obj->send_cmd = bnx2x_func_send_cmd;
5620adfc5217SJeff Kirsher 	obj->check_transition = bnx2x_func_chk_transition;
5621adfc5217SJeff Kirsher 	obj->complete_cmd = bnx2x_func_comp_cmd;
5622adfc5217SJeff Kirsher 	obj->wait_comp = bnx2x_func_wait_comp;
5623adfc5217SJeff Kirsher 
5624adfc5217SJeff Kirsher 	obj->drv = drv_iface;
5625adfc5217SJeff Kirsher }
5626adfc5217SJeff Kirsher 
5627adfc5217SJeff Kirsher /**
5628adfc5217SJeff Kirsher  * bnx2x_func_state_change - perform Function state change transition
5629adfc5217SJeff Kirsher  *
5630adfc5217SJeff Kirsher  * @bp:		device handle
5631adfc5217SJeff Kirsher  * @params:	parameters to perform the transaction
5632adfc5217SJeff Kirsher  *
5633adfc5217SJeff Kirsher  * returns 0 in case of successfully completed transition,
5634adfc5217SJeff Kirsher  *         negative error code in case of failure, positive
5635adfc5217SJeff Kirsher  *         (EBUSY) value if there is a completion to that is
5636adfc5217SJeff Kirsher  *         still pending (possible only if RAMROD_COMP_WAIT is
5637adfc5217SJeff Kirsher  *         not set in params->ramrod_flags for asynchronous
5638adfc5217SJeff Kirsher  *         commands).
5639adfc5217SJeff Kirsher  */
5640adfc5217SJeff Kirsher int bnx2x_func_state_change(struct bnx2x *bp,
5641adfc5217SJeff Kirsher 			    struct bnx2x_func_state_params *params)
5642adfc5217SJeff Kirsher {
5643adfc5217SJeff Kirsher 	struct bnx2x_func_sp_obj *o = params->f_obj;
5644adfc5217SJeff Kirsher 	int rc;
5645adfc5217SJeff Kirsher 	enum bnx2x_func_cmd cmd = params->cmd;
5646adfc5217SJeff Kirsher 	unsigned long *pending = &o->pending;
5647adfc5217SJeff Kirsher 
5648adfc5217SJeff Kirsher 	mutex_lock(&o->one_pending_mutex);
5649adfc5217SJeff Kirsher 
5650adfc5217SJeff Kirsher 	/* Check that the requested transition is legal */
5651adfc5217SJeff Kirsher 	if (o->check_transition(bp, o, params)) {
5652adfc5217SJeff Kirsher 		mutex_unlock(&o->one_pending_mutex);
5653adfc5217SJeff Kirsher 		return -EINVAL;
5654adfc5217SJeff Kirsher 	}
5655adfc5217SJeff Kirsher 
5656adfc5217SJeff Kirsher 	/* Set "pending" bit */
5657adfc5217SJeff Kirsher 	set_bit(cmd, pending);
5658adfc5217SJeff Kirsher 
5659adfc5217SJeff Kirsher 	/* Don't send a command if only driver cleanup was requested */
5660adfc5217SJeff Kirsher 	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
5661adfc5217SJeff Kirsher 		bnx2x_func_state_change_comp(bp, o, cmd);
5662adfc5217SJeff Kirsher 		mutex_unlock(&o->one_pending_mutex);
5663adfc5217SJeff Kirsher 	} else {
5664adfc5217SJeff Kirsher 		/* Send a ramrod */
5665adfc5217SJeff Kirsher 		rc = o->send_cmd(bp, params);
5666adfc5217SJeff Kirsher 
5667adfc5217SJeff Kirsher 		mutex_unlock(&o->one_pending_mutex);
5668adfc5217SJeff Kirsher 
5669adfc5217SJeff Kirsher 		if (rc) {
5670adfc5217SJeff Kirsher 			o->next_state = BNX2X_F_STATE_MAX;
5671adfc5217SJeff Kirsher 			clear_bit(cmd, pending);
5672adfc5217SJeff Kirsher 			smp_mb__after_clear_bit();
5673adfc5217SJeff Kirsher 			return rc;
5674adfc5217SJeff Kirsher 		}
5675adfc5217SJeff Kirsher 
5676adfc5217SJeff Kirsher 		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
5677adfc5217SJeff Kirsher 			rc = o->wait_comp(bp, o, cmd);
5678adfc5217SJeff Kirsher 			if (rc)
5679adfc5217SJeff Kirsher 				return rc;
5680adfc5217SJeff Kirsher 
5681adfc5217SJeff Kirsher 			return 0;
5682adfc5217SJeff Kirsher 		}
5683adfc5217SJeff Kirsher 	}
5684adfc5217SJeff Kirsher 
5685adfc5217SJeff Kirsher 	return !!test_bit(cmd, pending);
5686adfc5217SJeff Kirsher }
5687