131 lines
3.3 KiB
C
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
|