Lines Matching +full:next +full:- +full:mode

1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
3 * Copyright (c) 2015-2017 QLogic Corporation
4 * Copyright (c) 2019-2020 Marvell International Ltd.
19 /* Each Page contains a next pointer at its end */
22 /* Chain is a single page (next ptr) is not required */
36 /* The chain's size/prod/cons are kept in 16-bit variables */
39 /* The chain's size/prod/cons are kept in 32-bit variables */
59 /* Cyclic index of next element to produce/consume */
65 /* Cyclic index of next element to produce/consume */
76 /* Fastpath portion of the chain - required for commands such
80 /* Point to next element to produce/consume */
108 enum qed_chain_mode mode; member
120 /* Slowpath of the chain - required for initialization and destruction,
126 /* Base address of a pre-allocated buffer for pbl */
133 /* Address of first page of the chain - the address is required
149 enum qed_chain_mode mode; member
166 #define UNUSABLE_ELEMS_PER_PAGE(elem_size, mode) \ argument
167 (((mode) == QED_CHAIN_MODE_NEXT_PTR) ? \
168 (u8)(1 + ((sizeof(struct qed_chain_next) - 1) / (elem_size))) : \
171 #define USABLE_ELEMS_PER_PAGE(elem_size, page_size, mode) \ argument
172 ((u32)(ELEMS_PER_PAGE((elem_size), (page_size)) - \
173 UNUSABLE_ELEMS_PER_PAGE((elem_size), (mode))))
175 #define QED_CHAIN_PAGE_CNT(elem_cnt, elem_size, page_size, mode) \ argument
177 USABLE_ELEMS_PER_PAGE((elem_size), (page_size), (mode)))
180 ((p)->cnt_type == QED_CHAIN_CNT_TYPE_U16)
182 ((p)->cnt_type == QED_CHAIN_CNT_TYPE_U32)
188 return chain->u.chain16.prod_idx; in qed_chain_get_prod_idx()
193 return chain->u.chain16.cons_idx; in qed_chain_get_cons_idx()
198 return chain->u.chain32.prod_idx; in qed_chain_get_prod_idx_u32()
203 return chain->u.chain32.cons_idx; in qed_chain_get_cons_idx_u32()
210 u16 elem_per_page = chain->elem_per_page; in qed_chain_get_elem_used()
216 used = (u16)(prod - cons); in qed_chain_get_elem_used()
217 if (chain->mode == QED_CHAIN_MODE_NEXT_PTR) in qed_chain_get_elem_used()
218 used -= (u16)(prod / elem_per_page - cons / elem_per_page); in qed_chain_get_elem_used()
225 return (u16)(chain->capacity - qed_chain_get_elem_used(chain)); in qed_chain_get_elem_left()
232 u16 elem_per_page = chain->elem_per_page; in qed_chain_get_elem_used_u32()
238 used = (u32)(prod - cons); in qed_chain_get_elem_used_u32()
239 if (chain->mode == QED_CHAIN_MODE_NEXT_PTR) in qed_chain_get_elem_used_u32()
240 used -= (u32)(prod / elem_per_page - cons / elem_per_page); in qed_chain_get_elem_used_u32()
247 return chain->capacity - qed_chain_get_elem_used_u32(chain); in qed_chain_get_elem_left_u32()
252 return chain->usable_per_page; in qed_chain_get_usable_per_page()
257 return chain->elem_unusable; in qed_chain_get_unusable_per_page()
262 return chain->page_cnt; in qed_chain_get_page_cnt()
267 return chain->pbl_sp.table_phys; in qed_chain_get_pbl_phys()
271 * qed_chain_advance_page(): Advance the next element across pages for a
288 switch (p_chain->mode) { in qed_chain_advance_page()
291 *p_next_elem = p_next->next_virt; in qed_chain_advance_page()
293 *(u16 *)idx_to_inc += p_chain->elem_unusable; in qed_chain_advance_page()
295 *(u32 *)idx_to_inc += p_chain->elem_unusable; in qed_chain_advance_page()
298 *p_next_elem = p_chain->p_virt_addr; in qed_chain_advance_page()
303 if (++(*(u16 *)page_to_inc) == p_chain->page_cnt) in qed_chain_advance_page()
307 if (++(*(u32 *)page_to_inc) == p_chain->page_cnt) in qed_chain_advance_page()
311 *p_next_elem = p_chain->pbl.pp_addr_tbl[page_index].virt_addr; in qed_chain_advance_page()
316 (((p)->u.chain16.idx & (p)->elem_per_page_mask) == (p)->usable_per_page)
319 (((p)->u.chain32.idx & (p)->elem_per_page_mask) == (p)->usable_per_page)
321 ((((p)->u.chain16.idx + 1) & (p)->elem_per_page_mask) == \
322 (p)->usable_per_page)
325 ((((p)->u.chain32.idx + 1) & (p)->elem_per_page_mask) == \
326 (p)->usable_per_page)
332 (p)->u.chain16.idx += (p)->elem_unusable; \
335 (p)->u.chain32.idx += (p)->elem_unusable; \
352 p_chain->u.chain16.cons_idx++; in qed_chain_return_produced()
354 p_chain->u.chain32.cons_idx++; in qed_chain_return_produced()
361 * the next element which can be "Produced". It's driver
367 * Return: void*, a pointer to next element.
374 if ((p_chain->u.chain16.prod_idx & in qed_chain_produce()
375 p_chain->elem_per_page_mask) == p_chain->next_page_mask) { in qed_chain_produce()
376 p_prod_idx = &p_chain->u.chain16.prod_idx; in qed_chain_produce()
377 p_prod_page_idx = &p_chain->pbl.c.u16.prod_page_idx; in qed_chain_produce()
378 qed_chain_advance_page(p_chain, &p_chain->p_prod_elem, in qed_chain_produce()
381 p_chain->u.chain16.prod_idx++; in qed_chain_produce()
383 if ((p_chain->u.chain32.prod_idx & in qed_chain_produce()
384 p_chain->elem_per_page_mask) == p_chain->next_page_mask) { in qed_chain_produce()
385 p_prod_idx = &p_chain->u.chain32.prod_idx; in qed_chain_produce()
386 p_prod_page_idx = &p_chain->pbl.c.u32.prod_page_idx; in qed_chain_produce()
387 qed_chain_advance_page(p_chain, &p_chain->p_prod_elem, in qed_chain_produce()
390 p_chain->u.chain32.prod_idx++; in qed_chain_produce()
393 p_ret = p_chain->p_prod_elem; in qed_chain_produce()
394 p_chain->p_prod_elem = (void *)(((u8 *)p_chain->p_prod_elem) + in qed_chain_produce()
395 p_chain->elem_size); in qed_chain_produce()
409 return p_chain->capacity; in qed_chain_get_capacity()
426 p_chain->u.chain16.prod_idx++; in qed_chain_recycle_consumed()
428 p_chain->u.chain32.prod_idx++; in qed_chain_recycle_consumed()
438 * Return: void*, a pointer to the next buffer written.
445 if ((p_chain->u.chain16.cons_idx & in qed_chain_consume()
446 p_chain->elem_per_page_mask) == p_chain->next_page_mask) { in qed_chain_consume()
447 p_cons_idx = &p_chain->u.chain16.cons_idx; in qed_chain_consume()
448 p_cons_page_idx = &p_chain->pbl.c.u16.cons_page_idx; in qed_chain_consume()
449 qed_chain_advance_page(p_chain, &p_chain->p_cons_elem, in qed_chain_consume()
452 p_chain->u.chain16.cons_idx++; in qed_chain_consume()
454 if ((p_chain->u.chain32.cons_idx & in qed_chain_consume()
455 p_chain->elem_per_page_mask) == p_chain->next_page_mask) { in qed_chain_consume()
456 p_cons_idx = &p_chain->u.chain32.cons_idx; in qed_chain_consume()
457 p_cons_page_idx = &p_chain->pbl.c.u32.cons_page_idx; in qed_chain_consume()
458 qed_chain_advance_page(p_chain, &p_chain->p_cons_elem, in qed_chain_consume()
461 p_chain->u.chain32.cons_idx++; in qed_chain_consume()
464 p_ret = p_chain->p_cons_elem; in qed_chain_consume()
465 p_chain->p_cons_elem = (void *)(((u8 *)p_chain->p_cons_elem) + in qed_chain_consume()
466 p_chain->elem_size); in qed_chain_consume()
483 p_chain->u.chain16.prod_idx = 0; in qed_chain_reset()
484 p_chain->u.chain16.cons_idx = 0; in qed_chain_reset()
486 p_chain->u.chain32.prod_idx = 0; in qed_chain_reset()
487 p_chain->u.chain32.cons_idx = 0; in qed_chain_reset()
489 p_chain->p_cons_elem = p_chain->p_virt_addr; in qed_chain_reset()
490 p_chain->p_prod_elem = p_chain->p_virt_addr; in qed_chain_reset()
492 if (p_chain->mode == QED_CHAIN_MODE_PBL) { in qed_chain_reset()
493 /* Use (page_cnt - 1) as a reset value for the prod/cons page's in qed_chain_reset()
498 u32 reset_val = p_chain->page_cnt - 1; in qed_chain_reset()
501 p_chain->pbl.c.u16.prod_page_idx = (u16)reset_val; in qed_chain_reset()
502 p_chain->pbl.c.u16.cons_page_idx = (u16)reset_val; in qed_chain_reset()
504 p_chain->pbl.c.u32.prod_page_idx = reset_val; in qed_chain_reset()
505 p_chain->pbl.c.u32.cons_page_idx = reset_val; in qed_chain_reset()
509 switch (p_chain->intended_use) { in qed_chain_reset()
512 for (i = 0; i < p_chain->capacity; i++) in qed_chain_reset()
538 if (!p_chain->p_virt_addr) in qed_chain_get_last_elem()
541 switch (p_chain->mode) { in qed_chain_get_last_elem()
543 size = p_chain->elem_size * p_chain->usable_per_page; in qed_chain_get_last_elem()
544 p_virt_addr = p_chain->p_virt_addr; in qed_chain_get_last_elem()
546 while (p_next->next_virt != p_chain->p_virt_addr) { in qed_chain_get_last_elem()
547 p_virt_addr = p_next->next_virt; in qed_chain_get_last_elem()
553 p_virt_addr = p_chain->p_virt_addr; in qed_chain_get_last_elem()
556 last_page_idx = p_chain->page_cnt - 1; in qed_chain_get_last_elem()
557 p_virt_addr = p_chain->pbl.pp_addr_tbl[last_page_idx].virt_addr; in qed_chain_get_last_elem()
561 size = p_chain->elem_size * (p_chain->usable_per_page - 1); in qed_chain_get_last_elem()
579 if (p_chain->mode == QED_CHAIN_MODE_PBL) { in qed_chain_set_prod()
582 cur_prod = is_chain_u16(p_chain) ? p_chain->u.chain16.prod_idx : in qed_chain_set_prod()
583 p_chain->u.chain32.prod_idx; in qed_chain_set_prod()
586 page_mask = ~p_chain->elem_per_page_mask; in qed_chain_set_prod()
588 /* Use "cur_prod - 1" and "prod_idx - 1" since producer index in qed_chain_set_prod()
589 * reaches the first element of next page before the page index in qed_chain_set_prod()
595 page_diff = (((cur_prod - 1) & page_mask) - in qed_chain_set_prod()
596 ((prod_idx - 1) & page_mask)) / in qed_chain_set_prod()
597 p_chain->elem_per_page; in qed_chain_set_prod()
601 p_chain->pbl.c.u16.prod_page_idx = in qed_chain_set_prod()
602 (p_chain->pbl.c.u16.prod_page_idx - in qed_chain_set_prod()
605 p_chain->pbl.c.u32.prod_page_idx = in qed_chain_set_prod()
606 (p_chain->pbl.c.u32.prod_page_idx - in qed_chain_set_prod()
611 p_chain->u.chain16.prod_idx = (u16) prod_idx; in qed_chain_set_prod()
613 p_chain->u.chain32.prod_idx = prod_idx; in qed_chain_set_prod()
614 p_chain->p_prod_elem = p_prod_elem; in qed_chain_set_prod()
628 if (p_chain->mode != QED_CHAIN_MODE_PBL) in qed_chain_pbl_zero_mem()
634 memset(p_chain->pbl.pp_addr_tbl[i].virt_addr, 0, in qed_chain_pbl_zero_mem()
635 p_chain->page_size); in qed_chain_pbl_zero_mem()