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