1 /*
2  * Huawei HiNIC PCI Express Linux driver
3  * Copyright(c) 2017 Huawei Technologies Co., Ltd
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * for more details.
13  *
14  */
15 
16 #ifndef HINIC_HW_WQ_H
17 #define HINIC_HW_WQ_H
18 
19 #include <linux/types.h>
20 #include <linux/semaphore.h>
21 #include <linux/atomic.h>
22 
23 #include "hinic_hw_if.h"
24 #include "hinic_hw_wqe.h"
25 
26 struct hinic_free_block {
27 	int     page_idx;
28 	int     block_idx;
29 };
30 
31 struct hinic_wq {
32 	struct hinic_hwif       *hwif;
33 
34 	int             page_idx;
35 	int             block_idx;
36 
37 	u16             wqebb_size;
38 	u16             wq_page_size;
39 	u16             q_depth;
40 	u16             max_wqe_size;
41 	u16             num_wqebbs_per_page;
42 	u16		wqebbs_per_page_shift;
43 	u16		wqebb_size_shift;
44 	/* The addresses are 64 bit in the HW */
45 	u64             block_paddr;
46 	void            **shadow_block_vaddr;
47 	u64             *block_vaddr;
48 
49 	int             num_q_pages;
50 	u8              *shadow_wqe;
51 	u16             *shadow_idx;
52 
53 	atomic_t        cons_idx;
54 	atomic_t        prod_idx;
55 	atomic_t        delta;
56 	u16             mask;
57 };
58 
59 struct hinic_wqs {
60 	struct hinic_hwif       *hwif;
61 	int                     num_pages;
62 
63 	/* The addresses are 64 bit in the HW */
64 	u64                     *page_paddr;
65 	u64                     **page_vaddr;
66 	void                    ***shadow_page_vaddr;
67 
68 	struct hinic_free_block *free_blocks;
69 	int                     alloc_blk_pos;
70 	int                     return_blk_pos;
71 	int                     num_free_blks;
72 
73 	/* Lock for getting a free block from the WQ set */
74 	struct semaphore        alloc_blocks_lock;
75 };
76 
77 struct hinic_cmdq_pages {
78 	/* The addresses are 64 bit in the HW */
79 	u64                     page_paddr;
80 	u64                     *page_vaddr;
81 	void                    **shadow_page_vaddr;
82 
83 	struct hinic_hwif       *hwif;
84 };
85 
86 int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages,
87 			 struct hinic_wq *wq, struct hinic_hwif *hwif,
88 			 int cmdq_blocks, u16 wqebb_size, u16 wq_page_size,
89 			 u16 q_depth, u16 max_wqe_size);
90 
91 void hinic_wqs_cmdq_free(struct hinic_cmdq_pages *cmdq_pages,
92 			 struct hinic_wq *wq, int cmdq_blocks);
93 
94 int hinic_wqs_alloc(struct hinic_wqs *wqs, int num_wqs,
95 		    struct hinic_hwif *hwif);
96 
97 void hinic_wqs_free(struct hinic_wqs *wqs);
98 
99 int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq,
100 		      u16 wqebb_size, u16 wq_page_size, u16 q_depth,
101 		      u16 max_wqe_size);
102 
103 void hinic_wq_free(struct hinic_wqs *wqs, struct hinic_wq *wq);
104 
105 struct hinic_hw_wqe *hinic_get_wqe(struct hinic_wq *wq, unsigned int wqe_size,
106 				   u16 *prod_idx);
107 
108 void hinic_return_wqe(struct hinic_wq *wq, unsigned int wqe_size);
109 
110 void hinic_put_wqe(struct hinic_wq *wq, unsigned int wqe_size);
111 
112 struct hinic_hw_wqe *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size,
113 				    u16 *cons_idx);
114 
115 struct hinic_hw_wqe *hinic_read_wqe_direct(struct hinic_wq *wq, u16 cons_idx);
116 
117 void hinic_write_wqe(struct hinic_wq *wq, struct hinic_hw_wqe *wqe,
118 		     unsigned int wqe_size);
119 
120 #endif
121