1 /*
2 * Copyright (c) 2017-2018 Cavium, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29 #ifndef __ECORE_INT_API_H__
30 #define __ECORE_INT_API_H__
31
32 #include "common_hsi.h"
33
34 #ifndef __EXTRACT__LINUX__
35 #define ECORE_SB_IDX 0x0002
36
37 #define RX_PI 0
38 #define TX_PI(tc) (RX_PI + 1 + tc)
39
40 #ifndef ECORE_INT_MODE
41 #define ECORE_INT_MODE
42 enum ecore_int_mode {
43 ECORE_INT_MODE_INTA,
44 ECORE_INT_MODE_MSIX,
45 ECORE_INT_MODE_MSI,
46 ECORE_INT_MODE_POLL,
47 };
48 #endif
49
50 struct ecore_sb_info {
51 struct status_block_e4 *sb_virt;
52 dma_addr_t sb_phys;
53 u32 sb_ack; /* Last given ack */
54 u16 igu_sb_id;
55 void OSAL_IOMEM *igu_addr;
56 u8 flags;
57 #define ECORE_SB_INFO_INIT 0x1
58 #define ECORE_SB_INFO_SETUP 0x2
59
60 #ifdef ECORE_CONFIG_DIRECT_HWFN
61 struct ecore_hwfn *p_hwfn;
62 #endif
63 struct ecore_dev *p_dev;
64 };
65
66 struct ecore_sb_info_dbg {
67 u32 igu_prod;
68 u32 igu_cons;
69 u16 pi[PIS_PER_SB_E4];
70 };
71
72 struct ecore_sb_cnt_info {
73 /* Original, current, and free SBs for PF */
74 int orig;
75 int cnt;
76 int free_cnt;
77
78 /* Original, current and free SBS for child VFs */
79 int iov_orig;
80 int iov_cnt;
81 int free_cnt_iov;
82 };
83
ecore_sb_update_sb_idx(struct ecore_sb_info * sb_info)84 static OSAL_INLINE u16 ecore_sb_update_sb_idx(struct ecore_sb_info *sb_info)
85 {
86 u32 prod = 0;
87 u16 rc = 0;
88
89 // barrier(); /* status block is written to by the chip */
90 // FIXME: need some sort of barrier.
91 prod = OSAL_LE32_TO_CPU(sb_info->sb_virt->prod_index) &
92 STATUS_BLOCK_E4_PROD_INDEX_MASK;
93 if (sb_info->sb_ack != prod) {
94 sb_info->sb_ack = prod;
95 rc |= ECORE_SB_IDX;
96 }
97
98 OSAL_MMIOWB(sb_info->p_dev);
99 return rc;
100 }
101
102 /**
103 * @brief This function creates an update command for interrupts that is
104 * written to the IGU.
105 *
106 * @param sb_info - This is the structure allocated and
107 * initialized per status block. Assumption is
108 * that it was initialized using ecore_sb_init
109 * @param int_cmd - Enable/Disable/Nop
110 * @param upd_flg - whether igu consumer should be
111 * updated.
112 *
113 * @return OSAL_INLINE void
114 */
ecore_sb_ack(struct ecore_sb_info * sb_info,enum igu_int_cmd int_cmd,u8 upd_flg)115 static OSAL_INLINE void ecore_sb_ack(struct ecore_sb_info *sb_info,
116 enum igu_int_cmd int_cmd, u8 upd_flg)
117 {
118 struct igu_prod_cons_update igu_ack = { 0 };
119
120 #ifndef ECORE_CONFIG_DIRECT_HWFN
121 u32 val;
122 #endif
123
124 #ifndef LINUX_REMOVE
125 if (sb_info->p_dev->int_mode == ECORE_INT_MODE_POLL)
126 return;
127 #endif
128 igu_ack.sb_id_and_flags =
129 OSAL_CPU_TO_LE32((sb_info->sb_ack <<
130 IGU_PROD_CONS_UPDATE_SB_INDEX_SHIFT) |
131 (upd_flg << IGU_PROD_CONS_UPDATE_UPDATE_FLAG_SHIFT) |
132 (int_cmd << IGU_PROD_CONS_UPDATE_ENABLE_INT_SHIFT) |
133 (IGU_SEG_ACCESS_REG <<
134 IGU_PROD_CONS_UPDATE_SEGMENT_ACCESS_SHIFT));
135
136 #ifdef ECORE_CONFIG_DIRECT_HWFN
137 DIRECT_REG_WR(sb_info->p_hwfn, sb_info->igu_addr,
138 igu_ack.sb_id_and_flags);
139 #else
140 val = OSAL_LE32_TO_CPU(igu_ack.sb_id_and_flags);
141 DIRECT_REG_WR(OSAL_NULL, sb_info->igu_addr, val);
142 #endif
143 /* Both segments (interrupts & acks) are written to same place address;
144 * Need to guarantee all commands will be received (in-order) by HW.
145 */
146 OSAL_MMIOWB(sb_info->p_dev);
147 OSAL_BARRIER(sb_info->p_dev);
148 }
149
150 #ifdef ECORE_CONFIG_DIRECT_HWFN
__internal_ram_wr(struct ecore_hwfn * p_hwfn,void OSAL_IOMEM * addr,int size,u32 * data)151 static OSAL_INLINE void __internal_ram_wr(struct ecore_hwfn *p_hwfn,
152 void OSAL_IOMEM *addr,
153 int size, u32 *data)
154 #else
155 static OSAL_INLINE void __internal_ram_wr(void *p_hwfn,
156 void OSAL_IOMEM *addr,
157 int size, u32 *data)
158
159 #endif
160 {
161 unsigned int i;
162
163 for (i = 0; i < size / sizeof(*data); i++)
164 DIRECT_REG_WR(p_hwfn, &((u32 OSAL_IOMEM *)addr)[i], data[i]);
165 }
166
167 #ifdef ECORE_CONFIG_DIRECT_HWFN
internal_ram_wr(struct ecore_hwfn * p_hwfn,void OSAL_IOMEM * addr,int size,u32 * data)168 static OSAL_INLINE void internal_ram_wr(struct ecore_hwfn *p_hwfn,
169 void OSAL_IOMEM *addr,
170 int size, u32 *data)
171 {
172 __internal_ram_wr(p_hwfn, addr, size, data);
173 }
174 #else
internal_ram_wr(void OSAL_IOMEM * addr,int size,u32 * data)175 static OSAL_INLINE void internal_ram_wr(void OSAL_IOMEM *addr,
176 int size, u32 *data)
177 {
178 __internal_ram_wr(OSAL_NULL, addr, size, data);
179 }
180 #endif
181 #endif
182
183 struct ecore_hwfn;
184 struct ecore_ptt;
185
186 enum ecore_coalescing_fsm {
187 ECORE_COAL_RX_STATE_MACHINE,
188 ECORE_COAL_TX_STATE_MACHINE
189 };
190
191 /**
192 * @brief ecore_int_cau_conf_pi - configure cau for a given
193 * status block
194 *
195 * @param p_hwfn
196 * @param p_ptt
197 * @param p_sb
198 * @param pi_index
199 * @param state
200 * @param timeset
201 */
202 void ecore_int_cau_conf_pi(struct ecore_hwfn *p_hwfn,
203 struct ecore_ptt *p_ptt,
204 struct ecore_sb_info *p_sb,
205 u32 pi_index,
206 enum ecore_coalescing_fsm coalescing_fsm,
207 u8 timeset);
208
209 /**
210 * @brief ecore_int_igu_enable_int - enable device interrupts
211 *
212 * @param p_hwfn
213 * @param p_ptt
214 * @param int_mode - interrupt mode to use
215 */
216 void ecore_int_igu_enable_int(struct ecore_hwfn *p_hwfn,
217 struct ecore_ptt *p_ptt,
218 enum ecore_int_mode int_mode);
219
220 /**
221 * @brief ecore_int_igu_disable_int - disable device interrupts
222 *
223 * @param p_hwfn
224 * @param p_ptt
225 */
226 void ecore_int_igu_disable_int(struct ecore_hwfn *p_hwfn,
227 struct ecore_ptt *p_ptt);
228
229 /**
230 * @brief ecore_int_igu_read_sisr_reg - Reads the single isr multiple dpc
231 * register from igu.
232 *
233 * @param p_hwfn
234 *
235 * @return u64
236 */
237 u64 ecore_int_igu_read_sisr_reg(struct ecore_hwfn *p_hwfn);
238
239 #define ECORE_SP_SB_ID 0xffff
240
241 /**
242 * @brief ecore_int_sb_init - Initializes the sb_info structure.
243 *
244 * once the structure is initialized it can be passed to sb related functions.
245 *
246 * @param p_hwfn
247 * @param p_ptt
248 * @param sb_info points to an uninitialized (but
249 * allocated) sb_info structure
250 * @param sb_virt_addr
251 * @param sb_phy_addr
252 * @param sb_id the sb_id to be used (zero based in driver)
253 * should use ECORE_SP_SB_ID for SP Status block
254 *
255 * @return enum _ecore_status_t
256 */
257 enum _ecore_status_t ecore_int_sb_init(struct ecore_hwfn *p_hwfn,
258 struct ecore_ptt *p_ptt,
259 struct ecore_sb_info *sb_info,
260 void *sb_virt_addr,
261 dma_addr_t sb_phy_addr,
262 u16 sb_id);
263 /**
264 * @brief ecore_int_sb_setup - Setup the sb.
265 *
266 * @param p_hwfn
267 * @param p_ptt
268 * @param sb_info initialized sb_info structure
269 */
270 void ecore_int_sb_setup(
271 struct ecore_hwfn *p_hwfn,
272 struct ecore_ptt *p_ptt,
273 struct ecore_sb_info *sb_info);
274
275 /**
276 * @brief ecore_int_sb_release - releases the sb_info structure.
277 *
278 * once the structure is released, it's memory can be freed
279 *
280 * @param p_hwfn
281 * @param sb_info points to an allocated sb_info structure
282 * @param sb_id the sb_id to be used (zero based in driver)
283 * should never be equal to ECORE_SP_SB_ID
284 * (SP Status block)
285 *
286 * @return enum _ecore_status_t
287 */
288 enum _ecore_status_t ecore_int_sb_release(struct ecore_hwfn *p_hwfn,
289 struct ecore_sb_info *sb_info,
290 u16 sb_id);
291
292 /**
293 * @brief ecore_int_sp_dpc - To be called when an interrupt is received on the
294 * default status block.
295 *
296 * @param p_hwfn - pointer to hwfn
297 *
298 */
299 void ecore_int_sp_dpc(osal_int_ptr_t hwfn_cookie);
300
301 /**
302 * @brief ecore_int_get_num_sbs - get the number of status
303 * blocks configured for this funciton in the igu.
304 *
305 * @param p_hwfn
306 * @param p_sb_cnt_info
307 *
308 * @return
309 */
310 void ecore_int_get_num_sbs(struct ecore_hwfn *p_hwfn,
311 struct ecore_sb_cnt_info *p_sb_cnt_info);
312
313 /**
314 * @brief ecore_int_disable_post_isr_release - performs the cleanup post ISR
315 * release. The API need to be called after releasing all slowpath IRQs
316 * of the device.
317 *
318 * @param p_dev
319 *
320 */
321 void ecore_int_disable_post_isr_release(struct ecore_dev *p_dev);
322
323 /**
324 * @brief ecore_int_attn_clr_enable - sets whether the general behavior is
325 * preventing attentions from being reasserted, or following the
326 * attributes of the specific attention.
327 *
328 * @param p_dev
329 * @param clr_enable
330 *
331 */
332 void ecore_int_attn_clr_enable(struct ecore_dev *p_dev, bool clr_enable);
333
334 /**
335 * @brief Read debug information regarding a given SB.
336 *
337 * @param p_hwfn
338 * @param p_ptt
339 * @param p_sb - point to Status block for which we want to get info.
340 * @param p_info - pointer to struct to fill with information regarding SB.
341 *
342 * @return ECORE_SUCCESS if pointer is filled; failure otherwise.
343 */
344 enum _ecore_status_t ecore_int_get_sb_dbg(struct ecore_hwfn *p_hwfn,
345 struct ecore_ptt *p_ptt,
346 struct ecore_sb_info *p_sb,
347 struct ecore_sb_info_dbg *p_info);
348
349 /**
350 * @brief - Move a free Status block between PF and child VF
351 *
352 * @param p_hwfn
353 * @param p_ptt
354 * @param sb_id - The PF fastpath vector to be moved [re-assigned if claiming
355 * from VF, given-up if moving to VF]
356 * @param b_to_vf - PF->VF == true, VF->PF == false
357 *
358 * @return ECORE_SUCCESS if SB successfully moved.
359 */
360 enum _ecore_status_t
361 ecore_int_igu_relocate_sb(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
362 u16 sb_id, bool b_to_vf);
363 #endif
364