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_EQS_H
17 #define HINIC_HW_EQS_H
18 
19 #include <linux/types.h>
20 #include <linux/workqueue.h>
21 #include <linux/pci.h>
22 #include <linux/sizes.h>
23 #include <linux/bitops.h>
24 #include <linux/interrupt.h>
25 
26 #include "hinic_hw_if.h"
27 
28 #define HINIC_AEQ_CTRL_0_INT_IDX_SHIFT          0
29 #define HINIC_AEQ_CTRL_0_DMA_ATTR_SHIFT         12
30 #define HINIC_AEQ_CTRL_0_PCI_INTF_IDX_SHIFT     20
31 #define HINIC_AEQ_CTRL_0_INT_MODE_SHIFT         31
32 
33 #define HINIC_AEQ_CTRL_0_INT_IDX_MASK           0x3FF
34 #define HINIC_AEQ_CTRL_0_DMA_ATTR_MASK          0x3F
35 #define HINIC_AEQ_CTRL_0_PCI_INTF_IDX_MASK      0x3
36 #define HINIC_AEQ_CTRL_0_INT_MODE_MASK          0x1
37 
38 #define HINIC_AEQ_CTRL_0_SET(val, member)       \
39 			(((u32)(val) & HINIC_AEQ_CTRL_0_##member##_MASK) << \
40 			 HINIC_AEQ_CTRL_0_##member##_SHIFT)
41 
42 #define HINIC_AEQ_CTRL_0_CLEAR(val, member)     \
43 			((val) & (~(HINIC_AEQ_CTRL_0_##member##_MASK \
44 			 << HINIC_AEQ_CTRL_0_##member##_SHIFT)))
45 
46 #define HINIC_AEQ_CTRL_1_LEN_SHIFT              0
47 #define HINIC_AEQ_CTRL_1_ELEM_SIZE_SHIFT        24
48 #define HINIC_AEQ_CTRL_1_PAGE_SIZE_SHIFT        28
49 
50 #define HINIC_AEQ_CTRL_1_LEN_MASK               0x1FFFFF
51 #define HINIC_AEQ_CTRL_1_ELEM_SIZE_MASK         0x3
52 #define HINIC_AEQ_CTRL_1_PAGE_SIZE_MASK         0xF
53 
54 #define HINIC_AEQ_CTRL_1_SET(val, member)       \
55 			(((u32)(val) & HINIC_AEQ_CTRL_1_##member##_MASK) << \
56 			 HINIC_AEQ_CTRL_1_##member##_SHIFT)
57 
58 #define HINIC_AEQ_CTRL_1_CLEAR(val, member)     \
59 			((val) & (~(HINIC_AEQ_CTRL_1_##member##_MASK \
60 			 << HINIC_AEQ_CTRL_1_##member##_SHIFT)))
61 
62 #define HINIC_CEQ_CTRL_0_INTR_IDX_SHIFT         0
63 #define HINIC_CEQ_CTRL_0_DMA_ATTR_SHIFT         12
64 #define HINIC_CEQ_CTRL_0_KICK_THRESH_SHIFT      20
65 #define HINIC_CEQ_CTRL_0_PCI_INTF_IDX_SHIFT     24
66 #define HINIC_CEQ_CTRL_0_INTR_MODE_SHIFT        31
67 
68 #define HINIC_CEQ_CTRL_0_INTR_IDX_MASK          0x3FF
69 #define HINIC_CEQ_CTRL_0_DMA_ATTR_MASK          0x3F
70 #define HINIC_CEQ_CTRL_0_KICK_THRESH_MASK       0xF
71 #define HINIC_CEQ_CTRL_0_PCI_INTF_IDX_MASK      0x3
72 #define HINIC_CEQ_CTRL_0_INTR_MODE_MASK         0x1
73 
74 #define HINIC_CEQ_CTRL_0_SET(val, member)       \
75 			(((u32)(val) & HINIC_CEQ_CTRL_0_##member##_MASK) << \
76 			 HINIC_CEQ_CTRL_0_##member##_SHIFT)
77 
78 #define HINIC_CEQ_CTRL_0_CLEAR(val, member)     \
79 			((val) & (~(HINIC_CEQ_CTRL_0_##member##_MASK \
80 			 << HINIC_CEQ_CTRL_0_##member##_SHIFT)))
81 
82 #define HINIC_CEQ_CTRL_1_LEN_SHIFT              0
83 #define HINIC_CEQ_CTRL_1_PAGE_SIZE_SHIFT        28
84 
85 #define HINIC_CEQ_CTRL_1_LEN_MASK               0x1FFFFF
86 #define HINIC_CEQ_CTRL_1_PAGE_SIZE_MASK         0xF
87 
88 #define HINIC_CEQ_CTRL_1_SET(val, member)       \
89 			(((u32)(val) & HINIC_CEQ_CTRL_1_##member##_MASK) << \
90 			 HINIC_CEQ_CTRL_1_##member##_SHIFT)
91 
92 #define HINIC_CEQ_CTRL_1_CLEAR(val, member)     \
93 			((val) & (~(HINIC_CEQ_CTRL_1_##member##_MASK \
94 			 << HINIC_CEQ_CTRL_1_##member##_SHIFT)))
95 
96 #define HINIC_EQ_ELEM_DESC_TYPE_SHIFT           0
97 #define HINIC_EQ_ELEM_DESC_SRC_SHIFT            7
98 #define HINIC_EQ_ELEM_DESC_SIZE_SHIFT           8
99 #define HINIC_EQ_ELEM_DESC_WRAPPED_SHIFT        31
100 
101 #define HINIC_EQ_ELEM_DESC_TYPE_MASK            0x7F
102 #define HINIC_EQ_ELEM_DESC_SRC_MASK             0x1
103 #define HINIC_EQ_ELEM_DESC_SIZE_MASK            0xFF
104 #define HINIC_EQ_ELEM_DESC_WRAPPED_MASK         0x1
105 
106 #define HINIC_EQ_ELEM_DESC_SET(val, member)     \
107 			(((u32)(val) & HINIC_EQ_ELEM_DESC_##member##_MASK) << \
108 			 HINIC_EQ_ELEM_DESC_##member##_SHIFT)
109 
110 #define HINIC_EQ_ELEM_DESC_GET(val, member)     \
111 			(((val) >> HINIC_EQ_ELEM_DESC_##member##_SHIFT) & \
112 			 HINIC_EQ_ELEM_DESC_##member##_MASK)
113 
114 #define HINIC_EQ_CI_IDX_SHIFT                   0
115 #define HINIC_EQ_CI_WRAPPED_SHIFT               20
116 #define HINIC_EQ_CI_XOR_CHKSUM_SHIFT            24
117 #define HINIC_EQ_CI_INT_ARMED_SHIFT             31
118 
119 #define HINIC_EQ_CI_IDX_MASK                    0xFFFFF
120 #define HINIC_EQ_CI_WRAPPED_MASK                0x1
121 #define HINIC_EQ_CI_XOR_CHKSUM_MASK             0xF
122 #define HINIC_EQ_CI_INT_ARMED_MASK              0x1
123 
124 #define HINIC_EQ_CI_SET(val, member)            \
125 			(((u32)(val) & HINIC_EQ_CI_##member##_MASK) << \
126 			 HINIC_EQ_CI_##member##_SHIFT)
127 
128 #define HINIC_EQ_CI_CLEAR(val, member)          \
129 			((val) & (~(HINIC_EQ_CI_##member##_MASK \
130 			 << HINIC_EQ_CI_##member##_SHIFT)))
131 
132 #define HINIC_MAX_AEQS                  4
133 #define HINIC_MAX_CEQS                  32
134 
135 #define HINIC_AEQE_SIZE                 64
136 #define HINIC_CEQE_SIZE                 4
137 
138 #define HINIC_AEQE_DESC_SIZE            4
139 #define HINIC_AEQE_DATA_SIZE            \
140 			(HINIC_AEQE_SIZE - HINIC_AEQE_DESC_SIZE)
141 
142 #define HINIC_DEFAULT_AEQ_LEN           64
143 #define HINIC_DEFAULT_CEQ_LEN           1024
144 
145 #define HINIC_EQ_PAGE_SIZE              SZ_4K
146 
147 #define HINIC_CEQ_ID_CMDQ               0
148 
149 enum hinic_eq_type {
150 	HINIC_AEQ,
151 	HINIC_CEQ,
152 };
153 
154 enum hinic_aeq_type {
155 	HINIC_MSG_FROM_MGMT_CPU = 2,
156 
157 	HINIC_MAX_AEQ_EVENTS,
158 };
159 
160 enum hinic_ceq_type {
161 	HINIC_CEQ_CMDQ = 3,
162 
163 	HINIC_MAX_CEQ_EVENTS,
164 };
165 
166 enum hinic_eqe_state {
167 	HINIC_EQE_ENABLED = BIT(0),
168 	HINIC_EQE_RUNNING = BIT(1),
169 };
170 
171 struct hinic_aeq_elem {
172 	u8      data[HINIC_AEQE_DATA_SIZE];
173 	u32     desc;
174 };
175 
176 struct hinic_eq_work {
177 	struct work_struct      work;
178 	void                    *data;
179 };
180 
181 struct hinic_eq {
182 	struct hinic_hwif       *hwif;
183 
184 	enum hinic_eq_type      type;
185 	int                     q_id;
186 	u32                     q_len;
187 	u32                     page_size;
188 
189 	u32                     cons_idx;
190 	int                     wrapped;
191 
192 	size_t                  elem_size;
193 	int                     num_pages;
194 	int                     num_elem_in_pg;
195 
196 	struct msix_entry       msix_entry;
197 
198 	dma_addr_t              *dma_addr;
199 	void                    **virt_addr;
200 
201 	struct hinic_eq_work    aeq_work;
202 
203 	struct tasklet_struct   ceq_tasklet;
204 };
205 
206 struct hinic_hw_event_cb {
207 	void    (*hwe_handler)(void *handle, void *data, u8 size);
208 	void                    *handle;
209 	unsigned long           hwe_state;
210 };
211 
212 struct hinic_aeqs {
213 	struct hinic_hwif       *hwif;
214 
215 	struct hinic_eq         aeq[HINIC_MAX_AEQS];
216 	int                     num_aeqs;
217 
218 	struct hinic_hw_event_cb hwe_cb[HINIC_MAX_AEQ_EVENTS];
219 
220 	struct workqueue_struct *workq;
221 };
222 
223 struct hinic_ceq_cb {
224 	void    (*handler)(void *handle, u32 ceqe_data);
225 	void                    *handle;
226 	enum hinic_eqe_state    ceqe_state;
227 };
228 
229 struct hinic_ceqs {
230 	struct hinic_hwif       *hwif;
231 
232 	struct hinic_eq         ceq[HINIC_MAX_CEQS];
233 	int                     num_ceqs;
234 
235 	struct hinic_ceq_cb     ceq_cb[HINIC_MAX_CEQ_EVENTS];
236 };
237 
238 void hinic_aeq_register_hw_cb(struct hinic_aeqs *aeqs,
239 			      enum hinic_aeq_type event, void *handle,
240 			      void (*hwe_handler)(void *handle, void *data,
241 						  u8 size));
242 
243 void hinic_aeq_unregister_hw_cb(struct hinic_aeqs *aeqs,
244 				enum hinic_aeq_type event);
245 
246 void hinic_ceq_register_cb(struct hinic_ceqs *ceqs,
247 			   enum hinic_ceq_type event, void *handle,
248 			   void (*ceq_cb)(void *handle, u32 ceqe_data));
249 
250 void hinic_ceq_unregister_cb(struct hinic_ceqs *ceqs,
251 			     enum hinic_ceq_type event);
252 
253 int hinic_aeqs_init(struct hinic_aeqs *aeqs, struct hinic_hwif *hwif,
254 		    int num_aeqs, u32 q_len, u32 page_size,
255 		    struct msix_entry *msix_entries);
256 
257 void hinic_aeqs_free(struct hinic_aeqs *aeqs);
258 
259 int hinic_ceqs_init(struct hinic_ceqs *ceqs, struct hinic_hwif *hwif,
260 		    int num_ceqs, u32 q_len, u32 page_size,
261 		    struct msix_entry *msix_entries);
262 
263 void hinic_ceqs_free(struct hinic_ceqs *ceqs);
264 
265 #endif
266