xref: /linux/include/linux/qed/qed_chain.h (revision e8f1cb50)
1fe56b9e6SYuval Mintz /* QLogic qed NIC Driver
2*e8f1cb50SMintz, Yuval  * Copyright (c) 2015-2017  QLogic Corporation
3fe56b9e6SYuval Mintz  *
4*e8f1cb50SMintz, Yuval  * This software is available to you under a choice of one of two
5*e8f1cb50SMintz, Yuval  * licenses.  You may choose to be licensed under the terms of the GNU
6*e8f1cb50SMintz, Yuval  * General Public License (GPL) Version 2, available from the file
7*e8f1cb50SMintz, Yuval  * COPYING in the main directory of this source tree, or the
8*e8f1cb50SMintz, Yuval  * OpenIB.org BSD license below:
9*e8f1cb50SMintz, Yuval  *
10*e8f1cb50SMintz, Yuval  *     Redistribution and use in source and binary forms, with or
11*e8f1cb50SMintz, Yuval  *     without modification, are permitted provided that the following
12*e8f1cb50SMintz, Yuval  *     conditions are met:
13*e8f1cb50SMintz, Yuval  *
14*e8f1cb50SMintz, Yuval  *      - Redistributions of source code must retain the above
15*e8f1cb50SMintz, Yuval  *        copyright notice, this list of conditions and the following
16*e8f1cb50SMintz, Yuval  *        disclaimer.
17*e8f1cb50SMintz, Yuval  *
18*e8f1cb50SMintz, Yuval  *      - Redistributions in binary form must reproduce the above
19*e8f1cb50SMintz, Yuval  *        copyright notice, this list of conditions and the following
20*e8f1cb50SMintz, Yuval  *        disclaimer in the documentation and /or other materials
21*e8f1cb50SMintz, Yuval  *        provided with the distribution.
22*e8f1cb50SMintz, Yuval  *
23*e8f1cb50SMintz, Yuval  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24*e8f1cb50SMintz, Yuval  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25*e8f1cb50SMintz, Yuval  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26*e8f1cb50SMintz, Yuval  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27*e8f1cb50SMintz, Yuval  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28*e8f1cb50SMintz, Yuval  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29*e8f1cb50SMintz, Yuval  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30*e8f1cb50SMintz, Yuval  * SOFTWARE.
31fe56b9e6SYuval Mintz  */
32fe56b9e6SYuval Mintz 
33fe56b9e6SYuval Mintz #ifndef _QED_CHAIN_H
34fe56b9e6SYuval Mintz #define _QED_CHAIN_H
35fe56b9e6SYuval Mintz 
36fe56b9e6SYuval Mintz #include <linux/types.h>
37fe56b9e6SYuval Mintz #include <asm/byteorder.h>
38fe56b9e6SYuval Mintz #include <linux/kernel.h>
39fe56b9e6SYuval Mintz #include <linux/list.h>
40fe56b9e6SYuval Mintz #include <linux/slab.h>
41fe56b9e6SYuval Mintz #include <linux/qed/common_hsi.h>
42fe56b9e6SYuval Mintz 
43fe56b9e6SYuval Mintz enum qed_chain_mode {
44fe56b9e6SYuval Mintz 	/* Each Page contains a next pointer at its end */
45fe56b9e6SYuval Mintz 	QED_CHAIN_MODE_NEXT_PTR,
46fe56b9e6SYuval Mintz 
47fe56b9e6SYuval Mintz 	/* Chain is a single page (next ptr) is unrequired */
48fe56b9e6SYuval Mintz 	QED_CHAIN_MODE_SINGLE,
49fe56b9e6SYuval Mintz 
50fe56b9e6SYuval Mintz 	/* Page pointers are located in a side list */
51fe56b9e6SYuval Mintz 	QED_CHAIN_MODE_PBL,
52fe56b9e6SYuval Mintz };
53fe56b9e6SYuval Mintz 
54fe56b9e6SYuval Mintz enum qed_chain_use_mode {
55fe56b9e6SYuval Mintz 	QED_CHAIN_USE_TO_PRODUCE,		/* Chain starts empty */
56fe56b9e6SYuval Mintz 	QED_CHAIN_USE_TO_CONSUME,		/* Chain starts full */
57fe56b9e6SYuval Mintz 	QED_CHAIN_USE_TO_CONSUME_PRODUCE,	/* Chain starts empty */
58fe56b9e6SYuval Mintz };
59fe56b9e6SYuval Mintz 
60a91eb52aSYuval Mintz enum qed_chain_cnt_type {
61a91eb52aSYuval Mintz 	/* The chain's size/prod/cons are kept in 16-bit variables */
62a91eb52aSYuval Mintz 	QED_CHAIN_CNT_TYPE_U16,
63a91eb52aSYuval Mintz 
64a91eb52aSYuval Mintz 	/* The chain's size/prod/cons are kept in 32-bit variables  */
65a91eb52aSYuval Mintz 	QED_CHAIN_CNT_TYPE_U32,
66a91eb52aSYuval Mintz };
67a91eb52aSYuval Mintz 
68fe56b9e6SYuval Mintz struct qed_chain_next {
69fe56b9e6SYuval Mintz 	struct regpair	next_phys;
70fe56b9e6SYuval Mintz 	void		*next_virt;
71fe56b9e6SYuval Mintz };
72fe56b9e6SYuval Mintz 
73a91eb52aSYuval Mintz struct qed_chain_pbl_u16 {
74fe56b9e6SYuval Mintz 	u16 prod_page_idx;
75fe56b9e6SYuval Mintz 	u16 cons_page_idx;
76fe56b9e6SYuval Mintz };
77fe56b9e6SYuval Mintz 
78a91eb52aSYuval Mintz struct qed_chain_pbl_u32 {
79a91eb52aSYuval Mintz 	u32 prod_page_idx;
80a91eb52aSYuval Mintz 	u32 cons_page_idx;
81a91eb52aSYuval Mintz };
82a91eb52aSYuval Mintz 
83a91eb52aSYuval Mintz struct qed_chain_u16 {
84a91eb52aSYuval Mintz 	/* Cyclic index of next element to produce/consme */
85a91eb52aSYuval Mintz 	u16 prod_idx;
86a91eb52aSYuval Mintz 	u16 cons_idx;
87a91eb52aSYuval Mintz };
88a91eb52aSYuval Mintz 
89a91eb52aSYuval Mintz struct qed_chain_u32 {
90a91eb52aSYuval Mintz 	/* Cyclic index of next element to produce/consme */
91a91eb52aSYuval Mintz 	u32 prod_idx;
92a91eb52aSYuval Mintz 	u32 cons_idx;
93a91eb52aSYuval Mintz };
94a91eb52aSYuval Mintz 
95fe56b9e6SYuval Mintz struct qed_chain {
966d937acfSMintz, Yuval 	/* fastpath portion of the chain - required for commands such
976d937acfSMintz, Yuval 	 * as produce / consume.
986d937acfSMintz, Yuval 	 */
996d937acfSMintz, Yuval 	/* Point to next element to produce/consume */
100fe56b9e6SYuval Mintz 	void *p_prod_elem;
101fe56b9e6SYuval Mintz 	void *p_cons_elem;
102a91eb52aSYuval Mintz 
1036d937acfSMintz, Yuval 	/* Fastpath portions of the PBL [if exists] */
1046d937acfSMintz, Yuval 	struct {
1056d937acfSMintz, Yuval 		/* Table for keeping the virtual addresses of the chain pages,
1066d937acfSMintz, Yuval 		 * respectively to the physical addresses in the pbl table.
1076d937acfSMintz, Yuval 		 */
1086d937acfSMintz, Yuval 		void **pp_virt_addr_tbl;
1096d937acfSMintz, Yuval 
1106d937acfSMintz, Yuval 		union {
1116d937acfSMintz, Yuval 			struct qed_chain_pbl_u16 u16;
1126d937acfSMintz, Yuval 			struct qed_chain_pbl_u32 u32;
1136d937acfSMintz, Yuval 		} c;
1146d937acfSMintz, Yuval 	} pbl;
115a91eb52aSYuval Mintz 
116a91eb52aSYuval Mintz 	union {
117a91eb52aSYuval Mintz 		struct qed_chain_u16 chain16;
118a91eb52aSYuval Mintz 		struct qed_chain_u32 chain32;
119a91eb52aSYuval Mintz 	} u;
120a91eb52aSYuval Mintz 
1216d937acfSMintz, Yuval 	/* Capacity counts only usable elements */
1226d937acfSMintz, Yuval 	u32 capacity;
123a91eb52aSYuval Mintz 	u32 page_cnt;
124a91eb52aSYuval Mintz 
1256d937acfSMintz, Yuval 	enum qed_chain_mode mode;
126a91eb52aSYuval Mintz 
127a91eb52aSYuval Mintz 	/* Elements information for fast calculations */
128fe56b9e6SYuval Mintz 	u16 elem_per_page;
129fe56b9e6SYuval Mintz 	u16 elem_per_page_mask;
130fe56b9e6SYuval Mintz 	u16 elem_size;
131fe56b9e6SYuval Mintz 	u16 next_page_mask;
1326d937acfSMintz, Yuval 	u16 usable_per_page;
1336d937acfSMintz, Yuval 	u8 elem_unusable;
1346d937acfSMintz, Yuval 
1356d937acfSMintz, Yuval 	u8 cnt_type;
1366d937acfSMintz, Yuval 
1376d937acfSMintz, Yuval 	/* Slowpath of the chain - required for initialization and destruction,
1386d937acfSMintz, Yuval 	 * but isn't involved in regular functionality.
1396d937acfSMintz, Yuval 	 */
1406d937acfSMintz, Yuval 
1416d937acfSMintz, Yuval 	/* Base address of a pre-allocated buffer for pbl */
1426d937acfSMintz, Yuval 	struct {
1436d937acfSMintz, Yuval 		dma_addr_t p_phys_table;
1446d937acfSMintz, Yuval 		void *p_virt_table;
1456d937acfSMintz, Yuval 	} pbl_sp;
1466d937acfSMintz, Yuval 
1476d937acfSMintz, Yuval 	/* Address of first page of the chain - the address is required
1486d937acfSMintz, Yuval 	 * for fastpath operation [consume/produce] but only for the the SINGLE
1496d937acfSMintz, Yuval 	 * flavour which isn't considered fastpath [== SPQ].
1506d937acfSMintz, Yuval 	 */
1516d937acfSMintz, Yuval 	void *p_virt_addr;
1526d937acfSMintz, Yuval 	dma_addr_t p_phys_addr;
1536d937acfSMintz, Yuval 
1546d937acfSMintz, Yuval 	/* Total number of elements [for entire chain] */
1556d937acfSMintz, Yuval 	u32 size;
1566d937acfSMintz, Yuval 
1576d937acfSMintz, Yuval 	u8 intended_use;
158fe56b9e6SYuval Mintz };
159fe56b9e6SYuval Mintz 
160fe56b9e6SYuval Mintz #define QED_CHAIN_PBL_ENTRY_SIZE        (8)
161fe56b9e6SYuval Mintz #define QED_CHAIN_PAGE_SIZE             (0x1000)
162fe56b9e6SYuval Mintz #define ELEMS_PER_PAGE(elem_size)       (QED_CHAIN_PAGE_SIZE / (elem_size))
163fe56b9e6SYuval Mintz 
164fe56b9e6SYuval Mintz #define UNUSABLE_ELEMS_PER_PAGE(elem_size, mode)	 \
1656d937acfSMintz, Yuval 	(((mode) == QED_CHAIN_MODE_NEXT_PTR) ?		 \
1666d937acfSMintz, Yuval 	 (u8)(1 + ((sizeof(struct qed_chain_next) - 1) / \
167fe56b9e6SYuval Mintz 		   (elem_size))) : 0)
168fe56b9e6SYuval Mintz 
169fe56b9e6SYuval Mintz #define USABLE_ELEMS_PER_PAGE(elem_size, mode) \
170fe56b9e6SYuval Mintz 	((u32)(ELEMS_PER_PAGE(elem_size) -     \
171fe56b9e6SYuval Mintz 	       UNUSABLE_ELEMS_PER_PAGE(elem_size, mode)))
172fe56b9e6SYuval Mintz 
173fe56b9e6SYuval Mintz #define QED_CHAIN_PAGE_CNT(elem_cnt, elem_size, mode) \
174fe56b9e6SYuval Mintz 	DIV_ROUND_UP(elem_cnt, USABLE_ELEMS_PER_PAGE(elem_size, mode))
175fe56b9e6SYuval Mintz 
176a91eb52aSYuval Mintz #define is_chain_u16(p) ((p)->cnt_type == QED_CHAIN_CNT_TYPE_U16)
177a91eb52aSYuval Mintz #define is_chain_u32(p) ((p)->cnt_type == QED_CHAIN_CNT_TYPE_U32)
178a91eb52aSYuval Mintz 
179fe56b9e6SYuval Mintz /* Accessors */
180fe56b9e6SYuval Mintz static inline u16 qed_chain_get_prod_idx(struct qed_chain *p_chain)
181fe56b9e6SYuval Mintz {
182a91eb52aSYuval Mintz 	return p_chain->u.chain16.prod_idx;
183fe56b9e6SYuval Mintz }
184fe56b9e6SYuval Mintz 
185fe56b9e6SYuval Mintz static inline u16 qed_chain_get_cons_idx(struct qed_chain *p_chain)
186fe56b9e6SYuval Mintz {
187a91eb52aSYuval Mintz 	return p_chain->u.chain16.cons_idx;
188a91eb52aSYuval Mintz }
189a91eb52aSYuval Mintz 
190a91eb52aSYuval Mintz static inline u32 qed_chain_get_cons_idx_u32(struct qed_chain *p_chain)
191a91eb52aSYuval Mintz {
192a91eb52aSYuval Mintz 	return p_chain->u.chain32.cons_idx;
193fe56b9e6SYuval Mintz }
194fe56b9e6SYuval Mintz 
195fe56b9e6SYuval Mintz static inline u16 qed_chain_get_elem_left(struct qed_chain *p_chain)
196fe56b9e6SYuval Mintz {
197fe56b9e6SYuval Mintz 	u16 used;
198fe56b9e6SYuval Mintz 
199a91eb52aSYuval Mintz 	used = (u16) (((u32)0x10000 +
200a91eb52aSYuval Mintz 		       (u32)p_chain->u.chain16.prod_idx) -
201a91eb52aSYuval Mintz 		      (u32)p_chain->u.chain16.cons_idx);
202fe56b9e6SYuval Mintz 	if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR)
203a91eb52aSYuval Mintz 		used -= p_chain->u.chain16.prod_idx / p_chain->elem_per_page -
204a91eb52aSYuval Mintz 		    p_chain->u.chain16.cons_idx / p_chain->elem_per_page;
205a91eb52aSYuval Mintz 
206a91eb52aSYuval Mintz 	return (u16)(p_chain->capacity - used);
207a91eb52aSYuval Mintz }
208a91eb52aSYuval Mintz 
209a91eb52aSYuval Mintz static inline u32 qed_chain_get_elem_left_u32(struct qed_chain *p_chain)
210a91eb52aSYuval Mintz {
211a91eb52aSYuval Mintz 	u32 used;
212a91eb52aSYuval Mintz 
213a91eb52aSYuval Mintz 	used = (u32) (((u64)0x100000000ULL +
214a91eb52aSYuval Mintz 		       (u64)p_chain->u.chain32.prod_idx) -
215a91eb52aSYuval Mintz 		      (u64)p_chain->u.chain32.cons_idx);
216a91eb52aSYuval Mintz 	if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR)
217a91eb52aSYuval Mintz 		used -= p_chain->u.chain32.prod_idx / p_chain->elem_per_page -
218a91eb52aSYuval Mintz 		    p_chain->u.chain32.cons_idx / p_chain->elem_per_page;
219fe56b9e6SYuval Mintz 
220fe56b9e6SYuval Mintz 	return p_chain->capacity - used;
221fe56b9e6SYuval Mintz }
222fe56b9e6SYuval Mintz 
223a91eb52aSYuval Mintz static inline u16 qed_chain_get_usable_per_page(struct qed_chain *p_chain)
224fe56b9e6SYuval Mintz {
225fe56b9e6SYuval Mintz 	return p_chain->usable_per_page;
226fe56b9e6SYuval Mintz }
227fe56b9e6SYuval Mintz 
2286d937acfSMintz, Yuval static inline u8 qed_chain_get_unusable_per_page(struct qed_chain *p_chain)
229fe56b9e6SYuval Mintz {
230fe56b9e6SYuval Mintz 	return p_chain->elem_unusable;
231fe56b9e6SYuval Mintz }
232fe56b9e6SYuval Mintz 
233a91eb52aSYuval Mintz static inline u32 qed_chain_get_page_cnt(struct qed_chain *p_chain)
234fe56b9e6SYuval Mintz {
235a91eb52aSYuval Mintz 	return p_chain->page_cnt;
236fe56b9e6SYuval Mintz }
237fe56b9e6SYuval Mintz 
238a91eb52aSYuval Mintz static inline dma_addr_t qed_chain_get_pbl_phys(struct qed_chain *p_chain)
239fe56b9e6SYuval Mintz {
2406d937acfSMintz, Yuval 	return p_chain->pbl_sp.p_phys_table;
241fe56b9e6SYuval Mintz }
242fe56b9e6SYuval Mintz 
243fe56b9e6SYuval Mintz /**
244fe56b9e6SYuval Mintz  * @brief qed_chain_advance_page -
245fe56b9e6SYuval Mintz  *
246fe56b9e6SYuval Mintz  * Advance the next element accros pages for a linked chain
247fe56b9e6SYuval Mintz  *
248fe56b9e6SYuval Mintz  * @param p_chain
249fe56b9e6SYuval Mintz  * @param p_next_elem
250fe56b9e6SYuval Mintz  * @param idx_to_inc
251fe56b9e6SYuval Mintz  * @param page_to_inc
252fe56b9e6SYuval Mintz  */
253fe56b9e6SYuval Mintz static inline void
254fe56b9e6SYuval Mintz qed_chain_advance_page(struct qed_chain *p_chain,
255a91eb52aSYuval Mintz 		       void **p_next_elem, void *idx_to_inc, void *page_to_inc)
256fe56b9e6SYuval Mintz {
257a91eb52aSYuval Mintz 	struct qed_chain_next *p_next = NULL;
258a91eb52aSYuval Mintz 	u32 page_index = 0;
2596d937acfSMintz, Yuval 
260fe56b9e6SYuval Mintz 	switch (p_chain->mode) {
261fe56b9e6SYuval Mintz 	case QED_CHAIN_MODE_NEXT_PTR:
262a91eb52aSYuval Mintz 		p_next = *p_next_elem;
263fe56b9e6SYuval Mintz 		*p_next_elem = p_next->next_virt;
264a91eb52aSYuval Mintz 		if (is_chain_u16(p_chain))
265a91eb52aSYuval Mintz 			*(u16 *)idx_to_inc += p_chain->elem_unusable;
266a91eb52aSYuval Mintz 		else
267a91eb52aSYuval Mintz 			*(u32 *)idx_to_inc += p_chain->elem_unusable;
268fe56b9e6SYuval Mintz 		break;
269fe56b9e6SYuval Mintz 	case QED_CHAIN_MODE_SINGLE:
270fe56b9e6SYuval Mintz 		*p_next_elem = p_chain->p_virt_addr;
271fe56b9e6SYuval Mintz 		break;
272fe56b9e6SYuval Mintz 
273fe56b9e6SYuval Mintz 	case QED_CHAIN_MODE_PBL:
274a91eb52aSYuval Mintz 		if (is_chain_u16(p_chain)) {
275a91eb52aSYuval Mintz 			if (++(*(u16 *)page_to_inc) == p_chain->page_cnt)
276a91eb52aSYuval Mintz 				*(u16 *)page_to_inc = 0;
277a91eb52aSYuval Mintz 			page_index = *(u16 *)page_to_inc;
278a91eb52aSYuval Mintz 		} else {
279a91eb52aSYuval Mintz 			if (++(*(u32 *)page_to_inc) == p_chain->page_cnt)
280a91eb52aSYuval Mintz 				*(u32 *)page_to_inc = 0;
281a91eb52aSYuval Mintz 			page_index = *(u32 *)page_to_inc;
282fe56b9e6SYuval Mintz 		}
283a91eb52aSYuval Mintz 		*p_next_elem = p_chain->pbl.pp_virt_addr_tbl[page_index];
284fe56b9e6SYuval Mintz 	}
285fe56b9e6SYuval Mintz }
286fe56b9e6SYuval Mintz 
287fe56b9e6SYuval Mintz #define is_unusable_idx(p, idx)	\
288a91eb52aSYuval Mintz 	(((p)->u.chain16.idx & (p)->elem_per_page_mask) == (p)->usable_per_page)
289fe56b9e6SYuval Mintz 
290a91eb52aSYuval Mintz #define is_unusable_idx_u32(p, idx) \
291a91eb52aSYuval Mintz 	(((p)->u.chain32.idx & (p)->elem_per_page_mask) == (p)->usable_per_page)
292fe56b9e6SYuval Mintz #define is_unusable_next_idx(p, idx)				 \
293a91eb52aSYuval Mintz 	((((p)->u.chain16.idx + 1) & (p)->elem_per_page_mask) == \
294a91eb52aSYuval Mintz 	 (p)->usable_per_page)
295fe56b9e6SYuval Mintz 
296a91eb52aSYuval Mintz #define is_unusable_next_idx_u32(p, idx)			 \
297a91eb52aSYuval Mintz 	((((p)->u.chain32.idx + 1) & (p)->elem_per_page_mask) == \
298a91eb52aSYuval Mintz 	 (p)->usable_per_page)
299a91eb52aSYuval Mintz 
300a91eb52aSYuval Mintz #define test_and_skip(p, idx)						   \
301fe56b9e6SYuval Mintz 	do {						\
302a91eb52aSYuval Mintz 		if (is_chain_u16(p)) {					   \
303a91eb52aSYuval Mintz 			if (is_unusable_idx(p, idx))			   \
304a91eb52aSYuval Mintz 				(p)->u.chain16.idx += (p)->elem_unusable;  \
305a91eb52aSYuval Mintz 		} else {						   \
306a91eb52aSYuval Mintz 			if (is_unusable_idx_u32(p, idx))		   \
307a91eb52aSYuval Mintz 				(p)->u.chain32.idx += (p)->elem_unusable;  \
308fe56b9e6SYuval Mintz 		}					\
309fe56b9e6SYuval Mintz 	} while (0)
310fe56b9e6SYuval Mintz 
311fe56b9e6SYuval Mintz /**
312fe56b9e6SYuval Mintz  * @brief qed_chain_return_produced -
313fe56b9e6SYuval Mintz  *
314fe56b9e6SYuval Mintz  * A chain in which the driver "Produces" elements should use this API
315fe56b9e6SYuval Mintz  * to indicate previous produced elements are now consumed.
316fe56b9e6SYuval Mintz  *
317fe56b9e6SYuval Mintz  * @param p_chain
318fe56b9e6SYuval Mintz  */
319fe56b9e6SYuval Mintz static inline void qed_chain_return_produced(struct qed_chain *p_chain)
320fe56b9e6SYuval Mintz {
321a91eb52aSYuval Mintz 	if (is_chain_u16(p_chain))
322a91eb52aSYuval Mintz 		p_chain->u.chain16.cons_idx++;
323a91eb52aSYuval Mintz 	else
324a91eb52aSYuval Mintz 		p_chain->u.chain32.cons_idx++;
325a91eb52aSYuval Mintz 	test_and_skip(p_chain, cons_idx);
326fe56b9e6SYuval Mintz }
327fe56b9e6SYuval Mintz 
328fe56b9e6SYuval Mintz /**
329fe56b9e6SYuval Mintz  * @brief qed_chain_produce -
330fe56b9e6SYuval Mintz  *
331fe56b9e6SYuval Mintz  * A chain in which the driver "Produces" elements should use this to get
332fe56b9e6SYuval Mintz  * a pointer to the next element which can be "Produced". It's driver
333fe56b9e6SYuval Mintz  * responsibility to validate that the chain has room for new element.
334fe56b9e6SYuval Mintz  *
335fe56b9e6SYuval Mintz  * @param p_chain
336fe56b9e6SYuval Mintz  *
337fe56b9e6SYuval Mintz  * @return void*, a pointer to next element
338fe56b9e6SYuval Mintz  */
339fe56b9e6SYuval Mintz static inline void *qed_chain_produce(struct qed_chain *p_chain)
340fe56b9e6SYuval Mintz {
341a91eb52aSYuval Mintz 	void *p_ret = NULL, *p_prod_idx, *p_prod_page_idx;
342fe56b9e6SYuval Mintz 
343a91eb52aSYuval Mintz 	if (is_chain_u16(p_chain)) {
344a91eb52aSYuval Mintz 		if ((p_chain->u.chain16.prod_idx &
345a91eb52aSYuval Mintz 		     p_chain->elem_per_page_mask) == p_chain->next_page_mask) {
346a91eb52aSYuval Mintz 			p_prod_idx = &p_chain->u.chain16.prod_idx;
3476d937acfSMintz, Yuval 			p_prod_page_idx = &p_chain->pbl.c.u16.prod_page_idx;
348fe56b9e6SYuval Mintz 			qed_chain_advance_page(p_chain, &p_chain->p_prod_elem,
349a91eb52aSYuval Mintz 					       p_prod_idx, p_prod_page_idx);
350a91eb52aSYuval Mintz 		}
351a91eb52aSYuval Mintz 		p_chain->u.chain16.prod_idx++;
352a91eb52aSYuval Mintz 	} else {
353a91eb52aSYuval Mintz 		if ((p_chain->u.chain32.prod_idx &
354a91eb52aSYuval Mintz 		     p_chain->elem_per_page_mask) == p_chain->next_page_mask) {
355a91eb52aSYuval Mintz 			p_prod_idx = &p_chain->u.chain32.prod_idx;
3566d937acfSMintz, Yuval 			p_prod_page_idx = &p_chain->pbl.c.u32.prod_page_idx;
357a91eb52aSYuval Mintz 			qed_chain_advance_page(p_chain, &p_chain->p_prod_elem,
358a91eb52aSYuval Mintz 					       p_prod_idx, p_prod_page_idx);
359a91eb52aSYuval Mintz 		}
360a91eb52aSYuval Mintz 		p_chain->u.chain32.prod_idx++;
361fe56b9e6SYuval Mintz 	}
362fe56b9e6SYuval Mintz 
363a91eb52aSYuval Mintz 	p_ret = p_chain->p_prod_elem;
364fe56b9e6SYuval Mintz 	p_chain->p_prod_elem = (void *)(((u8 *)p_chain->p_prod_elem) +
365fe56b9e6SYuval Mintz 					p_chain->elem_size);
366fe56b9e6SYuval Mintz 
367a91eb52aSYuval Mintz 	return p_ret;
368fe56b9e6SYuval Mintz }
369fe56b9e6SYuval Mintz 
370fe56b9e6SYuval Mintz /**
371fe56b9e6SYuval Mintz  * @brief qed_chain_get_capacity -
372fe56b9e6SYuval Mintz  *
373fe56b9e6SYuval Mintz  * Get the maximum number of BDs in chain
374fe56b9e6SYuval Mintz  *
375fe56b9e6SYuval Mintz  * @param p_chain
376fe56b9e6SYuval Mintz  * @param num
377fe56b9e6SYuval Mintz  *
378a91eb52aSYuval Mintz  * @return number of unusable BDs
379fe56b9e6SYuval Mintz  */
380a91eb52aSYuval Mintz static inline u32 qed_chain_get_capacity(struct qed_chain *p_chain)
381fe56b9e6SYuval Mintz {
382fe56b9e6SYuval Mintz 	return p_chain->capacity;
383fe56b9e6SYuval Mintz }
384fe56b9e6SYuval Mintz 
385fe56b9e6SYuval Mintz /**
386fe56b9e6SYuval Mintz  * @brief qed_chain_recycle_consumed -
387fe56b9e6SYuval Mintz  *
388fe56b9e6SYuval Mintz  * Returns an element which was previously consumed;
389fe56b9e6SYuval Mintz  * Increments producers so they could be written to FW.
390fe56b9e6SYuval Mintz  *
391fe56b9e6SYuval Mintz  * @param p_chain
392fe56b9e6SYuval Mintz  */
393a91eb52aSYuval Mintz static inline void qed_chain_recycle_consumed(struct qed_chain *p_chain)
394fe56b9e6SYuval Mintz {
395a91eb52aSYuval Mintz 	test_and_skip(p_chain, prod_idx);
396a91eb52aSYuval Mintz 	if (is_chain_u16(p_chain))
397a91eb52aSYuval Mintz 		p_chain->u.chain16.prod_idx++;
398a91eb52aSYuval Mintz 	else
399a91eb52aSYuval Mintz 		p_chain->u.chain32.prod_idx++;
400fe56b9e6SYuval Mintz }
401fe56b9e6SYuval Mintz 
402fe56b9e6SYuval Mintz /**
403fe56b9e6SYuval Mintz  * @brief qed_chain_consume -
404fe56b9e6SYuval Mintz  *
405fe56b9e6SYuval Mintz  * A Chain in which the driver utilizes data written by a different source
406fe56b9e6SYuval Mintz  * (i.e., FW) should use this to access passed buffers.
407fe56b9e6SYuval Mintz  *
408fe56b9e6SYuval Mintz  * @param p_chain
409fe56b9e6SYuval Mintz  *
410fe56b9e6SYuval Mintz  * @return void*, a pointer to the next buffer written
411fe56b9e6SYuval Mintz  */
412fe56b9e6SYuval Mintz static inline void *qed_chain_consume(struct qed_chain *p_chain)
413fe56b9e6SYuval Mintz {
414a91eb52aSYuval Mintz 	void *p_ret = NULL, *p_cons_idx, *p_cons_page_idx;
415fe56b9e6SYuval Mintz 
416a91eb52aSYuval Mintz 	if (is_chain_u16(p_chain)) {
417a91eb52aSYuval Mintz 		if ((p_chain->u.chain16.cons_idx &
418a91eb52aSYuval Mintz 		     p_chain->elem_per_page_mask) == p_chain->next_page_mask) {
419a91eb52aSYuval Mintz 			p_cons_idx = &p_chain->u.chain16.cons_idx;
4206d937acfSMintz, Yuval 			p_cons_page_idx = &p_chain->pbl.c.u16.cons_page_idx;
421fe56b9e6SYuval Mintz 			qed_chain_advance_page(p_chain, &p_chain->p_cons_elem,
422a91eb52aSYuval Mintz 					       p_cons_idx, p_cons_page_idx);
423a91eb52aSYuval Mintz 		}
424a91eb52aSYuval Mintz 		p_chain->u.chain16.cons_idx++;
425a91eb52aSYuval Mintz 	} else {
426a91eb52aSYuval Mintz 		if ((p_chain->u.chain32.cons_idx &
427a91eb52aSYuval Mintz 		     p_chain->elem_per_page_mask) == p_chain->next_page_mask) {
428a91eb52aSYuval Mintz 			p_cons_idx = &p_chain->u.chain32.cons_idx;
4296d937acfSMintz, Yuval 			p_cons_page_idx = &p_chain->pbl.c.u32.cons_page_idx;
430a91eb52aSYuval Mintz 			qed_chain_advance_page(p_chain, &p_chain->p_cons_elem,
431a91eb52aSYuval Mintz 					       p_cons_idx, p_cons_page_idx);
432a91eb52aSYuval Mintz 		}
433a91eb52aSYuval Mintz 		p_chain->u.chain32.cons_idx++;
434fe56b9e6SYuval Mintz 	}
435fe56b9e6SYuval Mintz 
436a91eb52aSYuval Mintz 	p_ret = p_chain->p_cons_elem;
437fe56b9e6SYuval Mintz 	p_chain->p_cons_elem = (void *)(((u8 *)p_chain->p_cons_elem) +
438fe56b9e6SYuval Mintz 					p_chain->elem_size);
439fe56b9e6SYuval Mintz 
440a91eb52aSYuval Mintz 	return p_ret;
441fe56b9e6SYuval Mintz }
442fe56b9e6SYuval Mintz 
443fe56b9e6SYuval Mintz /**
444fe56b9e6SYuval Mintz  * @brief qed_chain_reset - Resets the chain to its start state
445fe56b9e6SYuval Mintz  *
446fe56b9e6SYuval Mintz  * @param p_chain pointer to a previously allocted chain
447fe56b9e6SYuval Mintz  */
448fe56b9e6SYuval Mintz static inline void qed_chain_reset(struct qed_chain *p_chain)
449fe56b9e6SYuval Mintz {
450a91eb52aSYuval Mintz 	u32 i;
451fe56b9e6SYuval Mintz 
452a91eb52aSYuval Mintz 	if (is_chain_u16(p_chain)) {
453a91eb52aSYuval Mintz 		p_chain->u.chain16.prod_idx = 0;
454a91eb52aSYuval Mintz 		p_chain->u.chain16.cons_idx = 0;
455a91eb52aSYuval Mintz 	} else {
456a91eb52aSYuval Mintz 		p_chain->u.chain32.prod_idx = 0;
457a91eb52aSYuval Mintz 		p_chain->u.chain32.cons_idx = 0;
458a91eb52aSYuval Mintz 	}
459fe56b9e6SYuval Mintz 	p_chain->p_cons_elem = p_chain->p_virt_addr;
460fe56b9e6SYuval Mintz 	p_chain->p_prod_elem = p_chain->p_virt_addr;
461fe56b9e6SYuval Mintz 
462fe56b9e6SYuval Mintz 	if (p_chain->mode == QED_CHAIN_MODE_PBL) {
463a91eb52aSYuval Mintz 		/* Use (page_cnt - 1) as a reset value for the prod/cons page's
464a91eb52aSYuval Mintz 		 * indices, to avoid unnecessary page advancing on the first
465a91eb52aSYuval Mintz 		 * call to qed_chain_produce/consume. Instead, the indices
466a91eb52aSYuval Mintz 		 * will be advanced to page_cnt and then will be wrapped to 0.
467a91eb52aSYuval Mintz 		 */
468a91eb52aSYuval Mintz 		u32 reset_val = p_chain->page_cnt - 1;
469a91eb52aSYuval Mintz 
470a91eb52aSYuval Mintz 		if (is_chain_u16(p_chain)) {
4716d937acfSMintz, Yuval 			p_chain->pbl.c.u16.prod_page_idx = (u16)reset_val;
4726d937acfSMintz, Yuval 			p_chain->pbl.c.u16.cons_page_idx = (u16)reset_val;
473a91eb52aSYuval Mintz 		} else {
4746d937acfSMintz, Yuval 			p_chain->pbl.c.u32.prod_page_idx = reset_val;
4756d937acfSMintz, Yuval 			p_chain->pbl.c.u32.cons_page_idx = reset_val;
476a91eb52aSYuval Mintz 		}
477fe56b9e6SYuval Mintz 	}
478fe56b9e6SYuval Mintz 
479fe56b9e6SYuval Mintz 	switch (p_chain->intended_use) {
480fe56b9e6SYuval Mintz 	case QED_CHAIN_USE_TO_CONSUME:
481fe56b9e6SYuval Mintz 		/* produce empty elements */
482fe56b9e6SYuval Mintz 		for (i = 0; i < p_chain->capacity; i++)
483fe56b9e6SYuval Mintz 			qed_chain_recycle_consumed(p_chain);
484fe56b9e6SYuval Mintz 		break;
4856d937acfSMintz, Yuval 
4866d937acfSMintz, Yuval 	case QED_CHAIN_USE_TO_CONSUME_PRODUCE:
4876d937acfSMintz, Yuval 	case QED_CHAIN_USE_TO_PRODUCE:
4886d937acfSMintz, Yuval 	default:
4896d937acfSMintz, Yuval 		/* Do nothing */
4906d937acfSMintz, Yuval 		break;
491fe56b9e6SYuval Mintz 	}
492fe56b9e6SYuval Mintz }
493fe56b9e6SYuval Mintz 
494fe56b9e6SYuval Mintz /**
495fe56b9e6SYuval Mintz  * @brief qed_chain_init - Initalizes a basic chain struct
496fe56b9e6SYuval Mintz  *
497fe56b9e6SYuval Mintz  * @param p_chain
498fe56b9e6SYuval Mintz  * @param p_virt_addr
499fe56b9e6SYuval Mintz  * @param p_phys_addr	physical address of allocated buffer's beginning
500fe56b9e6SYuval Mintz  * @param page_cnt	number of pages in the allocated buffer
501fe56b9e6SYuval Mintz  * @param elem_size	size of each element in the chain
502fe56b9e6SYuval Mintz  * @param intended_use
503fe56b9e6SYuval Mintz  * @param mode
504fe56b9e6SYuval Mintz  */
505a91eb52aSYuval Mintz static inline void qed_chain_init_params(struct qed_chain *p_chain,
506a91eb52aSYuval Mintz 					 u32 page_cnt,
507fe56b9e6SYuval Mintz 					 u8 elem_size,
508fe56b9e6SYuval Mintz 					 enum qed_chain_use_mode intended_use,
509a91eb52aSYuval Mintz 					 enum qed_chain_mode mode,
510a91eb52aSYuval Mintz 					 enum qed_chain_cnt_type cnt_type)
511fe56b9e6SYuval Mintz {
512fe56b9e6SYuval Mintz 	/* chain fixed parameters */
513a91eb52aSYuval Mintz 	p_chain->p_virt_addr = NULL;
514a91eb52aSYuval Mintz 	p_chain->p_phys_addr = 0;
515fe56b9e6SYuval Mintz 	p_chain->elem_size	= elem_size;
5166d937acfSMintz, Yuval 	p_chain->intended_use = (u8)intended_use;
517a91eb52aSYuval Mintz 	p_chain->mode		= mode;
5186d937acfSMintz, Yuval 	p_chain->cnt_type = (u8)cnt_type;
519a91eb52aSYuval Mintz 
520fe56b9e6SYuval Mintz 	p_chain->elem_per_page = ELEMS_PER_PAGE(elem_size);
521a91eb52aSYuval Mintz 	p_chain->usable_per_page = USABLE_ELEMS_PER_PAGE(elem_size, mode);
522fe56b9e6SYuval Mintz 	p_chain->elem_per_page_mask = p_chain->elem_per_page - 1;
523fe56b9e6SYuval Mintz 	p_chain->elem_unusable = UNUSABLE_ELEMS_PER_PAGE(elem_size, mode);
524fe56b9e6SYuval Mintz 	p_chain->next_page_mask = (p_chain->usable_per_page &
525fe56b9e6SYuval Mintz 				   p_chain->elem_per_page_mask);
526fe56b9e6SYuval Mintz 
527a91eb52aSYuval Mintz 	p_chain->page_cnt = page_cnt;
528a91eb52aSYuval Mintz 	p_chain->capacity = p_chain->usable_per_page * page_cnt;
529a91eb52aSYuval Mintz 	p_chain->size = p_chain->elem_per_page * page_cnt;
530fe56b9e6SYuval Mintz 
5316d937acfSMintz, Yuval 	p_chain->pbl_sp.p_phys_table = 0;
5326d937acfSMintz, Yuval 	p_chain->pbl_sp.p_virt_table = NULL;
533a91eb52aSYuval Mintz 	p_chain->pbl.pp_virt_addr_tbl = NULL;
534fe56b9e6SYuval Mintz }
535fe56b9e6SYuval Mintz 
536fe56b9e6SYuval Mintz /**
537a91eb52aSYuval Mintz  * @brief qed_chain_init_mem -
538a91eb52aSYuval Mintz  *
539a91eb52aSYuval Mintz  * Initalizes a basic chain struct with its chain buffers
540a91eb52aSYuval Mintz  *
541fe56b9e6SYuval Mintz  * @param p_chain
542fe56b9e6SYuval Mintz  * @param p_virt_addr	virtual address of allocated buffer's beginning
543fe56b9e6SYuval Mintz  * @param p_phys_addr	physical address of allocated buffer's beginning
544a91eb52aSYuval Mintz  *
545fe56b9e6SYuval Mintz  */
546a91eb52aSYuval Mintz static inline void qed_chain_init_mem(struct qed_chain *p_chain,
547a91eb52aSYuval Mintz 				      void *p_virt_addr, dma_addr_t p_phys_addr)
548fe56b9e6SYuval Mintz {
549a91eb52aSYuval Mintz 	p_chain->p_virt_addr = p_virt_addr;
550a91eb52aSYuval Mintz 	p_chain->p_phys_addr = p_phys_addr;
551fe56b9e6SYuval Mintz }
552fe56b9e6SYuval Mintz 
553fe56b9e6SYuval Mintz /**
554a91eb52aSYuval Mintz  * @brief qed_chain_init_pbl_mem -
555a91eb52aSYuval Mintz  *
556a91eb52aSYuval Mintz  * Initalizes a basic chain struct with its pbl buffers
557a91eb52aSYuval Mintz  *
558a91eb52aSYuval Mintz  * @param p_chain
559a91eb52aSYuval Mintz  * @param p_virt_pbl	pointer to a pre allocated side table which will hold
560a91eb52aSYuval Mintz  *                      virtual page addresses.
561a91eb52aSYuval Mintz  * @param p_phys_pbl	pointer to a pre-allocated side table which will hold
562a91eb52aSYuval Mintz  *                      physical page addresses.
563a91eb52aSYuval Mintz  * @param pp_virt_addr_tbl
564a91eb52aSYuval Mintz  *                      pointer to a pre-allocated side table which will hold
565a91eb52aSYuval Mintz  *                      the virtual addresses of the chain pages.
566a91eb52aSYuval Mintz  *
567a91eb52aSYuval Mintz  */
568a91eb52aSYuval Mintz static inline void qed_chain_init_pbl_mem(struct qed_chain *p_chain,
569a91eb52aSYuval Mintz 					  void *p_virt_pbl,
570a91eb52aSYuval Mintz 					  dma_addr_t p_phys_pbl,
571a91eb52aSYuval Mintz 					  void **pp_virt_addr_tbl)
572a91eb52aSYuval Mintz {
5736d937acfSMintz, Yuval 	p_chain->pbl_sp.p_phys_table = p_phys_pbl;
5746d937acfSMintz, Yuval 	p_chain->pbl_sp.p_virt_table = p_virt_pbl;
575a91eb52aSYuval Mintz 	p_chain->pbl.pp_virt_addr_tbl = pp_virt_addr_tbl;
576a91eb52aSYuval Mintz }
577a91eb52aSYuval Mintz 
578a91eb52aSYuval Mintz /**
579a91eb52aSYuval Mintz  * @brief qed_chain_init_next_ptr_elem -
580a91eb52aSYuval Mintz  *
581a91eb52aSYuval Mintz  * Initalizes a next pointer element
582a91eb52aSYuval Mintz  *
583a91eb52aSYuval Mintz  * @param p_chain
584a91eb52aSYuval Mintz  * @param p_virt_curr	virtual address of a chain page of which the next
585a91eb52aSYuval Mintz  *                      pointer element is initialized
586a91eb52aSYuval Mintz  * @param p_virt_next	virtual address of the next chain page
587a91eb52aSYuval Mintz  * @param p_phys_next	physical address of the next chain page
588a91eb52aSYuval Mintz  *
589a91eb52aSYuval Mintz  */
590a91eb52aSYuval Mintz static inline void
591a91eb52aSYuval Mintz qed_chain_init_next_ptr_elem(struct qed_chain *p_chain,
592a91eb52aSYuval Mintz 			     void *p_virt_curr,
593a91eb52aSYuval Mintz 			     void *p_virt_next, dma_addr_t p_phys_next)
594a91eb52aSYuval Mintz {
595a91eb52aSYuval Mintz 	struct qed_chain_next *p_next;
596a91eb52aSYuval Mintz 	u32 size;
597a91eb52aSYuval Mintz 
598a91eb52aSYuval Mintz 	size = p_chain->elem_size * p_chain->usable_per_page;
599a91eb52aSYuval Mintz 	p_next = (struct qed_chain_next *)((u8 *)p_virt_curr + size);
600a91eb52aSYuval Mintz 
601a91eb52aSYuval Mintz 	DMA_REGPAIR_LE(p_next->next_phys, p_phys_next);
602a91eb52aSYuval Mintz 
603a91eb52aSYuval Mintz 	p_next->next_virt = p_virt_next;
604a91eb52aSYuval Mintz }
605a91eb52aSYuval Mintz 
606a91eb52aSYuval Mintz /**
607a91eb52aSYuval Mintz  * @brief qed_chain_get_last_elem -
608a91eb52aSYuval Mintz  *
609a91eb52aSYuval Mintz  * Returns a pointer to the last element of the chain
610a91eb52aSYuval Mintz  *
611a91eb52aSYuval Mintz  * @param p_chain
612a91eb52aSYuval Mintz  *
613a91eb52aSYuval Mintz  * @return void*
614a91eb52aSYuval Mintz  */
615a91eb52aSYuval Mintz static inline void *qed_chain_get_last_elem(struct qed_chain *p_chain)
616a91eb52aSYuval Mintz {
617a91eb52aSYuval Mintz 	struct qed_chain_next *p_next = NULL;
618a91eb52aSYuval Mintz 	void *p_virt_addr = NULL;
619a91eb52aSYuval Mintz 	u32 size, last_page_idx;
620a91eb52aSYuval Mintz 
621a91eb52aSYuval Mintz 	if (!p_chain->p_virt_addr)
622a91eb52aSYuval Mintz 		goto out;
623a91eb52aSYuval Mintz 
624a91eb52aSYuval Mintz 	switch (p_chain->mode) {
625a91eb52aSYuval Mintz 	case QED_CHAIN_MODE_NEXT_PTR:
626a91eb52aSYuval Mintz 		size = p_chain->elem_size * p_chain->usable_per_page;
627a91eb52aSYuval Mintz 		p_virt_addr = p_chain->p_virt_addr;
628a91eb52aSYuval Mintz 		p_next = (struct qed_chain_next *)((u8 *)p_virt_addr + size);
629a91eb52aSYuval Mintz 		while (p_next->next_virt != p_chain->p_virt_addr) {
630a91eb52aSYuval Mintz 			p_virt_addr = p_next->next_virt;
631a91eb52aSYuval Mintz 			p_next = (struct qed_chain_next *)((u8 *)p_virt_addr +
632a91eb52aSYuval Mintz 							   size);
633a91eb52aSYuval Mintz 		}
634a91eb52aSYuval Mintz 		break;
635a91eb52aSYuval Mintz 	case QED_CHAIN_MODE_SINGLE:
636a91eb52aSYuval Mintz 		p_virt_addr = p_chain->p_virt_addr;
637a91eb52aSYuval Mintz 		break;
638a91eb52aSYuval Mintz 	case QED_CHAIN_MODE_PBL:
639a91eb52aSYuval Mintz 		last_page_idx = p_chain->page_cnt - 1;
640a91eb52aSYuval Mintz 		p_virt_addr = p_chain->pbl.pp_virt_addr_tbl[last_page_idx];
641a91eb52aSYuval Mintz 		break;
642a91eb52aSYuval Mintz 	}
643a91eb52aSYuval Mintz 	/* p_virt_addr points at this stage to the last page of the chain */
644a91eb52aSYuval Mintz 	size = p_chain->elem_size * (p_chain->usable_per_page - 1);
645a91eb52aSYuval Mintz 	p_virt_addr = (u8 *)p_virt_addr + size;
646a91eb52aSYuval Mintz out:
647a91eb52aSYuval Mintz 	return p_virt_addr;
648a91eb52aSYuval Mintz }
649a91eb52aSYuval Mintz 
650a91eb52aSYuval Mintz /**
651a91eb52aSYuval Mintz  * @brief qed_chain_set_prod - sets the prod to the given value
652fe56b9e6SYuval Mintz  *
653fe56b9e6SYuval Mintz  * @param prod_idx
654fe56b9e6SYuval Mintz  * @param p_prod_elem
655fe56b9e6SYuval Mintz  */
656fe56b9e6SYuval Mintz static inline void qed_chain_set_prod(struct qed_chain *p_chain,
657a91eb52aSYuval Mintz 				      u32 prod_idx, void *p_prod_elem)
658fe56b9e6SYuval Mintz {
659a91eb52aSYuval Mintz 	if (is_chain_u16(p_chain))
660a91eb52aSYuval Mintz 		p_chain->u.chain16.prod_idx = (u16) prod_idx;
661a91eb52aSYuval Mintz 	else
662a91eb52aSYuval Mintz 		p_chain->u.chain32.prod_idx = prod_idx;
663fe56b9e6SYuval Mintz 	p_chain->p_prod_elem = p_prod_elem;
664fe56b9e6SYuval Mintz }
665fe56b9e6SYuval Mintz 
666fe56b9e6SYuval Mintz /**
667a91eb52aSYuval Mintz  * @brief qed_chain_pbl_zero_mem - set chain memory to 0
668fe56b9e6SYuval Mintz  *
669fe56b9e6SYuval Mintz  * @param p_chain
670fe56b9e6SYuval Mintz  */
671a91eb52aSYuval Mintz static inline void qed_chain_pbl_zero_mem(struct qed_chain *p_chain)
672fe56b9e6SYuval Mintz {
673a91eb52aSYuval Mintz 	u32 i, page_cnt;
674fe56b9e6SYuval Mintz 
675a91eb52aSYuval Mintz 	if (p_chain->mode != QED_CHAIN_MODE_PBL)
676a91eb52aSYuval Mintz 		return;
677fe56b9e6SYuval Mintz 
678a91eb52aSYuval Mintz 	page_cnt = qed_chain_get_page_cnt(p_chain);
679fe56b9e6SYuval Mintz 
680a91eb52aSYuval Mintz 	for (i = 0; i < page_cnt; i++)
681a91eb52aSYuval Mintz 		memset(p_chain->pbl.pp_virt_addr_tbl[i], 0,
682a91eb52aSYuval Mintz 		       QED_CHAIN_PAGE_SIZE);
683fe56b9e6SYuval Mintz }
684fe56b9e6SYuval Mintz 
685fe56b9e6SYuval Mintz #endif
686