1d14abf15SRobert Mustacchi #ifndef ECORE_ERASE
2d14abf15SRobert Mustacchi #ifdef __LINUX
3d14abf15SRobert Mustacchi 
4d14abf15SRobert Mustacchi #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
5d14abf15SRobert Mustacchi 
6d14abf15SRobert Mustacchi #include <linux/kernel.h>
7d14abf15SRobert Mustacchi #include <linux/types.h>
8d14abf15SRobert Mustacchi #include <asm/byteorder.h>
9d14abf15SRobert Mustacchi #include <linux/version.h>
10d14abf15SRobert Mustacchi #include <linux/module.h>
11d14abf15SRobert Mustacchi #include <linux/crc32.h>
12d14abf15SRobert Mustacchi #include <linux/etherdevice.h>
13d14abf15SRobert Mustacchi 
14d14abf15SRobert Mustacchi #define ECORE_ALIGN(x, a) ALIGN(x, a)
15d14abf15SRobert Mustacchi #endif
16d14abf15SRobert Mustacchi 
17d14abf15SRobert Mustacchi /* Always define ECORE_OOO for VBD */
18d14abf15SRobert Mustacchi #define ECORE_OOO
19d14abf15SRobert Mustacchi 
20d14abf15SRobert Mustacchi #include "bcmtype.h"
21d14abf15SRobert Mustacchi #include "utils.h"
22d14abf15SRobert Mustacchi #include "lm5710.h"
23d14abf15SRobert Mustacchi #include "ecore_sp_verbs.h"
24d14abf15SRobert Mustacchi #include "command.h"
25d14abf15SRobert Mustacchi #include "debug.h"
26d14abf15SRobert Mustacchi #include "ecore_common.h"
27d14abf15SRobert Mustacchi 
28d14abf15SRobert Mustacchi /************************ Debug print macros **********************************/
29d14abf15SRobert Mustacchi #if !defined(UEFI) && defined(DBG)
30d14abf15SRobert Mustacchi #define ECORE_MSG(pdev, m, ...) \
31d14abf15SRobert Mustacchi 	DbgMessage(pdev, WARNi, m, ##__VA_ARGS__)
32d14abf15SRobert Mustacchi #else
33d14abf15SRobert Mustacchi #define ECORE_MSG
34d14abf15SRobert Mustacchi #endif
35d14abf15SRobert Mustacchi 
36d14abf15SRobert Mustacchi /************************ Error prints ****************************************/
37d14abf15SRobert Mustacchi #if !defined(UEFI) && defined(DBG)
38d14abf15SRobert Mustacchi #define ECORE_ERR(str, ...) DbgMessage(pdev, FATAL, str, ##__VA_ARGS__)
39d14abf15SRobert Mustacchi #else
40d14abf15SRobert Mustacchi #define ECORE_ERR
41d14abf15SRobert Mustacchi #endif
42d14abf15SRobert Mustacchi 
43d14abf15SRobert Mustacchi 
44d14abf15SRobert Mustacchi /***********************  ECORE WRAPPER MACROS ********************************/
45d14abf15SRobert Mustacchi 
46d14abf15SRobert Mustacchi #define ECORE_RET_PENDING(pending_bit, pending) \
47d14abf15SRobert Mustacchi 	(ECORE_TEST_BIT(pending_bit, pending) ? ECORE_PENDING : ECORE_SUCCESS)
48d14abf15SRobert Mustacchi 
49d14abf15SRobert Mustacchi #define ECORE_ZALLOC(_size, _flags, _pdev) mm_rt_zalloc_mem(_pdev, _size)
50d14abf15SRobert Mustacchi #define ECORE_CALLOC(_len, _size, _flags, _pdev) mm_rt_zalloc_mem(_pdev, _len * _size)
51d14abf15SRobert Mustacchi #define ECORE_FREE(_pdev, _buf, _size) mm_rt_free_mem(_pdev, _buf, _size, 0)
52d14abf15SRobert Mustacchi 
53d14abf15SRobert Mustacchi /*
54d14abf15SRobert Mustacchi  *  Ecore implementation of set/get flag
55d14abf15SRobert Mustacchi  *  (differs from VBD set_flags, get_flags)
56d14abf15SRobert Mustacchi  */
57d14abf15SRobert Mustacchi #define ECORE_SET_FLAG(value, mask, flag) \
58d14abf15SRobert Mustacchi 	do {\
59d14abf15SRobert Mustacchi 		(value) &= ~(mask);\
60d14abf15SRobert Mustacchi 		(value) |= ((flag) << (mask##_SHIFT));\
61d14abf15SRobert Mustacchi 	} while (0)
62d14abf15SRobert Mustacchi 
63d14abf15SRobert Mustacchi #define ECORE_GET_FLAG(value, mask) \
64d14abf15SRobert Mustacchi 	(((value) &= (mask)) >> (mask##_SHIFT))
65d14abf15SRobert Mustacchi 
66d14abf15SRobert Mustacchi #define ecore_sp_post(_pdev, _cmd , _cid, _data, _con_type) \
67d14abf15SRobert Mustacchi 	lm_sq_post(_pdev, _cid, (u8)(_cmd), CMD_PRIORITY_NORMAL, _con_type, \
68d14abf15SRobert Mustacchi 	_data)
69d14abf15SRobert Mustacchi 
70d14abf15SRobert Mustacchi #define ECORE_SET_CTX_VALIDATION(_pdev, _cxt, _cid) \
71d14abf15SRobert Mustacchi 	lm_set_cdu_validation_data(_pdev, _cid, FALSE) /* context? type? */
72d14abf15SRobert Mustacchi /************************ TODO for LM people!!! *******************************/
73d14abf15SRobert Mustacchi #define ECORE_TODO_UPDATE_COALESCE_SB_INDEX(a1, a2, a3, a4, a5)
74d14abf15SRobert Mustacchi #define ECORE_TODO_LINK_REPORT(pdev)
75d14abf15SRobert Mustacchi #define ECORE_TODO_FW_COMMAND(_pdev, _drv_msg_code, _val) (-1)
76d14abf15SRobert Mustacchi 
77d14abf15SRobert Mustacchi /************************ Lists ***********************************************/
78d14abf15SRobert Mustacchi #define ECORE_LIST_FOR_EACH_ENTRY(pos, _head, _link, cast) \
79d14abf15SRobert Mustacchi 	for (pos = (cast *)d_list_peek_head(_head); \
80d14abf15SRobert Mustacchi 	     pos; \
81d14abf15SRobert Mustacchi 	     pos = (cast *)d_list_next_entry(&pos->_link))
82d14abf15SRobert Mustacchi 
83d14abf15SRobert Mustacchi /**
84d14abf15SRobert Mustacchi  * ECORE_LIST_FOR_EACH_ENTRY_SAFE - iterate over list of given type
85d14abf15SRobert Mustacchi  * @pos:        the type * to use as a loop cursor.
86d14abf15SRobert Mustacchi  * @n:          another type * to use as temporary storage
87d14abf15SRobert Mustacchi  * @head:       the head for your list.
88d14abf15SRobert Mustacchi  * @member:     the name of the list_struct within the struct.
89d14abf15SRobert Mustacchi  *
90d14abf15SRobert Mustacchi  * iterate over list of given type safe against removal of list entry
91d14abf15SRobert Mustacchi  */
92d14abf15SRobert Mustacchi #define ECORE_LIST_FOR_EACH_ENTRY_SAFE(pos, n, head, member, cast)   \
93d14abf15SRobert Mustacchi 	 for (pos = (cast *)d_list_peek_head(head), \
94d14abf15SRobert Mustacchi 	      n = (pos) ? (cast *)d_list_next_entry(&pos->member) : NULL; \
95d14abf15SRobert Mustacchi 	      pos != NULL;  \
96d14abf15SRobert Mustacchi 	      pos = (cast *)n, \
97d14abf15SRobert Mustacchi 	      n = (pos) ? (cast *)d_list_next_entry(&pos->member) : NULL)
98d14abf15SRobert Mustacchi 
99d14abf15SRobert Mustacchi #define ECORE_LIST_IS_LAST(_link, _list)                (_link == (_list)->tail)
100d14abf15SRobert Mustacchi 
101d14abf15SRobert Mustacchi #define ECORE_LIST_IS_EMPTY(head)                       \
102d14abf15SRobert Mustacchi 	d_list_is_empty(head)
103d14abf15SRobert Mustacchi 
104d14abf15SRobert Mustacchi #define ECORE_LIST_FIRST_ENTRY(head, cast, link)	\
105d14abf15SRobert Mustacchi 	(cast *)d_list_peek_head(head)
106d14abf15SRobert Mustacchi 
107d14abf15SRobert Mustacchi #define ECORE_LIST_NEXT(pos, link, cast)	\
108d14abf15SRobert Mustacchi 	(cast *)d_list_next_entry(&((pos)->link))
109d14abf15SRobert Mustacchi 
110d14abf15SRobert Mustacchi #define ECORE_LIST_INIT(head)				\
111d14abf15SRobert Mustacchi do { \
112d14abf15SRobert Mustacchi 	d_list_clear(head); \
113d14abf15SRobert Mustacchi } while (0)
114d14abf15SRobert Mustacchi 
115d14abf15SRobert Mustacchi #define ECORE_LIST_PUSH_TAIL(link, head)		\
116d14abf15SRobert Mustacchi do { \
117d14abf15SRobert Mustacchi 	d_list_push_tail(head, link); \
118d14abf15SRobert Mustacchi } while (0)
119d14abf15SRobert Mustacchi 
120d14abf15SRobert Mustacchi #define ECORE_LIST_PUSH_HEAD(link, head)		\
121d14abf15SRobert Mustacchi do { \
122d14abf15SRobert Mustacchi 	d_list_push_head(head, link); \
123d14abf15SRobert Mustacchi } while (0)
124d14abf15SRobert Mustacchi 
125d14abf15SRobert Mustacchi #define ECORE_LIST_REMOVE_ENTRY(link, head)		\
126d14abf15SRobert Mustacchi do { \
127d14abf15SRobert Mustacchi 	d_list_remove_entry(head, link); \
128d14abf15SRobert Mustacchi } while (0)
129d14abf15SRobert Mustacchi 
130d14abf15SRobert Mustacchi #define ECORE_LIST_SPLICE_INIT(new_head, head) \
131d14abf15SRobert Mustacchi do { \
132d14abf15SRobert Mustacchi 	d_list_add_head(head, new_head); \
133d14abf15SRobert Mustacchi 	d_list_clear(new_head); \
134d14abf15SRobert Mustacchi } while (0)
135d14abf15SRobert Mustacchi 
ecore_crc32_le(u32_t seed,u8_t * mac,u32_t len)136d14abf15SRobert Mustacchi static __inline u32_t ecore_crc32_le(u32_t seed, u8_t *mac, u32_t len)
137d14abf15SRobert Mustacchi {
138d14abf15SRobert Mustacchi 	u32_t packet_buf[2] = {0};
139d14abf15SRobert Mustacchi 
140d14abf15SRobert Mustacchi 	memcpy(((u8_t *)(&packet_buf[0]))+2, &mac[0], 2);
141d14abf15SRobert Mustacchi 	memcpy(&packet_buf[1], &mac[2], 4);
142d14abf15SRobert Mustacchi 	return SWAP_BYTES32(calc_crc32((u8_t *)packet_buf, 8, seed, 0));
143d14abf15SRobert Mustacchi }
144d14abf15SRobert Mustacchi 
145d14abf15SRobert Mustacchi /************************ Per compilation target ******************************/
146d14abf15SRobert Mustacchi #ifdef __LINUX
147d14abf15SRobert Mustacchi 
148d14abf15SRobert Mustacchi #define ECORE_UNLIKELY	unlikely
149d14abf15SRobert Mustacchi #define ECORE_LIKELY	likely
150d14abf15SRobert Mustacchi 
151d14abf15SRobert Mustacchi #define ecore_atomic_read		mm_atomic_read
152d14abf15SRobert Mustacchi #define ecore_atomic_cmpxchg		mm_atomic_cmpxchg
153d14abf15SRobert Mustacchi #define ecore_atomic_set(a, v)		mm_atomic_set((u32_t *)(a), v)
154d14abf15SRobert Mustacchi #define smp_mb__before_atomic() mm_barrier()
155d14abf15SRobert Mustacchi #define smp_mb__after_atomic()  mm_barrier()
156d14abf15SRobert Mustacchi 
157d14abf15SRobert Mustacchi /* Other */
158d14abf15SRobert Mustacchi #define ECORE_IS_VALID_ETHER_ADDR(_mac)               is_valid_ether_addr(_mac)
159d14abf15SRobert Mustacchi #define ECORE_SET_WAIT_COUNT(_cnt)
160d14abf15SRobert Mustacchi #define ECORE_SET_WAIT_DELAY_US(_cnt, _delay_us)
161d14abf15SRobert Mustacchi 
162d14abf15SRobert Mustacchi /* Mutex related */
163d14abf15SRobert Mustacchi #define ECORE_MUTEX_INIT(_mutex)	mutex_init(_mutex)
164d14abf15SRobert Mustacchi #define ECORE_MUTEX_LOCK(_mutex)	mutex_lock(_mutex)
165d14abf15SRobert Mustacchi #define ECORE_MUTEX_UNLOCK(_mutex)	mutex_unlock(_mutex)
166d14abf15SRobert Mustacchi 
167d14abf15SRobert Mustacchi #define ECORE_MIGHT_SLEEP() ediag_might_sleep()
168d14abf15SRobert Mustacchi #define ECORE_TEST_BIT(bit, var)  test_bit(bit, var)
169d14abf15SRobert Mustacchi #define ECORE_TEST_AND_CLEAR_BIT(bit, var) test_and_clear_bit(bit, var)
170d14abf15SRobert Mustacchi 
171d14abf15SRobert Mustacchi #else /* ! LINUX */
172d14abf15SRobert Mustacchi 
173d14abf15SRobert Mustacchi typedef u16 __le16;
174d14abf15SRobert Mustacchi 
175d14abf15SRobert Mustacchi #define ecore_atomic_read		mm_atomic_read
176d14abf15SRobert Mustacchi #define ecore_atomic_cmpxchg		mm_atomic_cmpxchg
177d14abf15SRobert Mustacchi #define ecore_atomic_set(a, val)	mm_atomic_set((u32_t *)(a), val)
178d14abf15SRobert Mustacchi 
179d14abf15SRobert Mustacchi #define ECORE_UNLIKELY(x)	(x)
180d14abf15SRobert Mustacchi #define ECORE_LIKELY(x)		(x)
181d14abf15SRobert Mustacchi #define BUG() DbgBreakMsg("Bug")
182d14abf15SRobert Mustacchi #define smp_mb()                   mm_barrier()
183d14abf15SRobert Mustacchi #define smp_mb__before_atomic() mm_barrier()
184d14abf15SRobert Mustacchi #define smp_mb__after_atomic()  mm_barrier()
185d14abf15SRobert Mustacchi #define mb()                       mm_barrier()
186d14abf15SRobert Mustacchi #define wmb()                      mm_barrier()
187d14abf15SRobert Mustacchi #define mmiowb()		   mm_barrier()
188d14abf15SRobert Mustacchi 
189d14abf15SRobert Mustacchi #define ECORE_MIGHT_SLEEP() /* IRQL_PASSIVE_CODE() */
190d14abf15SRobert Mustacchi 
191d14abf15SRobert Mustacchi /* Mutex related */
192d14abf15SRobert Mustacchi #define ECORE_MUTEX_INIT(_mutex)
193d14abf15SRobert Mustacchi #define ECORE_MUTEX_LOCK(_mutex)
194d14abf15SRobert Mustacchi #define ECORE_MUTEX_UNLOCK(_mutex)
195d14abf15SRobert Mustacchi 
196d14abf15SRobert Mustacchi /* Atomic Bit Manipulation */
197d14abf15SRobert Mustacchi #define ECORE_TEST_BIT(_bit, _var) \
198d14abf15SRobert Mustacchi 	(mm_atomic_long_read(_var) & (1 << (_bit)))
199d14abf15SRobert Mustacchi 
200d14abf15SRobert Mustacchi /* Other */
201d14abf15SRobert Mustacchi #define ECORE_IS_VALID_ETHER_ADDR(_mac)         TRUE
202d14abf15SRobert Mustacchi #define ECORE_SET_WAIT_DELAY_US(_cnt, _delay_us) \
203d14abf15SRobert Mustacchi do { \
204d14abf15SRobert Mustacchi 	_delay_us = (_cnt >= 2360) ? 100 : 25000; \
205d14abf15SRobert Mustacchi } while (0)
206d14abf15SRobert Mustacchi 
207d14abf15SRobert Mustacchi /*
208d14abf15SRobert Mustacchi  * In VBD We'll wait 10,000 times 100us (1 second) +
209d14abf15SRobert Mustacchi  * 2360 times 25000us (59sec) = total 60 sec
210d14abf15SRobert Mustacchi  * (Winodws only note) the 25000 wait will cause
211d14abf15SRobert Mustacchi  * wait to be without CPU stall (look in win_util.c)
212d14abf15SRobert Mustacchi  */
213d14abf15SRobert Mustacchi #define ECORE_SET_WAIT_COUNT(_cnt) \
214d14abf15SRobert Mustacchi do { \
215d14abf15SRobert Mustacchi 	_cnt = 10000 + 2360; \
216d14abf15SRobert Mustacchi } while (0)
217d14abf15SRobert Mustacchi 
ECORE_TEST_AND_CLEAR_BIT(int bit,unsigned long * vec)218d14abf15SRobert Mustacchi static __inline BOOL ECORE_TEST_AND_CLEAR_BIT(int bit, unsigned long *vec)
219d14abf15SRobert Mustacchi {
220d14abf15SRobert Mustacchi 	BOOL set = ECORE_TEST_BIT(bit, vec);
221d14abf15SRobert Mustacchi 	ECORE_CLEAR_BIT(bit, vec);
222d14abf15SRobert Mustacchi 
223d14abf15SRobert Mustacchi 	return set;
224d14abf15SRobert Mustacchi }
225d14abf15SRobert Mustacchi 
226d14abf15SRobert Mustacchi #endif /* END if "per LM target type" */
227d14abf15SRobert Mustacchi 
228d14abf15SRobert Mustacchi /* Spin lock related */
229d14abf15SRobert Mustacchi #define ECORE_SPIN_LOCK_INIT(_spin, _pdev)	mm_init_lock(_pdev, _spin)
230d14abf15SRobert Mustacchi #define ECORE_SPIN_LOCK_BH(_spin)		mm_acquire_lock(_spin)
231d14abf15SRobert Mustacchi #define ECORE_SPIN_UNLOCK_BH(_spin)		mm_release_lock(_spin)
232d14abf15SRobert Mustacchi 
233d14abf15SRobert Mustacchi #endif /* not ECORE_ERASE */
234d14abf15SRobert Mustacchi #if defined(__FreeBSD__) && !defined(NOT_LINUX)
235d14abf15SRobert Mustacchi #include "bxe.h"
236d14abf15SRobert Mustacchi #include "ecore_init.h"
237d14abf15SRobert Mustacchi #elif !defined(EDIAG)
238d14abf15SRobert Mustacchi #ifdef ECORE_ERASE
239d14abf15SRobert Mustacchi #include <linux/version.h>
240d14abf15SRobert Mustacchi #include <linux/module.h>
241d14abf15SRobert Mustacchi #include <linux/crc32.h>
242d14abf15SRobert Mustacchi #include <linux/netdevice.h>
243d14abf15SRobert Mustacchi #include <linux/etherdevice.h>
244d14abf15SRobert Mustacchi #if (LINUX_VERSION_CODE >= 0x02061b) && !defined(BNX2X_DRIVER_DISK) && !defined(__VMKLNX__) /* BNX2X_UPSTREAM */
245d14abf15SRobert Mustacchi #include <linux/crc32c.h>
246d14abf15SRobert Mustacchi #endif
247d14abf15SRobert Mustacchi #include "bnx2x.h"
248d14abf15SRobert Mustacchi #include "bnx2x_cmn.h"
249d14abf15SRobert Mustacchi #include "bnx2x_sp.h"
250d14abf15SRobert Mustacchi 
251d14abf15SRobert Mustacchi #define ECORE_MAX_EMUL_MULTI		16
252d14abf15SRobert Mustacchi #endif
253d14abf15SRobert Mustacchi #endif
254d14abf15SRobert Mustacchi 
255d14abf15SRobert Mustacchi /**** Exe Queue interfaces ****/
256d14abf15SRobert Mustacchi 
257d14abf15SRobert Mustacchi /**
258d14abf15SRobert Mustacchi  * ecore_exe_queue_init - init the Exe Queue object
259d14abf15SRobert Mustacchi  *
260d14abf15SRobert Mustacchi  * @o:		pointer to the object
261d14abf15SRobert Mustacchi  * @exe_len:	length
262d14abf15SRobert Mustacchi  * @owner:	pointer to the owner
263d14abf15SRobert Mustacchi  * @validate:	validate function pointer
264d14abf15SRobert Mustacchi  * @optimize:	optimize function pointer
265d14abf15SRobert Mustacchi  * @exec:	execute function pointer
266d14abf15SRobert Mustacchi  * @get:	get function pointer
267d14abf15SRobert Mustacchi  */
ecore_exe_queue_init(struct _lm_device_t * pdev,struct ecore_exe_queue_obj * o,int exe_len,union ecore_qable_obj * owner,exe_q_validate validate,exe_q_remove remove,exe_q_optimize optimize,exe_q_execute exec,exe_q_get get)268d14abf15SRobert Mustacchi static INLINE void ecore_exe_queue_init(struct _lm_device_t *pdev,
269d14abf15SRobert Mustacchi 					struct ecore_exe_queue_obj *o,
270d14abf15SRobert Mustacchi 					int exe_len,
271d14abf15SRobert Mustacchi 					union ecore_qable_obj *owner,
272d14abf15SRobert Mustacchi 					exe_q_validate validate,
273d14abf15SRobert Mustacchi 					exe_q_remove remove,
274d14abf15SRobert Mustacchi 					exe_q_optimize optimize,
275d14abf15SRobert Mustacchi 					exe_q_execute exec,
276d14abf15SRobert Mustacchi 					exe_q_get get)
277d14abf15SRobert Mustacchi {
278d14abf15SRobert Mustacchi 	mm_memset(o, 0, sizeof(*o));
279d14abf15SRobert Mustacchi 
280d14abf15SRobert Mustacchi 	ECORE_LIST_INIT(&o->exe_queue);
281d14abf15SRobert Mustacchi 	ECORE_LIST_INIT(&o->pending_comp);
282d14abf15SRobert Mustacchi 
283d14abf15SRobert Mustacchi 	ECORE_SPIN_LOCK_INIT(&o->lock, pdev);
284d14abf15SRobert Mustacchi 
285d14abf15SRobert Mustacchi 	o->exe_chunk_len = exe_len;
286d14abf15SRobert Mustacchi 	o->owner         = owner;
287d14abf15SRobert Mustacchi 
288d14abf15SRobert Mustacchi 	/* Owner specific callbacks */
289d14abf15SRobert Mustacchi 	o->validate      = validate;
290d14abf15SRobert Mustacchi 	o->remove        = remove;
291d14abf15SRobert Mustacchi 	o->optimize      = optimize;
292d14abf15SRobert Mustacchi 	o->execute       = exec;
293d14abf15SRobert Mustacchi 	o->get           = get;
294d14abf15SRobert Mustacchi 
295d14abf15SRobert Mustacchi 	ECORE_MSG(pdev, "Setup the execution queue with the chunk length of %d\n",
296d14abf15SRobert Mustacchi 		  exe_len);
297d14abf15SRobert Mustacchi }
298d14abf15SRobert Mustacchi 
ecore_exe_queue_free_elem(struct _lm_device_t * pdev,struct ecore_exeq_elem * elem)299d14abf15SRobert Mustacchi static INLINE void ecore_exe_queue_free_elem(struct _lm_device_t *pdev,
300d14abf15SRobert Mustacchi 					     struct ecore_exeq_elem *elem)
301d14abf15SRobert Mustacchi {
302d14abf15SRobert Mustacchi 	ECORE_MSG(pdev, "Deleting an exe_queue element\n");
303d14abf15SRobert Mustacchi 	ECORE_FREE(pdev, elem, sizeof(*elem));
304d14abf15SRobert Mustacchi }
305d14abf15SRobert Mustacchi 
ecore_exe_queue_length(struct ecore_exe_queue_obj * o)306d14abf15SRobert Mustacchi static INLINE int ecore_exe_queue_length(struct ecore_exe_queue_obj *o)
307d14abf15SRobert Mustacchi {
308d14abf15SRobert Mustacchi 	struct ecore_exeq_elem *elem;
309d14abf15SRobert Mustacchi 	int cnt = 0;
310d14abf15SRobert Mustacchi 
311d14abf15SRobert Mustacchi #ifdef ECORE_ERASE
312d14abf15SRobert Mustacchi 	spin_lock_bh(&o->lock);
313d14abf15SRobert Mustacchi #endif
314d14abf15SRobert Mustacchi 
315d14abf15SRobert Mustacchi 	ECORE_LIST_FOR_EACH_ENTRY(elem, &o->exe_queue, link,
316d14abf15SRobert Mustacchi 				  struct ecore_exeq_elem)
317d14abf15SRobert Mustacchi 		cnt++;
318d14abf15SRobert Mustacchi 
319d14abf15SRobert Mustacchi #ifdef ECORE_ERASE
320d14abf15SRobert Mustacchi 	spin_unlock_bh(&o->lock);
321d14abf15SRobert Mustacchi #endif
322d14abf15SRobert Mustacchi 
323d14abf15SRobert Mustacchi 	return cnt;
324d14abf15SRobert Mustacchi }
325d14abf15SRobert Mustacchi 
326d14abf15SRobert Mustacchi /**
327d14abf15SRobert Mustacchi  * ecore_exe_queue_add - add a new element to the execution queue
328d14abf15SRobert Mustacchi  *
329d14abf15SRobert Mustacchi  * @pdev:	driver handle
330d14abf15SRobert Mustacchi  * @o:		queue
331d14abf15SRobert Mustacchi  * @cmd:	new command to add
332d14abf15SRobert Mustacchi  * @restore:	true - do not optimize the command
333d14abf15SRobert Mustacchi  *
334d14abf15SRobert Mustacchi  * If the element is optimized or is illegal, frees it.
335d14abf15SRobert Mustacchi  */
ecore_exe_queue_add(struct _lm_device_t * pdev,struct ecore_exe_queue_obj * o,struct ecore_exeq_elem * elem,BOOL restore)336d14abf15SRobert Mustacchi static INLINE int ecore_exe_queue_add(struct _lm_device_t *pdev,
337d14abf15SRobert Mustacchi 				      struct ecore_exe_queue_obj *o,
338d14abf15SRobert Mustacchi 				      struct ecore_exeq_elem *elem,
339d14abf15SRobert Mustacchi 				      BOOL restore)
340d14abf15SRobert Mustacchi {
341d14abf15SRobert Mustacchi 	int rc;
342d14abf15SRobert Mustacchi 
343d14abf15SRobert Mustacchi 	ECORE_SPIN_LOCK_BH(&o->lock);
344d14abf15SRobert Mustacchi 
345d14abf15SRobert Mustacchi 	if (!restore) {
346d14abf15SRobert Mustacchi 		/* Try to cancel this element queue */
347d14abf15SRobert Mustacchi 		rc = o->optimize(pdev, o->owner, elem);
348d14abf15SRobert Mustacchi 		if (rc)
349d14abf15SRobert Mustacchi 			goto free_and_exit;
350d14abf15SRobert Mustacchi 
351d14abf15SRobert Mustacchi 		/* Check if this request is ok */
352d14abf15SRobert Mustacchi 		rc = o->validate(pdev, o->owner, elem);
353d14abf15SRobert Mustacchi 		if (rc) {
354d14abf15SRobert Mustacchi 			ECORE_MSG(pdev, "Preamble failed: %d\n", rc);
355d14abf15SRobert Mustacchi 			goto free_and_exit;
356d14abf15SRobert Mustacchi 		}
357d14abf15SRobert Mustacchi 	}
358d14abf15SRobert Mustacchi 
359d14abf15SRobert Mustacchi 	/* If so, add it to the execution queue */
360d14abf15SRobert Mustacchi 	ECORE_LIST_PUSH_TAIL(&elem->link, &o->exe_queue);
361d14abf15SRobert Mustacchi 
362d14abf15SRobert Mustacchi 	ECORE_SPIN_UNLOCK_BH(&o->lock);
363d14abf15SRobert Mustacchi 
364d14abf15SRobert Mustacchi 	return ECORE_SUCCESS;
365d14abf15SRobert Mustacchi 
366d14abf15SRobert Mustacchi free_and_exit:
367d14abf15SRobert Mustacchi 	ecore_exe_queue_free_elem(pdev, elem);
368d14abf15SRobert Mustacchi 
369d14abf15SRobert Mustacchi 	ECORE_SPIN_UNLOCK_BH(&o->lock);
370d14abf15SRobert Mustacchi 
371d14abf15SRobert Mustacchi 	return rc;
372d14abf15SRobert Mustacchi }
373d14abf15SRobert Mustacchi 
__ecore_exe_queue_reset_pending(struct _lm_device_t * pdev,struct ecore_exe_queue_obj * o)374d14abf15SRobert Mustacchi static INLINE void __ecore_exe_queue_reset_pending(
375d14abf15SRobert Mustacchi 	struct _lm_device_t *pdev,
376d14abf15SRobert Mustacchi 	struct ecore_exe_queue_obj *o)
377d14abf15SRobert Mustacchi {
378d14abf15SRobert Mustacchi 	struct ecore_exeq_elem *elem;
379d14abf15SRobert Mustacchi 
380d14abf15SRobert Mustacchi 	while (!ECORE_LIST_IS_EMPTY(&o->pending_comp)) {
381d14abf15SRobert Mustacchi 		elem = ECORE_LIST_FIRST_ENTRY(&o->pending_comp,
382d14abf15SRobert Mustacchi 					      struct ecore_exeq_elem,
383d14abf15SRobert Mustacchi 					      link);
384d14abf15SRobert Mustacchi 
385d14abf15SRobert Mustacchi 		ECORE_LIST_REMOVE_ENTRY(&elem->link, &o->pending_comp);
386d14abf15SRobert Mustacchi 		ecore_exe_queue_free_elem(pdev, elem);
387d14abf15SRobert Mustacchi 	}
388d14abf15SRobert Mustacchi }
389d14abf15SRobert Mustacchi 
390d14abf15SRobert Mustacchi /**
391d14abf15SRobert Mustacchi  * ecore_exe_queue_step - execute one execution chunk atomically
392d14abf15SRobert Mustacchi  *
393d14abf15SRobert Mustacchi  * @pdev:		driver handle
394d14abf15SRobert Mustacchi  * @o:			queue
395d14abf15SRobert Mustacchi  * @ramrod_flags:	flags
396d14abf15SRobert Mustacchi  *
397d14abf15SRobert Mustacchi  * (Should be called while holding the exe_queue->lock).
398d14abf15SRobert Mustacchi  */
ecore_exe_queue_step(struct _lm_device_t * pdev,struct ecore_exe_queue_obj * o,unsigned long * ramrod_flags)399d14abf15SRobert Mustacchi static INLINE int ecore_exe_queue_step(struct _lm_device_t *pdev,
400d14abf15SRobert Mustacchi 				       struct ecore_exe_queue_obj *o,
401d14abf15SRobert Mustacchi 				       unsigned long *ramrod_flags)
402d14abf15SRobert Mustacchi {
403d14abf15SRobert Mustacchi 	struct ecore_exeq_elem *elem, spacer;
404d14abf15SRobert Mustacchi 	int cur_len = 0, rc;
405d14abf15SRobert Mustacchi 
406d14abf15SRobert Mustacchi 	mm_memset(&spacer, 0, sizeof(spacer));
407d14abf15SRobert Mustacchi 
408d14abf15SRobert Mustacchi 	/* Next step should not be performed until the current is finished,
409d14abf15SRobert Mustacchi 	 * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
410d14abf15SRobert Mustacchi 	 * properly clear object internals without sending any command to the FW
411d14abf15SRobert Mustacchi 	 * which also implies there won't be any completion to clear the
412d14abf15SRobert Mustacchi 	 * 'pending' list.
413d14abf15SRobert Mustacchi 	 */
414d14abf15SRobert Mustacchi 	if (!ECORE_LIST_IS_EMPTY(&o->pending_comp)) {
415d14abf15SRobert Mustacchi 		if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
416d14abf15SRobert Mustacchi 			ECORE_MSG(pdev, "RAMROD_DRV_CLR_ONLY requested: resetting a pending_comp list\n");
417d14abf15SRobert Mustacchi 			__ecore_exe_queue_reset_pending(pdev, o);
418d14abf15SRobert Mustacchi 		} else {
419d14abf15SRobert Mustacchi 			return ECORE_PENDING;
420d14abf15SRobert Mustacchi 		}
421d14abf15SRobert Mustacchi 	}
422d14abf15SRobert Mustacchi 
423d14abf15SRobert Mustacchi 	/* Run through the pending commands list and create a next
424d14abf15SRobert Mustacchi 	 * execution chunk.
425d14abf15SRobert Mustacchi 	 */
426d14abf15SRobert Mustacchi 	while (!ECORE_LIST_IS_EMPTY(&o->exe_queue)) {
427d14abf15SRobert Mustacchi 		elem = ECORE_LIST_FIRST_ENTRY(&o->exe_queue,
428d14abf15SRobert Mustacchi 					      struct ecore_exeq_elem,
429d14abf15SRobert Mustacchi 					      link);
430d14abf15SRobert Mustacchi 		DbgBreakIf(!elem->cmd_len);
431d14abf15SRobert Mustacchi 
432d14abf15SRobert Mustacchi 		if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
433d14abf15SRobert Mustacchi 			cur_len += elem->cmd_len;
434d14abf15SRobert Mustacchi 			/* Prevent from both lists being empty when moving an
435d14abf15SRobert Mustacchi 			 * element. This will allow the call of
436d14abf15SRobert Mustacchi 			 * ecore_exe_queue_empty() without locking.
437d14abf15SRobert Mustacchi 			 */
438d14abf15SRobert Mustacchi 			ECORE_LIST_PUSH_TAIL(&spacer.link, &o->pending_comp);
439d14abf15SRobert Mustacchi 			mb();
440d14abf15SRobert Mustacchi 			ECORE_LIST_REMOVE_ENTRY(&elem->link, &o->exe_queue);
441d14abf15SRobert Mustacchi 			ECORE_LIST_PUSH_TAIL(&elem->link, &o->pending_comp);
442d14abf15SRobert Mustacchi 			ECORE_LIST_REMOVE_ENTRY(&spacer.link, &o->pending_comp);
443d14abf15SRobert Mustacchi 		} else
444d14abf15SRobert Mustacchi 			break;
445d14abf15SRobert Mustacchi 	}
446d14abf15SRobert Mustacchi 
447d14abf15SRobert Mustacchi 	/* Sanity check */
448d14abf15SRobert Mustacchi 	if (!cur_len)
449d14abf15SRobert Mustacchi 		return ECORE_SUCCESS;
450d14abf15SRobert Mustacchi 
451d14abf15SRobert Mustacchi 	rc = o->execute(pdev, o->owner, &o->pending_comp, ramrod_flags);
452d14abf15SRobert Mustacchi 	if (rc < 0)
453d14abf15SRobert Mustacchi 		/* In case of an error return the commands back to the queue
454d14abf15SRobert Mustacchi 		 *  and reset the pending_comp.
455d14abf15SRobert Mustacchi 		 */
456d14abf15SRobert Mustacchi 		ECORE_LIST_SPLICE_INIT(&o->pending_comp, &o->exe_queue);
457d14abf15SRobert Mustacchi 	else if (!rc)
458d14abf15SRobert Mustacchi 		/* If zero is returned, means there are no outstanding pending
459d14abf15SRobert Mustacchi 		 * completions and we may dismiss the pending list.
460d14abf15SRobert Mustacchi 		 */
461d14abf15SRobert Mustacchi 		__ecore_exe_queue_reset_pending(pdev, o);
462d14abf15SRobert Mustacchi 
463d14abf15SRobert Mustacchi 	return rc;
464d14abf15SRobert Mustacchi }
465d14abf15SRobert Mustacchi 
ecore_exe_queue_empty(struct ecore_exe_queue_obj * o)466d14abf15SRobert Mustacchi static INLINE BOOL ecore_exe_queue_empty(struct ecore_exe_queue_obj *o)
467d14abf15SRobert Mustacchi {
468d14abf15SRobert Mustacchi 	BOOL empty = ECORE_LIST_IS_EMPTY(&o->exe_queue);
469d14abf15SRobert Mustacchi 
470d14abf15SRobert Mustacchi 	/* Don't reorder!!! */
471d14abf15SRobert Mustacchi 	mb();
472d14abf15SRobert Mustacchi 
473d14abf15SRobert Mustacchi 	return empty && ECORE_LIST_IS_EMPTY(&o->pending_comp);
474d14abf15SRobert Mustacchi }
475d14abf15SRobert Mustacchi 
ecore_exe_queue_alloc_elem(struct _lm_device_t * pdev)476d14abf15SRobert Mustacchi static INLINE struct ecore_exeq_elem *ecore_exe_queue_alloc_elem(
477d14abf15SRobert Mustacchi 	struct _lm_device_t *pdev)
478d14abf15SRobert Mustacchi {
479d14abf15SRobert Mustacchi 	ECORE_MSG(pdev, "Allocating a new exe_queue element\n");
480d14abf15SRobert Mustacchi 	return ECORE_ZALLOC(sizeof(struct ecore_exeq_elem), GFP_ATOMIC,
481d14abf15SRobert Mustacchi 			    pdev);
482d14abf15SRobert Mustacchi }
483d14abf15SRobert Mustacchi 
484d14abf15SRobert Mustacchi /************************ raw_obj functions ***********************************/
ecore_raw_check_pending(struct ecore_raw_obj * o)485d14abf15SRobert Mustacchi static BOOL ecore_raw_check_pending(struct ecore_raw_obj *o)
486d14abf15SRobert Mustacchi {
487d14abf15SRobert Mustacchi 	/*
488d14abf15SRobert Mustacchi      * !! converts the value returned by ECORE_TEST_BIT such that it
489d14abf15SRobert Mustacchi      * is guaranteed not to be truncated regardless of BOOL definition.
490d14abf15SRobert Mustacchi 	 *
491d14abf15SRobert Mustacchi 	 * Note we cannot simply define the function's return value type
492d14abf15SRobert Mustacchi      * to match the type returned by ECORE_TEST_BIT, as it varies by
493d14abf15SRobert Mustacchi      * platform/implementation.
494d14abf15SRobert Mustacchi 	 */
495d14abf15SRobert Mustacchi 
496d14abf15SRobert Mustacchi 	return !!ECORE_TEST_BIT(o->state, o->pstate);
497d14abf15SRobert Mustacchi }
498d14abf15SRobert Mustacchi 
ecore_raw_clear_pending(struct ecore_raw_obj * o)499d14abf15SRobert Mustacchi static void ecore_raw_clear_pending(struct ecore_raw_obj *o)
500d14abf15SRobert Mustacchi {
501d14abf15SRobert Mustacchi 	smp_mb__before_atomic();
502d14abf15SRobert Mustacchi 	ECORE_CLEAR_BIT(o->state, o->pstate);
503d14abf15SRobert Mustacchi 	smp_mb__after_atomic();
504d14abf15SRobert Mustacchi }
505d14abf15SRobert Mustacchi 
ecore_raw_set_pending(struct ecore_raw_obj * o)506d14abf15SRobert Mustacchi static void ecore_raw_set_pending(struct ecore_raw_obj *o)
507d14abf15SRobert Mustacchi {
508d14abf15SRobert Mustacchi 	smp_mb__before_atomic();
509d14abf15SRobert Mustacchi 	ECORE_SET_BIT(o->state, o->pstate);
510d14abf15SRobert Mustacchi 	smp_mb__after_atomic();
511d14abf15SRobert Mustacchi }
512d14abf15SRobert Mustacchi 
513d14abf15SRobert Mustacchi /**
514d14abf15SRobert Mustacchi  * ecore_state_wait - wait until the given bit(state) is cleared
515d14abf15SRobert Mustacchi  *
516d14abf15SRobert Mustacchi  * @pdev:	device handle
517d14abf15SRobert Mustacchi  * @state:	state which is to be cleared
518d14abf15SRobert Mustacchi  * @state_p:	state buffer
519d14abf15SRobert Mustacchi  *
520d14abf15SRobert Mustacchi  */
ecore_state_wait(struct _lm_device_t * pdev,int state,unsigned long * pstate)521d14abf15SRobert Mustacchi static INLINE int ecore_state_wait(struct _lm_device_t *pdev, int state,
522d14abf15SRobert Mustacchi 				   unsigned long *pstate)
523d14abf15SRobert Mustacchi {
524d14abf15SRobert Mustacchi 	/* can take a while if any port is running */
525d14abf15SRobert Mustacchi 	int cnt = 5000;
526d14abf15SRobert Mustacchi 
527d14abf15SRobert Mustacchi #ifndef ECORE_ERASE
528d14abf15SRobert Mustacchi 	int delay_us = 1000;
529d14abf15SRobert Mustacchi 
530d14abf15SRobert Mustacchi 	/* In VBD We'll wait 10,000 times 100us (1 second) +
531d14abf15SRobert Mustacchi 	* 2360 times 25000us (59sec) = total 60 sec
532d14abf15SRobert Mustacchi 	* (Winodws only note) the 25000 wait will cause wait
533d14abf15SRobert Mustacchi 	* to be without CPU stall (look in win_util.c)
534d14abf15SRobert Mustacchi 	*/
535d14abf15SRobert Mustacchi 	cnt = 10000 + 2360;
536d14abf15SRobert Mustacchi #endif
537d14abf15SRobert Mustacchi 
538d14abf15SRobert Mustacchi 	if (CHIP_REV_IS_EMUL(pdev))
539d14abf15SRobert Mustacchi 		cnt *= 20;
540d14abf15SRobert Mustacchi 
541d14abf15SRobert Mustacchi 	ECORE_MSG(pdev, "waiting for state to become %d\n", state);
542d14abf15SRobert Mustacchi 
543d14abf15SRobert Mustacchi 	ECORE_MIGHT_SLEEP();
544d14abf15SRobert Mustacchi 	while (cnt--) {
545d14abf15SRobert Mustacchi 		if (!ECORE_TEST_BIT(state, pstate)) {
546d14abf15SRobert Mustacchi #ifdef ECORE_STOP_ON_ERROR
547d14abf15SRobert Mustacchi 			ECORE_MSG(pdev, "exit  (cnt %d)\n", 5000 - cnt);
548d14abf15SRobert Mustacchi #endif
549d14abf15SRobert Mustacchi 			return ECORE_SUCCESS;
550d14abf15SRobert Mustacchi 		}
551d14abf15SRobert Mustacchi 
552d14abf15SRobert Mustacchi #ifndef ECORE_ERASE
553d14abf15SRobert Mustacchi 		/* in case reset is in progress we won't get completion */
554d14abf15SRobert Mustacchi 		if (lm_reset_is_inprogress(pdev))
555d14abf15SRobert Mustacchi 			return 0;
556d14abf15SRobert Mustacchi 
557d14abf15SRobert Mustacchi 		delay_us = (cnt >= 2360) ? 100 : 25000;
558d14abf15SRobert Mustacchi #endif
559d14abf15SRobert Mustacchi 		mm_wait(pdev, delay_us);
560d14abf15SRobert Mustacchi 
561d14abf15SRobert Mustacchi 		if (pdev->panic)
562d14abf15SRobert Mustacchi 			return ECORE_IO;
563d14abf15SRobert Mustacchi 	}
564d14abf15SRobert Mustacchi 
565d14abf15SRobert Mustacchi 	/* timeout! */
566d14abf15SRobert Mustacchi 	ECORE_ERR("timeout waiting for state %d\n", state);
567d14abf15SRobert Mustacchi #ifdef ECORE_STOP_ON_ERROR
568d14abf15SRobert Mustacchi 	ecore_panic();
569d14abf15SRobert Mustacchi #endif
570d14abf15SRobert Mustacchi 
571d14abf15SRobert Mustacchi 	return ECORE_TIMEOUT;
572d14abf15SRobert Mustacchi }
573d14abf15SRobert Mustacchi 
ecore_raw_wait(struct _lm_device_t * pdev,struct ecore_raw_obj * raw)574d14abf15SRobert Mustacchi static int ecore_raw_wait(struct _lm_device_t *pdev, struct ecore_raw_obj *raw)
575d14abf15SRobert Mustacchi {
576d14abf15SRobert Mustacchi 	return ecore_state_wait(pdev, raw->state, raw->pstate);
577d14abf15SRobert Mustacchi }
578d14abf15SRobert Mustacchi 
579d14abf15SRobert Mustacchi /***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
580d14abf15SRobert Mustacchi /* credit handling callbacks */
ecore_get_cam_offset_mac(struct ecore_vlan_mac_obj * o,int * offset)581d14abf15SRobert Mustacchi static BOOL ecore_get_cam_offset_mac(struct ecore_vlan_mac_obj *o, int *offset)
582d14abf15SRobert Mustacchi {
583d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *mp = o->macs_pool;
584d14abf15SRobert Mustacchi 
585d14abf15SRobert Mustacchi 	DbgBreakIf(!mp);
586d14abf15SRobert Mustacchi 
587d14abf15SRobert Mustacchi 	return mp->get_entry(mp, offset);
588d14abf15SRobert Mustacchi }
589d14abf15SRobert Mustacchi 
ecore_get_credit_mac(struct ecore_vlan_mac_obj * o)590d14abf15SRobert Mustacchi static BOOL ecore_get_credit_mac(struct ecore_vlan_mac_obj *o)
591d14abf15SRobert Mustacchi {
592d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *mp = o->macs_pool;
593d14abf15SRobert Mustacchi 
594d14abf15SRobert Mustacchi 	DbgBreakIf(!mp);
595d14abf15SRobert Mustacchi 
596d14abf15SRobert Mustacchi 	return mp->get(mp, 1);
597d14abf15SRobert Mustacchi }
598d14abf15SRobert Mustacchi 
ecore_get_cam_offset_vlan(struct ecore_vlan_mac_obj * o,int * offset)599d14abf15SRobert Mustacchi static BOOL ecore_get_cam_offset_vlan(struct ecore_vlan_mac_obj *o, int *offset)
600d14abf15SRobert Mustacchi {
601d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
602d14abf15SRobert Mustacchi 
603d14abf15SRobert Mustacchi 	DbgBreakIf(!vp);
604d14abf15SRobert Mustacchi 
605d14abf15SRobert Mustacchi 	return vp->get_entry(vp, offset);
606d14abf15SRobert Mustacchi }
607d14abf15SRobert Mustacchi 
ecore_get_credit_vlan(struct ecore_vlan_mac_obj * o)608d14abf15SRobert Mustacchi static BOOL ecore_get_credit_vlan(struct ecore_vlan_mac_obj *o)
609d14abf15SRobert Mustacchi {
610d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
611d14abf15SRobert Mustacchi 
612d14abf15SRobert Mustacchi 	DbgBreakIf(!vp);
613d14abf15SRobert Mustacchi 
614d14abf15SRobert Mustacchi 	return vp->get(vp, 1);
615d14abf15SRobert Mustacchi }
616d14abf15SRobert Mustacchi 
ecore_get_credit_vlan_mac(struct ecore_vlan_mac_obj * o)617d14abf15SRobert Mustacchi static BOOL ecore_get_credit_vlan_mac(struct ecore_vlan_mac_obj *o)
618d14abf15SRobert Mustacchi {
619d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *mp = o->macs_pool;
620d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
621d14abf15SRobert Mustacchi 
622d14abf15SRobert Mustacchi 	if (!mp->get(mp, 1))
623d14abf15SRobert Mustacchi 		return FALSE;
624d14abf15SRobert Mustacchi 
625d14abf15SRobert Mustacchi 	if (!vp->get(vp, 1)) {
626d14abf15SRobert Mustacchi 		mp->put(mp, 1);
627d14abf15SRobert Mustacchi 		return FALSE;
628d14abf15SRobert Mustacchi 	}
629d14abf15SRobert Mustacchi 
630d14abf15SRobert Mustacchi 	return TRUE;
631d14abf15SRobert Mustacchi }
632d14abf15SRobert Mustacchi 
ecore_put_cam_offset_mac(struct ecore_vlan_mac_obj * o,int offset)633d14abf15SRobert Mustacchi static BOOL ecore_put_cam_offset_mac(struct ecore_vlan_mac_obj *o, int offset)
634d14abf15SRobert Mustacchi {
635d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *mp = o->macs_pool;
636d14abf15SRobert Mustacchi 
637d14abf15SRobert Mustacchi 	return mp->put_entry(mp, offset);
638d14abf15SRobert Mustacchi }
639d14abf15SRobert Mustacchi 
ecore_put_credit_mac(struct ecore_vlan_mac_obj * o)640d14abf15SRobert Mustacchi static BOOL ecore_put_credit_mac(struct ecore_vlan_mac_obj *o)
641d14abf15SRobert Mustacchi {
642d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *mp = o->macs_pool;
643d14abf15SRobert Mustacchi 
644d14abf15SRobert Mustacchi 	return mp->put(mp, 1);
645d14abf15SRobert Mustacchi }
646d14abf15SRobert Mustacchi 
ecore_put_cam_offset_vlan(struct ecore_vlan_mac_obj * o,int offset)647d14abf15SRobert Mustacchi static BOOL ecore_put_cam_offset_vlan(struct ecore_vlan_mac_obj *o, int offset)
648d14abf15SRobert Mustacchi {
649d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
650d14abf15SRobert Mustacchi 
651d14abf15SRobert Mustacchi 	return vp->put_entry(vp, offset);
652d14abf15SRobert Mustacchi }
653d14abf15SRobert Mustacchi 
ecore_put_credit_vlan(struct ecore_vlan_mac_obj * o)654d14abf15SRobert Mustacchi static BOOL ecore_put_credit_vlan(struct ecore_vlan_mac_obj *o)
655d14abf15SRobert Mustacchi {
656d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
657d14abf15SRobert Mustacchi 
658d14abf15SRobert Mustacchi 	return vp->put(vp, 1);
659d14abf15SRobert Mustacchi }
660d14abf15SRobert Mustacchi 
ecore_put_credit_vlan_mac(struct ecore_vlan_mac_obj * o)661d14abf15SRobert Mustacchi static BOOL ecore_put_credit_vlan_mac(struct ecore_vlan_mac_obj *o)
662d14abf15SRobert Mustacchi {
663d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *mp = o->macs_pool;
664d14abf15SRobert Mustacchi 	struct ecore_credit_pool_obj *vp = o->vlans_pool;
665d14abf15SRobert Mustacchi 
666d14abf15SRobert Mustacchi 	if (!mp->put(mp, 1))
667d14abf15SRobert Mustacchi 		return FALSE;
668d14abf15SRobert Mustacchi 
669d14abf15SRobert Mustacchi 	if (!vp->put(vp, 1)) {
670d14abf15SRobert Mustacchi 		mp->get(mp, 1);
671d14abf15SRobert Mustacchi 		return FALSE;
672d14abf15SRobert Mustacchi 	}
673d14abf15SRobert Mustacchi 
674d14abf15SRobert Mustacchi 	return TRUE;
675d14abf15SRobert Mustacchi }
676d14abf15SRobert Mustacchi 
677d14abf15SRobert Mustacchi /**
678d14abf15SRobert Mustacchi  * __ecore_vlan_mac_h_write_trylock - try getting the writer lock on vlan mac
679d14abf15SRobert Mustacchi  * head list.
680d14abf15SRobert Mustacchi  *
681d14abf15SRobert Mustacchi  * @pdev:	device handle
682d14abf15SRobert Mustacchi  * @o:		vlan_mac object
683d14abf15SRobert Mustacchi  *
684d14abf15SRobert Mustacchi  * @details: Non-blocking implementation; should be called under execution
685d14abf15SRobert Mustacchi  *           queue lock.
686d14abf15SRobert Mustacchi  */
__ecore_vlan_mac_h_write_trylock(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o)687d14abf15SRobert Mustacchi static int __ecore_vlan_mac_h_write_trylock(struct _lm_device_t *pdev,
688d14abf15SRobert Mustacchi 					    struct ecore_vlan_mac_obj *o)
689d14abf15SRobert Mustacchi {
690d14abf15SRobert Mustacchi 	if (o->head_reader) {
691d14abf15SRobert Mustacchi 		ECORE_MSG(pdev, "vlan_mac_lock writer - There are readers; Busy\n");
692d14abf15SRobert Mustacchi 		return ECORE_BUSY;
693d14abf15SRobert Mustacchi 	}
694d14abf15SRobert Mustacchi 
695d14abf15SRobert Mustacchi 	ECORE_MSG(pdev, "vlan_mac_lock writer - Taken\n");
696d14abf15SRobert Mustacchi 	return ECORE_SUCCESS;
697d14abf15SRobert Mustacchi }
698d14abf15SRobert Mustacchi 
699d14abf15SRobert Mustacchi /**
700d14abf15SRobert Mustacchi  * __ecore_vlan_mac_h_exec_pending - execute step instead of a previous step
701d14abf15SRobert Mustacchi  * which wasn't able to run due to a taken lock on vlan mac head list.
702d14abf15SRobert Mustacchi  *
703d14abf15SRobert Mustacchi  * @pdev:	device handle
704d14abf15SRobert Mustacchi  * @o:		vlan_mac object
705d14abf15SRobert Mustacchi  *
706d14abf15SRobert Mustacchi  * @details Should be called under execution queue lock; notice it might release
707d14abf15SRobert Mustacchi  *          and reclaim it during its run.
708d14abf15SRobert Mustacchi  */
__ecore_vlan_mac_h_exec_pending(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o)709d14abf15SRobert Mustacchi static void __ecore_vlan_mac_h_exec_pending(struct _lm_device_t *pdev,
710d14abf15SRobert Mustacchi 					    struct ecore_vlan_mac_obj *o)
711d14abf15SRobert Mustacchi {
712d14abf15SRobert Mustacchi 	int rc;
713d14abf15SRobert Mustacchi 	unsigned long ramrod_flags = o->saved_ramrod_flags;
714d14abf15SRobert Mustacchi 
715d14abf15SRobert Mustacchi 	ECORE_MSG(pdev, "vlan_mac_lock execute pending command with ramrod flags %lu\n",
716d14abf15SRobert Mustacchi 		  ramrod_flags);
717d14abf15SRobert Mustacchi 	o->head_exe_request = FALSE;
718d14abf15SRobert Mustacchi 	o->saved_ramrod_flags = 0;
719d14abf15SRobert Mustacchi 	rc = ecore_exe_queue_step(pdev, &o->exe_queue, &ramrod_flags);
720d14abf15SRobert Mustacchi 	if (rc != ECORE_SUCCESS) {
721d14abf15SRobert Mustacchi 		ECORE_ERR("execution of pending commands failed with rc %d\n",
722d14abf15SRobert Mustacchi 			  rc);
723d14abf15SRobert Mustacchi #ifdef ECORE_STOP_ON_ERROR
724d14abf15SRobert Mustacchi 		ecore_panic();
725d14abf15SRobert Mustacchi #endif
726d14abf15SRobert Mustacchi 	}
727d14abf15SRobert Mustacchi }
728d14abf15SRobert Mustacchi 
729d14abf15SRobert Mustacchi /**
730d14abf15SRobert Mustacchi  * __ecore_vlan_mac_h_pend - Pend an execution step which couldn't have been
731d14abf15SRobert Mustacchi  * called due to vlan mac head list lock being taken.
732d14abf15SRobert Mustacchi  *
733d14abf15SRobert Mustacchi  * @pdev:		device handle
734d14abf15SRobert Mustacchi  * @o:			vlan_mac object
735d14abf15SRobert Mustacchi  * @ramrod_flags:	ramrod flags of missed execution
736d14abf15SRobert Mustacchi  *
737d14abf15SRobert Mustacchi  * @details Should be called under execution queue lock.
738d14abf15SRobert Mustacchi  */
__ecore_vlan_mac_h_pend(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o,unsigned long ramrod_flags)739d14abf15SRobert Mustacchi static void __ecore_vlan_mac_h_pend(struct _lm_device_t *pdev,
740d14abf15SRobert Mustacchi 				    struct ecore_vlan_mac_obj *o,
741d14abf15SRobert Mustacchi 				    unsigned long ramrod_flags)
742d14abf15SRobert Mustacchi {
743d14abf15SRobert Mustacchi 	o->head_exe_request = TRUE;
744d14abf15SRobert Mustacchi 	o->saved_ramrod_flags = ramrod_flags;
745d14abf15SRobert Mustacchi 	ECORE_MSG(pdev, "Placing pending execution with ramrod flags %lu\n",
746d14abf15SRobert Mustacchi 		  ramrod_flags);
747d14abf15SRobert Mustacchi }
748d14abf15SRobert Mustacchi 
749d14abf15SRobert Mustacchi /**
750d14abf15SRobert Mustacchi  * __ecore_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock
751d14abf15SRobert Mustacchi  *
752d14abf15SRobert Mustacchi  * @pdev:		device handle
753d14abf15SRobert Mustacchi  * @o:			vlan_mac object
754d14abf15SRobert Mustacchi  *
755d14abf15SRobert Mustacchi  * @details Should be called under execution queue lock. Notice if a pending
756d14abf15SRobert Mustacchi  *          execution exists, it would perform it - possibly releasing and
757d14abf15SRobert Mustacchi  *          reclaiming the execution queue lock.
758d14abf15SRobert Mustacchi  */
__ecore_vlan_mac_h_write_unlock(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o)759d14abf15SRobert Mustacchi static void __ecore_vlan_mac_h_write_unlock(struct _lm_device_t *pdev,
760d14abf15SRobert Mustacchi 					    struct ecore_vlan_mac_obj *o)
761d14abf15SRobert Mustacchi {
762d14abf15SRobert Mustacchi 	/* It's possible a new pending execution was added since this writer
763d14abf15SRobert Mustacchi 	 * executed. If so, execute again. [Ad infinitum]
764d14abf15SRobert Mustacchi 	 */
765d14abf15SRobert Mustacchi 	while(o->head_exe_request) {
766d14abf15SRobert Mustacchi 		ECORE_MSG(pdev, "vlan_mac_lock - writer release encountered a pending request\n");
767d14abf15SRobert Mustacchi 		__ecore_vlan_mac_h_exec_pending(pdev, o);
768d14abf15SRobert Mustacchi 	}
769d14abf15SRobert Mustacchi }
770d14abf15SRobert Mustacchi 
771d14abf15SRobert Mustacchi /**
772d14abf15SRobert Mustacchi  * ecore_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock
773d14abf15SRobert Mustacchi  *
774d14abf15SRobert Mustacchi  * @pdev:		device handle
775d14abf15SRobert Mustacchi  * @o:			vlan_mac object
776d14abf15SRobert Mustacchi  *
777d14abf15SRobert Mustacchi  * @details Notice if a pending execution exists, it would perform it -
778d14abf15SRobert Mustacchi  *          possibly releasing and reclaiming the execution queue lock.
779d14abf15SRobert Mustacchi  */
ecore_vlan_mac_h_write_unlock(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o)780d14abf15SRobert Mustacchi void ecore_vlan_mac_h_write_unlock(struct _lm_device_t *pdev,
781d14abf15SRobert Mustacchi 				   struct ecore_vlan_mac_obj *o)
782d14abf15SRobert Mustacchi {
783d14abf15SRobert Mustacchi 	ECORE_SPIN_LOCK_BH(&o->exe_queue.lock);
784d14abf15SRobert Mustacchi 	__ecore_vlan_mac_h_write_unlock(pdev, o);
785d14abf15SRobert Mustacchi 	ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock);
786d14abf15SRobert Mustacchi }
787d14abf15SRobert Mustacchi 
788d14abf15SRobert Mustacchi /**
789d14abf15SRobert Mustacchi  * __ecore_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
790d14abf15SRobert Mustacchi  *
791d14abf15SRobert Mustacchi  * @pdev:		device handle
792d14abf15SRobert Mustacchi  * @o:			vlan_mac object
793d14abf15SRobert Mustacchi  *
794d14abf15SRobert Mustacchi  * @details Should be called under the execution queue lock. May sleep. May
795d14abf15SRobert Mustacchi  *          release and reclaim execution queue lock during its run.
796d14abf15SRobert Mustacchi  */
__ecore_vlan_mac_h_read_lock(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o)797d14abf15SRobert Mustacchi static int __ecore_vlan_mac_h_read_lock(struct _lm_device_t *pdev,
798d14abf15SRobert Mustacchi 					struct ecore_vlan_mac_obj *o)
799d14abf15SRobert Mustacchi {
800d14abf15SRobert Mustacchi 	/* If we got here, we're holding lock --> no WRITER exists */
801d14abf15SRobert Mustacchi 	o->head_reader++;
802d14abf15SRobert Mustacchi 	ECORE_MSG(pdev, "vlan_mac_lock - locked reader - number %d\n",
803d14abf15SRobert Mustacchi 		  o->head_reader);
804d14abf15SRobert Mustacchi 
805d14abf15SRobert Mustacchi 	return ECORE_SUCCESS;
806d14abf15SRobert Mustacchi }
807d14abf15SRobert Mustacchi 
808d14abf15SRobert Mustacchi /**
809d14abf15SRobert Mustacchi  * ecore_vlan_mac_h_read_lock - lock the vlan mac head list reader lock
810d14abf15SRobert Mustacchi  *
811d14abf15SRobert Mustacchi  * @pdev:		device handle
812d14abf15SRobert Mustacchi  * @o:			vlan_mac object
813d14abf15SRobert Mustacchi  *
814d14abf15SRobert Mustacchi  * @details May sleep. Claims and releases execution queue lock during its run.
815d14abf15SRobert Mustacchi  */
ecore_vlan_mac_h_read_lock(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o)816d14abf15SRobert Mustacchi int ecore_vlan_mac_h_read_lock(struct _lm_device_t *pdev,
817d14abf15SRobert Mustacchi 			       struct ecore_vlan_mac_obj *o)
818d14abf15SRobert Mustacchi {
819d14abf15SRobert Mustacchi 	int rc;
820d14abf15SRobert Mustacchi 
821d14abf15SRobert Mustacchi 	ECORE_SPIN_LOCK_BH(&o->exe_queue.lock);
822d14abf15SRobert Mustacchi 	rc = __ecore_vlan_mac_h_read_lock(pdev, o);
823d14abf15SRobert Mustacchi 	ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock);
824d14abf15SRobert Mustacchi 
825d14abf15SRobert Mustacchi 	return rc;
826d14abf15SRobert Mustacchi }
827d14abf15SRobert Mustacchi 
828d14abf15SRobert Mustacchi /**
829d14abf15SRobert Mustacchi  * __ecore_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
830d14abf15SRobert Mustacchi  *
831d14abf15SRobert Mustacchi  * @pdev:		device handle
832d14abf15SRobert Mustacchi  * @o:			vlan_mac object
833d14abf15SRobert Mustacchi  *
834d14abf15SRobert Mustacchi  * @details Should be called under execution queue lock. Notice if a pending
835d14abf15SRobert Mustacchi  *          execution exists, it would be performed if this was the last
836d14abf15SRobert Mustacchi  *          reader. possibly releasing and reclaiming the execution queue lock.
837d14abf15SRobert Mustacchi  */
__ecore_vlan_mac_h_read_unlock(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o)838d14abf15SRobert Mustacchi static void __ecore_vlan_mac_h_read_unlock(struct _lm_device_t *pdev,
839d14abf15SRobert Mustacchi 					  struct ecore_vlan_mac_obj *o)
840d14abf15SRobert Mustacchi {
841d14abf15SRobert Mustacchi 	if (!o->head_reader) {
842d14abf15SRobert Mustacchi 		ECORE_ERR("Need to release vlan mac reader lock, but lock isn't taken\n");
843d14abf15SRobert Mustacchi #ifdef ECORE_STOP_ON_ERROR
844d14abf15SRobert Mustacchi 		ecore_panic();
845d14abf15SRobert Mustacchi #endif
846d14abf15SRobert Mustacchi 	} else {
847d14abf15SRobert Mustacchi 		o->head_reader--;
848d14abf15SRobert Mustacchi 		ECORE_MSG(pdev, "vlan_mac_lock - decreased readers to %d\n",
849d14abf15SRobert Mustacchi 			  o->head_reader);
850d14abf15SRobert Mustacchi 	}
851d14abf15SRobert Mustacchi 
852d14abf15SRobert Mustacchi 	/* It's possible a new pending execution was added, and that this reader
853d14abf15SRobert Mustacchi 	 * was last - if so we need to execute the command.
854d14abf15SRobert Mustacchi 	 */
855d14abf15SRobert Mustacchi 	if (!o->head_reader && o->head_exe_request) {
856d14abf15SRobert Mustacchi 		ECORE_MSG(pdev, "vlan_mac_lock - reader release encountered a pending request\n");
857d14abf15SRobert Mustacchi 
858d14abf15SRobert Mustacchi 		/* Writer release will do the trick */
859d14abf15SRobert Mustacchi 		__ecore_vlan_mac_h_write_unlock(pdev, o);
860d14abf15SRobert Mustacchi 	}
861d14abf15SRobert Mustacchi }
862d14abf15SRobert Mustacchi 
863d14abf15SRobert Mustacchi /**
864d14abf15SRobert Mustacchi  * ecore_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
865d14abf15SRobert Mustacchi  *
866d14abf15SRobert Mustacchi  * @pdev:		device handle
867d14abf15SRobert Mustacchi  * @o:			vlan_mac object
868d14abf15SRobert Mustacchi  *
869d14abf15SRobert Mustacchi  * @details Notice if a pending execution exists, it would be performed if this
870d14abf15SRobert Mustacchi  *          was the last reader. Claims and releases the execution queue lock
871d14abf15SRobert Mustacchi  *          during its run.
872d14abf15SRobert Mustacchi  */
ecore_vlan_mac_h_read_unlock(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o)873d14abf15SRobert Mustacchi void ecore_vlan_mac_h_read_unlock(struct _lm_device_t *pdev,
874d14abf15SRobert Mustacchi 				  struct ecore_vlan_mac_obj *o)
875d14abf15SRobert Mustacchi {
876d14abf15SRobert Mustacchi 	ECORE_SPIN_LOCK_BH(&o->exe_queue.lock);
877d14abf15SRobert Mustacchi 	__ecore_vlan_mac_h_read_unlock(pdev, o);
878d14abf15SRobert Mustacchi 	ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock);
879d14abf15SRobert Mustacchi }
880d14abf15SRobert Mustacchi 
881d14abf15SRobert Mustacchi /**
882d14abf15SRobert Mustacchi  * ecore_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock
883d14abf15SRobert Mustacchi  *
884d14abf15SRobert Mustacchi  * @pdev:		device handle
885d14abf15SRobert Mustacchi  * @o:			vlan_mac object
886d14abf15SRobert Mustacchi  * @n:			number of elements to get
887d14abf15SRobert Mustacchi  * @base:		base address for element placement
888d14abf15SRobert Mustacchi  * @stride:		stride between elements (in bytes)
889d14abf15SRobert Mustacchi  */
ecore_get_n_elements(struct _lm_device_t * pdev,struct ecore_vlan_mac_obj * o,int n,u8 * base,u8 stride,u8 size)890d14abf15SRobert Mustacchi static int ecore_get_n_elements(struct _lm_device_t *pdev, struct ecore_vlan_mac_obj *o,
891d14abf15SRobert Mustacchi 				 int n, u8 *base, u8 stride, u8 size)
892d14abf15SRobert Mustacchi {
893d14abf15SRobert Mustacchi 	struct ecore_vlan_mac_registry_elem *pos;
894d14abf15SRobert Mustacchi 	u8 *next = base;
895d14abf15SRobert Mustacchi 	int counter = 0;
896d14abf15SRobert Mustacchi 	int read_lock;
897d14abf15SRobert Mustacchi 
898d14abf15SRobert Mustacchi 	ECORE_MSG(pdev, "get_n_elements - taking vlan_mac_lock (reader)\n");
899d14abf15SRobert Mustacchi 	read_lock = ecore_vlan_mac_h_read_lock(pdev, o);
900d14abf15SRobert Mustacchi 	if (read_lock != ECORE_SUCCESS)
901d14abf15SRobert Mustacchi 		ECORE_ERR("get_n_elements failed to get vlan mac reader lock; Access without lock\n");
902d14abf15