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