xref: /linux/drivers/net/ethernet/huawei/hinic3/hinic3_wq.h (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1*17fcb3dcSFan Gong /* SPDX-License-Identifier: GPL-2.0 */
2*17fcb3dcSFan Gong /* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. */
3*17fcb3dcSFan Gong 
4*17fcb3dcSFan Gong #ifndef _HINIC3_WQ_H_
5*17fcb3dcSFan Gong #define _HINIC3_WQ_H_
6*17fcb3dcSFan Gong 
7*17fcb3dcSFan Gong #include <linux/io.h>
8*17fcb3dcSFan Gong 
9*17fcb3dcSFan Gong #include "hinic3_queue_common.h"
10*17fcb3dcSFan Gong 
11*17fcb3dcSFan Gong struct hinic3_sq_bufdesc {
12*17fcb3dcSFan Gong 	/* 31-bits Length, L2NIC only uses length[17:0] */
13*17fcb3dcSFan Gong 	u32 len;
14*17fcb3dcSFan Gong 	u32 rsvd;
15*17fcb3dcSFan Gong 	u32 hi_addr;
16*17fcb3dcSFan Gong 	u32 lo_addr;
17*17fcb3dcSFan Gong };
18*17fcb3dcSFan Gong 
19*17fcb3dcSFan Gong /* Work queue is used to submit elements (tx, rx, cmd) to hw.
20*17fcb3dcSFan Gong  * Driver is the producer that advances prod_idx. cons_idx is advanced when
21*17fcb3dcSFan Gong  * HW reports completions of previously submitted elements.
22*17fcb3dcSFan Gong  */
23*17fcb3dcSFan Gong struct hinic3_wq {
24*17fcb3dcSFan Gong 	struct hinic3_queue_pages qpages;
25*17fcb3dcSFan Gong 	/* Unmasked producer/consumer indices that are advanced to natural
26*17fcb3dcSFan Gong 	 * integer overflow regardless of queue depth.
27*17fcb3dcSFan Gong 	 */
28*17fcb3dcSFan Gong 	u16                       cons_idx;
29*17fcb3dcSFan Gong 	u16                       prod_idx;
30*17fcb3dcSFan Gong 
31*17fcb3dcSFan Gong 	u32                       q_depth;
32*17fcb3dcSFan Gong 	u16                       idx_mask;
33*17fcb3dcSFan Gong 
34*17fcb3dcSFan Gong 	/* Work Queue (logical WQEBB array) is mapped to hw via Chip Logical
35*17fcb3dcSFan Gong 	 * Address (CLA) using 1 of 2 levels:
36*17fcb3dcSFan Gong 	 *     level 0 - direct mapping of single wq page
37*17fcb3dcSFan Gong 	 *     level 1 - indirect mapping of multiple pages via additional page
38*17fcb3dcSFan Gong 	 *               table.
39*17fcb3dcSFan Gong 	 * When wq uses level 1, wq_block will hold the allocated indirection
40*17fcb3dcSFan Gong 	 * table.
41*17fcb3dcSFan Gong 	 */
42*17fcb3dcSFan Gong 	dma_addr_t                wq_block_paddr;
43*17fcb3dcSFan Gong 	__be64                    *wq_block_vaddr;
44*17fcb3dcSFan Gong } ____cacheline_aligned;
45*17fcb3dcSFan Gong 
46*17fcb3dcSFan Gong /* Get number of elements in work queue that are in-use. */
47*17fcb3dcSFan Gong static inline u16 hinic3_wq_get_used(const struct hinic3_wq *wq)
48*17fcb3dcSFan Gong {
49*17fcb3dcSFan Gong 	return READ_ONCE(wq->prod_idx) - READ_ONCE(wq->cons_idx);
50*17fcb3dcSFan Gong }
51*17fcb3dcSFan Gong 
52*17fcb3dcSFan Gong static inline u16 hinic3_wq_free_wqebbs(struct hinic3_wq *wq)
53*17fcb3dcSFan Gong {
54*17fcb3dcSFan Gong 	/* Don't allow queue to become completely full, report (free - 1). */
55*17fcb3dcSFan Gong 	return wq->q_depth - hinic3_wq_get_used(wq) - 1;
56*17fcb3dcSFan Gong }
57*17fcb3dcSFan Gong 
58*17fcb3dcSFan Gong static inline void *hinic3_wq_get_one_wqebb(struct hinic3_wq *wq, u16 *pi)
59*17fcb3dcSFan Gong {
60*17fcb3dcSFan Gong 	*pi = wq->prod_idx & wq->idx_mask;
61*17fcb3dcSFan Gong 	wq->prod_idx++;
62*17fcb3dcSFan Gong 	return get_q_element(&wq->qpages, *pi, NULL);
63*17fcb3dcSFan Gong }
64*17fcb3dcSFan Gong 
65*17fcb3dcSFan Gong static inline void hinic3_wq_put_wqebbs(struct hinic3_wq *wq, u16 num_wqebbs)
66*17fcb3dcSFan Gong {
67*17fcb3dcSFan Gong 	wq->cons_idx += num_wqebbs;
68*17fcb3dcSFan Gong }
69*17fcb3dcSFan Gong 
70*17fcb3dcSFan Gong void hinic3_wq_get_multi_wqebbs(struct hinic3_wq *wq,
71*17fcb3dcSFan Gong 				u16 num_wqebbs, u16 *prod_idx,
72*17fcb3dcSFan Gong 				struct hinic3_sq_bufdesc **first_part_wqebbs,
73*17fcb3dcSFan Gong 				struct hinic3_sq_bufdesc **second_part_wqebbs,
74*17fcb3dcSFan Gong 				u16 *first_part_wqebbs_num);
75*17fcb3dcSFan Gong 
76*17fcb3dcSFan Gong #endif
77