2026-01-29 22:25:33 +08:00

131 lines
3.3 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 Huawei Technologies Co., Ltd */
#ifndef HINIC3_WQ_H
#define HINIC3_WQ_H
struct hinic3_wq {
u16 cons_idx;
u16 prod_idx;
u32 q_depth;
u16 idx_mask;
u16 wqebb_size_shift;
u16 rsvd1;
u16 num_wq_pages;
u32 wqebbs_per_page;
u16 wqebbs_per_page_shift;
u16 wqebbs_per_page_mask;
struct hinic3_dma_addr_align *wq_pages;
dma_addr_t wq_block_paddr;
u64 *wq_block_vaddr;
void *dev_hdl;
u32 wq_page_size;
u16 wqebb_size;
} ____cacheline_aligned;
#define WQ_MASK_IDX(wq, idx) ((idx) & (wq)->idx_mask)
#define WQ_MASK_PAGE(wq, pg_idx) \
((pg_idx) < (wq)->num_wq_pages ? (pg_idx) : 0)
#define WQ_PAGE_IDX(wq, idx) ((idx) >> (wq)->wqebbs_per_page_shift)
#define WQ_OFFSET_IN_PAGE(wq, idx) ((idx) & (wq)->wqebbs_per_page_mask)
#define WQ_GET_WQEBB_ADDR(wq, pg_idx, idx_in_pg) \
((u8 *)(wq)->wq_pages[pg_idx].align_vaddr + \
((idx_in_pg) << (wq)->wqebb_size_shift))
#define WQ_IS_0_LEVEL_CLA(wq) ((wq)->num_wq_pages == 1)
#ifdef static
#undef static
#define LLT_STATIC_DEF_SAVED
#endif
static inline u16 hinic3_wq_free_wqebbs(struct hinic3_wq *wq)
{
return wq->q_depth - ((wq->q_depth + wq->prod_idx - wq->cons_idx) &
wq->idx_mask) - 1;
}
static inline bool hinic3_wq_is_empty(struct hinic3_wq *wq)
{
return WQ_MASK_IDX(wq, wq->prod_idx) == WQ_MASK_IDX(wq, wq->cons_idx);
}
static inline void *hinic3_wq_get_one_wqebb(struct hinic3_wq *wq, u16 *pi)
{
*pi = WQ_MASK_IDX(wq, wq->prod_idx);
wq->prod_idx++;
return WQ_GET_WQEBB_ADDR(wq, WQ_PAGE_IDX(wq, *pi),
WQ_OFFSET_IN_PAGE(wq, *pi));
}
static inline void *hinic3_wq_get_multi_wqebbs(struct hinic3_wq *wq,
u16 num_wqebbs, u16 *prod_idx,
void **second_part_wqebbs_addr,
u16 *first_part_wqebbs_num)
{
u32 pg_idx, off_in_page;
*prod_idx = WQ_MASK_IDX(wq, wq->prod_idx);
wq->prod_idx += num_wqebbs;
pg_idx = WQ_PAGE_IDX(wq, *prod_idx);
off_in_page = WQ_OFFSET_IN_PAGE(wq, *prod_idx);
if (off_in_page + num_wqebbs > wq->wqebbs_per_page) {
/* wqe across wq page boundary */
*second_part_wqebbs_addr =
WQ_GET_WQEBB_ADDR(wq, WQ_MASK_PAGE(wq, pg_idx + 1), 0);
*first_part_wqebbs_num = wq->wqebbs_per_page - off_in_page;
} else {
*second_part_wqebbs_addr = NULL;
*first_part_wqebbs_num = num_wqebbs;
}
return WQ_GET_WQEBB_ADDR(wq, pg_idx, off_in_page);
}
static inline void hinic3_wq_put_wqebbs(struct hinic3_wq *wq, u16 num_wqebbs)
{
wq->cons_idx += num_wqebbs;
}
static inline void *hinic3_wq_wqebb_addr(struct hinic3_wq *wq, u16 idx)
{
return WQ_GET_WQEBB_ADDR(wq, WQ_PAGE_IDX(wq, idx),
WQ_OFFSET_IN_PAGE(wq, idx));
}
static inline void *hinic3_wq_read_one_wqebb(struct hinic3_wq *wq,
u16 *cons_idx)
{
*cons_idx = WQ_MASK_IDX(wq, wq->cons_idx);
return hinic3_wq_wqebb_addr(wq, *cons_idx);
}
static inline u64 hinic3_wq_get_first_wqe_page_addr(struct hinic3_wq *wq)
{
return wq->wq_pages[0].align_paddr;
}
static inline void hinic3_wq_reset(struct hinic3_wq *wq)
{
u16 pg_idx;
wq->cons_idx = 0;
wq->prod_idx = 0;
for (pg_idx = 0; pg_idx < wq->num_wq_pages; pg_idx++)
memset(wq->wq_pages[pg_idx].align_vaddr, 0, wq->wq_page_size);
}
int hinic3_wq_create(void *hwdev, struct hinic3_wq *wq, u32 q_depth,
u16 wqebb_size);
void hinic3_wq_destroy(struct hinic3_wq *wq);
#endif